diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-04-14 10:53:44 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-04-14 10:53:44 -0700 |
| commit | f21f7b5162e9dbde6d3d5ce727d4ca2552d76ce9 (patch) | |
| tree | 2c1d858605001adedeff10f66f031e20da1db34d /tools/testing | |
| parent | c1fe867b5bf9c57ab7856486d342720e2b205eed (diff) | |
| parent | 7138a8698a39e81eb153e05500823fff76d5b3bd (diff) | |
| download | lwn-f21f7b5162e9dbde6d3d5ce727d4ca2552d76ce9.tar.gz lwn-f21f7b5162e9dbde6d3d5ce727d4ca2552d76ce9.zip | |
Merge tag 'timers-vdso-2026-04-12' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull vdso updates from Thomas Gleixner:
- Make the handling of compat functions consistent and more robust
- Rework the underlying data store so that it is dynamically allocated,
which allows the conversion of the last holdout SPARC64 to the
generic VDSO implementation
- Rework the SPARC64 VDSO to utilize the generic implementation
- Mop up the left overs of the non-generic VDSO support in the core
code
- Expand the VDSO selftest and make them more robust
- Allow time namespaces to be enabled independently of the generic VDSO
support, which was not possible before due to SPARC64 not using it
- Various cleanups and improvements in the related code
* tag 'timers-vdso-2026-04-12' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (51 commits)
timens: Use task_lock guard in timens_get*()
timens: Use mutex guard in proc_timens_set_offset()
timens: Simplify some calls to put_time_ns()
timens: Add a __free() wrapper for put_time_ns()
timens: Remove dependency on the vDSO
vdso/timens: Move functions to new file
selftests: vDSO: vdso_test_correctness: Add a test for time()
selftests: vDSO: vdso_test_correctness: Use facilities from parse_vdso.c
selftests: vDSO: vdso_test_correctness: Handle different tv_usec types
selftests: vDSO: vdso_test_correctness: Drop SYS_getcpu fallbacks
selftests: vDSO: vdso_test_gettimeofday: Remove nolibc checks
Revert "selftests: vDSO: parse_vdso: Use UAPI headers instead of libc headers"
random: vDSO: Remove ifdeffery
random: vDSO: Trim vDSO includes
vdso/datapage: Trim down unnecessary includes
vdso/datapage: Remove inclusion of gettimeofday.h
vdso/helpers: Explicitly include vdso/processor.h
vdso/gettimeofday: Add explicit includes
random: vDSO: Add explicit includes
MIPS: vdso: Explicitly include asm/vdso/vdso.h
...
Diffstat (limited to 'tools/testing')
| -rw-r--r-- | tools/testing/selftests/vDSO/Makefile | 6 | ||||
| -rw-r--r-- | tools/testing/selftests/vDSO/parse_vdso.c | 3 | ||||
| -rw-r--r-- | tools/testing/selftests/vDSO/vdso_test_correctness.c | 112 | ||||
| -rw-r--r-- | tools/testing/selftests/vDSO/vdso_test_gettimeofday.c | 2 |
4 files changed, 85 insertions, 38 deletions
diff --git a/tools/testing/selftests/vDSO/Makefile b/tools/testing/selftests/vDSO/Makefile index e361aca22a74..a61047bdcd57 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) @@ -28,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/parse_vdso.c b/tools/testing/selftests/vDSO/parse_vdso.c index 3ff00fb624a4..c6ff4413ea36 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" diff --git a/tools/testing/selftests/vDSO/vdso_test_correctness.c b/tools/testing/selftests/vDSO/vdso_test_correctness.c index 055af95aa552..5c5a07dd1128 100644 --- a/tools/testing/selftests/vDSO/vdso_test_correctness.c +++ b/tools/testing/selftests/vDSO/vdso_test_correctness.c @@ -11,28 +11,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 "kselftest.h" +static const char *version; 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 @@ -61,6 +55,10 @@ typedef long (*vgtod_t)(struct timeval *tv, struct timezone *tz); vgtod_t vdso_gettimeofday; +typedef time_t (*vtime_t)(__kernel_time_t *tloc); + +vtime_t vdso_time; + typedef long (*getcpu_t)(unsigned *, unsigned *, void *); getcpu_t vgetcpu; @@ -110,42 +108,39 @@ 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 = (vgettime_t)dlsym(vdso, name[1]); + vdso_clock_gettime = (vgettime_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 = (vgettime64_t)dlsym(vdso, name[5]); + vdso_clock_gettime64 = (vgettime64_t)vdso_sym(version, 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 = (vgtod_t)vdso_sym(version, name[0]); if (!vdso_gettimeofday) printf("Warning: failed to find gettimeofday in vDSO\n"); + vdso_time = (vtime_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, @@ -169,6 +164,16 @@ static inline int sys_gettimeofday(struct timeval *tv, struct timezone *tz) return syscall(__NR_gettimeofday, tv, tz); } +static inline __kernel_old_time_t sys_time(__kernel_old_time_t *tloc) +{ +#ifdef __NR_time + return syscall(__NR_time, tloc); +#else + errno = ENOSYS; + return -1; +#endif +} + static void test_getcpu(void) { printf("[RUN]\tTesting getcpu...\n"); @@ -412,10 +417,10 @@ static void test_gettimeofday(void) return; } - printf("\t%llu.%06ld %llu.%06ld %llu.%06ld\n", - (unsigned long long)start.tv_sec, start.tv_usec, - (unsigned long long)vdso.tv_sec, vdso.tv_usec, - (unsigned long long)end.tv_sec, end.tv_usec); + printf("\t%llu.%06lld %llu.%06lld %llu.%06lld\n", + (unsigned long long)start.tv_sec, (long long)start.tv_usec, + (unsigned long long)vdso.tv_sec, (long long)vdso.tv_usec, + (unsigned long long)end.tv_sec, (long long)end.tv_usec); if (!tv_leq(&start, &vdso) || !tv_leq(&vdso, &end)) { printf("[FAIL]\tTimes are out of sequence\n"); @@ -435,8 +440,56 @@ 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) { + if (errno == -ENOSYS) { + printf("[SKIP]\tNo time() support\n"); + } else { + 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]; name = (const char **)&names[VDSO_NAMES]; fill_function_pointers(); @@ -444,6 +497,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, diff --git a/tools/testing/selftests/vDSO/vdso_test_gettimeofday.c b/tools/testing/selftests/vDSO/vdso_test_gettimeofday.c index 912edadad92c..990b29e0e272 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" |
