vdso_test_abi.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * vdso_full_test.c: Sample code to test all the timers.
  4. * Copyright (c) 2019 Arm Ltd.
  5. *
  6. * Compile with:
  7. * gcc -std=gnu99 vdso_full_test.c parse_vdso.c
  8. *
  9. */
  10. #include <stdint.h>
  11. #include <elf.h>
  12. #include <stdio.h>
  13. #include <time.h>
  14. #include <sys/auxv.h>
  15. #include <sys/time.h>
  16. #define _GNU_SOURCE
  17. #include <unistd.h>
  18. #include <sys/syscall.h>
  19. #include "../kselftest.h"
  20. #include "vdso_config.h"
  21. #include "vdso_call.h"
  22. #include "parse_vdso.h"
  23. static const char *version;
  24. static const char **name;
  25. typedef long (*vdso_gettimeofday_t)(struct timeval *tv, struct timezone *tz);
  26. typedef long (*vdso_clock_gettime_t)(clockid_t clk_id, struct timespec *ts);
  27. typedef long (*vdso_clock_getres_t)(clockid_t clk_id, struct timespec *ts);
  28. typedef time_t (*vdso_time_t)(time_t *t);
  29. const char *vdso_clock_name[12] = {
  30. "CLOCK_REALTIME",
  31. "CLOCK_MONOTONIC",
  32. "CLOCK_PROCESS_CPUTIME_ID",
  33. "CLOCK_THREAD_CPUTIME_ID",
  34. "CLOCK_MONOTONIC_RAW",
  35. "CLOCK_REALTIME_COARSE",
  36. "CLOCK_MONOTONIC_COARSE",
  37. "CLOCK_BOOTTIME",
  38. "CLOCK_REALTIME_ALARM",
  39. "CLOCK_BOOTTIME_ALARM",
  40. "CLOCK_SGI_CYCLE",
  41. "CLOCK_TAI",
  42. };
  43. static void vdso_test_gettimeofday(void)
  44. {
  45. /* Find gettimeofday. */
  46. vdso_gettimeofday_t vdso_gettimeofday =
  47. (vdso_gettimeofday_t)vdso_sym(version, name[0]);
  48. if (!vdso_gettimeofday) {
  49. ksft_print_msg("Couldn't find %s\n", name[0]);
  50. ksft_test_result_skip("%s\n", name[0]);
  51. return;
  52. }
  53. struct timeval tv;
  54. long ret = VDSO_CALL(vdso_gettimeofday, 2, &tv, 0);
  55. if (ret == 0) {
  56. ksft_print_msg("The time is %lld.%06lld\n",
  57. (long long)tv.tv_sec, (long long)tv.tv_usec);
  58. ksft_test_result_pass("%s\n", name[0]);
  59. } else {
  60. ksft_test_result_fail("%s\n", name[0]);
  61. }
  62. }
  63. static void vdso_test_clock_gettime(clockid_t clk_id)
  64. {
  65. /* Find clock_gettime. */
  66. vdso_clock_gettime_t vdso_clock_gettime =
  67. (vdso_clock_gettime_t)vdso_sym(version, name[1]);
  68. if (!vdso_clock_gettime) {
  69. ksft_print_msg("Couldn't find %s\n", name[1]);
  70. ksft_test_result_skip("%s %s\n", name[1],
  71. vdso_clock_name[clk_id]);
  72. return;
  73. }
  74. struct timespec ts;
  75. long ret = VDSO_CALL(vdso_clock_gettime, 2, clk_id, &ts);
  76. if (ret == 0) {
  77. ksft_print_msg("The time is %lld.%06lld\n",
  78. (long long)ts.tv_sec, (long long)ts.tv_nsec);
  79. ksft_test_result_pass("%s %s\n", name[1],
  80. vdso_clock_name[clk_id]);
  81. } else {
  82. ksft_test_result_fail("%s %s\n", name[1],
  83. vdso_clock_name[clk_id]);
  84. }
  85. }
  86. static void vdso_test_time(void)
  87. {
  88. /* Find time. */
  89. vdso_time_t vdso_time =
  90. (vdso_time_t)vdso_sym(version, name[2]);
  91. if (!vdso_time) {
  92. ksft_print_msg("Couldn't find %s\n", name[2]);
  93. ksft_test_result_skip("%s\n", name[2]);
  94. return;
  95. }
  96. long ret = VDSO_CALL(vdso_time, 1, NULL);
  97. if (ret > 0) {
  98. ksft_print_msg("The time in hours since January 1, 1970 is %lld\n",
  99. (long long)(ret / 3600));
  100. ksft_test_result_pass("%s\n", name[2]);
  101. } else {
  102. ksft_test_result_fail("%s\n", name[2]);
  103. }
  104. }
  105. static void vdso_test_clock_getres(clockid_t clk_id)
  106. {
  107. int clock_getres_fail = 0;
  108. /* Find clock_getres. */
  109. vdso_clock_getres_t vdso_clock_getres =
  110. (vdso_clock_getres_t)vdso_sym(version, name[3]);
  111. if (!vdso_clock_getres) {
  112. ksft_print_msg("Couldn't find %s\n", name[3]);
  113. ksft_test_result_skip("%s %s\n", name[3],
  114. vdso_clock_name[clk_id]);
  115. return;
  116. }
  117. struct timespec ts, sys_ts;
  118. long ret = VDSO_CALL(vdso_clock_getres, 2, clk_id, &ts);
  119. if (ret == 0) {
  120. ksft_print_msg("The vdso resolution is %lld %lld\n",
  121. (long long)ts.tv_sec, (long long)ts.tv_nsec);
  122. } else {
  123. clock_getres_fail++;
  124. }
  125. ret = syscall(SYS_clock_getres, clk_id, &sys_ts);
  126. ksft_print_msg("The syscall resolution is %lld %lld\n",
  127. (long long)sys_ts.tv_sec, (long long)sys_ts.tv_nsec);
  128. if ((sys_ts.tv_sec != ts.tv_sec) || (sys_ts.tv_nsec != ts.tv_nsec))
  129. clock_getres_fail++;
  130. if (clock_getres_fail > 0) {
  131. ksft_test_result_fail("%s %s\n", name[3],
  132. vdso_clock_name[clk_id]);
  133. } else {
  134. ksft_test_result_pass("%s %s\n", name[3],
  135. vdso_clock_name[clk_id]);
  136. }
  137. }
  138. /*
  139. * This function calls vdso_test_clock_gettime and vdso_test_clock_getres
  140. * with different values for clock_id.
  141. */
  142. static inline void vdso_test_clock(clockid_t clock_id)
  143. {
  144. ksft_print_msg("clock_id: %s\n", vdso_clock_name[clock_id]);
  145. vdso_test_clock_gettime(clock_id);
  146. vdso_test_clock_getres(clock_id);
  147. }
  148. #define VDSO_TEST_PLAN 16
  149. int main(int argc, char **argv)
  150. {
  151. unsigned long sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR);
  152. ksft_print_header();
  153. if (!sysinfo_ehdr)
  154. ksft_exit_skip("AT_SYSINFO_EHDR is not present!\n");
  155. ksft_set_plan(VDSO_TEST_PLAN);
  156. version = versions[VDSO_VERSION];
  157. name = (const char **)&names[VDSO_NAMES];
  158. ksft_print_msg("[vDSO kselftest] VDSO_VERSION: %s\n", version);
  159. vdso_init_from_sysinfo_ehdr(getauxval(AT_SYSINFO_EHDR));
  160. vdso_test_gettimeofday();
  161. #if _POSIX_TIMERS > 0
  162. #ifdef CLOCK_REALTIME
  163. vdso_test_clock(CLOCK_REALTIME);
  164. #endif
  165. #ifdef CLOCK_BOOTTIME
  166. vdso_test_clock(CLOCK_BOOTTIME);
  167. #endif
  168. #ifdef CLOCK_TAI
  169. vdso_test_clock(CLOCK_TAI);
  170. #endif
  171. #ifdef CLOCK_REALTIME_COARSE
  172. vdso_test_clock(CLOCK_REALTIME_COARSE);
  173. #endif
  174. #ifdef CLOCK_MONOTONIC
  175. vdso_test_clock(CLOCK_MONOTONIC);
  176. #endif
  177. #ifdef CLOCK_MONOTONIC_RAW
  178. vdso_test_clock(CLOCK_MONOTONIC_RAW);
  179. #endif
  180. #ifdef CLOCK_MONOTONIC_COARSE
  181. vdso_test_clock(CLOCK_MONOTONIC_COARSE);
  182. #endif
  183. #endif
  184. vdso_test_time();
  185. ksft_print_cnts();
  186. return ksft_get_fail_cnt() == 0 ? KSFT_PASS : KSFT_FAIL;
  187. }