Updates for the VDSO subsystem:

- Further consolidation of the VDSO infrastructure and the common data
     store.
 
   - Simplification of the related Kconfig logic
 
   - Improve the VDSO selftest suite
 -----BEGIN PGP SIGNATURE-----
 
 iQJHBAABCgAxFiEEQp8+kY+LLUocC4bMphj1TA10mKEFAmjaUJgTHHRnbHhAbGlu
 dXRyb25peC5kZQAKCRCmGPVMDXSYoT5VD/9l+TP42vJzwygPArefVM9QijAc4k+g
 iptaz5M+Lhk0BlwMUu502Tp1zcwGq5529LlE2P72DuYoZRtZKSFCGES2mye0JiAs
 A5Vk8d1zicg3IIGjYgw39shA9ghzuzV3gZdgHVqQ6024uSeKxUY3SqF156GGfPFG
 azXWDV7i4RGQvKLm2ye8m7JNYCE3P9f8Wh+GvPaq7qBlW1MsMCWC4FP5qu4iStf3
 mol9uA/EM2zSDwkpIpq6P5L2TpIH1dGDNGxVf/HG3J16UhNXzzXv/rxuKHKPNGWm
 MQZ8WdPjF+uwdUsNXaImC6aCE0hoQ1Ga7GE2YA3pMQYfySeiJ/fA5I1KfhlUCiHD
 oUgnb6PQfZjaBDrIODKcrFHAYc5pTOyJXnJ6q1Lc1yrOfoVcIpMaRXHO/phCeuwI
 61gfb9ggbFEH/7cL26Z9XGSqh4BDCKVP5Z+y98OnNEzV74ScpX13/szB3VgdN6LW
 tmTOeMPYCo4FQoPw8OV1xkeYOKD2JyqH+garnxDZNFjaVaeUkzlAMKz+1JUjxRZj
 UpUhZ8y5KFVjgKkqZHxhucr9cnwV/xd4n+IzZeG4l6XZp4VyirG+5QpAikGYe+Jq
 WFU4Ao1xvevyizrJEhoGJKznwtrNrsy6AQ+wLQxYiRR4aTnng8n9T/ry2DVvhJf8
 diYWxuRTR7KMxg==
 =i3UB
 -----END PGP SIGNATURE-----

Merge tag 'timers-vdso-2025-09-29' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull VDSO updates from Thomas Gleixner:

 - Further consolidation of the VDSO infrastructure and the common data
   store

 - Simplification of the related Kconfig logic

 - Improve the VDSO selftest suite

* tag 'timers-vdso-2025-09-29' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  selftests: vDSO: Drop vdso_test_clock_getres
  selftests: vDSO: vdso_test_abi: Add tests for clock_gettime64()
  selftests: vDSO: vdso_test_abi: Test CPUTIME clocks
  selftests: vDSO: vdso_test_abi: Use explicit indices for name array
  selftests: vDSO: vdso_test_abi: Drop clock availability tests
  selftests: vDSO: vdso_test_abi: Use ksft_finished()
  selftests: vDSO: vdso_test_abi: Correctly skip whole test with missing vDSO
  selftests: vDSO: Fix -Wunitialized in powerpc VDSO_CALL() wrapper
  vdso: Add struct __kernel_old_timeval forward declaration to gettime.h
  vdso: Gate VDSO_GETRANDOM behind HAVE_GENERIC_VDSO
  vdso: Drop Kconfig GENERIC_VDSO_TIME_NS
  vdso: Drop Kconfig GENERIC_VDSO_DATA_STORE
  vdso: Drop kconfig GENERIC_COMPAT_VDSO
  vdso: Drop kconfig GENERIC_VDSO_32
  riscv: vdso: Untangle Kconfig logic
  time: Build generic update_vsyscall() only with generic time vDSO
  vdso/gettimeofday: Remove !CONFIG_TIME_NS stubs
  vdso: Move ENABLE_COMPAT_VDSO from core to arm64
  ARM: VDSO: Remove cntvct_ok global variable
  vdso/datastore: Gate time data behind CONFIG_GENERIC_GETTIMEOFDAY
This commit is contained in:
Linus Torvalds 2025-09-30 16:58:21 -07:00
commit 4b81e2eb9e
30 changed files with 91 additions and 285 deletions

View File

@ -1657,7 +1657,7 @@ config HAVE_SPARSE_SYSCALL_NR
related optimizations for a given architecture. related optimizations for a given architecture.
config ARCH_HAS_VDSO_ARCH_DATA config ARCH_HAS_VDSO_ARCH_DATA
depends on GENERIC_VDSO_DATA_STORE depends on HAVE_GENERIC_VDSO
bool bool
config ARCH_HAS_VDSO_TIME_DATA config ARCH_HAS_VDSO_TIME_DATA

View File

@ -7,8 +7,6 @@
#include <vdso/datapage.h> #include <vdso/datapage.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
extern bool cntvct_ok;
static __always_inline static __always_inline
void __arch_sync_vdso_time_data(struct vdso_time_data *vdata) void __arch_sync_vdso_time_data(struct vdso_time_data *vdata)
{ {

View File

@ -54,11 +54,9 @@ struct elfinfo {
char *dynstr; /* ptr to .dynstr section */ char *dynstr; /* ptr to .dynstr section */
}; };
/* Cached result of boot-time check for whether the arch timer exists, /* Boot-time check for whether the arch timer exists, and if so,
* and if so, whether the virtual counter is useable. * whether the virtual counter is usable.
*/ */
bool cntvct_ok __ro_after_init;
static bool __init cntvct_functional(void) static bool __init cntvct_functional(void)
{ {
struct device_node *np; struct device_node *np;
@ -159,7 +157,7 @@ static void __init patch_vdso(void *ehdr)
* want programs to incur the slight additional overhead of * want programs to incur the slight additional overhead of
* dispatching through the VDSO only to fall back to syscalls. * dispatching through the VDSO only to fall back to syscalls.
*/ */
if (!cntvct_ok) { if (!cntvct_functional()) {
vdso_nullpatch_one(&einfo, "__vdso_gettimeofday"); vdso_nullpatch_one(&einfo, "__vdso_gettimeofday");
vdso_nullpatch_one(&einfo, "__vdso_clock_gettime"); vdso_nullpatch_one(&einfo, "__vdso_clock_gettime");
vdso_nullpatch_one(&einfo, "__vdso_clock_gettime64"); vdso_nullpatch_one(&einfo, "__vdso_clock_gettime64");
@ -197,8 +195,6 @@ static int __init vdso_init(void)
vdso_total_pages = VDSO_NR_PAGES; /* for the data/vvar pages */ vdso_total_pages = VDSO_NR_PAGES; /* for the data/vvar pages */
vdso_total_pages += text_pages; vdso_total_pages += text_pages;
cntvct_ok = cntvct_functional();
patch_vdso(vdso_start); patch_vdso(vdso_start);
return 0; return 0;

View File

@ -926,9 +926,7 @@ config VDSO
default y if ARM_ARCH_TIMER default y if ARM_ARCH_TIMER
select HAVE_GENERIC_VDSO select HAVE_GENERIC_VDSO
select GENERIC_TIME_VSYSCALL select GENERIC_TIME_VSYSCALL
select GENERIC_VDSO_32
select GENERIC_GETTIMEOFDAY select GENERIC_GETTIMEOFDAY
select GENERIC_VDSO_DATA_STORE
help help
Place in the process address space an ELF shared object Place in the process address space an ELF shared object
providing fast implementations of gettimeofday and providing fast implementations of gettimeofday and

View File

@ -166,8 +166,6 @@ config ARM64
select GENERIC_SMP_IDLE_THREAD select GENERIC_SMP_IDLE_THREAD
select GENERIC_TIME_VSYSCALL select GENERIC_TIME_VSYSCALL
select GENERIC_GETTIMEOFDAY select GENERIC_GETTIMEOFDAY
select GENERIC_VDSO_DATA_STORE
select GENERIC_VDSO_TIME_NS
select HARDIRQS_SW_RESEND select HARDIRQS_SW_RESEND
select HAS_IOPORT select HAS_IOPORT
select HAVE_MOVE_PMD select HAVE_MOVE_PMD
@ -1750,7 +1748,6 @@ config COMPAT_VDSO
bool "Enable vDSO for 32-bit applications" bool "Enable vDSO for 32-bit applications"
depends on !CPU_BIG_ENDIAN depends on !CPU_BIG_ENDIAN
depends on (CC_IS_CLANG && LD_IS_LLD) || "$(CROSS_COMPILE_COMPAT)" != "" depends on (CC_IS_CLANG && LD_IS_LLD) || "$(CROSS_COMPILE_COMPAT)" != ""
select GENERIC_COMPAT_VDSO
default y default y
help help
Place in the process address space of 32-bit applications an Place in the process address space of 32-bit applications an

View File

@ -7,11 +7,10 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
/* /*
* Warning: This code is meant to be used with * Warning: This code is meant to be used from the compat vDSO only.
* ENABLE_COMPAT_VDSO only.
*/ */
#ifndef ENABLE_COMPAT_VDSO #ifdef __arch64__
#error This header is meant to be used with ENABLE_COMPAT_VDSO only #error This header is meant to be used with from the compat vDSO only
#endif #endif
#ifdef dmb #ifdef dmb

View File

@ -2,8 +2,8 @@
/* /*
* Copyright (C) 2018 ARM Limited * Copyright (C) 2018 ARM Limited
*/ */
#ifndef __ASM_VDSO_GETTIMEOFDAY_H #ifndef __ASM_VDSO_COMPAT_GETTIMEOFDAY_H
#define __ASM_VDSO_GETTIMEOFDAY_H #define __ASM_VDSO_COMPAT_GETTIMEOFDAY_H
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
@ -163,4 +163,4 @@ static inline bool vdso_clocksource_ok(const struct vdso_clock *vc)
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */
#endif /* __ASM_VDSO_GETTIMEOFDAY_H */ #endif /* __ASM_VDSO_COMPAT_GETTIMEOFDAY_H */

View File

@ -5,6 +5,8 @@
#ifndef __ASM_VDSO_GETTIMEOFDAY_H #ifndef __ASM_VDSO_GETTIMEOFDAY_H
#define __ASM_VDSO_GETTIMEOFDAY_H #define __ASM_VDSO_GETTIMEOFDAY_H
#ifdef __aarch64__
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <asm/alternative.h> #include <asm/alternative.h>
@ -96,4 +98,10 @@ static __always_inline const struct vdso_time_data *__arch_get_vdso_u_time_data(
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */
#else /* !__aarch64__ */
#include "compat_gettimeofday.h"
#endif /* __aarch64__ */
#endif /* __ASM_VDSO_GETTIMEOFDAY_H */ #endif /* __ASM_VDSO_GETTIMEOFDAY_H */

View File

@ -57,7 +57,6 @@ VDSO_CAFLAGS += -DDISABLE_BRANCH_PROFILING
VDSO_CAFLAGS += -march=armv8-a VDSO_CAFLAGS += -march=armv8-a
VDSO_CFLAGS := $(VDSO_CAFLAGS) VDSO_CFLAGS := $(VDSO_CAFLAGS)
VDSO_CFLAGS += -DENABLE_COMPAT_VDSO=1
# KBUILD_CFLAGS from top-level Makefile # KBUILD_CFLAGS from top-level Makefile
VDSO_CFLAGS += -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ VDSO_CFLAGS += -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
-fno-strict-aliasing -fno-common \ -fno-strict-aliasing -fno-common \

View File

@ -110,8 +110,6 @@ config LOONGARCH
select GENERIC_SCHED_CLOCK select GENERIC_SCHED_CLOCK
select GENERIC_SMP_IDLE_THREAD select GENERIC_SMP_IDLE_THREAD
select GENERIC_TIME_VSYSCALL select GENERIC_TIME_VSYSCALL
select GENERIC_VDSO_DATA_STORE
select GENERIC_VDSO_TIME_NS
select GPIOLIB select GPIOLIB
select HAS_IOPORT select HAS_IOPORT
select HAVE_ARCH_AUDITSYSCALL select HAVE_ARCH_AUDITSYSCALL

View File

@ -51,7 +51,6 @@ config MIPS
select GENERIC_SMP_IDLE_THREAD select GENERIC_SMP_IDLE_THREAD
select GENERIC_IDLE_POLL_SETUP select GENERIC_IDLE_POLL_SETUP
select GENERIC_TIME_VSYSCALL select GENERIC_TIME_VSYSCALL
select GENERIC_VDSO_DATA_STORE
select GUP_GET_PXX_LOW_HIGH if CPU_MIPS32 && PHYS_ADDR_T_64BIT select GUP_GET_PXX_LOW_HIGH if CPU_MIPS32 && PHYS_ADDR_T_64BIT
select HAS_IOPORT if !NO_IOPORT_MAP || ISA select HAS_IOPORT if !NO_IOPORT_MAP || ISA
select HAVE_ARCH_COMPILER_H select HAVE_ARCH_COMPILER_H

View File

@ -210,8 +210,6 @@ config PPC
select GENERIC_PCI_IOMAP if PCI select GENERIC_PCI_IOMAP if PCI
select GENERIC_SMP_IDLE_THREAD select GENERIC_SMP_IDLE_THREAD
select GENERIC_TIME_VSYSCALL select GENERIC_TIME_VSYSCALL
select GENERIC_VDSO_DATA_STORE
select GENERIC_VDSO_TIME_NS
select HAS_IOPORT if PCI select HAS_IOPORT if PCI
select HAVE_ARCH_AUDITSYSCALL select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_HUGE_VMALLOC if HAVE_ARCH_HUGE_VMAP select HAVE_ARCH_HUGE_VMALLOC if HAVE_ARCH_HUGE_VMAP

View File

@ -53,7 +53,7 @@ config RISCV
select ARCH_HAS_SYSCALL_WRAPPER select ARCH_HAS_SYSCALL_WRAPPER
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
select ARCH_HAS_UBSAN select ARCH_HAS_UBSAN
select ARCH_HAS_VDSO_ARCH_DATA if GENERIC_VDSO_DATA_STORE select ARCH_HAS_VDSO_ARCH_DATA if HAVE_GENERIC_VDSO
select ARCH_HAVE_NMI_SAFE_CMPXCHG select ARCH_HAVE_NMI_SAFE_CMPXCHG
select ARCH_KEEP_MEMBLOCK if ACPI select ARCH_KEEP_MEMBLOCK if ACPI
select ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE if 64BIT && MMU select ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE if 64BIT && MMU
@ -110,7 +110,7 @@ config RISCV
select GENERIC_CPU_VULNERABILITIES select GENERIC_CPU_VULNERABILITIES
select GENERIC_EARLY_IOREMAP select GENERIC_EARLY_IOREMAP
select GENERIC_ENTRY select GENERIC_ENTRY
select GENERIC_GETTIMEOFDAY if HAVE_GENERIC_VDSO select GENERIC_GETTIMEOFDAY if HAVE_GENERIC_VDSO && 64BIT
select GENERIC_IDLE_POLL_SETUP select GENERIC_IDLE_POLL_SETUP
select GENERIC_IOREMAP if MMU select GENERIC_IOREMAP if MMU
select GENERIC_IRQ_IPI if SMP select GENERIC_IRQ_IPI if SMP
@ -123,9 +123,7 @@ config RISCV
select GENERIC_PCI_IOMAP select GENERIC_PCI_IOMAP
select GENERIC_SCHED_CLOCK select GENERIC_SCHED_CLOCK
select GENERIC_SMP_IDLE_THREAD select GENERIC_SMP_IDLE_THREAD
select GENERIC_TIME_VSYSCALL if MMU && 64BIT select GENERIC_TIME_VSYSCALL if GENERIC_GETTIMEOFDAY
select GENERIC_VDSO_DATA_STORE if MMU
select GENERIC_VDSO_TIME_NS if HAVE_GENERIC_VDSO
select HARDIRQS_SW_RESEND select HARDIRQS_SW_RESEND
select HAS_IOPORT if MMU select HAS_IOPORT if MMU
select HAVE_ALIGNED_STRUCT_PAGE select HAVE_ALIGNED_STRUCT_PAGE
@ -169,7 +167,7 @@ config RISCV
select HAVE_FUNCTION_ARG_ACCESS_API select HAVE_FUNCTION_ARG_ACCESS_API
select HAVE_FUNCTION_ERROR_INJECTION select HAVE_FUNCTION_ERROR_INJECTION
select HAVE_GCC_PLUGINS select HAVE_GCC_PLUGINS
select HAVE_GENERIC_VDSO if MMU && 64BIT select HAVE_GENERIC_VDSO if MMU
select HAVE_IRQ_TIME_ACCOUNTING select HAVE_IRQ_TIME_ACCOUNTING
select HAVE_KERNEL_BZIP2 if !XIP_KERNEL && !EFI_ZBOOT select HAVE_KERNEL_BZIP2 if !XIP_KERNEL && !EFI_ZBOOT
select HAVE_KERNEL_GZIP if !XIP_KERNEL && !EFI_ZBOOT select HAVE_KERNEL_GZIP if !XIP_KERNEL && !EFI_ZBOOT
@ -225,7 +223,7 @@ config RISCV
select THREAD_INFO_IN_TASK select THREAD_INFO_IN_TASK
select TRACE_IRQFLAGS_SUPPORT select TRACE_IRQFLAGS_SUPPORT
select UACCESS_MEMCPY if !MMU select UACCESS_MEMCPY if !MMU
select VDSO_GETRANDOM if HAVE_GENERIC_VDSO select VDSO_GETRANDOM if HAVE_GENERIC_VDSO && 64BIT
select USER_STACKTRACE_SUPPORT select USER_STACKTRACE_SUPPORT
select ZONE_DMA32 if 64BIT select ZONE_DMA32 if 64BIT

View File

@ -174,8 +174,6 @@ config S390
select GENERIC_GETTIMEOFDAY select GENERIC_GETTIMEOFDAY
select GENERIC_SMP_IDLE_THREAD select GENERIC_SMP_IDLE_THREAD
select GENERIC_TIME_VSYSCALL select GENERIC_TIME_VSYSCALL
select GENERIC_VDSO_DATA_STORE
select GENERIC_VDSO_TIME_NS
select GENERIC_IOREMAP if PCI select GENERIC_IOREMAP if PCI
select HAVE_ALIGNED_STRUCT_PAGE select HAVE_ALIGNED_STRUCT_PAGE
select HAVE_ARCH_AUDITSYSCALL select HAVE_ARCH_AUDITSYSCALL

View File

@ -14,7 +14,6 @@ config X86_32
select ARCH_WANT_IPC_PARSE_VERSION select ARCH_WANT_IPC_PARSE_VERSION
select CLKSRC_I8253 select CLKSRC_I8253
select CLONE_BACKWARDS select CLONE_BACKWARDS
select GENERIC_VDSO_32
select HAVE_DEBUG_STACKOVERFLOW select HAVE_DEBUG_STACKOVERFLOW
select KMAP_LOCAL select KMAP_LOCAL
select MODULES_USE_ELF_REL select MODULES_USE_ELF_REL
@ -182,8 +181,6 @@ config X86
select GENERIC_SMP_IDLE_THREAD select GENERIC_SMP_IDLE_THREAD
select GENERIC_TIME_VSYSCALL select GENERIC_TIME_VSYSCALL
select GENERIC_GETTIMEOFDAY select GENERIC_GETTIMEOFDAY
select GENERIC_VDSO_DATA_STORE
select GENERIC_VDSO_TIME_NS
select GENERIC_VDSO_OVERFLOW_PROTECT select GENERIC_VDSO_OVERFLOW_PROTECT
select GUP_GET_PXX_LOW_HIGH if X86_PAE select GUP_GET_PXX_LOW_HIGH if X86_PAE
select HARDIRQS_SW_RESEND select HARDIRQS_SW_RESEND

View File

@ -4,8 +4,6 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#ifdef CONFIG_GENERIC_VDSO_DATA_STORE
#ifndef __arch_get_vdso_u_time_data #ifndef __arch_get_vdso_u_time_data
static __always_inline const struct vdso_time_data *__arch_get_vdso_u_time_data(void) static __always_inline const struct vdso_time_data *__arch_get_vdso_u_time_data(void)
{ {
@ -20,8 +18,6 @@ static __always_inline const struct vdso_rng_data *__arch_get_vdso_u_rng_data(vo
} }
#endif #endif
#endif /* CONFIG_GENERIC_VDSO_DATA_STORE */
#ifndef __arch_update_vdso_clock #ifndef __arch_update_vdso_clock
static __always_inline void __arch_update_vdso_clock(struct vdso_clock *vc) static __always_inline void __arch_update_vdso_clock(struct vdso_clock *vc)
{ {

View File

@ -31,7 +31,7 @@ struct arch_vdso_time_data {};
#if defined(CONFIG_ARCH_HAS_VDSO_ARCH_DATA) #if defined(CONFIG_ARCH_HAS_VDSO_ARCH_DATA)
#include <asm/vdso/arch_data.h> #include <asm/vdso/arch_data.h>
#elif defined(CONFIG_GENERIC_VDSO_DATA_STORE) #else
struct vdso_arch_data { struct vdso_arch_data {
/* Needed for the generic code, never actually used at runtime */ /* Needed for the generic code, never actually used at runtime */
char __unused; char __unused;
@ -164,7 +164,6 @@ struct vdso_rng_data {
* With the hidden visibility, the compiler simply generates a PC-relative * With the hidden visibility, the compiler simply generates a PC-relative
* relocation, and this is what we need. * relocation, and this is what we need.
*/ */
#ifdef CONFIG_GENERIC_VDSO_DATA_STORE
extern struct vdso_time_data vdso_u_time_data __attribute__((visibility("hidden"))); extern struct vdso_time_data vdso_u_time_data __attribute__((visibility("hidden")));
extern struct vdso_rng_data vdso_u_rng_data __attribute__((visibility("hidden"))); extern struct vdso_rng_data vdso_u_rng_data __attribute__((visibility("hidden")));
extern struct vdso_arch_data vdso_u_arch_data __attribute__((visibility("hidden"))); extern struct vdso_arch_data vdso_u_arch_data __attribute__((visibility("hidden")));
@ -185,8 +184,6 @@ enum vdso_pages {
VDSO_NR_PAGES VDSO_NR_PAGES
}; };
#endif /* CONFIG_GENERIC_VDSO_DATA_STORE */
/* /*
* The generic vDSO implementation requires that gettimeofday.h * The generic vDSO implementation requires that gettimeofday.h
* provides: * provides:
@ -196,11 +193,7 @@ enum vdso_pages {
* - clock_gettime_fallback(): fallback for clock_gettime. * - clock_gettime_fallback(): fallback for clock_gettime.
* - clock_getres_fallback(): fallback for clock_getres. * - clock_getres_fallback(): fallback for clock_getres.
*/ */
#ifdef ENABLE_COMPAT_VDSO
#include <asm/vdso/compat_gettimeofday.h>
#else
#include <asm/vdso/gettimeofday.h> #include <asm/vdso/gettimeofday.h>
#endif /* ENABLE_COMPAT_VDSO */
#else /* !__ASSEMBLY__ */ #else /* !__ASSEMBLY__ */

View File

@ -5,6 +5,7 @@
#include <linux/types.h> #include <linux/types.h>
struct __kernel_timespec; struct __kernel_timespec;
struct __kernel_old_timeval;
struct timezone; struct timezone;
#if !defined(CONFIG_64BIT) || defined(BUILD_VDSO32_64) #if !defined(CONFIG_64BIT) || defined(BUILD_VDSO32_64)

View File

@ -1363,7 +1363,7 @@ config UTS_NS
config TIME_NS config TIME_NS
bool "TIME namespace" bool "TIME namespace"
depends on GENERIC_VDSO_TIME_NS depends on GENERIC_GETTIMEOFDAY
default y default y
help help
In this namespace boottime and monotonic clocks can be set. In this namespace boottime and monotonic clocks can be set.

View File

@ -26,7 +26,7 @@ obj-$(CONFIG_LEGACY_TIMER_TICK) += tick-legacy.o
ifeq ($(CONFIG_SMP),y) ifeq ($(CONFIG_SMP),y)
obj-$(CONFIG_NO_HZ_COMMON) += timer_migration.o obj-$(CONFIG_NO_HZ_COMMON) += timer_migration.o
endif endif
obj-$(CONFIG_HAVE_GENERIC_VDSO) += vsyscall.o obj-$(CONFIG_GENERIC_GETTIMEOFDAY) += vsyscall.o
obj-$(CONFIG_DEBUG_FS) += timekeeping_debug.o obj-$(CONFIG_DEBUG_FS) += timekeeping_debug.o
obj-$(CONFIG_TEST_UDELAY) += test_udelay.o obj-$(CONFIG_TEST_UDELAY) += test_udelay.o
obj-$(CONFIG_TIME_NS) += namespace.o obj-$(CONFIG_TIME_NS) += namespace.o

View File

@ -12,24 +12,6 @@ config GENERIC_GETTIMEOFDAY
Each architecture that enables this feature has to Each architecture that enables this feature has to
provide the fallback implementation. provide the fallback implementation.
config GENERIC_VDSO_32
bool
depends on GENERIC_GETTIMEOFDAY && !64BIT
help
This config option helps to avoid possible performance issues
in 32 bit only architectures.
config GENERIC_COMPAT_VDSO
bool
help
This config option enables the compat VDSO layer.
config GENERIC_VDSO_TIME_NS
bool
help
Selected by architectures which support time namespaces in the
VDSO
config GENERIC_VDSO_OVERFLOW_PROTECT config GENERIC_VDSO_OVERFLOW_PROTECT
bool bool
help help
@ -37,14 +19,9 @@ config GENERIC_VDSO_OVERFLOW_PROTECT
time getter functions for the price of an extra conditional time getter functions for the price of an extra conditional
in the hotpath. in the hotpath.
endif
config VDSO_GETRANDOM config VDSO_GETRANDOM
bool bool
help help
Selected by architectures that support vDSO getrandom(). Selected by architectures that support vDSO getrandom().
config GENERIC_VDSO_DATA_STORE endif
bool
help
Selected by architectures that use the generic vDSO data store.

View File

@ -1,3 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only # SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_GENERIC_VDSO_DATA_STORE) += datastore.o obj-$(CONFIG_HAVE_GENERIC_VDSO) += datastore.o

View File

@ -11,14 +11,14 @@
/* /*
* The vDSO data page. * The vDSO data page.
*/ */
#ifdef CONFIG_HAVE_GENERIC_VDSO #ifdef CONFIG_GENERIC_GETTIMEOFDAY
static union { static union {
struct vdso_time_data data; struct vdso_time_data data;
u8 page[PAGE_SIZE]; u8 page[PAGE_SIZE];
} vdso_time_data_store __page_aligned_data; } vdso_time_data_store __page_aligned_data;
struct vdso_time_data *vdso_k_time_data = &vdso_time_data_store.data; struct vdso_time_data *vdso_k_time_data = &vdso_time_data_store.data;
static_assert(sizeof(vdso_time_data_store) == PAGE_SIZE); static_assert(sizeof(vdso_time_data_store) == PAGE_SIZE);
#endif /* CONFIG_HAVE_GENERIC_VDSO */ #endif /* CONFIG_GENERIC_GETTIMEOFDAY */
#ifdef CONFIG_VDSO_GETRANDOM #ifdef CONFIG_VDSO_GETRANDOM
static union { static union {
@ -46,7 +46,7 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
switch (vmf->pgoff) { switch (vmf->pgoff) {
case VDSO_TIME_PAGE_OFFSET: case VDSO_TIME_PAGE_OFFSET:
if (!IS_ENABLED(CONFIG_HAVE_GENERIC_VDSO)) if (!IS_ENABLED(CONFIG_GENERIC_GETTIMEOFDAY))
return VM_FAULT_SIGBUS; return VM_FAULT_SIGBUS;
pfn = __phys_to_pfn(__pa_symbol(vdso_k_time_data)); pfn = __phys_to_pfn(__pa_symbol(vdso_k_time_data));
if (timens_page) { if (timens_page) {

View File

@ -108,15 +108,11 @@ bool vdso_get_timestamp(const struct vdso_time_data *vd, const struct vdso_clock
return true; return true;
} }
#ifdef CONFIG_TIME_NS
#ifdef CONFIG_GENERIC_VDSO_DATA_STORE
static __always_inline static __always_inline
const struct vdso_time_data *__arch_get_vdso_u_timens_data(const struct vdso_time_data *vd) const struct vdso_time_data *__arch_get_vdso_u_timens_data(const struct vdso_time_data *vd)
{ {
return (void *)vd + PAGE_SIZE; return (void *)vd + PAGE_SIZE;
} }
#endif /* CONFIG_GENERIC_VDSO_DATA_STORE */
static __always_inline static __always_inline
bool do_hres_timens(const struct vdso_time_data *vdns, const struct vdso_clock *vcns, bool do_hres_timens(const struct vdso_time_data *vdns, const struct vdso_clock *vcns,
@ -149,20 +145,6 @@ bool do_hres_timens(const struct vdso_time_data *vdns, const struct vdso_clock *
return true; return true;
} }
#else
static __always_inline
const struct vdso_time_data *__arch_get_vdso_u_timens_data(const struct vdso_time_data *vd)
{
return NULL;
}
static __always_inline
bool do_hres_timens(const struct vdso_time_data *vdns, const struct vdso_clock *vcns,
clockid_t clk, struct __kernel_timespec *ts)
{
return false;
}
#endif
static __always_inline static __always_inline
bool do_hres(const struct vdso_time_data *vd, const struct vdso_clock *vc, bool do_hres(const struct vdso_time_data *vd, const struct vdso_clock *vc,
@ -204,7 +186,6 @@ bool do_hres(const struct vdso_time_data *vd, const struct vdso_clock *vc,
return true; return true;
} }
#ifdef CONFIG_TIME_NS
static __always_inline static __always_inline
bool do_coarse_timens(const struct vdso_time_data *vdns, const struct vdso_clock *vcns, bool do_coarse_timens(const struct vdso_time_data *vdns, const struct vdso_clock *vcns,
clockid_t clk, struct __kernel_timespec *ts) clockid_t clk, struct __kernel_timespec *ts)
@ -233,14 +214,6 @@ bool do_coarse_timens(const struct vdso_time_data *vdns, const struct vdso_clock
return true; return true;
} }
#else
static __always_inline
bool do_coarse_timens(const struct vdso_time_data *vdns, const struct vdso_clock *vcns,
clockid_t clk, struct __kernel_timespec *ts)
{
return false;
}
#endif
static __always_inline static __always_inline
bool do_coarse(const struct vdso_time_data *vd, const struct vdso_clock *vc, bool do_coarse(const struct vdso_time_data *vd, const struct vdso_clock *vc,

View File

@ -4,6 +4,5 @@ CONFIG_USER_NS=y
CONFIG_PID_NS=y CONFIG_PID_NS=y
CONFIG_NET_NS=y CONFIG_NET_NS=y
CONFIG_TIME_NS=y CONFIG_TIME_NS=y
CONFIG_GENERIC_VDSO_TIME_NS=y
CONFIG_CGROUPS=y CONFIG_CGROUPS=y
CONFIG_CHECKPOINT_RESTORE=y CONFIG_CHECKPOINT_RESTORE=y

View File

@ -1,7 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only # SPDX-License-Identifier: GPL-2.0-only
vdso_test vdso_test
vdso_test_abi vdso_test_abi
vdso_test_clock_getres
vdso_test_correctness vdso_test_correctness
vdso_test_gettimeofday vdso_test_gettimeofday
vdso_test_getcpu vdso_test_getcpu

View File

@ -4,7 +4,6 @@ include ../../../scripts/Makefile.arch
TEST_GEN_PROGS := vdso_test_gettimeofday TEST_GEN_PROGS := vdso_test_gettimeofday
TEST_GEN_PROGS += vdso_test_getcpu TEST_GEN_PROGS += vdso_test_getcpu
TEST_GEN_PROGS += vdso_test_abi TEST_GEN_PROGS += vdso_test_abi
TEST_GEN_PROGS += vdso_test_clock_getres
ifeq ($(ARCH),$(filter $(ARCH),x86 x86_64)) ifeq ($(ARCH),$(filter $(ARCH),x86 x86_64))
TEST_GEN_PROGS += vdso_standalone_test_x86 TEST_GEN_PROGS += vdso_standalone_test_x86
endif endif
@ -29,7 +28,6 @@ CFLAGS_NOLIBC := -nostdlib -nostdinc -ffreestanding -fno-asynchronous-unwind-tab
$(OUTPUT)/vdso_test_gettimeofday: parse_vdso.c vdso_test_gettimeofday.c $(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_getcpu: parse_vdso.c vdso_test_getcpu.c
$(OUTPUT)/vdso_test_abi: parse_vdso.c vdso_test_abi.c $(OUTPUT)/vdso_test_abi: parse_vdso.c vdso_test_abi.c
$(OUTPUT)/vdso_test_clock_getres: vdso_test_clock_getres.c
$(OUTPUT)/vdso_standalone_test_x86: vdso_standalone_test_x86.c parse_vdso.c | headers $(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_standalone_test_x86: CFLAGS:=$(CFLAGS_NOLIBC) $(CFLAGS)

View File

@ -44,7 +44,6 @@
register long _r6 asm ("r6"); \ register long _r6 asm ("r6"); \
register long _r7 asm ("r7"); \ register long _r7 asm ("r7"); \
register long _r8 asm ("r8"); \ register long _r8 asm ("r8"); \
register long _rval asm ("r3"); \
\ \
LOADARGS_##nr(fn, args); \ LOADARGS_##nr(fn, args); \
\ \
@ -54,13 +53,13 @@
" bns+ 1f\n" \ " bns+ 1f\n" \
" neg 3, 3\n" \ " neg 3, 3\n" \
"1:" \ "1:" \
: "+r" (_r0), "=r" (_r3), "+r" (_r4), "+r" (_r5), \ : "+r" (_r0), "+r" (_r3), "+r" (_r4), "+r" (_r5), \
"+r" (_r6), "+r" (_r7), "+r" (_r8) \ "+r" (_r6), "+r" (_r7), "+r" (_r8) \
: "r" (_rval) \ : \
: "r9", "r10", "r11", "r12", "cr0", "cr1", "cr5", \ : "r9", "r10", "r11", "r12", "cr0", "cr1", "cr5", \
"cr6", "cr7", "xer", "lr", "ctr", "memory" \ "cr6", "cr7", "xer", "lr", "ctr", "memory" \
); \ ); \
_rval; \ _r3; \
}) })
#else #else

View File

@ -26,24 +26,31 @@
static const char *version; static const char *version;
static const char **name; 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_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_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 long (*vdso_clock_getres_t)(clockid_t clk_id, struct timespec *ts);
typedef time_t (*vdso_time_t)(time_t *t); typedef time_t (*vdso_time_t)(time_t *t);
const char *vdso_clock_name[12] = { static const char * const vdso_clock_name[] = {
"CLOCK_REALTIME", [CLOCK_REALTIME] = "CLOCK_REALTIME",
"CLOCK_MONOTONIC", [CLOCK_MONOTONIC] = "CLOCK_MONOTONIC",
"CLOCK_PROCESS_CPUTIME_ID", [CLOCK_PROCESS_CPUTIME_ID] = "CLOCK_PROCESS_CPUTIME_ID",
"CLOCK_THREAD_CPUTIME_ID", [CLOCK_THREAD_CPUTIME_ID] = "CLOCK_THREAD_CPUTIME_ID",
"CLOCK_MONOTONIC_RAW", [CLOCK_MONOTONIC_RAW] = "CLOCK_MONOTONIC_RAW",
"CLOCK_REALTIME_COARSE", [CLOCK_REALTIME_COARSE] = "CLOCK_REALTIME_COARSE",
"CLOCK_MONOTONIC_COARSE", [CLOCK_MONOTONIC_COARSE] = "CLOCK_MONOTONIC_COARSE",
"CLOCK_BOOTTIME", [CLOCK_BOOTTIME] = "CLOCK_BOOTTIME",
"CLOCK_REALTIME_ALARM", [CLOCK_REALTIME_ALARM] = "CLOCK_REALTIME_ALARM",
"CLOCK_BOOTTIME_ALARM", [CLOCK_BOOTTIME_ALARM] = "CLOCK_BOOTTIME_ALARM",
"CLOCK_SGI_CYCLE", [10 /* CLOCK_SGI_CYCLE */] = "CLOCK_SGI_CYCLE",
"CLOCK_TAI", [CLOCK_TAI] = "CLOCK_TAI",
}; };
static void vdso_test_gettimeofday(void) static void vdso_test_gettimeofday(void)
@ -70,6 +77,33 @@ static void vdso_test_gettimeofday(void)
} }
} }
static void vdso_test_clock_gettime64(clockid_t clk_id)
{
/* Find clock_gettime64. */
vdso_clock_gettime64_t vdso_clock_gettime64 =
(vdso_clock_gettime64_t)vdso_sym(version, name[5]);
if (!vdso_clock_gettime64) {
ksft_print_msg("Couldn't find %s\n", name[5]);
ksft_test_result_skip("%s %s\n", name[5],
vdso_clock_name[clk_id]);
return;
}
struct vdso_timespec64 ts;
long ret = VDSO_CALL(vdso_clock_gettime64, 2, clk_id, &ts);
if (ret == 0) {
ksft_print_msg("The time is %lld.%06lld\n",
(long long)ts.tv_sec, (long long)ts.tv_nsec);
ksft_test_result_pass("%s %s\n", name[5],
vdso_clock_name[clk_id]);
} else {
ksft_test_result_fail("%s %s\n", name[5],
vdso_clock_name[clk_id]);
}
}
static void vdso_test_clock_gettime(clockid_t clk_id) static void vdso_test_clock_gettime(clockid_t clk_id)
{ {
/* Find clock_gettime. */ /* Find clock_gettime. */
@ -171,23 +205,23 @@ static inline void vdso_test_clock(clockid_t clock_id)
ksft_print_msg("clock_id: %s\n", vdso_clock_name[clock_id]); ksft_print_msg("clock_id: %s\n", vdso_clock_name[clock_id]);
vdso_test_clock_gettime(clock_id); vdso_test_clock_gettime(clock_id);
vdso_test_clock_gettime64(clock_id);
vdso_test_clock_getres(clock_id); vdso_test_clock_getres(clock_id);
} }
#define VDSO_TEST_PLAN 16 #define VDSO_TEST_PLAN 29
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
unsigned long sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR); unsigned long sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR);
ksft_print_header(); ksft_print_header();
ksft_set_plan(VDSO_TEST_PLAN);
if (!sysinfo_ehdr) { if (!sysinfo_ehdr)
ksft_print_msg("AT_SYSINFO_EHDR is not present!\n"); ksft_exit_skip("AT_SYSINFO_EHDR is not present!\n");
return KSFT_SKIP;
} ksft_set_plan(VDSO_TEST_PLAN);
version = versions[VDSO_VERSION]; version = versions[VDSO_VERSION];
name = (const char **)&names[VDSO_NAMES]; name = (const char **)&names[VDSO_NAMES];
@ -198,40 +232,17 @@ int main(int argc, char **argv)
vdso_test_gettimeofday(); vdso_test_gettimeofday();
#if _POSIX_TIMERS > 0
#ifdef CLOCK_REALTIME
vdso_test_clock(CLOCK_REALTIME); vdso_test_clock(CLOCK_REALTIME);
#endif
#ifdef CLOCK_BOOTTIME
vdso_test_clock(CLOCK_BOOTTIME); vdso_test_clock(CLOCK_BOOTTIME);
#endif
#ifdef CLOCK_TAI
vdso_test_clock(CLOCK_TAI); vdso_test_clock(CLOCK_TAI);
#endif
#ifdef CLOCK_REALTIME_COARSE
vdso_test_clock(CLOCK_REALTIME_COARSE); vdso_test_clock(CLOCK_REALTIME_COARSE);
#endif
#ifdef CLOCK_MONOTONIC
vdso_test_clock(CLOCK_MONOTONIC); vdso_test_clock(CLOCK_MONOTONIC);
#endif
#ifdef CLOCK_MONOTONIC_RAW
vdso_test_clock(CLOCK_MONOTONIC_RAW); vdso_test_clock(CLOCK_MONOTONIC_RAW);
#endif
#ifdef CLOCK_MONOTONIC_COARSE
vdso_test_clock(CLOCK_MONOTONIC_COARSE); vdso_test_clock(CLOCK_MONOTONIC_COARSE);
#endif vdso_test_clock(CLOCK_PROCESS_CPUTIME_ID);
vdso_test_clock(CLOCK_THREAD_CPUTIME_ID);
#endif
vdso_test_time(); vdso_test_time();
ksft_print_cnts(); ksft_finished();
return ksft_get_fail_cnt() == 0 ? KSFT_PASS : KSFT_FAIL;
} }

View File

@ -1,123 +0,0 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
* vdso_clock_getres.c: Sample code to test clock_getres.
* Copyright (c) 2019 Arm Ltd.
*
* Compile with:
* gcc -std=gnu99 vdso_clock_getres.c
*
* Tested on ARM, ARM64, MIPS32, x86 (32-bit and 64-bit),
* Power (32-bit and 64-bit), S390x (32-bit and 64-bit).
* Might work on other architectures.
*/
#define _GNU_SOURCE
#include <elf.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/auxv.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/syscall.h>
#include "../kselftest.h"
static long syscall_clock_getres(clockid_t _clkid, struct timespec *_ts)
{
long ret;
ret = syscall(SYS_clock_getres, _clkid, _ts);
return ret;
}
const char *vdso_clock_name[12] = {
"CLOCK_REALTIME",
"CLOCK_MONOTONIC",
"CLOCK_PROCESS_CPUTIME_ID",
"CLOCK_THREAD_CPUTIME_ID",
"CLOCK_MONOTONIC_RAW",
"CLOCK_REALTIME_COARSE",
"CLOCK_MONOTONIC_COARSE",
"CLOCK_BOOTTIME",
"CLOCK_REALTIME_ALARM",
"CLOCK_BOOTTIME_ALARM",
"CLOCK_SGI_CYCLE",
"CLOCK_TAI",
};
/*
* This function calls clock_getres in vdso and by system call
* with different values for clock_id.
*
* Example of output:
*
* clock_id: CLOCK_REALTIME [PASS]
* clock_id: CLOCK_BOOTTIME [PASS]
* clock_id: CLOCK_TAI [PASS]
* clock_id: CLOCK_REALTIME_COARSE [PASS]
* clock_id: CLOCK_MONOTONIC [PASS]
* clock_id: CLOCK_MONOTONIC_RAW [PASS]
* clock_id: CLOCK_MONOTONIC_COARSE [PASS]
*/
static inline int vdso_test_clock(unsigned int clock_id)
{
struct timespec x, y;
printf("clock_id: %s", vdso_clock_name[clock_id]);
clock_getres(clock_id, &x);
syscall_clock_getres(clock_id, &y);
if ((x.tv_sec != y.tv_sec) || (x.tv_nsec != y.tv_nsec)) {
printf(" [FAIL]\n");
return KSFT_FAIL;
}
printf(" [PASS]\n");
return KSFT_PASS;
}
int main(int argc, char **argv)
{
int ret = 0;
#if _POSIX_TIMERS > 0
#ifdef CLOCK_REALTIME
ret += vdso_test_clock(CLOCK_REALTIME);
#endif
#ifdef CLOCK_BOOTTIME
ret += vdso_test_clock(CLOCK_BOOTTIME);
#endif
#ifdef CLOCK_TAI
ret += vdso_test_clock(CLOCK_TAI);
#endif
#ifdef CLOCK_REALTIME_COARSE
ret += vdso_test_clock(CLOCK_REALTIME_COARSE);
#endif
#ifdef CLOCK_MONOTONIC
ret += vdso_test_clock(CLOCK_MONOTONIC);
#endif
#ifdef CLOCK_MONOTONIC_RAW
ret += vdso_test_clock(CLOCK_MONOTONIC_RAW);
#endif
#ifdef CLOCK_MONOTONIC_COARSE
ret += vdso_test_clock(CLOCK_MONOTONIC_COARSE);
#endif
#endif
if (ret > 0)
return KSFT_FAIL;
return KSFT_PASS;
}