* [PATCH v2 01/14] Revert "selftests: vDSO: parse_vdso: Use UAPI headers instead of libc headers"
2025-11-13 15:30 [PATCH v2 00/14] selftests: vDSO: Stop using libc types for vDSO calls Thomas Weißschuh
@ 2025-11-13 15:30 ` Thomas Weißschuh
2025-11-13 15:30 ` [PATCH v2 02/14] selftests: vDSO: Introduce vdso_types.h Thomas Weißschuh
` (12 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-13 15:30 UTC (permalink / raw)
To: Andy Lutomirski, Thomas Gleixner, Vincenzo Frascino, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
This reverts commit c9fbaa879508 ("selftests: vDSO: parse_vdso: Use UAPI
headers instead of libc headers")
The kernel headers were used to make parse_vdso.c compatible with
nolibc. Unfortunately linux/elf.h is incompatible with glibc's
sys/auxv.h. When using glibc it is therefore not possible build
parse_vdso.c as part of the same compilation unit as its caller
as sys/auxv.h is needed for getauxval().
In the meantime nolibc gained its own elf.h, providing compatibility
with the documented libc interfaces.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
tools/testing/selftests/vDSO/Makefile | 2 --
tools/testing/selftests/vDSO/parse_vdso.c | 3 +--
2 files changed, 1 insertion(+), 4 deletions(-)
diff --git a/tools/testing/selftests/vDSO/Makefile b/tools/testing/selftests/vDSO/Makefile
index f94ea07cddc97ea8b13d8bed2b35a32bb99a2423..74dfc60e636edce91cc1df9643ca8aa008ecfe65 100644
--- a/tools/testing/selftests/vDSO/Makefile
+++ b/tools/testing/selftests/vDSO/Makefile
@@ -19,8 +19,6 @@ endif
include ../lib.mk
-CFLAGS += $(TOOLS_INCLUDES)
-
CFLAGS_NOLIBC := -nostdlib -nostdinc -ffreestanding -fno-asynchronous-unwind-tables \
-fno-stack-protector -include $(top_srcdir)/tools/include/nolibc/nolibc.h \
-I$(top_srcdir)/tools/include/nolibc/ $(KHDR_INCLUDES)
diff --git a/tools/testing/selftests/vDSO/parse_vdso.c b/tools/testing/selftests/vDSO/parse_vdso.c
index 3ff00fb624a44b964cc54954f1f088cabe11a901..c6ff4413ea367ae57bc6a60073314b29f938c99d 100644
--- a/tools/testing/selftests/vDSO/parse_vdso.c
+++ b/tools/testing/selftests/vDSO/parse_vdso.c
@@ -19,8 +19,7 @@
#include <stdint.h>
#include <string.h>
#include <limits.h>
-#include <linux/auxvec.h>
-#include <linux/elf.h>
+#include <elf.h>
#include "parse_vdso.h"
--
2.51.0
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH v2 02/14] selftests: vDSO: Introduce vdso_types.h
2025-11-13 15:30 [PATCH v2 00/14] selftests: vDSO: Stop using libc types for vDSO calls Thomas Weißschuh
2025-11-13 15:30 ` [PATCH v2 01/14] Revert "selftests: vDSO: parse_vdso: Use UAPI headers instead of libc headers" Thomas Weißschuh
@ 2025-11-13 15:30 ` Thomas Weißschuh
2025-11-13 15:30 ` [PATCH v2 03/14] selftests: vDSO: Introduce vdso_syscalls.h Thomas Weißschuh
` (11 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-13 15:30 UTC (permalink / raw)
To: Andy Lutomirski, Thomas Gleixner, Vincenzo Frascino, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
Currently the vDSO selftests use the time-related types from libc.
This works on glibc by chance today but will break with other libc
implementations or on distributions which switch to 64-bit times
everywhere.
The kernel's UAPI headers provide the proper types to use with the vDSO
(and raw syscalls) but are not necessarily compatible with libc types.
Introduce a new header which makes the UAPI headers compatible with the
libc.
Tested with glibc, musl and nolibc.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
tools/testing/selftests/vDSO/vdso_types.h | 70 +++++++++++++++++++++++++++++++
1 file changed, 70 insertions(+)
diff --git a/tools/testing/selftests/vDSO/vdso_types.h b/tools/testing/selftests/vDSO/vdso_types.h
new file mode 100644
index 0000000000000000000000000000000000000000..75f2b108ed0fb6956d05e2498879658608aa2f51
--- /dev/null
+++ b/tools/testing/selftests/vDSO/vdso_types.h
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2025 Thomas Weißschuh <thomas.weissschuh@linutronix.de>, Linutronix GmbH
+ *
+ * Types to use with vDSO functions.
+ *
+ * The types used by the vDSO functions do not necessarily match the ones used
+ * by libc. The kernel's UAPI headers do provide definitions for those types
+ * but are often not compatible with libc which applications need to use.
+ * As the types differ between platforms listing them manually is a lot of work
+ * and error prone. Instead hack around the incompatibilities of the libc and
+ * UAPI headers and use the UAPI types.
+ */
+#ifndef __VDSO_TYPES_H__
+#define __VDSO_TYPES_H__
+
+/*
+ * Include the headers from libc first to not override any of its types later.
+ */
+#include <time.h>
+#include <sys/time.h>
+
+/*
+ * Avoid collisions.
+ */
+#define timeval kernel_timeval_moved
+#define itimerspec kernel_itimerspec_moved
+#define itimerval kernel_itimerval_moved
+#define timezone kernel_timezone_moved
+
+/*
+ * Get the UAPI types.
+ */
+#include <linux/time.h>
+
+#undef timeval
+#undef itimerspec
+#undef itimerval
+#undef timezone
+
+/*
+ * The UAPI headers do not provide their own 'struct __kernel_timezone'.
+ * 'struct timezone' is the one from libc.
+ */
+struct kernel_timezone {
+ int tz_minuteswest;
+ int tz_dsttime;
+};
+
+#include <linux/version.h>
+
+/*
+ * UAPI headers from the libc may be older and not provide these.
+ */
+#if KERNEL_VERSION(5, 5, 0) > LINUX_VERSION_CODE
+typedef __kernel_long_t __kernel_old_time_t;
+
+struct __kernel_old_timespec {
+ __kernel_old_time_t tv_sec;
+ long tv_nsec;
+};
+#endif
+
+typedef long (*vdso_gettimeofday_t)(struct __kernel_old_timeval *tv, struct kernel_timezone *tz);
+typedef long (*vdso_clock_gettime_t)(__kernel_clockid_t clk_id, struct __kernel_old_timespec *ts);
+typedef long (*vdso_clock_gettime64_t)(__kernel_clockid_t clk_id, struct __kernel_timespec *ts);
+typedef long (*vdso_clock_getres_t)(__kernel_clockid_t clk_id, struct __kernel_old_timespec *ts);
+typedef __kernel_old_time_t (*vdso_time_t)(__kernel_old_time_t *t);
+
+#endif /* __VDSO_TYPES_H__ */
--
2.51.0
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH v2 03/14] selftests: vDSO: Introduce vdso_syscalls.h
2025-11-13 15:30 [PATCH v2 00/14] selftests: vDSO: Stop using libc types for vDSO calls Thomas Weißschuh
2025-11-13 15:30 ` [PATCH v2 01/14] Revert "selftests: vDSO: parse_vdso: Use UAPI headers instead of libc headers" Thomas Weißschuh
2025-11-13 15:30 ` [PATCH v2 02/14] selftests: vDSO: Introduce vdso_types.h Thomas Weißschuh
@ 2025-11-13 15:30 ` Thomas Weißschuh
2025-11-14 8:13 ` Arnd Bergmann
2025-11-13 15:30 ` [PATCH v2 04/14] selftests: vDSO: vdso_test_gettimeofday: Remove nolibc checks Thomas Weißschuh
` (10 subsequent siblings)
13 siblings, 1 reply; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-13 15:30 UTC (permalink / raw)
To: Andy Lutomirski, Thomas Gleixner, Vincenzo Frascino, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
The vDSO selftests use raw system call wrapper to validate the
correctness of the vDSO implementation. The exactly available system
calls differ between architectures and kernel configurations.
Raw system calls should not use libc types as these are not necessarily
compatible.
Introduce a helper header which uses the correct types and fallbacks.
Link: https://lore.kernel.org/lkml/29dd9e11-9ae8-415a-acb3-b96af56550b0@app.fastmail.com/
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
tools/testing/selftests/vDSO/vdso_syscalls.h | 93 ++++++++++++++++++++++++++++
1 file changed, 93 insertions(+)
diff --git a/tools/testing/selftests/vDSO/vdso_syscalls.h b/tools/testing/selftests/vDSO/vdso_syscalls.h
new file mode 100644
index 0000000000000000000000000000000000000000..1419f8dd3ea831beaf582c47f6acf2ce5d5d12f8
--- /dev/null
+++ b/tools/testing/selftests/vDSO/vdso_syscalls.h
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2025 Thomas Weißschuh <thomas.weissschuh@linutronix.de>, Linutronix GmbH
+ *
+ * System call wrappers to use for vDSO testing.
+ *
+ * vDSO calls are expected to return the same data as the equivalent system call.
+ * To ensure this the tests need to trigger system calls. Calling into libc may
+ * silently use the vDSO, so explicit system calls are necessary.
+ * Not all system calls are available on all platforms, so some fallback logic
+ * is needed. Use __NR_ constants from the kernel's UAPI headers over SYS_ from
+ * ones from libc to avoid any potential interference from libc.
+ * Always prefer the 64-bit time variants of the system calls as 32-bit ones
+ * may not be present on the platform or disabled in the kernel configuration.
+ */
+#ifndef __VDSO_SYSCALLS_H__
+#define __VDSO_SYSCALLS_H__
+
+#include "vdso_types.h"
+
+#include <stddef.h>
+#include <sys/syscall.h>
+#include <linux/unistd.h>
+
+#define typeof_member(T, m) typeof(((T*)0)->m)
+#define sizeof_member(T, m) sizeof(typeof_member(T, m))
+
+/*
+ * To keep the fallback logic simple we assume that although the types between
+ * the wrapper and the system call are different they are compatible.
+ * Validate that assumption.
+ * On x32 tv_nsec of __kernel_old_timespec is smaller than the one from
+ * __kernel_timespec. This is fine, as only the lower 4 bytes are relevant and
+ * it is a little-endian architecture.
+ */
+#define ASSERT_TIMESPEC_COMPATIBLE(T1, T2) \
+ do { \
+ _Static_assert(sizeof(T2) == sizeof(T2)); \
+ _Static_assert(offsetof(T1, tv_sec) == offsetof(T2, tv_sec)); \
+ _Static_assert(sizeof_member(T1, tv_sec) == sizeof_member(T2, tv_sec)); \
+ _Static_assert(offsetof(T1, tv_nsec) == offsetof(T2, tv_nsec)); \
+ _Static_assert(sizeof_member(T1, tv_nsec) == sizeof_member(T2, tv_nsec) || \
+ (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && \
+ sizeof_member(T1, tv_nsec) > sizeof_member(T2, tv_nsec))); \
+ } while(0)
+
+static inline
+int sys_clock_getres(__kernel_clockid_t clock, struct __kernel_timespec *ts)
+{
+#ifdef __NR_clock_getres_time64
+ return syscall(__NR_clock_getres_time64, clock, ts);
+#else
+ ASSERT_TIMESPEC_COMPATIBLE(typeof(*ts), struct __kernel_old_timespec);
+ return syscall(__NR_clock_getres, clock, ts);
+#endif
+}
+
+static inline
+int sys_clock_gettime(__kernel_clockid_t clock, struct __kernel_timespec *ts)
+{
+#ifdef __NR_clock_gettime64
+ return syscall(__NR_clock_gettime64, clock, ts);
+#else
+ ASSERT_TIMESPEC_COMPATIBLE(typeof(*ts), struct __kernel_old_timespec);
+ return syscall(__NR_clock_gettime, clock, ts);
+#endif
+}
+
+static inline
+int sys_gettimeofday(struct __kernel_old_timeval *tv, struct kernel_timezone *tz)
+{
+#ifdef __NR_gettimeofday
+ return syscall(__NR_gettimeofday, tv, tz);
+#else
+ /* Architectures with vdso_gettimeofday() also have __NR_gettimeofday */
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+static inline
+__kernel_old_time_t sys_time(__kernel_old_time_t *tloc)
+{
+#ifdef __NR_time
+ return syscall(__NR_time, tloc);
+#else
+ /* Architectures with vdso_time() also have __NR_time */
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+#endif /* __VDSO_SYSCALLS_H__ */
--
2.51.0
^ permalink raw reply related [flat|nested] 24+ messages in thread* Re: [PATCH v2 03/14] selftests: vDSO: Introduce vdso_syscalls.h
2025-11-13 15:30 ` [PATCH v2 03/14] selftests: vDSO: Introduce vdso_syscalls.h Thomas Weißschuh
@ 2025-11-14 8:13 ` Arnd Bergmann
2025-11-14 8:48 ` Thomas Weißschuh
0 siblings, 1 reply; 24+ messages in thread
From: Arnd Bergmann @ 2025-11-14 8:13 UTC (permalink / raw)
To: Thomas Weißschuh, Andy Lutomirski, Thomas Gleixner,
Vincenzo Frascino, shuah
Cc: linux-kernel, linux-kselftest
On Thu, Nov 13, 2025, at 16:30, Thomas Weißschuh wrote:
> The vDSO selftests use raw system call wrapper to validate the
> correctness of the vDSO implementation. The exactly available system
> calls differ between architectures and kernel configurations.
> Raw system calls should not use libc types as these are not necessarily
> compatible.
>
> Introduce a helper header which uses the correct types and fallbacks.
After I looked at how these are used in patch 8, I think it's
much easier to just always use the same types as the kernel interfaces
here and skip the type mangling entirely:
> +static inline
> +int sys_clock_getres(__kernel_clockid_t clock, struct
> __kernel_timespec *ts)
> +{
> +#ifdef __NR_clock_getres_time64
> + return syscall(__NR_clock_getres_time64, clock, ts);
> +#else
> + ASSERT_TIMESPEC_COMPATIBLE(typeof(*ts), struct __kernel_old_timespec);
> + return syscall(__NR_clock_getres, clock, ts);
> +#endif
> +}
__NR_clock_getres and vdso_clock_getres() both always return a
__kernel_old_timespec, so I now think it's best to return that from
sys_clock_getres() without the __NR_clock_getres_time64 alternative
here and not worry about whether that is a 32-bit or 64-bit type,
I should have thought this through better in my comments to the
previous version.
In kernels without CONFIG_COMPAT_32BIT_TIME, we currently leave
out the clock_getres/clock_gettime/gettimeofday/time syscalls,
but still provide the vdso interfaces. For consistency we should
probably leave out both syscall and vdso in that configuration,
and then we also don't need to compare the vdso_getres result
against sys_getres_time64.
> +static inline
> +int sys_clock_gettime(__kernel_clockid_t clock, struct
> __kernel_timespec *ts)
> +{
> +#ifdef __NR_clock_gettime64
> + return syscall(__NR_clock_gettime64, clock, ts);
> +#else
> + ASSERT_TIMESPEC_COMPATIBLE(typeof(*ts), struct __kernel_old_timespec);
> + return syscall(__NR_clock_gettime, clock, ts);
> +#endif
> +}
Same here.
> +static inline
> +int sys_gettimeofday(struct __kernel_old_timeval *tv, struct
> kernel_timezone *tz)
> +{
> +#ifdef __NR_gettimeofday
> + return syscall(__NR_gettimeofday, tv, tz);
> +#else
> + /* Architectures with vdso_gettimeofday() also have __NR_gettimeofday
> */
> + errno = ENOSYS;
> + return -1;
> +#endif
> +}
> +
> +static inline
> +__kernel_old_time_t sys_time(__kernel_old_time_t *tloc)
> +{
> +#ifdef __NR_time
> + return syscall(__NR_time, tloc);
> +#else
> + /* Architectures with vdso_time() also have __NR_time */
> + errno = ENOSYS;
> + return -1;
> +#endif
> +}
These both look good to me.
Arnd
^ permalink raw reply [flat|nested] 24+ messages in thread* Re: [PATCH v2 03/14] selftests: vDSO: Introduce vdso_syscalls.h
2025-11-14 8:13 ` Arnd Bergmann
@ 2025-11-14 8:48 ` Thomas Weißschuh
2025-11-14 9:16 ` Arnd Bergmann
0 siblings, 1 reply; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-14 8:48 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Andy Lutomirski, Thomas Gleixner, Vincenzo Frascino, shuah,
linux-kernel, linux-kselftest
On Fri, Nov 14, 2025 at 09:13:02AM +0100, Arnd Bergmann wrote:
> On Thu, Nov 13, 2025, at 16:30, Thomas Weißschuh wrote:
> > The vDSO selftests use raw system call wrapper to validate the
> > correctness of the vDSO implementation. The exactly available system
> > calls differ between architectures and kernel configurations.
> > Raw system calls should not use libc types as these are not necessarily
> > compatible.
> >
> > Introduce a helper header which uses the correct types and fallbacks.
>
> After I looked at how these are used in patch 8, I think it's
> much easier to just always use the same types as the kernel interfaces
> here and skip the type mangling entirely:
Please see below.
> > +static inline
> > +int sys_clock_getres(__kernel_clockid_t clock, struct
> > __kernel_timespec *ts)
> > +{
> > +#ifdef __NR_clock_getres_time64
> > + return syscall(__NR_clock_getres_time64, clock, ts);
> > +#else
> > + ASSERT_TIMESPEC_COMPATIBLE(typeof(*ts), struct __kernel_old_timespec);
> > + return syscall(__NR_clock_getres, clock, ts);
> > +#endif
> > +}
>
> __NR_clock_getres and vdso_clock_getres() both always return a
> __kernel_old_timespec, so I now think it's best to return that from
> sys_clock_getres() without the __NR_clock_getres_time64 alternative
> here and not worry about whether that is a 32-bit or 64-bit type,
>
> I should have thought this through better in my comments to the
> previous version.
>
> In kernels without CONFIG_COMPAT_32BIT_TIME, we currently leave
> out the clock_getres/clock_gettime/gettimeofday/time syscalls,
> but still provide the vdso interfaces. For consistency we should
> probably leave out both syscall and vdso in that configuration,
> and then we also don't need to compare the vdso_getres result
> against sys_getres_time64.
That sounds good. But today no vDSO provides clock_getres_time64,
so removing clock_getres from the vDSO will affect users.
So we will end up with some sort of inconsistency in any case.
While I agree that it would be nice if the type mangling was unnecessary,
I prefer to correctly test what we have today. If we decide to simplify
the vDSO itself then we have working tests.
sys_clock_gettime() should probably be called sys_clock_gettime64(),
as that is what it actually is.
FYI: gettimeoday() seems to be available even in kernels without
CONFIG_COMPAT_32BIT_TIME.
Thomas
^ permalink raw reply [flat|nested] 24+ messages in thread* Re: [PATCH v2 03/14] selftests: vDSO: Introduce vdso_syscalls.h
2025-11-14 8:48 ` Thomas Weißschuh
@ 2025-11-14 9:16 ` Arnd Bergmann
2025-11-14 10:02 ` Thomas Weißschuh
0 siblings, 1 reply; 24+ messages in thread
From: Arnd Bergmann @ 2025-11-14 9:16 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Andy Lutomirski, Thomas Gleixner, Vincenzo Frascino, shuah,
linux-kernel, linux-kselftest
On Fri, Nov 14, 2025, at 09:48, Thomas Weißschuh wrote:
> On Fri, Nov 14, 2025 at 09:13:02AM +0100, Arnd Bergmann wrote:
>> On Thu, Nov 13, 2025, at 16:30, Thomas Weißschuh wrote:
>>
>> __NR_clock_getres and vdso_clock_getres() both always return a
>> __kernel_old_timespec, so I now think it's best to return that from
>> sys_clock_getres() without the __NR_clock_getres_time64 alternative
>> here and not worry about whether that is a 32-bit or 64-bit type,
>>
>> I should have thought this through better in my comments to the
>> previous version.
>>
>> In kernels without CONFIG_COMPAT_32BIT_TIME, we currently leave
>> out the clock_getres/clock_gettime/gettimeofday/time syscalls,
>> but still provide the vdso interfaces. For consistency we should
>> probably leave out both syscall and vdso in that configuration,
>> and then we also don't need to compare the vdso_getres result
>> against sys_getres_time64.
>
> That sounds good. But today no vDSO provides clock_getres_time64,
> so removing clock_getres from the vDSO will affect users.
In what way? When we introduced the clock_gettime64()
vdso call, we debated also adding time64(), gettimeofday_time64()
and clock_getres_time64() but decided against that based on
the argument that the libc can implement all of these efficiently
with just clock_gettime64().
If you think that clock_getres_time64() is important, I don't
mind changing that, especially now that we have a shared vdso
for all architectures. The arguments here is a bit different,
since an efficient clock_getres() function in libc requires
caching the values in userspace, while an efficient gettimeofday()
is much simpler, by calling vdso_clock_gettime_time64()
> So we will end up with some sort of inconsistency in any case.
> While I agree that it would be nice if the type mangling was unnecessary,
> I prefer to correctly test what we have today. If we decide to simplify
> the vDSO itself then we have working tests.
Sorry, I'm not following. Do you mean we need the mangling since we
support the vdso for configurations without the direct syscalls, or
do you mean something else?
I don't think we can actually build a full userspace (other than nolibc)
that works with CONFIG_COMPAT_32BIT_TIME=n, so I'm not particularly
worried about testing the vdso for that case. You already skip
testing vdso_time() if sys_time() is unavailable, and I think
we can do it the exact same way for all five vdso calls.
> sys_clock_gettime() should probably be called sys_clock_gettime64(),
> as that is what it actually is.
That also seems wrong, as there is no clock_gettime64 on 64-bit
architectures, only clock_gettime.
> FYI: gettimeoday() seems to be available even in kernels without
> CONFIG_COMPAT_32BIT_TIME.
I see, that does sound like a mistake. It's relatively harmless,
but I think it would be safe to change this along with changing
the vdso to only expose the time32 interfaces when COMPAT_32BIT_TIME
is enabled.
Arnd
^ permalink raw reply [flat|nested] 24+ messages in thread* Re: [PATCH v2 03/14] selftests: vDSO: Introduce vdso_syscalls.h
2025-11-14 9:16 ` Arnd Bergmann
@ 2025-11-14 10:02 ` Thomas Weißschuh
2025-11-14 10:40 ` Arnd Bergmann
0 siblings, 1 reply; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-14 10:02 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Andy Lutomirski, Thomas Gleixner, Vincenzo Frascino, shuah,
linux-kernel, linux-kselftest
On Fri, Nov 14, 2025 at 10:16:01AM +0100, Arnd Bergmann wrote:
> On Fri, Nov 14, 2025, at 09:48, Thomas Weißschuh wrote:
> > On Fri, Nov 14, 2025 at 09:13:02AM +0100, Arnd Bergmann wrote:
> >> On Thu, Nov 13, 2025, at 16:30, Thomas Weißschuh wrote:
> >>
> >> __NR_clock_getres and vdso_clock_getres() both always return a
> >> __kernel_old_timespec, so I now think it's best to return that from
> >> sys_clock_getres() without the __NR_clock_getres_time64 alternative
> >> here and not worry about whether that is a 32-bit or 64-bit type,
> >>
> >> I should have thought this through better in my comments to the
> >> previous version.
> >>
> >> In kernels without CONFIG_COMPAT_32BIT_TIME, we currently leave
> >> out the clock_getres/clock_gettime/gettimeofday/time syscalls,
> >> but still provide the vdso interfaces. For consistency we should
> >> probably leave out both syscall and vdso in that configuration,
> >> and then we also don't need to compare the vdso_getres result
> >> against sys_getres_time64.
> >
> > That sounds good. But today no vDSO provides clock_getres_time64,
> > so removing clock_getres from the vDSO will affect users.
>
> In what way? When we introduced the clock_gettime64()
> vdso call, we debated also adding time64(), gettimeofday_time64()
> and clock_getres_time64() but decided against that based on
> the argument that the libc can implement all of these efficiently
> with just clock_gettime64().
clock_getres_time64() can't be implemented with vdso_clock_gettime64().
It could use vdso_clock_getres() as the resolution should never
overflow the type. But nobody seems to do this either.
> If you think that clock_getres_time64() is important, I don't
> mind changing that, especially now that we have a shared vdso
> for all architectures. The arguments here is a bit different,
> since an efficient clock_getres() function in libc requires
> caching the values in userspace, while an efficient gettimeofday()
> is much simpler, by calling vdso_clock_gettime_time64()
I don't think it is important. For my SPARC vDSO series I even
dropped the regular clock_getres() after your request. But because it
doesn't exist we need to handle the presence of vdso_clock_getres() and
the simultaneous absence of sys_clock_getres() in the test.
> > So we will end up with some sort of inconsistency in any case.
> > While I agree that it would be nice if the type mangling was unnecessary,
> > I prefer to correctly test what we have today. If we decide to simplify
> > the vDSO itself then we have working tests.
>
> Sorry, I'm not following. Do you mean we need the mangling since we
> support the vdso for configurations without the direct syscalls, or
> do you mean something else?
Exactly.
> I don't think we can actually build a full userspace (other than nolibc)
> that works with CONFIG_COMPAT_32BIT_TIME=n, so I'm not particularly
> worried about testing the vdso for that case.
musl 1.2 started to always use 64-bit times. Looking at both the musl and glibc
code, they always try the 64-bit variant first.
I think they should work fine.
Personally I'd like to have tests for the functionality that exists.
Even if there are currently no users.
> You already skip testing vdso_time() if sys_time() is unavailable, and I
> think we can do it the exact same way for all five vdso calls.
That was an oversight.
> > sys_clock_gettime() should probably be called sys_clock_gettime64(),
> > as that is what it actually is.
>
> That also seems wrong, as there is no clock_gettime64 on 64-bit
> architectures, only clock_gettime.
I referred to the type that it returns, which is always 64-bit.
Another name, without the sys_ prefix, would be better.
> > FYI: gettimeoday() seems to be available even in kernels without
> > CONFIG_COMPAT_32BIT_TIME.
>
> I see, that does sound like a mistake. It's relatively harmless,
> but I think it would be safe to change this along with changing
> the vdso to only expose the time32 interfaces when COMPAT_32BIT_TIME
> is enabled.
IMO that would need to be another series with its own discussion.
Thomas
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v2 03/14] selftests: vDSO: Introduce vdso_syscalls.h
2025-11-14 10:02 ` Thomas Weißschuh
@ 2025-11-14 10:40 ` Arnd Bergmann
2025-11-18 14:22 ` Thomas Weißschuh
0 siblings, 1 reply; 24+ messages in thread
From: Arnd Bergmann @ 2025-11-14 10:40 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Andy Lutomirski, Thomas Gleixner, Vincenzo Frascino, shuah,
linux-kernel, linux-kselftest
On Fri, Nov 14, 2025, at 11:02, Thomas Weißschuh wrote:
> On Fri, Nov 14, 2025 at 10:16:01AM +0100, Arnd Bergmann wrote:
>> On Fri, Nov 14, 2025, at 09:48, Thomas Weißschuh wrote:
>> If you think that clock_getres_time64() is important, I don't
>> mind changing that, especially now that we have a shared vdso
>> for all architectures. The arguments here is a bit different,
>> since an efficient clock_getres() function in libc requires
>> caching the values in userspace, while an efficient gettimeofday()
>> is much simpler, by calling vdso_clock_gettime_time64()
>
> I don't think it is important. For my SPARC vDSO series I even
> dropped the regular clock_getres() after your request. But because it
> doesn't exist we need to handle the presence of vdso_clock_getres() and
> the simultaneous absence of sys_clock_getres() in the test.
But that is the other way round, right? On sparc32 we have
(optionally) sys_clock_getres() but never vdso_clock_getres().
>> I don't think we can actually build a full userspace (other than nolibc)
>> that works with CONFIG_COMPAT_32BIT_TIME=n, so I'm not particularly
>> worried about testing the vdso for that case.
>
> musl 1.2 started to always use 64-bit times. Looking at both the musl and glibc
> code, they always try the 64-bit variant first.
> I think they should work fine.
No, musl only uses the time64 syscalls when it actually passes
a 64-bit time value, but e.g. still uses __NR_futex instead of
__NR_futex_time64 when waiting for a futex without a timeout, and it uses
__NR_clock_settime instead of __NR_clock_settime_time64 when setting a
time within the 32-bit time_t range (1902..2037).
> Personally I'd like to have tests for the functionality that exists.
> Even if there are currently no users.
>
>> You already skip testing vdso_time() if sys_time() is unavailable, and I
>> think we can do it the exact same way for all five vdso calls.
>
> That was an oversight.
Ok. So you'd want to check all the time32 and time64 vdso calls
against the __kernel_timespec values returned from
sys_clock_get{res_time64,time64} and their 64-bit equivalents?
I think in this case we have to actually address the inconsistency
in the rounding between the interfaces, which I don't think is
well documented and possibly differs across implementations.
As far as I can tell, gettimeofday() always returns the
CLOCK_REALTIME value rounded down to full microseconds and
truncated to signed 'long' seconds, while time() returns the
CLOCK_REALTIME_COARSE value rounded down to full seconds.
This can be a second earlier than a previous CLOCK_REALTIME
value.
I see that glibc's time() function uses CLOCK_REALTIME_COARSE
to be consistent with the Linux sys_time() and vdso_time(),
while musl's time() uses CLOCK_REALTIME for consistency with
gettimeofday() and sensible user expectations.
>> > sys_clock_gettime() should probably be called sys_clock_gettime64(),
>> > as that is what it actually is.
>>
>> That also seems wrong, as there is no clock_gettime64 on 64-bit
>> architectures, only clock_gettime.
>
> I referred to the type that it returns, which is always 64-bit.
> Another name, without the sys_ prefix, would be better.
Right, but then I would make it return 'struct timespec', not
'struct __kernel_timespec', because it's no longer the kernel
interface.
>> > FYI: gettimeoday() seems to be available even in kernels without
>> > CONFIG_COMPAT_32BIT_TIME.
>>
>> I see, that does sound like a mistake. It's relatively harmless,
>> but I think it would be safe to change this along with changing
>> the vdso to only expose the time32 interfaces when COMPAT_32BIT_TIME
>> is enabled.
>
> IMO that would need to be another series with its own discussion.
Sure.
Arnd
^ permalink raw reply [flat|nested] 24+ messages in thread* Re: [PATCH v2 03/14] selftests: vDSO: Introduce vdso_syscalls.h
2025-11-14 10:40 ` Arnd Bergmann
@ 2025-11-18 14:22 ` Thomas Weißschuh
2025-11-18 21:40 ` Arnd Bergmann
0 siblings, 1 reply; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-18 14:22 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Andy Lutomirski, Thomas Gleixner, Vincenzo Frascino, shuah,
linux-kernel, linux-kselftest
On Fri, Nov 14, 2025 at 11:40:31AM +0100, Arnd Bergmann wrote:
> On Fri, Nov 14, 2025, at 11:02, Thomas Weißschuh wrote:
> > On Fri, Nov 14, 2025 at 10:16:01AM +0100, Arnd Bergmann wrote:
> >> On Fri, Nov 14, 2025, at 09:48, Thomas Weißschuh wrote:
> >> If you think that clock_getres_time64() is important, I don't
> >> mind changing that, especially now that we have a shared vdso
> >> for all architectures. The arguments here is a bit different,
> >> since an efficient clock_getres() function in libc requires
> >> caching the values in userspace, while an efficient gettimeofday()
> >> is much simpler, by calling vdso_clock_gettime_time64()
> >
> > I don't think it is important. For my SPARC vDSO series I even
> > dropped the regular clock_getres() after your request. But because it
> > doesn't exist we need to handle the presence of vdso_clock_getres() and
> > the simultaneous absence of sys_clock_getres() in the test.
>
> But that is the other way round, right? On sparc32 we have
> (optionally) sys_clock_getres() but never vdso_clock_getres().
Here SPARC was just an example to show that I don't really care about
clock_getres() in the vDSO in general.
But if it was present before for an architecture and we now drop it without a
replacement, userspace developers might complain. Manually caching the value
in userspace sounds ugly and brittle, as it could even change at some point.
Introducing a time64 replacement on the other hand wouldn't make much
difference as the values never would exceed the 32-bit range anyways.
So I would keep vdso_clock_getres() where it exists today even with
CONFIG_COMPAT_32BIT_TIME=n.
> >> I don't think we can actually build a full userspace (other than nolibc)
> >> that works with CONFIG_COMPAT_32BIT_TIME=n, so I'm not particularly
> >> worried about testing the vdso for that case.
> >
> > musl 1.2 started to always use 64-bit times. Looking at both the musl and glibc
> > code, they always try the 64-bit variant first.
> > I think they should work fine.
>
> No, musl only uses the time64 syscalls when it actually passes
> a 64-bit time value, but e.g. still uses __NR_futex instead of
> __NR_futex_time64 when waiting for a futex without a timeout, and it uses
> __NR_clock_settime instead of __NR_clock_settime_time64 when setting a
> time within the 32-bit time_t range (1902..2037).
Yes indeed. Sorry, I only looked at the time-reading functions.
> > Personally I'd like to have tests for the functionality that exists.
> > Even if there are currently no users.
> >
> >> You already skip testing vdso_time() if sys_time() is unavailable, and I
> >> think we can do it the exact same way for all five vdso calls.
> >
> > That was an oversight.
>
> Ok. So you'd want to check all the time32 and time64 vdso calls
> against the __kernel_timespec values returned from
> sys_clock_get{res_time64,time64} and their 64-bit equivalents?
Yes. As these are the only ones which are guaranteed to be available.
> I think in this case we have to actually address the inconsistency
> in the rounding between the interfaces, which I don't think is
> well documented and possibly differs across implementations.
Borrowing words from Jon Corbet:
It probably is meticulously undocumented.
> As far as I can tell, gettimeofday() always returns the
> CLOCK_REALTIME value rounded down to full microseconds and
> truncated to signed 'long' seconds, while time() returns the
> CLOCK_REALTIME_COARSE value rounded down to full seconds.
> This can be a second earlier than a previous CLOCK_REALTIME
> value.
Ack. Having tests for this should be useful in general.
> I see that glibc's time() function uses CLOCK_REALTIME_COARSE
> to be consistent with the Linux sys_time() and vdso_time(),
> while musl's time() uses CLOCK_REALTIME for consistency with
> gettimeofday() and sensible user expectations.
>
> >> > sys_clock_gettime() should probably be called sys_clock_gettime64(),
> >> > as that is what it actually is.
> >>
> >> That also seems wrong, as there is no clock_gettime64 on 64-bit
> >> architectures, only clock_gettime.
> >
> > I referred to the type that it returns, which is always 64-bit.
> > Another name, without the sys_ prefix, would be better.
>
> Right, but then I would make it return 'struct timespec', not
> 'struct __kernel_timespec', because it's no longer the kernel
> interface.
'struct timespec' might be only 32-bit, breaking the tests after y2038.
While that shouldn't happen in actual y2038 it would be nice if we can
validate the future behavior today without reconfiguring libc.
Given that this is also no longer a libc interface, can't we just use
the UAPI type?
What is the general expectation for userspace using 32-bit interfaces
after y2038 from the kernel's perspective?
(...)
Thomas
^ permalink raw reply [flat|nested] 24+ messages in thread* Re: [PATCH v2 03/14] selftests: vDSO: Introduce vdso_syscalls.h
2025-11-18 14:22 ` Thomas Weißschuh
@ 2025-11-18 21:40 ` Arnd Bergmann
2025-11-20 13:27 ` Thomas Weißschuh
0 siblings, 1 reply; 24+ messages in thread
From: Arnd Bergmann @ 2025-11-18 21:40 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Andy Lutomirski, Thomas Gleixner, Vincenzo Frascino, shuah,
linux-kernel, linux-kselftest
On Tue, Nov 18, 2025, at 15:22, Thomas Weißschuh wrote:
> On Fri, Nov 14, 2025 at 11:40:31AM +0100, Arnd Bergmann wrote:
>> On Fri, Nov 14, 2025, at 11:02, Thomas Weißschuh wrote:
>> > On Fri, Nov 14, 2025 at 10:16:01AM +0100, Arnd Bergmann wrote:
>> >
>> > I don't think it is important. For my SPARC vDSO series I even
>> > dropped the regular clock_getres() after your request. But because it
>> > doesn't exist we need to handle the presence of vdso_clock_getres() and
>> > the simultaneous absence of sys_clock_getres() in the test.
>>
>> But that is the other way round, right? On sparc32 we have
>> (optionally) sys_clock_getres() but never vdso_clock_getres().
>
> Here SPARC was just an example to show that I don't really care about
> clock_getres() in the vDSO in general.
> But if it was present before for an architecture and we now drop it without a
> replacement, userspace developers might complain. Manually caching the value
> in userspace sounds ugly and brittle, as it could even change at some point.
> Introducing a time64 replacement on the other hand wouldn't make much
> difference as the values never would exceed the 32-bit range anyways.
>
> So I would keep vdso_clock_getres() where it exists today even with
> CONFIG_COMPAT_32BIT_TIME=n.
It is rather inconsistent with all the other interfaces though:
when we originally did the time64 conversion, there were a number
of interfaces that didn't really need a replacement, but we
deliberately made new interfaces wherever possible. For architectures
without time32 support, and for validating the time64 support,
it should be possible to build both kernel and userspace without
even defining the __kernel_old_time{_t,spec,val} types.
>> Right, but then I would make it return 'struct timespec', not
>> 'struct __kernel_timespec', because it's no longer the kernel
>> interface.
>
> 'struct timespec' might be only 32-bit, breaking the tests after y2038.
> While that shouldn't happen in actual y2038 it would be nice if we can
> validate the future behavior today without reconfiguring libc.
> Given that this is also no longer a libc interface, can't we just use
> the UAPI type?
It clearly works, it just feels a bit wrong to me as mixing up
the types and the interfaces is what caused the problem
originally.
> What is the general expectation for userspace using 32-bit interfaces
> after y2038 from the kernel's perspective?
I would hope that we'll end up turning off the fallback path
and eventually remove that code entirely as we get closer to
y2038, but not everyone agrees with that. An important
open question is whether we'd want to still support running
a 32-bit kernel from 2038+ with time32 userland but the RTC
backdated to 1970.
Arnd
^ permalink raw reply [flat|nested] 24+ messages in thread* Re: [PATCH v2 03/14] selftests: vDSO: Introduce vdso_syscalls.h
2025-11-18 21:40 ` Arnd Bergmann
@ 2025-11-20 13:27 ` Thomas Weißschuh
0 siblings, 0 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-20 13:27 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Andy Lutomirski, Thomas Gleixner, Vincenzo Frascino, shuah,
linux-kernel, linux-kselftest
On Tue, Nov 18, 2025 at 10:40:03PM +0100, Arnd Bergmann wrote:
> On Tue, Nov 18, 2025, at 15:22, Thomas Weißschuh wrote:
> > On Fri, Nov 14, 2025 at 11:40:31AM +0100, Arnd Bergmann wrote:
> >> On Fri, Nov 14, 2025, at 11:02, Thomas Weißschuh wrote:
> >> > On Fri, Nov 14, 2025 at 10:16:01AM +0100, Arnd Bergmann wrote:
> >> >
> >> > I don't think it is important. For my SPARC vDSO series I even
> >> > dropped the regular clock_getres() after your request. But because it
> >> > doesn't exist we need to handle the presence of vdso_clock_getres() and
> >> > the simultaneous absence of sys_clock_getres() in the test.
> >>
> >> But that is the other way round, right? On sparc32 we have
> >> (optionally) sys_clock_getres() but never vdso_clock_getres().
> >
> > Here SPARC was just an example to show that I don't really care about
> > clock_getres() in the vDSO in general.
> > But if it was present before for an architecture and we now drop it without a
> > replacement, userspace developers might complain. Manually caching the value
> > in userspace sounds ugly and brittle, as it could even change at some point.
> > Introducing a time64 replacement on the other hand wouldn't make much
> > difference as the values never would exceed the 32-bit range anyways.
> >
> > So I would keep vdso_clock_getres() where it exists today even with
> > CONFIG_COMPAT_32BIT_TIME=n.
>
> It is rather inconsistent with all the other interfaces though:
> when we originally did the time64 conversion, there were a number
> of interfaces that didn't really need a replacement, but we
> deliberately made new interfaces wherever possible. For architectures
> without time32 support, and for validating the time64 support,
> it should be possible to build both kernel and userspace without
> even defining the __kernel_old_time{_t,spec,val} types.
Fair enough. I'll add this to my TODO list.
> >> Right, but then I would make it return 'struct timespec', not
> >> 'struct __kernel_timespec', because it's no longer the kernel
> >> interface.
(...)
Thomas
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v2 04/14] selftests: vDSO: vdso_test_gettimeofday: Remove nolibc checks
2025-11-13 15:30 [PATCH v2 00/14] selftests: vDSO: Stop using libc types for vDSO calls Thomas Weißschuh
` (2 preceding siblings ...)
2025-11-13 15:30 ` [PATCH v2 03/14] selftests: vDSO: Introduce vdso_syscalls.h Thomas Weißschuh
@ 2025-11-13 15:30 ` Thomas Weißschuh
2025-11-13 15:30 ` [PATCH v2 05/14] selftests: vDSO: vdso_test_gettimeofday: Use types from vdso_types.h Thomas Weißschuh
` (9 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-13 15:30 UTC (permalink / raw)
To: Andy Lutomirski, Thomas Gleixner, Vincenzo Frascino, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
nolibc now provides these headers, making the check unnecessary.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
tools/testing/selftests/vDSO/vdso_test_gettimeofday.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/tools/testing/selftests/vDSO/vdso_test_gettimeofday.c b/tools/testing/selftests/vDSO/vdso_test_gettimeofday.c
index 9ce795b806f0992b83cef78c7e16fac0e54750da..636a56ccf8e4e7943ca446fe3fad6897598ca77f 100644
--- a/tools/testing/selftests/vDSO/vdso_test_gettimeofday.c
+++ b/tools/testing/selftests/vDSO/vdso_test_gettimeofday.c
@@ -11,10 +11,8 @@
*/
#include <stdio.h>
-#ifndef NOLIBC
#include <sys/auxv.h>
#include <sys/time.h>
-#endif
#include "../kselftest.h"
#include "parse_vdso.h"
--
2.51.0
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH v2 05/14] selftests: vDSO: vdso_test_gettimeofday: Use types from vdso_types.h
2025-11-13 15:30 [PATCH v2 00/14] selftests: vDSO: Stop using libc types for vDSO calls Thomas Weißschuh
` (3 preceding siblings ...)
2025-11-13 15:30 ` [PATCH v2 04/14] selftests: vDSO: vdso_test_gettimeofday: Remove nolibc checks Thomas Weißschuh
@ 2025-11-13 15:30 ` Thomas Weißschuh
2025-11-13 15:30 ` [PATCH v2 06/14] selftests: vDSO: vdso_test_abi: " Thomas Weißschuh
` (8 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-13 15:30 UTC (permalink / raw)
To: Andy Lutomirski, Thomas Gleixner, Vincenzo Frascino, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
The libc types are not necessarily compatible with the vDSO functions.
Use the dedicated types from vdso_types.h instead.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
tools/testing/selftests/vDSO/vdso_test_gettimeofday.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/tools/testing/selftests/vDSO/vdso_test_gettimeofday.c b/tools/testing/selftests/vDSO/vdso_test_gettimeofday.c
index 636a56ccf8e4e7943ca446fe3fad6897598ca77f..3c14ed654428e0dbe08e9d44671e82737ac61486 100644
--- a/tools/testing/selftests/vDSO/vdso_test_gettimeofday.c
+++ b/tools/testing/selftests/vDSO/vdso_test_gettimeofday.c
@@ -12,12 +12,12 @@
#include <stdio.h>
#include <sys/auxv.h>
-#include <sys/time.h>
#include "../kselftest.h"
#include "parse_vdso.h"
#include "vdso_config.h"
#include "vdso_call.h"
+#include "vdso_types.h"
int main(int argc, char **argv)
{
@@ -33,15 +33,14 @@ int main(int argc, char **argv)
vdso_init_from_sysinfo_ehdr(getauxval(AT_SYSINFO_EHDR));
/* Find gettimeofday. */
- typedef long (*gtod_t)(struct timeval *tv, struct timezone *tz);
- gtod_t gtod = (gtod_t)vdso_sym(version, name[0]);
+ vdso_gettimeofday_t gtod = (vdso_gettimeofday_t)vdso_sym(version, name[0]);
if (!gtod) {
printf("Could not find %s\n", name[0]);
return KSFT_SKIP;
}
- struct timeval tv;
+ struct __kernel_old_timeval tv;
long ret = VDSO_CALL(gtod, 2, &tv, 0);
if (ret == 0) {
--
2.51.0
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH v2 06/14] selftests: vDSO: vdso_test_abi: Use types from vdso_types.h
2025-11-13 15:30 [PATCH v2 00/14] selftests: vDSO: Stop using libc types for vDSO calls Thomas Weißschuh
` (4 preceding siblings ...)
2025-11-13 15:30 ` [PATCH v2 05/14] selftests: vDSO: vdso_test_gettimeofday: Use types from vdso_types.h Thomas Weißschuh
@ 2025-11-13 15:30 ` Thomas Weißschuh
2025-11-13 15:30 ` [PATCH v2 07/14] selftests: vDSO: vdso_test_abi: Validate return value of syscall(clock_getres) Thomas Weißschuh
` (7 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-13 15:30 UTC (permalink / raw)
To: Andy Lutomirski, Thomas Gleixner, Vincenzo Frascino, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
The libc types are not necessarily compatible with the vDSO functions.
Use the dedicated types from vdso_types.h instead.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
tools/testing/selftests/vDSO/vdso_test_abi.c | 32 +++++++++-------------------
1 file changed, 10 insertions(+), 22 deletions(-)
diff --git a/tools/testing/selftests/vDSO/vdso_test_abi.c b/tools/testing/selftests/vDSO/vdso_test_abi.c
index 238d609a457a281d802734b40d6a2c35ba7f6d72..7826d9c10ccaf313dc003e8959d9eb84b2cda874 100644
--- a/tools/testing/selftests/vDSO/vdso_test_abi.c
+++ b/tools/testing/selftests/vDSO/vdso_test_abi.c
@@ -11,9 +11,7 @@
#include <stdint.h>
#include <elf.h>
#include <stdio.h>
-#include <time.h>
#include <sys/auxv.h>
-#include <sys/time.h>
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
@@ -21,23 +19,12 @@
#include "../kselftest.h"
#include "vdso_config.h"
#include "vdso_call.h"
+#include "vdso_types.h"
#include "parse_vdso.h"
static const char *version;
static const char **name;
-/* The same as struct __kernel_timespec */
-struct vdso_timespec64 {
- uint64_t tv_sec;
- uint64_t tv_nsec;
-};
-
-typedef long (*vdso_gettimeofday_t)(struct timeval *tv, struct timezone *tz);
-typedef long (*vdso_clock_gettime_t)(clockid_t clk_id, struct timespec *ts);
-typedef long (*vdso_clock_gettime64_t)(clockid_t clk_id, struct vdso_timespec64 *ts);
-typedef long (*vdso_clock_getres_t)(clockid_t clk_id, struct timespec *ts);
-typedef time_t (*vdso_time_t)(time_t *t);
-
static const char * const vdso_clock_name[] = {
[CLOCK_REALTIME] = "CLOCK_REALTIME",
[CLOCK_MONOTONIC] = "CLOCK_MONOTONIC",
@@ -65,7 +52,7 @@ static void vdso_test_gettimeofday(void)
return;
}
- struct timeval tv;
+ struct __kernel_old_timeval tv;
long ret = VDSO_CALL(vdso_gettimeofday, 2, &tv, 0);
if (ret == 0) {
@@ -77,7 +64,7 @@ static void vdso_test_gettimeofday(void)
}
}
-static void vdso_test_clock_gettime64(clockid_t clk_id)
+static void vdso_test_clock_gettime64(__kernel_clockid_t clk_id)
{
/* Find clock_gettime64. */
vdso_clock_gettime64_t vdso_clock_gettime64 =
@@ -90,7 +77,7 @@ static void vdso_test_clock_gettime64(clockid_t clk_id)
return;
}
- struct vdso_timespec64 ts;
+ struct __kernel_timespec ts;
long ret = VDSO_CALL(vdso_clock_gettime64, 2, clk_id, &ts);
if (ret == 0) {
@@ -104,7 +91,7 @@ static void vdso_test_clock_gettime64(clockid_t clk_id)
}
}
-static void vdso_test_clock_gettime(clockid_t clk_id)
+static void vdso_test_clock_gettime(__kernel_clockid_t clk_id)
{
/* Find clock_gettime. */
vdso_clock_gettime_t vdso_clock_gettime =
@@ -117,7 +104,7 @@ static void vdso_test_clock_gettime(clockid_t clk_id)
return;
}
- struct timespec ts;
+ struct __kernel_old_timespec ts;
long ret = VDSO_CALL(vdso_clock_gettime, 2, clk_id, &ts);
if (ret == 0) {
@@ -154,7 +141,7 @@ static void vdso_test_time(void)
}
}
-static void vdso_test_clock_getres(clockid_t clk_id)
+static void vdso_test_clock_getres(__kernel_clockid_t clk_id)
{
int clock_getres_fail = 0;
@@ -169,7 +156,8 @@ static void vdso_test_clock_getres(clockid_t clk_id)
return;
}
- struct timespec ts, sys_ts;
+ struct __kernel_old_timespec ts;
+ struct timespec sys_ts;
long ret = VDSO_CALL(vdso_clock_getres, 2, clk_id, &ts);
if (ret == 0) {
@@ -200,7 +188,7 @@ static void vdso_test_clock_getres(clockid_t clk_id)
* This function calls vdso_test_clock_gettime and vdso_test_clock_getres
* with different values for clock_id.
*/
-static inline void vdso_test_clock(clockid_t clock_id)
+static inline void vdso_test_clock(__kernel_clockid_t clock_id)
{
ksft_print_msg("clock_id: %s\n", vdso_clock_name[clock_id]);
--
2.51.0
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH v2 07/14] selftests: vDSO: vdso_test_abi: Validate return value of syscall(clock_getres)
2025-11-13 15:30 [PATCH v2 00/14] selftests: vDSO: Stop using libc types for vDSO calls Thomas Weißschuh
` (5 preceding siblings ...)
2025-11-13 15:30 ` [PATCH v2 06/14] selftests: vDSO: vdso_test_abi: " Thomas Weißschuh
@ 2025-11-13 15:30 ` Thomas Weißschuh
2025-11-13 15:30 ` [PATCH v2 08/14] selftests: vDSO: vdso_test_abi: Use system call wrappers from vdso_syscalls.h Thomas Weißschuh
` (6 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-13 15:30 UTC (permalink / raw)
To: Andy Lutomirski, Thomas Gleixner, Vincenzo Frascino, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
If the system call failed the output memory is not usable.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
tools/testing/selftests/vDSO/vdso_test_abi.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/tools/testing/selftests/vDSO/vdso_test_abi.c b/tools/testing/selftests/vDSO/vdso_test_abi.c
index 7826d9c10ccaf313dc003e8959d9eb84b2cda874..ff142b3b9075b18e60a46b77492d285e9937fa71 100644
--- a/tools/testing/selftests/vDSO/vdso_test_abi.c
+++ b/tools/testing/selftests/vDSO/vdso_test_abi.c
@@ -168,12 +168,15 @@ static void vdso_test_clock_getres(__kernel_clockid_t clk_id)
}
ret = syscall(SYS_clock_getres, clk_id, &sys_ts);
+ if (ret == 0) {
+ ksft_print_msg("The syscall resolution is %lld %lld\n",
+ (long long)sys_ts.tv_sec, (long long)sys_ts.tv_nsec);
- ksft_print_msg("The syscall resolution is %lld %lld\n",
- (long long)sys_ts.tv_sec, (long long)sys_ts.tv_nsec);
-
- if ((sys_ts.tv_sec != ts.tv_sec) || (sys_ts.tv_nsec != ts.tv_nsec))
+ if ((sys_ts.tv_sec != ts.tv_sec) || (sys_ts.tv_nsec != ts.tv_nsec))
+ clock_getres_fail++;
+ } else {
clock_getres_fail++;
+ }
if (clock_getres_fail > 0) {
ksft_test_result_fail("%s %s\n", name[3],
--
2.51.0
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH v2 08/14] selftests: vDSO: vdso_test_abi: Use system call wrappers from vdso_syscalls.h
2025-11-13 15:30 [PATCH v2 00/14] selftests: vDSO: Stop using libc types for vDSO calls Thomas Weißschuh
` (6 preceding siblings ...)
2025-11-13 15:30 ` [PATCH v2 07/14] selftests: vDSO: vdso_test_abi: Validate return value of syscall(clock_getres) Thomas Weißschuh
@ 2025-11-13 15:30 ` Thomas Weißschuh
2025-11-13 15:30 ` [PATCH v2 09/14] selftests: vDSO: vdso_test_correctness: Drop SYS_getcpu fallbacks Thomas Weißschuh
` (5 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-13 15:30 UTC (permalink / raw)
To: Andy Lutomirski, Thomas Gleixner, Vincenzo Frascino, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
Using syscall(SYS_getcpu) is problematic for the reasons outlined in
vdso_syscalls.h.
Use the wrappers from the utility header instead.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
tools/testing/selftests/vDSO/vdso_test_abi.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/vDSO/vdso_test_abi.c b/tools/testing/selftests/vDSO/vdso_test_abi.c
index ff142b3b9075b18e60a46b77492d285e9937fa71..5a1bd0c2742ae14053d826c8d9f3bdc1018d91f3 100644
--- a/tools/testing/selftests/vDSO/vdso_test_abi.c
+++ b/tools/testing/selftests/vDSO/vdso_test_abi.c
@@ -19,6 +19,7 @@
#include "../kselftest.h"
#include "vdso_config.h"
#include "vdso_call.h"
+#include "vdso_syscalls.h"
#include "vdso_types.h"
#include "parse_vdso.h"
@@ -157,7 +158,7 @@ static void vdso_test_clock_getres(__kernel_clockid_t clk_id)
}
struct __kernel_old_timespec ts;
- struct timespec sys_ts;
+ struct __kernel_timespec sys_ts;
long ret = VDSO_CALL(vdso_clock_getres, 2, clk_id, &ts);
if (ret == 0) {
@@ -167,7 +168,7 @@ static void vdso_test_clock_getres(__kernel_clockid_t clk_id)
clock_getres_fail++;
}
- ret = syscall(SYS_clock_getres, clk_id, &sys_ts);
+ ret = sys_clock_getres(clk_id, &sys_ts);
if (ret == 0) {
ksft_print_msg("The syscall resolution is %lld %lld\n",
(long long)sys_ts.tv_sec, (long long)sys_ts.tv_nsec);
--
2.51.0
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH v2 09/14] selftests: vDSO: vdso_test_correctness: Drop SYS_getcpu fallbacks
2025-11-13 15:30 [PATCH v2 00/14] selftests: vDSO: Stop using libc types for vDSO calls Thomas Weißschuh
` (7 preceding siblings ...)
2025-11-13 15:30 ` [PATCH v2 08/14] selftests: vDSO: vdso_test_abi: Use system call wrappers from vdso_syscalls.h Thomas Weißschuh
@ 2025-11-13 15:30 ` Thomas Weißschuh
2025-11-13 15:30 ` [PATCH v2 10/14] selftests: vDSO: vdso_test_correctness: Make ts_leq() and tv_leq() more generic Thomas Weißschuh
` (4 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-13 15:30 UTC (permalink / raw)
To: Andy Lutomirski, Thomas Gleixner, Vincenzo Frascino, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
These fallbacks are only valid on x86 and unused in the first place.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
tools/testing/selftests/vDSO/vdso_test_correctness.c | 8 --------
1 file changed, 8 deletions(-)
diff --git a/tools/testing/selftests/vDSO/vdso_test_correctness.c b/tools/testing/selftests/vDSO/vdso_test_correctness.c
index da651cf53c6ca4242085de109c7fc57bd807297c..66cd1d4c19872e78c0e608f5e0fb5215cf902b50 100644
--- a/tools/testing/selftests/vDSO/vdso_test_correctness.c
+++ b/tools/testing/selftests/vDSO/vdso_test_correctness.c
@@ -25,14 +25,6 @@
static const char **name;
-#ifndef SYS_getcpu
-# ifdef __x86_64__
-# define SYS_getcpu 309
-# else
-# define SYS_getcpu 318
-# endif
-#endif
-
#ifndef __NR_clock_gettime64
#define __NR_clock_gettime64 403
#endif
--
2.51.0
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH v2 10/14] selftests: vDSO: vdso_test_correctness: Make ts_leq() and tv_leq() more generic
2025-11-13 15:30 [PATCH v2 00/14] selftests: vDSO: Stop using libc types for vDSO calls Thomas Weißschuh
` (8 preceding siblings ...)
2025-11-13 15:30 ` [PATCH v2 09/14] selftests: vDSO: vdso_test_correctness: Drop SYS_getcpu fallbacks Thomas Weißschuh
@ 2025-11-13 15:30 ` Thomas Weißschuh
2025-11-13 15:30 ` [PATCH v2 11/14] selftests: vDSO: vdso_test_correctness: Use types from vdso_types.h Thomas Weißschuh
` (3 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-13 15:30 UTC (permalink / raw)
To: Andy Lutomirski, Thomas Gleixner, Vincenzo Frascino, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
Upcoming changes will shuffle around the timespec and timeval types.
To keep ts_leq() and tv_leq() working with all of those types, transform
them into macros.
Also drop ts64_leq() as it can now be replaced by the regular ts_leq().
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
.../testing/selftests/vDSO/vdso_test_correctness.c | 47 ++++++++++------------
1 file changed, 22 insertions(+), 25 deletions(-)
diff --git a/tools/testing/selftests/vDSO/vdso_test_correctness.c b/tools/testing/selftests/vDSO/vdso_test_correctness.c
index 66cd1d4c19872e78c0e608f5e0fb5215cf902b50..5a127fc93e7368cbe8d9fb4a4482a6a735ffd46c 100644
--- a/tools/testing/selftests/vDSO/vdso_test_correctness.c
+++ b/tools/testing/selftests/vDSO/vdso_test_correctness.c
@@ -213,30 +213,27 @@ static void test_getcpu(void)
}
}
-static bool ts_leq(const struct timespec *a, const struct timespec *b)
-{
- if (a->tv_sec != b->tv_sec)
- return a->tv_sec < b->tv_sec;
- else
- return a->tv_nsec <= b->tv_nsec;
-}
-
-static bool ts64_leq(const struct __kernel_timespec *a,
- const struct __kernel_timespec *b)
-{
- if (a->tv_sec != b->tv_sec)
- return a->tv_sec < b->tv_sec;
- else
- return a->tv_nsec <= b->tv_nsec;
-}
-
-static bool tv_leq(const struct timeval *a, const struct timeval *b)
-{
- if (a->tv_sec != b->tv_sec)
- return a->tv_sec < b->tv_sec;
- else
- return a->tv_usec <= b->tv_usec;
-}
+#define ts_leq(_a, _b) ({ \
+ bool _ret; \
+ \
+ if ((_a)->tv_sec != (_b)->tv_sec) \
+ _ret = (_a)->tv_sec < (_b)->tv_sec; \
+ else \
+ _ret = (_a)->tv_nsec <= (_b)->tv_nsec; \
+ \
+ _ret; \
+})
+
+#define tv_leq(_a, _b) ({ \
+ bool _ret; \
+ \
+ if ((_a)->tv_sec != (_b)->tv_sec) \
+ _ret = (_a)->tv_sec < (_b)->tv_sec; \
+ else \
+ _ret = (_a)->tv_usec <= (_b)->tv_usec; \
+ \
+ _ret; \
+})
static char const * const clocknames[] = {
[0] = "CLOCK_REALTIME",
@@ -352,7 +349,7 @@ static void test_one_clock_gettime64(int clock, const char *name)
(unsigned long long)vdso.tv_sec, vdso.tv_nsec,
(unsigned long long)end.tv_sec, end.tv_nsec);
- if (!ts64_leq(&start, &vdso) || !ts64_leq(&vdso, &end)) {
+ if (!ts_leq(&start, &vdso) || !ts_leq(&vdso, &end)) {
printf("[FAIL]\tTimes are out of sequence\n");
nerrs++;
return;
--
2.51.0
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH v2 11/14] selftests: vDSO: vdso_test_correctness: Use types from vdso_types.h
2025-11-13 15:30 [PATCH v2 00/14] selftests: vDSO: Stop using libc types for vDSO calls Thomas Weißschuh
` (9 preceding siblings ...)
2025-11-13 15:30 ` [PATCH v2 10/14] selftests: vDSO: vdso_test_correctness: Make ts_leq() and tv_leq() more generic Thomas Weißschuh
@ 2025-11-13 15:30 ` Thomas Weißschuh
2025-11-13 15:30 ` [PATCH v2 12/14] selftests: vDSO: vdso_test_correctness: Use system call wrappers from vdso_syscalls.h Thomas Weißschuh
` (2 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-13 15:30 UTC (permalink / raw)
To: Andy Lutomirski, Thomas Gleixner, Vincenzo Frascino, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
The libc types are not necessarily compatible with the vDSO functions.
Use the dedicated types from vdso_types.h instead.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
.../testing/selftests/vDSO/vdso_test_correctness.c | 38 ++++++++--------------
1 file changed, 13 insertions(+), 25 deletions(-)
diff --git a/tools/testing/selftests/vDSO/vdso_test_correctness.c b/tools/testing/selftests/vDSO/vdso_test_correctness.c
index 5a127fc93e7368cbe8d9fb4a4482a6a735ffd46c..276446d24f55d6b28910320e3d601bac501c2ca1 100644
--- a/tools/testing/selftests/vDSO/vdso_test_correctness.c
+++ b/tools/testing/selftests/vDSO/vdso_test_correctness.c
@@ -7,7 +7,6 @@
#define _GNU_SOURCE
#include <stdio.h>
-#include <sys/time.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
@@ -21,6 +20,7 @@
#include "vdso_config.h"
#include "vdso_call.h"
+#include "vdso_types.h"
#include "../kselftest.h"
static const char **name;
@@ -29,29 +29,14 @@ static const char **name;
#define __NR_clock_gettime64 403
#endif
-#ifndef __kernel_timespec
-struct __kernel_timespec {
- long long tv_sec;
- long long tv_nsec;
-};
-#endif
-
/* max length of lines in /proc/self/maps - anything longer is skipped here */
#define MAPS_LINE_LEN 128
int nerrs = 0;
-typedef int (*vgettime_t)(clockid_t, struct timespec *);
-
-vgettime_t vdso_clock_gettime;
-
-typedef int (*vgettime64_t)(clockid_t, struct __kernel_timespec *);
-
-vgettime64_t vdso_clock_gettime64;
-
-typedef long (*vgtod_t)(struct timeval *tv, struct timezone *tz);
-
-vgtod_t vdso_gettimeofday;
+vdso_clock_gettime_t vdso_clock_gettime;
+vdso_clock_gettime64_t vdso_clock_gettime64;
+vdso_gettimeofday_t vdso_gettimeofday;
typedef long (*getcpu_t)(unsigned *, unsigned *, void *);
@@ -124,17 +109,17 @@ static void fill_function_pointers(void)
vgetcpu = (getcpu_t) vsyscall_getcpu();
- vdso_clock_gettime = (vgettime_t)dlsym(vdso, name[1]);
+ vdso_clock_gettime = (vdso_clock_gettime_t)dlsym(vdso, name[1]);
if (!vdso_clock_gettime)
printf("Warning: failed to find clock_gettime in vDSO\n");
#if defined(VDSO_32BIT)
- vdso_clock_gettime64 = (vgettime64_t)dlsym(vdso, name[5]);
+ vdso_clock_gettime64 = (vdso_clock_gettime64_t)dlsym(vdso, name[5]);
if (!vdso_clock_gettime64)
printf("Warning: failed to find clock_gettime64 in vDSO\n");
#endif
- vdso_gettimeofday = (vgtod_t)dlsym(vdso, name[0]);
+ vdso_gettimeofday = (vdso_gettimeofday_t)dlsym(vdso, name[0]);
if (!vdso_gettimeofday)
printf("Warning: failed to find gettimeofday in vDSO\n");
@@ -252,7 +237,8 @@ static char const * const clocknames[] = {
static void test_one_clock_gettime(int clock, const char *name)
{
- struct timespec start, vdso, end;
+ struct __kernel_old_timespec vdso;
+ struct timespec start, end;
int vdso_ret, end_ret;
printf("[RUN]\tTesting clock_gettime for clock %s (%d)...\n", name, clock);
@@ -376,8 +362,10 @@ static void test_clock_gettime64(void)
static void test_gettimeofday(void)
{
- struct timeval start, vdso, end;
- struct timezone sys_tz, vdso_tz;
+ struct __kernel_old_timeval vdso;
+ struct kernel_timezone vdso_tz;
+ struct timeval start, end;
+ struct timezone sys_tz;
int vdso_ret, end_ret;
if (!vdso_gettimeofday)
--
2.51.0
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH v2 12/14] selftests: vDSO: vdso_test_correctness: Use system call wrappers from vdso_syscalls.h
2025-11-13 15:30 [PATCH v2 00/14] selftests: vDSO: Stop using libc types for vDSO calls Thomas Weißschuh
` (10 preceding siblings ...)
2025-11-13 15:30 ` [PATCH v2 11/14] selftests: vDSO: vdso_test_correctness: Use types from vdso_types.h Thomas Weißschuh
@ 2025-11-13 15:30 ` Thomas Weißschuh
2025-11-14 8:01 ` Arnd Bergmann
2025-11-13 15:30 ` [PATCH v2 13/14] selftests: vDSO: vdso_test_correctness: Use facilities from parse_vdso.c Thomas Weißschuh
2025-11-13 15:30 ` [PATCH v2 14/14] selftests: vDSO: vdso_test_correctness: Add a test for time() Thomas Weißschuh
13 siblings, 1 reply; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-13 15:30 UTC (permalink / raw)
To: Andy Lutomirski, Thomas Gleixner, Vincenzo Frascino, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
Using syscall() is problematic for the reasons outlined in vdso_syscalls.h.
Use the wrappers from the utility header instead.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
.../testing/selftests/vDSO/vdso_test_correctness.c | 34 ++++++----------------
1 file changed, 9 insertions(+), 25 deletions(-)
diff --git a/tools/testing/selftests/vDSO/vdso_test_correctness.c b/tools/testing/selftests/vDSO/vdso_test_correctness.c
index 276446d24f55d6b28910320e3d601bac501c2ca1..ac5fa3e906806c28d3238e6f4e767e370932c5d1 100644
--- a/tools/testing/selftests/vDSO/vdso_test_correctness.c
+++ b/tools/testing/selftests/vDSO/vdso_test_correctness.c
@@ -20,6 +20,7 @@
#include "vdso_config.h"
#include "vdso_call.h"
+#include "vdso_syscalls.h"
#include "vdso_types.h"
#include "../kselftest.h"
@@ -131,21 +132,6 @@ static long sys_getcpu(unsigned * cpu, unsigned * node,
return syscall(__NR_getcpu, cpu, node, cache);
}
-static inline int sys_clock_gettime(clockid_t id, struct timespec *ts)
-{
- return syscall(__NR_clock_gettime, id, ts);
-}
-
-static inline int sys_clock_gettime64(clockid_t id, struct __kernel_timespec *ts)
-{
- return syscall(__NR_clock_gettime64, id, ts);
-}
-
-static inline int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
-{
- return syscall(__NR_gettimeofday, tv, tz);
-}
-
static void test_getcpu(void)
{
printf("[RUN]\tTesting getcpu...\n");
@@ -237,8 +223,8 @@ static char const * const clocknames[] = {
static void test_one_clock_gettime(int clock, const char *name)
{
+ struct __kernel_timespec start, end;
struct __kernel_old_timespec vdso;
- struct timespec start, end;
int vdso_ret, end_ret;
printf("[RUN]\tTesting clock_gettime for clock %s (%d)...\n", name, clock);
@@ -269,9 +255,9 @@ static void test_one_clock_gettime(int clock, const char *name)
}
printf("\t%llu.%09ld %llu.%09ld %llu.%09ld\n",
- (unsigned long long)start.tv_sec, start.tv_nsec,
- (unsigned long long)vdso.tv_sec, vdso.tv_nsec,
- (unsigned long long)end.tv_sec, end.tv_nsec);
+ (unsigned long long)start.tv_sec, (unsigned long)start.tv_nsec,
+ (unsigned long long)vdso.tv_sec, (unsigned long)vdso.tv_nsec,
+ (unsigned long long)end.tv_sec, (unsigned long)end.tv_nsec);
if (!ts_leq(&start, &vdso) || !ts_leq(&vdso, &end)) {
printf("[FAIL]\tTimes are out of sequence\n");
@@ -305,7 +291,7 @@ static void test_one_clock_gettime64(int clock, const char *name)
printf("[RUN]\tTesting clock_gettime64 for clock %s (%d)...\n", name, clock);
- if (sys_clock_gettime64(clock, &start) < 0) {
+ if (sys_clock_gettime(clock, &start) < 0) {
if (errno == EINVAL) {
vdso_ret = VDSO_CALL(vdso_clock_gettime64, 2, clock, &vdso);
if (vdso_ret == -EINVAL) {
@@ -321,7 +307,7 @@ static void test_one_clock_gettime64(int clock, const char *name)
}
vdso_ret = VDSO_CALL(vdso_clock_gettime64, 2, clock, &vdso);
- end_ret = sys_clock_gettime64(clock, &end);
+ end_ret = sys_clock_gettime(clock, &end);
if (vdso_ret != 0 || end_ret != 0) {
printf("[FAIL]\tvDSO returned %d, syscall errno=%d\n",
@@ -362,10 +348,8 @@ static void test_clock_gettime64(void)
static void test_gettimeofday(void)
{
- struct __kernel_old_timeval vdso;
- struct kernel_timezone vdso_tz;
- struct timeval start, end;
- struct timezone sys_tz;
+ struct __kernel_old_timeval start, vdso, end;
+ struct kernel_timezone vdso_tz, sys_tz;
int vdso_ret, end_ret;
if (!vdso_gettimeofday)
--
2.51.0
^ permalink raw reply related [flat|nested] 24+ messages in thread* Re: [PATCH v2 12/14] selftests: vDSO: vdso_test_correctness: Use system call wrappers from vdso_syscalls.h
2025-11-13 15:30 ` [PATCH v2 12/14] selftests: vDSO: vdso_test_correctness: Use system call wrappers from vdso_syscalls.h Thomas Weißschuh
@ 2025-11-14 8:01 ` Arnd Bergmann
0 siblings, 0 replies; 24+ messages in thread
From: Arnd Bergmann @ 2025-11-14 8:01 UTC (permalink / raw)
To: Thomas Weißschuh, Andy Lutomirski, Thomas Gleixner,
Vincenzo Frascino, shuah
Cc: linux-kernel, linux-kselftest
On Thu, Nov 13, 2025, at 16:30, Thomas Weißschuh wrote:
>
> static void test_one_clock_gettime(int clock, const char *name)
> {
> + struct __kernel_timespec start, end;
> struct __kernel_old_timespec vdso;
> - struct timespec start, end;
> int vdso_ret, end_ret;
>
> printf("[RUN]\tTesting clock_gettime for clock %s (%d)...\n", name,
This looks confusing to me: I can see that the existing code is
wrong because it passes a (libc-defined) timespec into the
sys_clock_gettime() that expects __kernel_old_timespec.
It looks like you are changing a sometimes-wrong type into
a consistently wrong type, but then you also change the
sys_clock_gettime() definition to return __kernel_timespec
instead of __kernel_old_timespec, so it ends up working.
Why not always use __kernel_old_timespec for the local variables
and the sys_clock_gettime() calls here?
> @@ -305,7 +291,7 @@ static void test_one_clock_gettime64(int clock, const char *name)
>
> printf("[RUN]\tTesting clock_gettime64 for clock %s (%d)...\n", name, clock);
>
> - if (sys_clock_gettime64(clock, &start) < 0) {
> + if (sys_clock_gettime(clock, &start) < 0) {
> if (errno == EINVAL) {
> vdso_ret = VDSO_CALL(vdso_clock_gettime64, 2, clock, &vdso);
> if (vdso_ret == -EINVAL) {
This looks like the correct fix to me. We were already uses the same
types for syscall and vdso paths, and now the types match the interface.
Arnd
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v2 13/14] selftests: vDSO: vdso_test_correctness: Use facilities from parse_vdso.c
2025-11-13 15:30 [PATCH v2 00/14] selftests: vDSO: Stop using libc types for vDSO calls Thomas Weißschuh
` (11 preceding siblings ...)
2025-11-13 15:30 ` [PATCH v2 12/14] selftests: vDSO: vdso_test_correctness: Use system call wrappers from vdso_syscalls.h Thomas Weißschuh
@ 2025-11-13 15:30 ` Thomas Weißschuh
2025-11-13 15:30 ` [PATCH v2 14/14] selftests: vDSO: vdso_test_correctness: Add a test for time() Thomas Weißschuh
13 siblings, 0 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-13 15:30 UTC (permalink / raw)
To: Andy Lutomirski, Thomas Gleixner, Vincenzo Frascino, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
The soname from the vDSO is not a public API. Furthermore it requires
libc to implement dlsym() and friends.
Use the facilities from parse_vdso.c instead which uses the official
vDSO ABI to find it, aligned with the other vDSO selftests.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
tools/testing/selftests/vDSO/Makefile | 4 +--
.../testing/selftests/vDSO/vdso_test_correctness.c | 30 ++++++++++------------
2 files changed, 14 insertions(+), 20 deletions(-)
diff --git a/tools/testing/selftests/vDSO/Makefile b/tools/testing/selftests/vDSO/Makefile
index 74dfc60e636edce91cc1df9643ca8aa008ecfe65..504b30155ae7c6da3065c4472384f54e5547332a 100644
--- a/tools/testing/selftests/vDSO/Makefile
+++ b/tools/testing/selftests/vDSO/Makefile
@@ -26,13 +26,11 @@ CFLAGS_NOLIBC := -nostdlib -nostdinc -ffreestanding -fno-asynchronous-unwind-tab
$(OUTPUT)/vdso_test_gettimeofday: parse_vdso.c vdso_test_gettimeofday.c
$(OUTPUT)/vdso_test_getcpu: parse_vdso.c vdso_test_getcpu.c
$(OUTPUT)/vdso_test_abi: parse_vdso.c vdso_test_abi.c
+$(OUTPUT)/vdso_test_correctness: parse_vdso.c vdso_test_correctness.c
$(OUTPUT)/vdso_standalone_test_x86: vdso_standalone_test_x86.c parse_vdso.c | headers
$(OUTPUT)/vdso_standalone_test_x86: CFLAGS:=$(CFLAGS_NOLIBC) $(CFLAGS)
-$(OUTPUT)/vdso_test_correctness: vdso_test_correctness.c
-$(OUTPUT)/vdso_test_correctness: LDFLAGS += -ldl
-
$(OUTPUT)/vdso_test_getrandom: parse_vdso.c
$(OUTPUT)/vdso_test_getrandom: CFLAGS += -isystem $(top_srcdir)/tools/include \
$(KHDR_INCLUDES) \
diff --git a/tools/testing/selftests/vDSO/vdso_test_correctness.c b/tools/testing/selftests/vDSO/vdso_test_correctness.c
index ac5fa3e906806c28d3238e6f4e767e370932c5d1..310688e1379511e2c564b460c6379cc00b7a5f9a 100644
--- a/tools/testing/selftests/vDSO/vdso_test_correctness.c
+++ b/tools/testing/selftests/vDSO/vdso_test_correctness.c
@@ -10,20 +10,22 @@
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
+#include <sys/auxv.h>
#include <sys/syscall.h>
-#include <dlfcn.h>
#include <string.h>
#include <errno.h>
#include <sched.h>
#include <stdbool.h>
#include <limits.h>
+#include "parse_vdso.h"
#include "vdso_config.h"
#include "vdso_call.h"
#include "vdso_syscalls.h"
#include "vdso_types.h"
#include "../kselftest.h"
+static const char *version;
static const char **name;
#ifndef __NR_clock_gettime64
@@ -88,39 +90,32 @@ static void *vsyscall_getcpu(void)
static void fill_function_pointers(void)
{
- void *vdso = dlopen("linux-vdso.so.1",
- RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
- if (!vdso)
- vdso = dlopen("linux-gate.so.1",
- RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
- if (!vdso)
- vdso = dlopen("linux-vdso32.so.1",
- RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
- if (!vdso)
- vdso = dlopen("linux-vdso64.so.1",
- RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
- if (!vdso) {
+ unsigned long sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR);
+
+ if (!sysinfo_ehdr) {
printf("[WARN]\tfailed to find vDSO\n");
return;
}
- vdso_getcpu = (getcpu_t)dlsym(vdso, name[4]);
+ vdso_init_from_sysinfo_ehdr(sysinfo_ehdr);
+
+ vdso_getcpu = (getcpu_t)vdso_sym(version, name[4]);
if (!vdso_getcpu)
printf("Warning: failed to find getcpu in vDSO\n");
vgetcpu = (getcpu_t) vsyscall_getcpu();
- vdso_clock_gettime = (vdso_clock_gettime_t)dlsym(vdso, name[1]);
+ vdso_clock_gettime = (vdso_clock_gettime_t)vdso_sym(version, name[1]);
if (!vdso_clock_gettime)
printf("Warning: failed to find clock_gettime in vDSO\n");
#if defined(VDSO_32BIT)
- vdso_clock_gettime64 = (vdso_clock_gettime64_t)dlsym(vdso, name[5]);
+ vdso_clock_gettime64 = (vdso_clock_gettime64_t)vdso_sym(version, name[5]);
if (!vdso_clock_gettime64)
printf("Warning: failed to find clock_gettime64 in vDSO\n");
#endif
- vdso_gettimeofday = (vdso_gettimeofday_t)dlsym(vdso, name[0]);
+ vdso_gettimeofday = (vdso_gettimeofday_t)vdso_sym(version, name[0]);
if (!vdso_gettimeofday)
printf("Warning: failed to find gettimeofday in vDSO\n");
@@ -398,6 +393,7 @@ static void test_gettimeofday(void)
int main(int argc, char **argv)
{
+ version = versions[VDSO_VERSION];
name = (const char **)&names[VDSO_NAMES];
fill_function_pointers();
--
2.51.0
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH v2 14/14] selftests: vDSO: vdso_test_correctness: Add a test for time()
2025-11-13 15:30 [PATCH v2 00/14] selftests: vDSO: Stop using libc types for vDSO calls Thomas Weißschuh
` (12 preceding siblings ...)
2025-11-13 15:30 ` [PATCH v2 13/14] selftests: vDSO: vdso_test_correctness: Use facilities from parse_vdso.c Thomas Weißschuh
@ 2025-11-13 15:30 ` Thomas Weißschuh
13 siblings, 0 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-13 15:30 UTC (permalink / raw)
To: Andy Lutomirski, Thomas Gleixner, Vincenzo Frascino, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
Extend the test to also cover the time() function.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
.../testing/selftests/vDSO/vdso_test_correctness.c | 49 ++++++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/tools/testing/selftests/vDSO/vdso_test_correctness.c b/tools/testing/selftests/vDSO/vdso_test_correctness.c
index 310688e1379511e2c564b460c6379cc00b7a5f9a..67cb8f11aa3c6977616def286b9a7d35fa6579e7 100644
--- a/tools/testing/selftests/vDSO/vdso_test_correctness.c
+++ b/tools/testing/selftests/vDSO/vdso_test_correctness.c
@@ -40,6 +40,7 @@ int nerrs = 0;
vdso_clock_gettime_t vdso_clock_gettime;
vdso_clock_gettime64_t vdso_clock_gettime64;
vdso_gettimeofday_t vdso_gettimeofday;
+vdso_time_t vdso_time;
typedef long (*getcpu_t)(unsigned *, unsigned *, void *);
@@ -119,6 +120,10 @@ static void fill_function_pointers(void)
if (!vdso_gettimeofday)
printf("Warning: failed to find gettimeofday in vDSO\n");
+ vdso_time = (vdso_time_t)vdso_sym(version, name[2]);
+ if (!vdso_time)
+ printf("Warning: failed to find time in vDSO\n");
+
}
static long sys_getcpu(unsigned * cpu, unsigned * node,
@@ -391,6 +396,49 @@ static void test_gettimeofday(void)
VDSO_CALL(vdso_gettimeofday, 2, &vdso, NULL);
}
+static void test_time(void)
+{
+ __kernel_old_time_t start, end, vdso_ret, vdso_param;
+
+ if (!vdso_time)
+ return;
+
+ printf("[RUN]\tTesting time...\n");
+
+ if (sys_time(&start) < 0) {
+ printf("[FAIL]\tsys_time failed (%d)\n", errno);
+ nerrs++;
+ return;
+ }
+
+ vdso_ret = VDSO_CALL(vdso_time, 1, &vdso_param);
+ end = sys_time(NULL);
+
+ if (vdso_ret < 0 || end < 0) {
+ printf("[FAIL]\tvDSO returned %d, syscall errno=%d\n",
+ (int)vdso_ret, errno);
+ nerrs++;
+ return;
+ }
+
+ printf("\t%lld %lld %lld\n",
+ (long long)start,
+ (long long)vdso_ret,
+ (long long)end);
+
+ if (vdso_ret != vdso_param) {
+ printf("[FAIL]\tinconsistent return values: %lld %lld\n",
+ (long long)vdso_ret, (long long)vdso_param);
+ nerrs++;
+ return;
+ }
+
+ if (!(start <= vdso_ret) || !(vdso_ret <= end)) {
+ printf("[FAIL]\tTimes are out of sequence\n");
+ nerrs++;
+ }
+}
+
int main(int argc, char **argv)
{
version = versions[VDSO_VERSION];
@@ -401,6 +449,7 @@ int main(int argc, char **argv)
test_clock_gettime();
test_clock_gettime64();
test_gettimeofday();
+ test_time();
/*
* Test getcpu() last so that, if something goes wrong setting affinity,
--
2.51.0
^ permalink raw reply related [flat|nested] 24+ messages in thread