xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/clock_adjtime/clock_adjtime.h (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2019 Linaro Limited. All rights reserved.
4  * Author: Rafael David Tinoco <[email protected]>
5  */
6 
7 #ifndef CLOCK_ADJTIME_H__
8 #define CLOCK_ADJTIME_H__
9 
10 #include "config.h"
11 #include "tst_test.h"
12 #include "tst_timer.h"
13 #include "tst_safe_clocks.h"
14 #include "lapi/syscalls.h"
15 #include "lapi/posix_clocks.h"
16 #include <time.h>
17 #include <pwd.h>
18 #include <sys/timex.h>
19 #include <sys/types.h>
20 #include <asm/posix_types.h>
21 #include "lapi/timex.h"
22 
23 struct __kernel_old_timex {
24 	unsigned int modes;	/* mode selector */
25 	__kernel_long_t offset;	/* time offset (usec) */
26 	__kernel_long_t freq;	/* frequency offset (scaled ppm) */
27 	__kernel_long_t maxerror;/* maximum error (usec) */
28 	__kernel_long_t esterror;/* estimated error (usec) */
29 	int status;		/* clock command/status */
30 	__kernel_long_t constant;/* pll time constant */
31 	__kernel_long_t precision;/* clock precision (usec) (read only) */
32 	__kernel_long_t tolerance;/* clock frequency tolerance (ppm)
33 				   * (read only)
34 				   */
35 	struct __kernel_old_timeval time;	/* (read only, except for ADJ_SETOFFSET) */
36 	__kernel_long_t tick;	/* (modified) usecs between clock ticks */
37 
38 	__kernel_long_t ppsfreq;/* pps frequency (scaled ppm) (ro) */
39 	__kernel_long_t jitter; /* pps jitter (us) (ro) */
40 	int shift;              /* interval duration (s) (shift) (ro) */
41 	__kernel_long_t stabil;            /* pps stability (scaled ppm) (ro) */
42 	__kernel_long_t jitcnt; /* jitter limit exceeded (ro) */
43 	__kernel_long_t calcnt; /* calibration intervals (ro) */
44 	__kernel_long_t errcnt; /* calibration errors (ro) */
45 	__kernel_long_t stbcnt; /* stability limit exceeded (ro) */
46 
47 	int tai;		/* TAI offset (ro) */
48 
49 	int  :32; int  :32; int  :32; int  :32;
50 	int  :32; int  :32; int  :32; int  :32;
51 	int  :32; int  :32; int  :32;
52 };
53 
54 #ifndef HAVE_STRUCT___KERNEL_TIMEX_TIMEVAL
55 struct __kernel_timex_timeval {
56 	__kernel_time64_t       tv_sec;
57 	long long		tv_usec;
58 };
59 #endif
60 
61 #ifndef HAVE_STRUCT___KERNEL_TIMEX
62 struct __kernel_timex {
63 	unsigned int modes;	/* mode selector */
64 	int :32;            /* pad */
65 	long long offset;	/* time offset (usec) */
66 	long long freq;	/* frequency offset (scaled ppm) */
67 	long long maxerror;/* maximum error (usec) */
68 	long long esterror;/* estimated error (usec) */
69 	int status;		/* clock command/status */
70 	int :32;            /* pad */
71 	long long constant;/* pll time constant */
72 	long long precision;/* clock precision (usec) (read only) */
73 	long long tolerance;/* clock frequency tolerance (ppm)
74 				   * (read only)
75 				   */
76 	struct __kernel_timex_timeval time;	/* (read only, except for ADJ_SETOFFSET) */
77 	long long tick;	/* (modified) usecs between clock ticks */
78 
79 	long long ppsfreq;/* pps frequency (scaled ppm) (ro) */
80 	long long jitter; /* pps jitter (us) (ro) */
81 	int shift;              /* interval duration (s) (shift) (ro) */
82 	int :32;            /* pad */
83 	long long stabil;            /* pps stability (scaled ppm) (ro) */
84 	long long jitcnt; /* jitter limit exceeded (ro) */
85 	long long calcnt; /* calibration intervals (ro) */
86 	long long errcnt; /* calibration errors (ro) */
87 	long long stbcnt; /* stability limit exceeded (ro) */
88 
89 	int tai;		/* TAI offset (ro) */
90 
91 	int  :32; int  :32; int  :32; int  :32;
92 	int  :32; int  :32; int  :32; int  :32;
93 	int  :32; int  :32; int  :32;
94 };
95 #endif
96 
97 enum tst_timex_type {
98 	TST_KERN_OLD_TIMEX,
99 	TST_KERN_TIMEX
100 };
101 
102 struct tst_timex {
103 	enum tst_timex_type type;
104 	union tx{
105 		struct __kernel_old_timex kern_old_timex;
106 		struct __kernel_timex kern_timex;
107 	} tx;
108 };
109 
tst_timex_get(struct tst_timex * t)110 static inline void *tst_timex_get(struct tst_timex *t)
111 {
112 	switch (t->type) {
113 	case TST_KERN_OLD_TIMEX:
114 		return &t->tx.kern_old_timex;
115 	case TST_KERN_TIMEX:
116 		return &t->tx.kern_timex;
117 	default:
118 		tst_brk(TBROK, "Invalid type: %d", t->type);
119 		return NULL;
120 	}
121 }
122 
sys_clock_adjtime(clockid_t clk_id,void * timex)123 static inline int sys_clock_adjtime(clockid_t clk_id, void *timex)
124 {
125 	return tst_syscall(__NR_clock_adjtime, clk_id, timex);
126 }
127 
sys_clock_adjtime64(clockid_t clk_id,void * timex)128 static inline int sys_clock_adjtime64(clockid_t clk_id, void *timex)
129 {
130 	return tst_syscall(__NR_clock_adjtime64, clk_id, timex);
131 }
132 
133 #define TIMEX_SHOW(tx, mode, fmt)					\
134 	tst_res(TINFO,  "%s\n"						\
135 			"             mode: %u\n"			\
136 			"           offset: "fmt"\n"			\
137 			"        frequency: "fmt"\n"			\
138 			"         maxerror: "fmt"\n"			\
139 			"         esterror: "fmt"\n"			\
140 			"           status: %d (0x%x)\n"		\
141 			"    time_constant: "fmt"\n"			\
142 			"        precision: "fmt"\n"			\
143 			"        tolerance: "fmt"\n"			\
144 			"             tick: "fmt"\n"			\
145 			"         raw time: "fmt"(s) "fmt"(us)",	\
146 			mode,						\
147 			tx.modes,					\
148 			tx.offset,					\
149 			tx.freq,					\
150 			tx.maxerror,					\
151 			tx.esterror,					\
152 			tx.status,					\
153 			tx.status,					\
154 			tx.constant,					\
155 			tx.precision,					\
156 			tx.tolerance,					\
157 			tx.tick,					\
158 			tx.time.tv_sec,					\
159 			tx.time.tv_usec)
160 
timex_show(const char * mode,struct tst_timex * timex)161 static inline void timex_show(const char *mode, struct tst_timex *timex)
162 {
163 	switch (timex->type) {
164 	case TST_KERN_OLD_TIMEX:
165 		TIMEX_SHOW(timex->tx.kern_old_timex, mode, "%ld");
166 		return;
167 	case TST_KERN_TIMEX:
168 		TIMEX_SHOW(timex->tx.kern_timex, mode, "%lld");
169 		return;
170 	default:
171 		tst_brk(TBROK, "Invalid type: %d", timex->type);
172 	}
173 }
174 
175 #undef TIMEX_SHOW
176 
177 #define ADJ_MODES	0
178 
179 #define SELECT_FIELD(tx, field)						\
180 {									\
181 	switch (field) {						\
182 	case ADJ_MODES:							\
183 		return &tx.modes;					\
184 	case ADJ_OFFSET:						\
185 		return &tx.offset;					\
186 	case ADJ_FREQUENCY:						\
187 		return &tx.freq;					\
188 	case ADJ_MAXERROR:						\
189 		return &tx.maxerror;					\
190 	case ADJ_ESTERROR:						\
191 		return &tx.esterror;					\
192 	case ADJ_TIMECONST:						\
193 		return &tx.constant;					\
194 	case ADJ_TICK:							\
195 		return &tx.tick;					\
196 	case ADJ_STATUS:						\
197 		return &tx.status;					\
198 	default:							\
199 		tst_brk(TBROK, "Invalid type: %d", timex->type);	\
200 		return NULL;						\
201 	}								\
202 }
203 
timex_get_field(struct tst_timex * timex,unsigned int field)204 static inline void *timex_get_field(struct tst_timex *timex, unsigned int field)
205 {
206 	switch (timex->type) {
207 	case TST_KERN_OLD_TIMEX:
208 		SELECT_FIELD(timex->tx.kern_old_timex, field);
209 	case TST_KERN_TIMEX:
210 		SELECT_FIELD(timex->tx.kern_timex, field);
211 	default:
212 		tst_brk(TBROK, "Invalid type: %d", timex->type);
213 		return NULL;
214 	}
215 }
216 
217 #undef SELECT_FIELD
218 
219 #define TIMEX_GET_SET_FIELD_TYPE(type_libc, type_kern)			\
220 static inline type_kern							\
221 timex_get_field_##type_libc(struct tst_timex *timex, unsigned int field) \
222 {									\
223 	switch (timex->type) {						\
224 	case TST_KERN_OLD_TIMEX:						\
225 		return *((type_libc*)timex_get_field(timex, field));	\
226 	case TST_KERN_TIMEX:						\
227 		return *((type_kern*)timex_get_field(timex, field));	\
228 	default:							\
229 		tst_res(TFAIL, "Invalid type: %d", timex->type);	\
230 		return 0;						\
231 	}								\
232 }									\
233 									\
234 static inline void							\
235 timex_set_field_##type_libc(struct tst_timex *timex, unsigned int field, \
236 			    type_kern value)				\
237 {									\
238 	switch (timex->type) {						\
239 	case TST_KERN_OLD_TIMEX:						\
240 		*((type_libc*)timex_get_field(timex, field)) = value;	\
241 		return;							\
242 	case TST_KERN_TIMEX:						\
243 		*((type_kern*)timex_get_field(timex, field)) = value;	\
244 		return;							\
245 	default:							\
246 		tst_res(TFAIL, "Invalid type: %d", timex->type);	\
247 	}								\
248 }
249 
250 TIMEX_GET_SET_FIELD_TYPE(uint, uint);
251 TIMEX_GET_SET_FIELD_TYPE(long, long long);
252 
253 #undef TIMEX_GET_SET_FIELD_TYPE
254 
255 #endif /* CLOCK_ADJTIME_H__ */
256