1693f5ca0SVincenzo Frascino // SPDX-License-Identifier: GPL-2.0
2693f5ca0SVincenzo Frascino /*
3693f5ca0SVincenzo Frascino * vdso_full_test.c: Sample code to test all the timers.
4693f5ca0SVincenzo Frascino * Copyright (c) 2019 Arm Ltd.
5693f5ca0SVincenzo Frascino *
6693f5ca0SVincenzo Frascino * Compile with:
7693f5ca0SVincenzo Frascino * gcc -std=gnu99 vdso_full_test.c parse_vdso.c
8693f5ca0SVincenzo Frascino *
9693f5ca0SVincenzo Frascino */
10693f5ca0SVincenzo Frascino
11693f5ca0SVincenzo Frascino #include <stdint.h>
12693f5ca0SVincenzo Frascino #include <elf.h>
13693f5ca0SVincenzo Frascino #include <stdio.h>
14693f5ca0SVincenzo Frascino #include <time.h>
15693f5ca0SVincenzo Frascino #include <sys/auxv.h>
16693f5ca0SVincenzo Frascino #include <sys/time.h>
17693f5ca0SVincenzo Frascino #define _GNU_SOURCE
18693f5ca0SVincenzo Frascino #include <unistd.h>
19693f5ca0SVincenzo Frascino #include <sys/syscall.h>
20693f5ca0SVincenzo Frascino
21693f5ca0SVincenzo Frascino #include "../kselftest.h"
22693f5ca0SVincenzo Frascino #include "vdso_config.h"
23693f5ca0SVincenzo Frascino
24693f5ca0SVincenzo Frascino extern void *vdso_sym(const char *version, const char *name);
25693f5ca0SVincenzo Frascino extern void vdso_init_from_sysinfo_ehdr(uintptr_t base);
26693f5ca0SVincenzo Frascino extern void vdso_init_from_auxv(void *auxv);
27693f5ca0SVincenzo Frascino
28693f5ca0SVincenzo Frascino static const char *version;
29693f5ca0SVincenzo Frascino static const char **name;
30693f5ca0SVincenzo Frascino
31693f5ca0SVincenzo Frascino typedef long (*vdso_gettimeofday_t)(struct timeval *tv, struct timezone *tz);
32693f5ca0SVincenzo Frascino typedef long (*vdso_clock_gettime_t)(clockid_t clk_id, struct timespec *ts);
33693f5ca0SVincenzo Frascino typedef long (*vdso_clock_getres_t)(clockid_t clk_id, struct timespec *ts);
34693f5ca0SVincenzo Frascino typedef time_t (*vdso_time_t)(time_t *t);
35693f5ca0SVincenzo Frascino
36*ec049891SVincenzo Frascino #define VDSO_TEST_PASS_MSG() "\n%s(): PASS\n", __func__
37*ec049891SVincenzo Frascino #define VDSO_TEST_FAIL_MSG(x) "\n%s(): %s FAIL\n", __func__, x
38*ec049891SVincenzo Frascino #define VDSO_TEST_SKIP_MSG(x) "\n%s(): SKIP: Could not find %s\n", __func__, x
39*ec049891SVincenzo Frascino
vdso_test_gettimeofday(void)40*ec049891SVincenzo Frascino static void vdso_test_gettimeofday(void)
41693f5ca0SVincenzo Frascino {
42693f5ca0SVincenzo Frascino /* Find gettimeofday. */
43693f5ca0SVincenzo Frascino vdso_gettimeofday_t vdso_gettimeofday =
44693f5ca0SVincenzo Frascino (vdso_gettimeofday_t)vdso_sym(version, name[0]);
45693f5ca0SVincenzo Frascino
46693f5ca0SVincenzo Frascino if (!vdso_gettimeofday) {
47*ec049891SVincenzo Frascino ksft_test_result_skip(VDSO_TEST_SKIP_MSG(name[0]));
48*ec049891SVincenzo Frascino return;
49693f5ca0SVincenzo Frascino }
50693f5ca0SVincenzo Frascino
51693f5ca0SVincenzo Frascino struct timeval tv;
52693f5ca0SVincenzo Frascino long ret = vdso_gettimeofday(&tv, 0);
53693f5ca0SVincenzo Frascino
54693f5ca0SVincenzo Frascino if (ret == 0) {
55*ec049891SVincenzo Frascino ksft_print_msg("The time is %lld.%06lld\n",
56693f5ca0SVincenzo Frascino (long long)tv.tv_sec, (long long)tv.tv_usec);
57*ec049891SVincenzo Frascino ksft_test_result_pass(VDSO_TEST_PASS_MSG());
58693f5ca0SVincenzo Frascino } else {
59*ec049891SVincenzo Frascino ksft_test_result_fail(VDSO_TEST_FAIL_MSG(name[0]));
60*ec049891SVincenzo Frascino }
61693f5ca0SVincenzo Frascino }
62693f5ca0SVincenzo Frascino
vdso_test_clock_gettime(clockid_t clk_id)63*ec049891SVincenzo Frascino static void vdso_test_clock_gettime(clockid_t clk_id)
64693f5ca0SVincenzo Frascino {
65693f5ca0SVincenzo Frascino /* Find clock_gettime. */
66693f5ca0SVincenzo Frascino vdso_clock_gettime_t vdso_clock_gettime =
67693f5ca0SVincenzo Frascino (vdso_clock_gettime_t)vdso_sym(version, name[1]);
68693f5ca0SVincenzo Frascino
69693f5ca0SVincenzo Frascino if (!vdso_clock_gettime) {
70*ec049891SVincenzo Frascino ksft_test_result_skip(VDSO_TEST_SKIP_MSG(name[1]));
71*ec049891SVincenzo Frascino return;
72693f5ca0SVincenzo Frascino }
73693f5ca0SVincenzo Frascino
74693f5ca0SVincenzo Frascino struct timespec ts;
75693f5ca0SVincenzo Frascino long ret = vdso_clock_gettime(clk_id, &ts);
76693f5ca0SVincenzo Frascino
77693f5ca0SVincenzo Frascino if (ret == 0) {
78*ec049891SVincenzo Frascino ksft_print_msg("The time is %lld.%06lld\n",
79693f5ca0SVincenzo Frascino (long long)ts.tv_sec, (long long)ts.tv_nsec);
80*ec049891SVincenzo Frascino ksft_test_result_pass(VDSO_TEST_PASS_MSG());
81693f5ca0SVincenzo Frascino } else {
82*ec049891SVincenzo Frascino ksft_test_result_fail(VDSO_TEST_FAIL_MSG(name[1]));
83*ec049891SVincenzo Frascino }
84693f5ca0SVincenzo Frascino }
85693f5ca0SVincenzo Frascino
vdso_test_time(void)86*ec049891SVincenzo Frascino static void vdso_test_time(void)
87693f5ca0SVincenzo Frascino {
88693f5ca0SVincenzo Frascino /* Find time. */
89693f5ca0SVincenzo Frascino vdso_time_t vdso_time =
90693f5ca0SVincenzo Frascino (vdso_time_t)vdso_sym(version, name[2]);
91693f5ca0SVincenzo Frascino
92693f5ca0SVincenzo Frascino if (!vdso_time) {
93*ec049891SVincenzo Frascino ksft_test_result_skip(VDSO_TEST_SKIP_MSG(name[2]));
94*ec049891SVincenzo Frascino return;
95693f5ca0SVincenzo Frascino }
96693f5ca0SVincenzo Frascino
97693f5ca0SVincenzo Frascino long ret = vdso_time(NULL);
98693f5ca0SVincenzo Frascino
99693f5ca0SVincenzo Frascino if (ret > 0) {
100*ec049891SVincenzo Frascino ksft_print_msg("The time in hours since January 1, 1970 is %lld\n",
101693f5ca0SVincenzo Frascino (long long)(ret / 3600));
102*ec049891SVincenzo Frascino ksft_test_result_pass(VDSO_TEST_PASS_MSG());
103693f5ca0SVincenzo Frascino } else {
104*ec049891SVincenzo Frascino ksft_test_result_fail(VDSO_TEST_FAIL_MSG(name[2]));
105*ec049891SVincenzo Frascino }
106693f5ca0SVincenzo Frascino }
107693f5ca0SVincenzo Frascino
vdso_test_clock_getres(clockid_t clk_id)108*ec049891SVincenzo Frascino static void vdso_test_clock_getres(clockid_t clk_id)
109693f5ca0SVincenzo Frascino {
110*ec049891SVincenzo Frascino int clock_getres_fail = 0;
111*ec049891SVincenzo Frascino
112693f5ca0SVincenzo Frascino /* Find clock_getres. */
113693f5ca0SVincenzo Frascino vdso_clock_getres_t vdso_clock_getres =
114693f5ca0SVincenzo Frascino (vdso_clock_getres_t)vdso_sym(version, name[3]);
115693f5ca0SVincenzo Frascino
116693f5ca0SVincenzo Frascino if (!vdso_clock_getres) {
117*ec049891SVincenzo Frascino ksft_test_result_skip(VDSO_TEST_SKIP_MSG(name[3]));
118*ec049891SVincenzo Frascino return;
119693f5ca0SVincenzo Frascino }
120693f5ca0SVincenzo Frascino
121693f5ca0SVincenzo Frascino struct timespec ts, sys_ts;
122693f5ca0SVincenzo Frascino long ret = vdso_clock_getres(clk_id, &ts);
123693f5ca0SVincenzo Frascino
124693f5ca0SVincenzo Frascino if (ret == 0) {
125*ec049891SVincenzo Frascino ksft_print_msg("The vdso resolution is %lld %lld\n",
126693f5ca0SVincenzo Frascino (long long)ts.tv_sec, (long long)ts.tv_nsec);
127693f5ca0SVincenzo Frascino } else {
128*ec049891SVincenzo Frascino clock_getres_fail++;
129693f5ca0SVincenzo Frascino }
130693f5ca0SVincenzo Frascino
131693f5ca0SVincenzo Frascino ret = syscall(SYS_clock_getres, clk_id, &sys_ts);
132693f5ca0SVincenzo Frascino
133*ec049891SVincenzo Frascino ksft_print_msg("The syscall resolution is %lld %lld\n",
134*ec049891SVincenzo Frascino (long long)sys_ts.tv_sec, (long long)sys_ts.tv_nsec);
135693f5ca0SVincenzo Frascino
136*ec049891SVincenzo Frascino if ((sys_ts.tv_sec != ts.tv_sec) || (sys_ts.tv_nsec != ts.tv_nsec))
137*ec049891SVincenzo Frascino clock_getres_fail++;
138*ec049891SVincenzo Frascino
139*ec049891SVincenzo Frascino if (clock_getres_fail > 0) {
140*ec049891SVincenzo Frascino ksft_test_result_fail(VDSO_TEST_FAIL_MSG(name[3]));
141*ec049891SVincenzo Frascino } else {
142*ec049891SVincenzo Frascino ksft_test_result_pass(VDSO_TEST_PASS_MSG());
143*ec049891SVincenzo Frascino }
144693f5ca0SVincenzo Frascino }
145693f5ca0SVincenzo Frascino
146693f5ca0SVincenzo Frascino const char *vdso_clock_name[12] = {
147693f5ca0SVincenzo Frascino "CLOCK_REALTIME",
148693f5ca0SVincenzo Frascino "CLOCK_MONOTONIC",
149693f5ca0SVincenzo Frascino "CLOCK_PROCESS_CPUTIME_ID",
150693f5ca0SVincenzo Frascino "CLOCK_THREAD_CPUTIME_ID",
151693f5ca0SVincenzo Frascino "CLOCK_MONOTONIC_RAW",
152693f5ca0SVincenzo Frascino "CLOCK_REALTIME_COARSE",
153693f5ca0SVincenzo Frascino "CLOCK_MONOTONIC_COARSE",
154693f5ca0SVincenzo Frascino "CLOCK_BOOTTIME",
155693f5ca0SVincenzo Frascino "CLOCK_REALTIME_ALARM",
156693f5ca0SVincenzo Frascino "CLOCK_BOOTTIME_ALARM",
157693f5ca0SVincenzo Frascino "CLOCK_SGI_CYCLE",
158693f5ca0SVincenzo Frascino "CLOCK_TAI",
159693f5ca0SVincenzo Frascino };
160693f5ca0SVincenzo Frascino
161693f5ca0SVincenzo Frascino /*
162693f5ca0SVincenzo Frascino * This function calls vdso_test_clock_gettime and vdso_test_clock_getres
163693f5ca0SVincenzo Frascino * with different values for clock_id.
164693f5ca0SVincenzo Frascino */
vdso_test_clock(clockid_t clock_id)165*ec049891SVincenzo Frascino static inline void vdso_test_clock(clockid_t clock_id)
166693f5ca0SVincenzo Frascino {
167*ec049891SVincenzo Frascino ksft_print_msg("\nclock_id: %s\n", vdso_clock_name[clock_id]);
168693f5ca0SVincenzo Frascino
169*ec049891SVincenzo Frascino vdso_test_clock_gettime(clock_id);
170693f5ca0SVincenzo Frascino
171*ec049891SVincenzo Frascino vdso_test_clock_getres(clock_id);
172693f5ca0SVincenzo Frascino }
173693f5ca0SVincenzo Frascino
174*ec049891SVincenzo Frascino #define VDSO_TEST_PLAN 16
175*ec049891SVincenzo Frascino
main(int argc,char ** argv)176693f5ca0SVincenzo Frascino int main(int argc, char **argv)
177693f5ca0SVincenzo Frascino {
178693f5ca0SVincenzo Frascino unsigned long sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR);
179*ec049891SVincenzo Frascino
180*ec049891SVincenzo Frascino ksft_print_header();
181*ec049891SVincenzo Frascino ksft_set_plan(VDSO_TEST_PLAN);
182693f5ca0SVincenzo Frascino
183693f5ca0SVincenzo Frascino if (!sysinfo_ehdr) {
184693f5ca0SVincenzo Frascino printf("AT_SYSINFO_EHDR is not present!\n");
185693f5ca0SVincenzo Frascino return KSFT_SKIP;
186693f5ca0SVincenzo Frascino }
187693f5ca0SVincenzo Frascino
188693f5ca0SVincenzo Frascino version = versions[VDSO_VERSION];
189693f5ca0SVincenzo Frascino name = (const char **)&names[VDSO_NAMES];
190693f5ca0SVincenzo Frascino
191693f5ca0SVincenzo Frascino printf("[vDSO kselftest] VDSO_VERSION: %s\n", version);
192693f5ca0SVincenzo Frascino
193693f5ca0SVincenzo Frascino vdso_init_from_sysinfo_ehdr(getauxval(AT_SYSINFO_EHDR));
194693f5ca0SVincenzo Frascino
195*ec049891SVincenzo Frascino vdso_test_gettimeofday();
196693f5ca0SVincenzo Frascino
197693f5ca0SVincenzo Frascino #if _POSIX_TIMERS > 0
198693f5ca0SVincenzo Frascino
199693f5ca0SVincenzo Frascino #ifdef CLOCK_REALTIME
200*ec049891SVincenzo Frascino vdso_test_clock(CLOCK_REALTIME);
201693f5ca0SVincenzo Frascino #endif
202693f5ca0SVincenzo Frascino
203693f5ca0SVincenzo Frascino #ifdef CLOCK_BOOTTIME
204*ec049891SVincenzo Frascino vdso_test_clock(CLOCK_BOOTTIME);
205693f5ca0SVincenzo Frascino #endif
206693f5ca0SVincenzo Frascino
207693f5ca0SVincenzo Frascino #ifdef CLOCK_TAI
208*ec049891SVincenzo Frascino vdso_test_clock(CLOCK_TAI);
209693f5ca0SVincenzo Frascino #endif
210693f5ca0SVincenzo Frascino
211693f5ca0SVincenzo Frascino #ifdef CLOCK_REALTIME_COARSE
212*ec049891SVincenzo Frascino vdso_test_clock(CLOCK_REALTIME_COARSE);
213693f5ca0SVincenzo Frascino #endif
214693f5ca0SVincenzo Frascino
215693f5ca0SVincenzo Frascino #ifdef CLOCK_MONOTONIC
216*ec049891SVincenzo Frascino vdso_test_clock(CLOCK_MONOTONIC);
217693f5ca0SVincenzo Frascino #endif
218693f5ca0SVincenzo Frascino
219693f5ca0SVincenzo Frascino #ifdef CLOCK_MONOTONIC_RAW
220*ec049891SVincenzo Frascino vdso_test_clock(CLOCK_MONOTONIC_RAW);
221693f5ca0SVincenzo Frascino #endif
222693f5ca0SVincenzo Frascino
223693f5ca0SVincenzo Frascino #ifdef CLOCK_MONOTONIC_COARSE
224*ec049891SVincenzo Frascino vdso_test_clock(CLOCK_MONOTONIC_COARSE);
225693f5ca0SVincenzo Frascino #endif
226693f5ca0SVincenzo Frascino
227693f5ca0SVincenzo Frascino #endif
228693f5ca0SVincenzo Frascino
229*ec049891SVincenzo Frascino vdso_test_time();
230693f5ca0SVincenzo Frascino
231*ec049891SVincenzo Frascino ksft_print_cnts();
232*ec049891SVincenzo Frascino return ksft_get_fail_cnt() == 0 ? KSFT_PASS : KSFT_FAIL;
233693f5ca0SVincenzo Frascino }
234