Extend the auxclock test to also cover the vDSO.

Signed-off-by: Thomas Weißschuh <thomas.weisssc...@linutronix.de>
---
 tools/testing/selftests/timers/auxclock.c | 95 +++++++++++++++++++++++++++++--
 1 file changed, 91 insertions(+), 4 deletions(-)

diff --git a/tools/testing/selftests/timers/auxclock.c 
b/tools/testing/selftests/timers/auxclock.c
index 
0ba2f9996114ade3147f0f3aec49904556a23cd4..314037839c1c7dd32ca32722231c67bc408a2ea3
 100644
--- a/tools/testing/selftests/timers/auxclock.c
+++ b/tools/testing/selftests/timers/auxclock.c
@@ -10,11 +10,16 @@
 #include <linux/timex.h>
 #include <sched.h>
 #include <stdio.h>
+#include <sys/auxv.h>
 #include <sys/syscall.h>
 #include <unistd.h>
 
 #include "../kselftest_harness.h"
 
+#include "../vDSO/parse_vdso.c"
+#include "../vDSO/vdso_config.h"
+#include "../vDSO/vdso_call.h"
+
 #ifndef CLOCK_AUX
 #define        CLOCK_AUX       16
 #endif
@@ -133,7 +138,45 @@ static int sys_clock_adjtime64(__kernel_clockid_t clockid, 
struct __kernel_timex
 #endif
 }
 
-FIXTURE(auxclock) {};
+FIXTURE(auxclock) {
+       int (*vdso_clock_gettime)(__kernel_clockid_t clockid, struct timespec 
*ts);
+       int (*vdso_clock_gettime64)(__kernel_clockid_t clockid, struct 
__kernel_timespec *ts);
+       int (*vdso_clock_getres)(__kernel_clockid_t clockid, struct timespec 
*ts);
+};
+
+static int vdso_clock_gettime64(FIXTURE_DATA(auxclock) *self, 
__kernel_clockid_t clockid,
+                               struct __kernel_timespec *ts)
+{
+       struct timespec _ts;
+       int ret;
+
+       if (self->vdso_clock_gettime64) {
+               return VDSO_CALL(self->vdso_clock_gettime64, 2, clockid, ts);
+       } else if (self->vdso_clock_gettime) {
+               ret = VDSO_CALL(self->vdso_clock_gettime, 2, clockid, &_ts);
+               if (!ret)
+                       timespec_to_kernel_timespec(&_ts, ts);
+               return ret;
+       } else {
+               return -ENOSYS;
+       }
+}
+
+static int vdso_clock_getres_time64(FIXTURE_DATA(auxclock) *self, 
__kernel_clockid_t clockid,
+                                   struct __kernel_timespec *ts)
+{
+       struct timespec _ts;
+       int ret;
+
+       if (self->vdso_clock_getres) {
+               ret = VDSO_CALL(self->vdso_clock_getres, 2, clockid, &_ts);
+               if (!ret)
+                       timespec_to_kernel_timespec(&_ts, ts);
+               return ret;
+       } else {
+               return -ENOSYS;
+       }
+}
 
 FIXTURE_VARIANT(auxclock) {
        __kernel_clockid_t clock;
@@ -193,6 +236,18 @@ static void enter_timens(struct __test_metadata *_metadata)
 FIXTURE_SETUP(auxclock) {
        int ret;
 
+#ifdef AT_SYSINFO_EHDR
+       unsigned long sysinfo_ehdr;
+
+       sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR);
+       if (sysinfo_ehdr)
+               vdso_init_from_sysinfo_ehdr(sysinfo_ehdr);
+
+       self->vdso_clock_gettime = vdso_sym(versions[VDSO_VERSION], 
names[VDSO_NAMES][1]);
+       self->vdso_clock_gettime64 = vdso_sym(versions[VDSO_VERSION], 
names[VDSO_NAMES][5]);
+       self->vdso_clock_getres = vdso_sym(versions[VDSO_VERSION], 
names[VDSO_NAMES][3]);
+#endif /* !AT_SYSINFO_EHDR */
+
        ret = configure_auxclock(variant->clock, variant->clock_enabled);
        if (ret == -ENOENT)
                SKIP(return, "auxclocks not enabled");
@@ -220,6 +275,20 @@ TEST_F(auxclock, sys_clock_getres) {
        ASSERT_EQ(1, ts.tv_nsec);
 }
 
+TEST_F(auxclock, vdso_clock_getres) {
+       struct __kernel_timespec ts;
+       int ret;
+
+       ret = vdso_clock_getres_time64(self, variant->clock, &ts);
+       if (ret == -ENOSYS) {
+               SKIP(return, "no clock_getres() in vDSO");
+       } else {
+               ASSERT_EQ(0, ret);
+               ASSERT_EQ(0, ts.tv_sec);
+               ASSERT_EQ(1, ts.tv_nsec);
+       }
+}
+
 TEST_F(auxclock, sys_clock_gettime) {
        struct __kernel_timespec ts;
        int ret;
@@ -233,6 +302,20 @@ TEST_F(auxclock, sys_clock_gettime) {
        }
 }
 
+TEST_F(auxclock, vdso_clock_gettime) {
+       struct __kernel_timespec ts;
+       int ret;
+
+       ret = vdso_clock_gettime64(self, variant->clock, &ts);
+       if (ret == -ENOSYS) {
+               SKIP(return, "no clock_gettime() in vDSO");
+       } else if (variant->clock_enabled) {
+               ASSERT_EQ(0, ret);
+       } else {
+               ASSERT_EQ(-ENODEV, ret);
+       }
+}
+
 static void auxclock_validate_progression(struct __test_metadata *_metadata,
                                          const struct __kernel_timespec *a,
                                          const struct __kernel_timespec *b)
@@ -310,9 +393,13 @@ TEST_F(auxclock, progression) {
                auxclock_validate_progression(_metadata, &a, &b);
 
                memset(&a, 0, sizeof(a));
-               ret = sys_clock_gettime64(variant->clock, &a);
-               ASSERT_EQ(0, ret);
-               auxclock_validate_progression(_metadata, &b, &a);
+               ret = vdso_clock_gettime64(self, variant->clock, &a);
+               if (ret == -ENOSYS) {
+                       a = b;
+               } else {
+                       ASSERT_EQ(0, ret);
+                       auxclock_validate_progression(_metadata, &b, &a);
+               }
        }
 }
 

-- 
2.50.0


Reply via email to