Commit 0b3bc335 authored by Thomas Weißschuh's avatar Thomas Weißschuh Committed by Thomas Gleixner
Browse files

arm64: vdso: Switch to generic storage implementation



The generic storage implementation provides the same features as the
custom one. However it can be shared between architectures, making
maintenance easier.

This switch also moves the random state data out of the time data page.
The currently used hardcoded __VDSO_RND_DATA_OFFSET does not take into
account changes to the time data page layout.

Co-developed-by: default avatarNam Cao <namcao@linutronix.de>
Signed-off-by: default avatarNam Cao <namcao@linutronix.de>
Signed-off-by: default avatarThomas Weißschuh <thomas.weissschuh@linutronix.de>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/all/20250204-vdso-store-rng-v3-8-13a4669dfc8c@linutronix.de
parent 365841e1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -162,6 +162,7 @@ config ARM64
	select GENERIC_SMP_IDLE_THREAD
	select GENERIC_TIME_VSYSCALL
	select GENERIC_GETTIMEOFDAY
	select GENERIC_VDSO_DATA_STORE
	select GENERIC_VDSO_TIME_NS
	select HARDIRQS_SW_RESEND
	select HAS_IOPORT
+1 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@
#ifndef __ASM_VDSO_H
#define __ASM_VDSO_H

#define __VVAR_PAGES    2
#define __VDSO_PAGES    4

#ifndef __ASSEMBLY__

+12 −24
Original line number Diff line number Diff line
@@ -104,7 +104,7 @@ int clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
}

static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
						 const struct vdso_data *vd)
						 const struct vdso_time_data *vd)
{
	u64 res;

@@ -131,43 +131,31 @@ static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
	return res;
}

static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
static __always_inline const struct vdso_time_data *__arch_get_vdso_u_time_data(void)
{
	const struct vdso_data *ret;
	const struct vdso_time_data *ret;

	/*
	 * This simply puts &_vdso_data into ret. The reason why we don't use
	 * `ret = _vdso_data` is that the compiler tends to optimise this in a
	 * very suboptimal way: instead of keeping &_vdso_data in a register,
	 * it goes through a relocation almost every time _vdso_data must be
	 * This simply puts &_vdso_time_data into ret. The reason why we don't use
	 * `ret = _vdso_time_data` is that the compiler tends to optimise this in a
	 * very suboptimal way: instead of keeping &_vdso_time_data in a register,
	 * it goes through a relocation almost every time _vdso_time_data must be
	 * accessed (even in subfunctions). This is both time and space
	 * consuming: each relocation uses a word in the code section, and it
	 * has to be loaded at runtime.
	 *
	 * This trick hides the assignment from the compiler. Since it cannot
	 * track where the pointer comes from, it will only use one relocation
	 * where __arch_get_vdso_data() is called, and then keep the result in
	 * a register.
	 * where __aarch64_get_vdso_u_time_data() is called, and then keep the
	 * result in a register.
	 */
	asm volatile("mov %0, %1" : "=r"(ret) : "r"(_vdso_data));
	asm volatile("mov %0, %1" : "=r"(ret) : "r"(vdso_u_time_data));

	return ret;
}
#define __arch_get_vdso_u_time_data __arch_get_vdso_u_time_data

#ifdef CONFIG_TIME_NS
static __always_inline
const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd)
{
	const struct vdso_data *ret;

	/* See __arch_get_vdso_data(). */
	asm volatile("mov %0, %1" : "=r"(ret) : "r"(_timens_data));

	return ret;
}
#endif

static inline bool vdso_clocksource_ok(const struct vdso_data *vd)
static inline bool vdso_clocksource_ok(const struct vdso_time_data *vd)
{
	return vd->clock_mode == VDSO_CLOCKMODE_ARCHTIMER;
}
+0 −12
Original line number Diff line number Diff line
@@ -33,18 +33,6 @@ static __always_inline ssize_t getrandom_syscall(void *_buffer, size_t _len, uns
	return ret;
}

static __always_inline const struct vdso_rng_data *__arch_get_vdso_rng_data(void)
{
	/*
	 * The RNG data is in the real VVAR data page, but if a task belongs to a time namespace
	 * then VVAR_DATA_PAGE_OFFSET points to the namespace-specific VVAR page and VVAR_TIMENS_
	 * PAGE_OFFSET points to the real VVAR page.
	 */
	if (IS_ENABLED(CONFIG_TIME_NS) && _vdso_data->clock_mode == VDSO_CLOCKMODE_TIMENS)
		return (void *)&_vdso_rng_data + VVAR_TIMENS_PAGE_OFFSET * (1UL << CONFIG_PAGE_SHIFT);
	return &_vdso_rng_data;
}

#endif /* !__ASSEMBLY__ */

#endif /* __ASM_VDSO_GETRANDOM_H */
+1 −15
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@ int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
}

static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
						 const struct vdso_data *vd)
						 const struct vdso_time_data *vd)
{
	u64 res;

@@ -99,20 +99,6 @@ static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
	return res;
}

static __always_inline
const struct vdso_data *__arch_get_vdso_data(void)
{
	return _vdso_data;
}

#ifdef CONFIG_TIME_NS
static __always_inline
const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd)
{
	return _timens_data;
}
#endif

#endif /* !__ASSEMBLY__ */

#endif /* __ASM_VDSO_GETTIMEOFDAY_H */
Loading