summaryrefslogtreecommitdiff
path: root/tools/testing
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-04-14 10:53:44 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-04-14 10:53:44 -0700
commitf21f7b5162e9dbde6d3d5ce727d4ca2552d76ce9 (patch)
tree2c1d858605001adedeff10f66f031e20da1db34d /tools/testing
parentc1fe867b5bf9c57ab7856486d342720e2b205eed (diff)
parent7138a8698a39e81eb153e05500823fff76d5b3bd (diff)
downloadlwn-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/Makefile6
-rw-r--r--tools/testing/selftests/vDSO/parse_vdso.c3
-rw-r--r--tools/testing/selftests/vDSO/vdso_test_correctness.c112
-rw-r--r--tools/testing/selftests/vDSO/vdso_test_gettimeofday.c2
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"