1de52133fSJohn Stultz /* valid adjtimex test
2de52133fSJohn Stultz * by: John Stultz <john.stultz@linaro.org>
3de52133fSJohn Stultz * (C) Copyright Linaro 2015
4de52133fSJohn Stultz * Licensed under the GPLv2
5de52133fSJohn Stultz *
6de52133fSJohn Stultz * This test validates adjtimex interface with valid
7de52133fSJohn Stultz * and invalid test data.
8de52133fSJohn Stultz *
9de52133fSJohn Stultz * Usage: valid-adjtimex
10de52133fSJohn Stultz *
11de52133fSJohn Stultz * To build:
12de52133fSJohn Stultz * $ gcc valid-adjtimex.c -o valid-adjtimex -lrt
13de52133fSJohn Stultz *
14de52133fSJohn Stultz * This program is free software: you can redistribute it and/or modify
15de52133fSJohn Stultz * it under the terms of the GNU General Public License as published by
16de52133fSJohn Stultz * the Free Software Foundation, either version 2 of the License, or
17de52133fSJohn Stultz * (at your option) any later version.
18de52133fSJohn Stultz *
19de52133fSJohn Stultz * This program is distributed in the hope that it will be useful,
20de52133fSJohn Stultz * but WITHOUT ANY WARRANTY; without even the implied warranty of
21de52133fSJohn Stultz * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22de52133fSJohn Stultz * GNU General Public License for more details.
23de52133fSJohn Stultz */
24de52133fSJohn Stultz #include <stdio.h>
25de52133fSJohn Stultz #include <stdlib.h>
26de52133fSJohn Stultz #include <time.h>
27de52133fSJohn Stultz #include <sys/time.h>
28de52133fSJohn Stultz #include <sys/timex.h>
29de52133fSJohn Stultz #include <string.h>
30de52133fSJohn Stultz #include <signal.h>
31de52133fSJohn Stultz #include <unistd.h>
32de52133fSJohn Stultz #include "../kselftest.h"
33de52133fSJohn Stultz
34e03a58c3SJohn Stultz #define NSEC_PER_SEC 1000000000LL
35e03a58c3SJohn Stultz #define USEC_PER_SEC 1000000LL
36e03a58c3SJohn Stultz
37e03a58c3SJohn Stultz #define ADJ_SETOFFSET 0x0100
38e03a58c3SJohn Stultz
39e03a58c3SJohn Stultz #include <sys/syscall.h>
clock_adjtime(clockid_t id,struct timex * tx)409a162977SWolfram Sang int clock_adjtime(clockid_t id, struct timex *tx)
41e03a58c3SJohn Stultz {
42e03a58c3SJohn Stultz return syscall(__NR_clock_adjtime, id, tx);
43e03a58c3SJohn Stultz }
44e03a58c3SJohn Stultz
45de52133fSJohn Stultz
46de52133fSJohn Stultz /* clear NTP time_status & time_state */
clear_time_state(void)47de52133fSJohn Stultz int clear_time_state(void)
48de52133fSJohn Stultz {
49de52133fSJohn Stultz struct timex tx;
50de52133fSJohn Stultz int ret;
51de52133fSJohn Stultz
52de52133fSJohn Stultz tx.modes = ADJ_STATUS;
53de52133fSJohn Stultz tx.status = 0;
54de52133fSJohn Stultz ret = adjtimex(&tx);
55de52133fSJohn Stultz return ret;
56de52133fSJohn Stultz }
57de52133fSJohn Stultz
58de52133fSJohn Stultz #define NUM_FREQ_VALID 32
59de52133fSJohn Stultz #define NUM_FREQ_OUTOFRANGE 4
60de52133fSJohn Stultz #define NUM_FREQ_INVALID 2
61de52133fSJohn Stultz
6207636136SJohn Stultz #define SHIFTED_PPM (1 << 16)
6307636136SJohn Stultz
64de52133fSJohn Stultz long valid_freq[NUM_FREQ_VALID] = {
6507636136SJohn Stultz -499 * SHIFTED_PPM,
6607636136SJohn Stultz -450 * SHIFTED_PPM,
6707636136SJohn Stultz -400 * SHIFTED_PPM,
6807636136SJohn Stultz -350 * SHIFTED_PPM,
6907636136SJohn Stultz -300 * SHIFTED_PPM,
7007636136SJohn Stultz -250 * SHIFTED_PPM,
7107636136SJohn Stultz -200 * SHIFTED_PPM,
7207636136SJohn Stultz -150 * SHIFTED_PPM,
7307636136SJohn Stultz -100 * SHIFTED_PPM,
7407636136SJohn Stultz -75 * SHIFTED_PPM,
7507636136SJohn Stultz -50 * SHIFTED_PPM,
7607636136SJohn Stultz -25 * SHIFTED_PPM,
7707636136SJohn Stultz -10 * SHIFTED_PPM,
7807636136SJohn Stultz -5 * SHIFTED_PPM,
7907636136SJohn Stultz -1 * SHIFTED_PPM,
80de52133fSJohn Stultz -1000,
8107636136SJohn Stultz 1 * SHIFTED_PPM,
8207636136SJohn Stultz 5 * SHIFTED_PPM,
8307636136SJohn Stultz 10 * SHIFTED_PPM,
8407636136SJohn Stultz 25 * SHIFTED_PPM,
8507636136SJohn Stultz 50 * SHIFTED_PPM,
8607636136SJohn Stultz 75 * SHIFTED_PPM,
8707636136SJohn Stultz 100 * SHIFTED_PPM,
8807636136SJohn Stultz 150 * SHIFTED_PPM,
8907636136SJohn Stultz 200 * SHIFTED_PPM,
9007636136SJohn Stultz 250 * SHIFTED_PPM,
9107636136SJohn Stultz 300 * SHIFTED_PPM,
9207636136SJohn Stultz 350 * SHIFTED_PPM,
9307636136SJohn Stultz 400 * SHIFTED_PPM,
9407636136SJohn Stultz 450 * SHIFTED_PPM,
9507636136SJohn Stultz 499 * SHIFTED_PPM,
96de52133fSJohn Stultz };
97de52133fSJohn Stultz
98de52133fSJohn Stultz long outofrange_freq[NUM_FREQ_OUTOFRANGE] = {
9907636136SJohn Stultz -1000 * SHIFTED_PPM,
10007636136SJohn Stultz -550 * SHIFTED_PPM,
10107636136SJohn Stultz 550 * SHIFTED_PPM,
10207636136SJohn Stultz 1000 * SHIFTED_PPM,
103de52133fSJohn Stultz };
104de52133fSJohn Stultz
105de52133fSJohn Stultz #define LONG_MAX (~0UL>>1)
106de52133fSJohn Stultz #define LONG_MIN (-LONG_MAX - 1)
107de52133fSJohn Stultz
108de52133fSJohn Stultz long invalid_freq[NUM_FREQ_INVALID] = {
109de52133fSJohn Stultz LONG_MAX,
110de52133fSJohn Stultz LONG_MIN,
111de52133fSJohn Stultz };
112de52133fSJohn Stultz
validate_freq(void)113de52133fSJohn Stultz int validate_freq(void)
114de52133fSJohn Stultz {
115de52133fSJohn Stultz struct timex tx;
116de52133fSJohn Stultz int ret, pass = 0;
117de52133fSJohn Stultz int i;
118de52133fSJohn Stultz
119de52133fSJohn Stultz clear_time_state();
120de52133fSJohn Stultz
121de52133fSJohn Stultz memset(&tx, 0, sizeof(struct timex));
122de52133fSJohn Stultz /* Set the leap second insert flag */
123de52133fSJohn Stultz
124de52133fSJohn Stultz printf("Testing ADJ_FREQ... ");
125fe483192SKees Cook fflush(stdout);
126de52133fSJohn Stultz for (i = 0; i < NUM_FREQ_VALID; i++) {
127de52133fSJohn Stultz tx.modes = ADJ_FREQUENCY;
128de52133fSJohn Stultz tx.freq = valid_freq[i];
129de52133fSJohn Stultz
130de52133fSJohn Stultz ret = adjtimex(&tx);
131de52133fSJohn Stultz if (ret < 0) {
132de52133fSJohn Stultz printf("[FAIL]\n");
133de52133fSJohn Stultz printf("Error: adjtimex(ADJ_FREQ, %ld - %ld ppm\n",
134de52133fSJohn Stultz valid_freq[i], valid_freq[i]>>16);
135de52133fSJohn Stultz pass = -1;
136de52133fSJohn Stultz goto out;
137de52133fSJohn Stultz }
138de52133fSJohn Stultz tx.modes = 0;
139de52133fSJohn Stultz ret = adjtimex(&tx);
140de52133fSJohn Stultz if (tx.freq != valid_freq[i]) {
141de52133fSJohn Stultz printf("Warning: freq value %ld not what we set it (%ld)!\n",
142de52133fSJohn Stultz tx.freq, valid_freq[i]);
143de52133fSJohn Stultz }
144de52133fSJohn Stultz }
145de52133fSJohn Stultz for (i = 0; i < NUM_FREQ_OUTOFRANGE; i++) {
146de52133fSJohn Stultz tx.modes = ADJ_FREQUENCY;
147de52133fSJohn Stultz tx.freq = outofrange_freq[i];
148de52133fSJohn Stultz
149de52133fSJohn Stultz ret = adjtimex(&tx);
150de52133fSJohn Stultz if (ret < 0) {
151de52133fSJohn Stultz printf("[FAIL]\n");
152de52133fSJohn Stultz printf("Error: adjtimex(ADJ_FREQ, %ld - %ld ppm\n",
153de52133fSJohn Stultz outofrange_freq[i], outofrange_freq[i]>>16);
154de52133fSJohn Stultz pass = -1;
155de52133fSJohn Stultz goto out;
156de52133fSJohn Stultz }
157de52133fSJohn Stultz tx.modes = 0;
158de52133fSJohn Stultz ret = adjtimex(&tx);
159de52133fSJohn Stultz if (tx.freq == outofrange_freq[i]) {
160de52133fSJohn Stultz printf("[FAIL]\n");
161de52133fSJohn Stultz printf("ERROR: out of range value %ld actually set!\n",
162de52133fSJohn Stultz tx.freq);
163de52133fSJohn Stultz pass = -1;
164de52133fSJohn Stultz goto out;
165de52133fSJohn Stultz }
166de52133fSJohn Stultz }
167de52133fSJohn Stultz
168de52133fSJohn Stultz
169de52133fSJohn Stultz if (sizeof(long) == 8) { /* this case only applies to 64bit systems */
170de52133fSJohn Stultz for (i = 0; i < NUM_FREQ_INVALID; i++) {
171de52133fSJohn Stultz tx.modes = ADJ_FREQUENCY;
172de52133fSJohn Stultz tx.freq = invalid_freq[i];
173de52133fSJohn Stultz ret = adjtimex(&tx);
174de52133fSJohn Stultz if (ret >= 0) {
175de52133fSJohn Stultz printf("[FAIL]\n");
176de52133fSJohn Stultz printf("Error: No failure on invalid ADJ_FREQUENCY %ld\n",
177de52133fSJohn Stultz invalid_freq[i]);
178de52133fSJohn Stultz pass = -1;
179de52133fSJohn Stultz goto out;
180de52133fSJohn Stultz }
181de52133fSJohn Stultz }
182de52133fSJohn Stultz }
183de52133fSJohn Stultz
184de52133fSJohn Stultz printf("[OK]\n");
185de52133fSJohn Stultz out:
186de52133fSJohn Stultz /* reset freq to zero */
187de52133fSJohn Stultz tx.modes = ADJ_FREQUENCY;
188de52133fSJohn Stultz tx.freq = 0;
189de52133fSJohn Stultz ret = adjtimex(&tx);
190de52133fSJohn Stultz
191de52133fSJohn Stultz return pass;
192de52133fSJohn Stultz }
193de52133fSJohn Stultz
194de52133fSJohn Stultz
set_offset(long long offset,int use_nano)195e03a58c3SJohn Stultz int set_offset(long long offset, int use_nano)
196e03a58c3SJohn Stultz {
197e03a58c3SJohn Stultz struct timex tmx = {};
198e03a58c3SJohn Stultz int ret;
199e03a58c3SJohn Stultz
200e03a58c3SJohn Stultz tmx.modes = ADJ_SETOFFSET;
201e03a58c3SJohn Stultz if (use_nano) {
202e03a58c3SJohn Stultz tmx.modes |= ADJ_NANO;
203e03a58c3SJohn Stultz
204e03a58c3SJohn Stultz tmx.time.tv_sec = offset / NSEC_PER_SEC;
205e03a58c3SJohn Stultz tmx.time.tv_usec = offset % NSEC_PER_SEC;
206e03a58c3SJohn Stultz
207e03a58c3SJohn Stultz if (offset < 0 && tmx.time.tv_usec) {
208e03a58c3SJohn Stultz tmx.time.tv_sec -= 1;
209e03a58c3SJohn Stultz tmx.time.tv_usec += NSEC_PER_SEC;
210e03a58c3SJohn Stultz }
211e03a58c3SJohn Stultz } else {
212e03a58c3SJohn Stultz tmx.time.tv_sec = offset / USEC_PER_SEC;
213e03a58c3SJohn Stultz tmx.time.tv_usec = offset % USEC_PER_SEC;
214e03a58c3SJohn Stultz
215e03a58c3SJohn Stultz if (offset < 0 && tmx.time.tv_usec) {
216e03a58c3SJohn Stultz tmx.time.tv_sec -= 1;
217e03a58c3SJohn Stultz tmx.time.tv_usec += USEC_PER_SEC;
218e03a58c3SJohn Stultz }
219e03a58c3SJohn Stultz }
220e03a58c3SJohn Stultz
221e03a58c3SJohn Stultz ret = clock_adjtime(CLOCK_REALTIME, &tmx);
222e03a58c3SJohn Stultz if (ret < 0) {
223e03a58c3SJohn Stultz printf("(sec: %ld usec: %ld) ", tmx.time.tv_sec, tmx.time.tv_usec);
224e03a58c3SJohn Stultz printf("[FAIL]\n");
225e03a58c3SJohn Stultz return -1;
226e03a58c3SJohn Stultz }
227e03a58c3SJohn Stultz return 0;
228e03a58c3SJohn Stultz }
229e03a58c3SJohn Stultz
set_bad_offset(long sec,long usec,int use_nano)230e03a58c3SJohn Stultz int set_bad_offset(long sec, long usec, int use_nano)
231e03a58c3SJohn Stultz {
232e03a58c3SJohn Stultz struct timex tmx = {};
233e03a58c3SJohn Stultz int ret;
234e03a58c3SJohn Stultz
235e03a58c3SJohn Stultz tmx.modes = ADJ_SETOFFSET;
236e03a58c3SJohn Stultz if (use_nano)
237e03a58c3SJohn Stultz tmx.modes |= ADJ_NANO;
238e03a58c3SJohn Stultz
239e03a58c3SJohn Stultz tmx.time.tv_sec = sec;
240e03a58c3SJohn Stultz tmx.time.tv_usec = usec;
241e03a58c3SJohn Stultz ret = clock_adjtime(CLOCK_REALTIME, &tmx);
242e03a58c3SJohn Stultz if (ret >= 0) {
243e03a58c3SJohn Stultz printf("Invalid (sec: %ld usec: %ld) did not fail! ", tmx.time.tv_sec, tmx.time.tv_usec);
244e03a58c3SJohn Stultz printf("[FAIL]\n");
245e03a58c3SJohn Stultz return -1;
246e03a58c3SJohn Stultz }
247e03a58c3SJohn Stultz return 0;
248e03a58c3SJohn Stultz }
249e03a58c3SJohn Stultz
validate_set_offset(void)250e03a58c3SJohn Stultz int validate_set_offset(void)
251e03a58c3SJohn Stultz {
252e03a58c3SJohn Stultz printf("Testing ADJ_SETOFFSET... ");
253fe483192SKees Cook fflush(stdout);
254e03a58c3SJohn Stultz
255e03a58c3SJohn Stultz /* Test valid values */
256e03a58c3SJohn Stultz if (set_offset(NSEC_PER_SEC - 1, 1))
257e03a58c3SJohn Stultz return -1;
258e03a58c3SJohn Stultz
259e03a58c3SJohn Stultz if (set_offset(-NSEC_PER_SEC + 1, 1))
260e03a58c3SJohn Stultz return -1;
261e03a58c3SJohn Stultz
262e03a58c3SJohn Stultz if (set_offset(-NSEC_PER_SEC - 1, 1))
263e03a58c3SJohn Stultz return -1;
264e03a58c3SJohn Stultz
265e03a58c3SJohn Stultz if (set_offset(5 * NSEC_PER_SEC, 1))
266e03a58c3SJohn Stultz return -1;
267e03a58c3SJohn Stultz
268e03a58c3SJohn Stultz if (set_offset(-5 * NSEC_PER_SEC, 1))
269e03a58c3SJohn Stultz return -1;
270e03a58c3SJohn Stultz
271e03a58c3SJohn Stultz if (set_offset(5 * NSEC_PER_SEC + NSEC_PER_SEC / 2, 1))
272e03a58c3SJohn Stultz return -1;
273e03a58c3SJohn Stultz
274e03a58c3SJohn Stultz if (set_offset(-5 * NSEC_PER_SEC - NSEC_PER_SEC / 2, 1))
275e03a58c3SJohn Stultz return -1;
276e03a58c3SJohn Stultz
277e03a58c3SJohn Stultz if (set_offset(USEC_PER_SEC - 1, 0))
278e03a58c3SJohn Stultz return -1;
279e03a58c3SJohn Stultz
280e03a58c3SJohn Stultz if (set_offset(-USEC_PER_SEC + 1, 0))
281e03a58c3SJohn Stultz return -1;
282e03a58c3SJohn Stultz
283e03a58c3SJohn Stultz if (set_offset(-USEC_PER_SEC - 1, 0))
284e03a58c3SJohn Stultz return -1;
285e03a58c3SJohn Stultz
286e03a58c3SJohn Stultz if (set_offset(5 * USEC_PER_SEC, 0))
287e03a58c3SJohn Stultz return -1;
288e03a58c3SJohn Stultz
289e03a58c3SJohn Stultz if (set_offset(-5 * USEC_PER_SEC, 0))
290e03a58c3SJohn Stultz return -1;
291e03a58c3SJohn Stultz
292e03a58c3SJohn Stultz if (set_offset(5 * USEC_PER_SEC + USEC_PER_SEC / 2, 0))
293e03a58c3SJohn Stultz return -1;
294e03a58c3SJohn Stultz
295e03a58c3SJohn Stultz if (set_offset(-5 * USEC_PER_SEC - USEC_PER_SEC / 2, 0))
296e03a58c3SJohn Stultz return -1;
297e03a58c3SJohn Stultz
298e03a58c3SJohn Stultz /* Test invalid values */
299e03a58c3SJohn Stultz if (set_bad_offset(0, -1, 1))
300e03a58c3SJohn Stultz return -1;
301e03a58c3SJohn Stultz if (set_bad_offset(0, -1, 0))
302e03a58c3SJohn Stultz return -1;
303e03a58c3SJohn Stultz if (set_bad_offset(0, 2 * NSEC_PER_SEC, 1))
304e03a58c3SJohn Stultz return -1;
305e03a58c3SJohn Stultz if (set_bad_offset(0, 2 * USEC_PER_SEC, 0))
306e03a58c3SJohn Stultz return -1;
307e03a58c3SJohn Stultz if (set_bad_offset(0, NSEC_PER_SEC, 1))
308e03a58c3SJohn Stultz return -1;
309e03a58c3SJohn Stultz if (set_bad_offset(0, USEC_PER_SEC, 0))
310e03a58c3SJohn Stultz return -1;
311e03a58c3SJohn Stultz if (set_bad_offset(0, -NSEC_PER_SEC, 1))
312e03a58c3SJohn Stultz return -1;
313e03a58c3SJohn Stultz if (set_bad_offset(0, -USEC_PER_SEC, 0))
314e03a58c3SJohn Stultz return -1;
315e03a58c3SJohn Stultz
316e03a58c3SJohn Stultz printf("[OK]\n");
317e03a58c3SJohn Stultz return 0;
318e03a58c3SJohn Stultz }
319e03a58c3SJohn Stultz
main(int argc,char ** argv)320de52133fSJohn Stultz int main(int argc, char **argv)
321de52133fSJohn Stultz {
322de52133fSJohn Stultz if (validate_freq())
323*bc7e5d23SNathan Chancellor ksft_exit_fail();
324de52133fSJohn Stultz
325e03a58c3SJohn Stultz if (validate_set_offset())
326*bc7e5d23SNathan Chancellor ksft_exit_fail();
327e03a58c3SJohn Stultz
328*bc7e5d23SNathan Chancellor ksft_exit_pass();
329de52133fSJohn Stultz }
330