• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2019 Linaro Limited. All rights reserved.
4  * Author: Rafael David Tinoco <rafael.tinoco@linaro.org>
5  */
6 
7 /*
8  * clock_adjtime() syscall might have as execution path:
9  *
10  *   1) a regular POSIX clock (only REALTIME clock implements adjtime())
11  *      - will behave exactly like adjtimex() system call.
12  *      - only one being tested here.
13  *
14  *   2) a dynamic POSIX clock (which ops are implemented by PTP clocks)
15  *      - will trigger the PTP clock driver function "adjtime()"
16  *      - different implementations from one PTP clock to another
17  *      - might return EOPNOTSUPP (like ptp_kvm_caps, for example)
18  *      - no entry point for clock_adjtime(), missing "CLOCK_PTP" model
19  *
20  * so it is sane to check possible adjustments:
21  *
22  *    - ADJ_OFFSET     - usec or nsec, kernel adjusts time gradually by offset
23  *                       (-512000 < offset < 512000)
24  *    - ADJ_FREQUENCY  - system clock frequency offset
25  *    - ADJ_MAXERROR   - maximum error (usec)
26  *    - ADJ_ESTERROR   - estimated time error in us
27  *    - ADJ_STATUS     - clock command/status of ntp implementation
28  *    - ADJ_TIMECONST  - PLL stiffness (jitter dependent) + poll int for PLL
29  *    - ADJ_TICK       - us between clock ticks
30  *                       (>= 900000/HZ, <= 1100000/HZ)
31  *
32  * and also the standalone ones (using .offset variable):
33  *
34  *    - ADJ_OFFSET_SINGLESHOT - behave like adjtime()
35  *    - ADJ_OFFSET_SS_READ - ret remaining time for completion after SINGLESHOT
36  *
37  * For ADJ_STATUS, consider the following flags:
38  *
39  *      rw  STA_PLL - enable phase-locked loop updates (ADJ_OFFSET)
40  *      rw  STA_PPSFREQ - enable PPS (pulse-per-second) freq discipline
41  *      rw  STA_PPSTIME - enable PPS time discipline
42  *      rw  STA_FLL - select freq-locked loop mode.
43  *      rw  STA_INS - ins leap sec after the last sec of UTC day (all days)
44  *      rw  STA_DEL - del leap sec at last sec of UTC day (all days)
45  *      rw  STA_UNSYNC - clock unsynced
46  *      rw  STA_FREQHOLD - hold freq. ADJ_OFFSET made w/out auto small adjs
47  *      ro  STA_PPSSIGNAL - valid PPS (pulse-per-second) signal is present
48  *      ro  STA_PPSJITTER - PPS signal jitter exceeded.
49  *      ro  STA_PPSWANDER - PPS signal wander exceeded.
50  *      ro  STA_PPSERROR - PPS signal calibration error.
51  *      ro  STA_CLOKERR - clock HW fault.
52  *      ro  STA_NANO - 0 = us, 1 = ns (set = ADJ_NANO, cl = ADJ_MICRO)
53  *      rw  STA_MODE - mode: 0 = phased locked loop. 1 = freq locked loop
54  *      ro  STA_CLK - clock source. unused.
55  */
56 
57 #include "clock_adjtime.h"
58 
59 static long hz;
60 static struct timex saved, ttxc;
61 static int supported;
62 
63 struct test_case {
64 	unsigned int modes;
65 	long highlimit;
66 	long *ptr;
67 	long delta;
68 };
69 
70 struct test_case tc[] = {
71 	{
72 	 .modes = ADJ_OFFSET_SINGLESHOT,
73 	},
74 	{
75 	 .modes = ADJ_OFFSET_SS_READ,
76 	},
77 	{
78 	 .modes = ADJ_ALL,
79 	},
80 	{
81 	 .modes = ADJ_OFFSET,
82 	 .highlimit = 500000,
83 	 .ptr = &ttxc.offset,
84 	 .delta = 10000,
85 	},
86 	{
87 	 .modes = ADJ_FREQUENCY,
88 	 .ptr = &ttxc.freq,
89 	 .delta = 100,
90 	},
91 	{
92 	 .modes = ADJ_MAXERROR,
93 	 .ptr = &ttxc.maxerror,
94 	 .delta = 100,
95 	},
96 	{
97 	 .modes = ADJ_ESTERROR,
98 	 .ptr = &ttxc.esterror,
99 	 .delta = 100,
100 	},
101 	{
102 	 .modes = ADJ_TIMECONST,
103 	 .ptr = &ttxc.constant,
104 	 .delta = 1,
105 	},
106 	{
107 	 .modes = ADJ_TICK,
108 	 .highlimit = 1100000,
109 	 .ptr = &ttxc.tick,
110 	 .delta = 1000,
111 	},
112 };
113 
verify_clock_adjtime(unsigned int i)114 static void verify_clock_adjtime(unsigned int i)
115 {
116 	long ptroff, *ptr = NULL;
117 	struct timex verify;
118 
119 	memset(&ttxc, 0, sizeof(struct timex));
120 	memset(&verify, 0, sizeof(struct timex));
121 
122 	SAFE_CLOCK_ADJTIME(CLOCK_REALTIME, &ttxc);
123 	timex_show("GET", ttxc);
124 
125 	ttxc.modes = tc[i].modes;
126 
127 	if (tc[i].ptr && tc[i].delta) {
128 
129 		*tc[i].ptr += tc[i].delta;
130 
131 		/* fix limits, if existent, so no errors occur */
132 
133 		if (tc[i].highlimit) {
134 			if (*tc[i].ptr >= tc[i].highlimit)
135 				*tc[i].ptr = tc[i].highlimit;
136 		}
137 	}
138 
139 	SAFE_CLOCK_ADJTIME(CLOCK_REALTIME, &ttxc);
140 	timex_show("SET", ttxc);
141 
142 	if (tc[i].ptr) {
143 
144 		/* adjtimex field being tested so we can verify later */
145 
146 		ptroff = (long) tc[i].ptr - (long) &ttxc;
147 		ptr = (void *) &verify + ptroff;
148 	}
149 
150 	TEST(sys_clock_adjtime(CLOCK_REALTIME, &verify));
151 	timex_show("VERIFY", verify);
152 
153 	if (tc[i].ptr && *tc[i].ptr != *ptr) {
154 		tst_res(TFAIL, "clock_adjtime(): could not set value (mode=%x)",
155 				tc[i].modes);
156 	}
157 
158 	if (TST_RET < 0) {
159 		tst_res(TFAIL | TTERRNO, "clock_adjtime(): mode=%x, returned "
160 				"error", tc[i].modes);
161 	}
162 
163 	tst_res(TPASS, "clock_adjtime(): success (mode=%x)", tc[i].modes);
164 }
165 
setup(void)166 static void setup(void)
167 {
168 	size_t i;
169 	int rval;
170 
171 	rval = SAFE_CLOCK_ADJTIME(CLOCK_REALTIME, &saved);
172 	supported = 1;
173 
174 	if (rval != TIME_OK && rval != TIME_ERROR) {
175 		timex_show("SAVE_STATUS", saved);
176 		tst_brk(TBROK | TTERRNO, "clock has on-going leap changes, "
177 				"returned: %i", rval);
178 	}
179 
180 	hz = SAFE_SYSCONF(_SC_CLK_TCK);
181 
182 	for (i = 0; i < ARRAY_SIZE(tc); i++) {
183 
184 		/* fix high and low limits by dividing it per HZ value */
185 
186 		if (tc[i].modes == ADJ_TICK)
187 			tc[i].highlimit /= hz;
188 
189 		/* fix usec as being test default resolution */
190 
191 		if (saved.modes & ADJ_NANO) {
192 			if (tc[i].modes == ADJ_OFFSET) {
193 				tc[i].highlimit *= 1000;
194 				tc[i].delta *= 1000;
195 			}
196 		}
197 	}
198 }
199 
cleanup(void)200 static void cleanup(void)
201 {
202 	if (supported == 0)
203 		return;
204 
205 	saved.modes = ADJ_ALL;
206 
207 	/* restore clock resolution based on original status flag */
208 
209 	if (saved.status & STA_NANO)
210 		saved.modes |= ADJ_NANO;
211 	else
212 		saved.modes |= ADJ_MICRO;
213 
214 	/* restore original clock flags */
215 
216 	SAFE_CLOCK_ADJTIME(CLOCK_REALTIME, &saved);
217 }
218 
219 static struct tst_test test = {
220 	.test = verify_clock_adjtime,
221 	.setup = setup,
222 	.cleanup = cleanup,
223 	.tcnt = ARRAY_SIZE(tc),
224 	.needs_root = 1,
225 	.restore_wallclock = 1,
226 };
227