Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * vdso_full_test.c: Sample code to test all the timers.
0004  * Copyright (c) 2019 Arm Ltd.
0005  *
0006  * Compile with:
0007  * gcc -std=gnu99 vdso_full_test.c parse_vdso.c
0008  *
0009  */
0010 
0011 #include <stdint.h>
0012 #include <elf.h>
0013 #include <stdio.h>
0014 #include <time.h>
0015 #include <sys/auxv.h>
0016 #include <sys/time.h>
0017 #define _GNU_SOURCE
0018 #include <unistd.h>
0019 #include <sys/syscall.h>
0020 
0021 #include "../kselftest.h"
0022 #include "vdso_config.h"
0023 
0024 extern void *vdso_sym(const char *version, const char *name);
0025 extern void vdso_init_from_sysinfo_ehdr(uintptr_t base);
0026 extern void vdso_init_from_auxv(void *auxv);
0027 
0028 static const char *version;
0029 static const char **name;
0030 
0031 typedef long (*vdso_gettimeofday_t)(struct timeval *tv, struct timezone *tz);
0032 typedef long (*vdso_clock_gettime_t)(clockid_t clk_id, struct timespec *ts);
0033 typedef long (*vdso_clock_getres_t)(clockid_t clk_id, struct timespec *ts);
0034 typedef time_t (*vdso_time_t)(time_t *t);
0035 
0036 #define VDSO_TEST_PASS_MSG()    "\n%s(): PASS\n", __func__
0037 #define VDSO_TEST_FAIL_MSG(x)   "\n%s(): %s FAIL\n", __func__, x
0038 #define VDSO_TEST_SKIP_MSG(x)   "\n%s(): SKIP: Could not find %s\n", __func__, x
0039 
0040 static void vdso_test_gettimeofday(void)
0041 {
0042     /* Find gettimeofday. */
0043     vdso_gettimeofday_t vdso_gettimeofday =
0044         (vdso_gettimeofday_t)vdso_sym(version, name[0]);
0045 
0046     if (!vdso_gettimeofday) {
0047         ksft_test_result_skip(VDSO_TEST_SKIP_MSG(name[0]));
0048         return;
0049     }
0050 
0051     struct timeval tv;
0052     long ret = vdso_gettimeofday(&tv, 0);
0053 
0054     if (ret == 0) {
0055         ksft_print_msg("The time is %lld.%06lld\n",
0056                    (long long)tv.tv_sec, (long long)tv.tv_usec);
0057         ksft_test_result_pass(VDSO_TEST_PASS_MSG());
0058     } else {
0059         ksft_test_result_fail(VDSO_TEST_FAIL_MSG(name[0]));
0060     }
0061 }
0062 
0063 static void vdso_test_clock_gettime(clockid_t clk_id)
0064 {
0065     /* Find clock_gettime. */
0066     vdso_clock_gettime_t vdso_clock_gettime =
0067         (vdso_clock_gettime_t)vdso_sym(version, name[1]);
0068 
0069     if (!vdso_clock_gettime) {
0070         ksft_test_result_skip(VDSO_TEST_SKIP_MSG(name[1]));
0071         return;
0072     }
0073 
0074     struct timespec ts;
0075     long ret = vdso_clock_gettime(clk_id, &ts);
0076 
0077     if (ret == 0) {
0078         ksft_print_msg("The time is %lld.%06lld\n",
0079                    (long long)ts.tv_sec, (long long)ts.tv_nsec);
0080         ksft_test_result_pass(VDSO_TEST_PASS_MSG());
0081     } else {
0082         ksft_test_result_fail(VDSO_TEST_FAIL_MSG(name[1]));
0083     }
0084 }
0085 
0086 static void vdso_test_time(void)
0087 {
0088     /* Find time. */
0089     vdso_time_t vdso_time =
0090         (vdso_time_t)vdso_sym(version, name[2]);
0091 
0092     if (!vdso_time) {
0093         ksft_test_result_skip(VDSO_TEST_SKIP_MSG(name[2]));
0094         return;
0095     }
0096 
0097     long ret = vdso_time(NULL);
0098 
0099     if (ret > 0) {
0100         ksft_print_msg("The time in hours since January 1, 1970 is %lld\n",
0101                 (long long)(ret / 3600));
0102         ksft_test_result_pass(VDSO_TEST_PASS_MSG());
0103     } else {
0104         ksft_test_result_fail(VDSO_TEST_FAIL_MSG(name[2]));
0105     }
0106 }
0107 
0108 static void vdso_test_clock_getres(clockid_t clk_id)
0109 {
0110     int clock_getres_fail = 0;
0111 
0112     /* Find clock_getres. */
0113     vdso_clock_getres_t vdso_clock_getres =
0114         (vdso_clock_getres_t)vdso_sym(version, name[3]);
0115 
0116     if (!vdso_clock_getres) {
0117         ksft_test_result_skip(VDSO_TEST_SKIP_MSG(name[3]));
0118         return;
0119     }
0120 
0121     struct timespec ts, sys_ts;
0122     long ret = vdso_clock_getres(clk_id, &ts);
0123 
0124     if (ret == 0) {
0125         ksft_print_msg("The vdso resolution is %lld %lld\n",
0126                    (long long)ts.tv_sec, (long long)ts.tv_nsec);
0127     } else {
0128         clock_getres_fail++;
0129     }
0130 
0131     ret = syscall(SYS_clock_getres, clk_id, &sys_ts);
0132 
0133     ksft_print_msg("The syscall resolution is %lld %lld\n",
0134             (long long)sys_ts.tv_sec, (long long)sys_ts.tv_nsec);
0135 
0136     if ((sys_ts.tv_sec != ts.tv_sec) || (sys_ts.tv_nsec != ts.tv_nsec))
0137         clock_getres_fail++;
0138 
0139     if (clock_getres_fail > 0) {
0140         ksft_test_result_fail(VDSO_TEST_FAIL_MSG(name[3]));
0141     } else {
0142         ksft_test_result_pass(VDSO_TEST_PASS_MSG());
0143     }
0144 }
0145 
0146 const char *vdso_clock_name[12] = {
0147     "CLOCK_REALTIME",
0148     "CLOCK_MONOTONIC",
0149     "CLOCK_PROCESS_CPUTIME_ID",
0150     "CLOCK_THREAD_CPUTIME_ID",
0151     "CLOCK_MONOTONIC_RAW",
0152     "CLOCK_REALTIME_COARSE",
0153     "CLOCK_MONOTONIC_COARSE",
0154     "CLOCK_BOOTTIME",
0155     "CLOCK_REALTIME_ALARM",
0156     "CLOCK_BOOTTIME_ALARM",
0157     "CLOCK_SGI_CYCLE",
0158     "CLOCK_TAI",
0159 };
0160 
0161 /*
0162  * This function calls vdso_test_clock_gettime and vdso_test_clock_getres
0163  * with different values for clock_id.
0164  */
0165 static inline void vdso_test_clock(clockid_t clock_id)
0166 {
0167     ksft_print_msg("\nclock_id: %s\n", vdso_clock_name[clock_id]);
0168 
0169     vdso_test_clock_gettime(clock_id);
0170 
0171     vdso_test_clock_getres(clock_id);
0172 }
0173 
0174 #define VDSO_TEST_PLAN  16
0175 
0176 int main(int argc, char **argv)
0177 {
0178     unsigned long sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR);
0179 
0180     ksft_print_header();
0181     ksft_set_plan(VDSO_TEST_PLAN);
0182 
0183     if (!sysinfo_ehdr) {
0184         printf("AT_SYSINFO_EHDR is not present!\n");
0185         return KSFT_SKIP;
0186     }
0187 
0188     version = versions[VDSO_VERSION];
0189     name = (const char **)&names[VDSO_NAMES];
0190 
0191     printf("[vDSO kselftest] VDSO_VERSION: %s\n", version);
0192 
0193     vdso_init_from_sysinfo_ehdr(getauxval(AT_SYSINFO_EHDR));
0194 
0195     vdso_test_gettimeofday();
0196 
0197 #if _POSIX_TIMERS > 0
0198 
0199 #ifdef CLOCK_REALTIME
0200     vdso_test_clock(CLOCK_REALTIME);
0201 #endif
0202 
0203 #ifdef CLOCK_BOOTTIME
0204     vdso_test_clock(CLOCK_BOOTTIME);
0205 #endif
0206 
0207 #ifdef CLOCK_TAI
0208     vdso_test_clock(CLOCK_TAI);
0209 #endif
0210 
0211 #ifdef CLOCK_REALTIME_COARSE
0212     vdso_test_clock(CLOCK_REALTIME_COARSE);
0213 #endif
0214 
0215 #ifdef CLOCK_MONOTONIC
0216     vdso_test_clock(CLOCK_MONOTONIC);
0217 #endif
0218 
0219 #ifdef CLOCK_MONOTONIC_RAW
0220     vdso_test_clock(CLOCK_MONOTONIC_RAW);
0221 #endif
0222 
0223 #ifdef CLOCK_MONOTONIC_COARSE
0224     vdso_test_clock(CLOCK_MONOTONIC_COARSE);
0225 #endif
0226 
0227 #endif
0228 
0229     vdso_test_time();
0230 
0231     ksft_print_cnts();
0232     return ksft_get_fail_cnt() == 0 ? KSFT_PASS : KSFT_FAIL;
0233 }