From nobody Thu Oct 2 12:06:46 2025 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3C80C2EBDD0; Wed, 17 Sep 2025 14:02:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758117743; cv=none; b=BQgX0iS7JVEH2Mgp4QrYUO5qkrG5XjAK2xjl7Ru1cLzGih9YCDu7ac9foZIqyYvrtsNRNeWFH0ShWBVMblKdwUltLMImthb/mjdsrmkIV63asNhQlzUzS89IaK5ShJNzyf08fiq4RzU/NHOc97OeoIeEXVwehp25q3J87NLzD8k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758117743; c=relaxed/simple; bh=uIHG8/DHTvVjzMWaCGRY2s8fX58POtYLQHdWB4svlA0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=BbDDPVhv5coL9cshq/6UHVOE/DQrQDl8IYf8VP4MbWRBgZvqyCzcsTwFgPGT9CmayLFoUOgaxHM9Z/KS2/ppB2KCGL9QtIMs4zyAymZSULkHaTqZHfyD2sPLOoK6YTFMAzCWcqPF+3ePEjEIrTgMfUmfRa672B/wRA6g+i6HDlY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=OpxthBMc; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=9MfPijRt; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="OpxthBMc"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="9MfPijRt" From: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1758117731; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=0VoRtmBbnDeAfWqXQKMVCRYa+PHhph7sAHFkF4l3tqQ=; b=OpxthBMcJQ2VmQuK5vrnz2vvOjS64QqsIeou5vFizuR1+wu1Q4kHQDNPS23Mp7Amk70OkK r1bahErOD8RQOih9N4Jku4IKKTAV6fLcm8JYfWOdSP8RsWmdpV6h0zGbMC8ivRtV5eJ4I5 0/RypX6ztGAZN92t8Qi0NIonRBEFsELsZkkucw6c0jKvA7FctWMJ8YlV4RvJ6SHY7cvQVI Nyc5AKcd+FH/EZ204lR9Oqz5VO5ptmdP4N2YtbLEVkO669pV0yHXo3qG4azHZa6WvtgBJm eH0cK0GzqP3Acb4nSGqauxUACCxr0pPfUGMi32xVH7L+UlQcpGy8DT095ePisw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1758117731; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=0VoRtmBbnDeAfWqXQKMVCRYa+PHhph7sAHFkF4l3tqQ=; b=9MfPijRtp1CYqxu7Fv0vWvhbuj4+iUhuAVOfD8K3hw9LVbz09yRhXSHo8yxbTgOTnvT10s I3o6FfMKUT0rr0Cg== Date: Wed, 17 Sep 2025 16:00:33 +0200 Subject: [PATCH v3 31/36] sparc64: vdso: Switch to the generic vDSO library Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250917-vdso-sparc64-generic-2-v3-31-3679b1bc8ee8@linutronix.de> References: <20250917-vdso-sparc64-generic-2-v3-0-3679b1bc8ee8@linutronix.de> In-Reply-To: <20250917-vdso-sparc64-generic-2-v3-0-3679b1bc8ee8@linutronix.de> To: Andy Lutomirski , Thomas Gleixner , Vincenzo Frascino , Arnd Bergmann , "David S. Miller" , Andreas Larsson , Nick Alcock , John Stultz , Stephen Boyd , John Paul Adrian Glaubitz , Shuah Khan , Catalin Marinas , Will Deacon , Theodore Ts'o , "Jason A. Donenfeld" , Russell King , Madhavan Srinivasan , Michael Ellerman , Nicholas Piggin , Christophe Leroy , Huacai Chen , WANG Xuerui , Thomas Bogendoerfer , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Christian Borntraeger , Sven Schnelle , Nagarathnam Muthusamy , Shannon Nelson Cc: linux-kernel@vger.kernel.org, sparclinux@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linuxppc-dev@lists.ozlabs.org, loongarch@lists.linux.dev, linux-mips@vger.kernel.org, linux-s390@vger.kernel.org, =?utf-8?q?Thomas_Wei=C3=9Fschuh?= X-Developer-Signature: v=1; a=ed25519-sha256; t=1758117712; l=24574; i=thomas.weissschuh@linutronix.de; s=20240209; h=from:subject:message-id; bh=uIHG8/DHTvVjzMWaCGRY2s8fX58POtYLQHdWB4svlA0=; b=Y6o9QvbqrRTxCZxJCk/cllNLBaqhmT854+3s7kQ6qjKyfT/vxbD/vZA+ugbuTx35OqCrUHKDW Xy0xDssli4nDDEguOKF+AlTnSZ7a9onb1UGvdhdH4Sxe/0i5dvIa7If X-Developer-Key: i=thomas.weissschuh@linutronix.de; a=ed25519; pk=pfvxvpFUDJV2h2nY0FidLUml22uGLSjByFbM6aqQQws= The generic vDSO provides a lot common functionality shared between different architectures. SPARC is the last architecture not using it, preventing some necessary code cleanup. Make use of the generic infrastructure. Signed-off-by: Thomas Wei=C3=9Fschuh --- arch/sparc/Kconfig | 3 +- arch/sparc/include/asm/clocksource.h | 9 -- arch/sparc/include/asm/vdso/clocksource.h | 10 ++ arch/sparc/include/asm/vdso/gettimeofday.h | 58 ++++++++-- arch/sparc/include/asm/vdso/vsyscall.h | 10 ++ arch/sparc/include/asm/vvar.h | 75 ------------- arch/sparc/kernel/Makefile | 1 - arch/sparc/kernel/time_64.c | 6 +- arch/sparc/kernel/vdso.c | 69 ------------ arch/sparc/vdso/Makefile | 6 +- arch/sparc/vdso/vclock_gettime.c | 169 ++++---------------------= ---- arch/sparc/vdso/vdso-layout.lds.S | 7 +- arch/sparc/vdso/vma.c | 70 +++--------- 13 files changed, 118 insertions(+), 375 deletions(-) diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 7b595092cbfb65bf196fdae7039be38f7d201a7a..4f973efc962391d3a1dab0bf9aa= 1ddeebf8a0c8d 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -102,7 +102,6 @@ config SPARC64 select ARCH_USE_QUEUED_RWLOCKS select ARCH_USE_QUEUED_SPINLOCKS select GENERIC_TIME_VSYSCALL - select ARCH_CLOCKSOURCE_DATA select ARCH_HAS_PTE_SPECIAL select PCI_DOMAINS if PCI select ARCH_HAS_GIGANTIC_PAGE @@ -110,6 +109,8 @@ config SPARC64 select HAVE_SETUP_PER_CPU_AREA select NEED_PER_CPU_EMBED_FIRST_CHUNK select NEED_PER_CPU_PAGE_FIRST_CHUNK + select HAVE_GENERIC_VDSO + select GENERIC_GETTIMEOFDAY =20 config ARCH_PROC_KCORE_TEXT def_bool y diff --git a/arch/sparc/include/asm/clocksource.h b/arch/sparc/include/asm/= clocksource.h index d63ef224befebd68637d0be5d19c5cbf657d590d..68303ad26eb26e99180bb71789f= 1d6fafe4a2225 100644 --- a/arch/sparc/include/asm/clocksource.h +++ b/arch/sparc/include/asm/clocksource.h @@ -5,13 +5,4 @@ #ifndef _ASM_SPARC_CLOCKSOURCE_H #define _ASM_SPARC_CLOCKSOURCE_H =20 -/* VDSO clocksources */ -#define VCLOCK_NONE 0 /* Nothing userspace can do. */ -#define VCLOCK_TICK 1 /* Use %tick. */ -#define VCLOCK_STICK 2 /* Use %stick. */ - -struct arch_clocksource_data { - int vclock_mode; -}; - #endif /* _ASM_SPARC_CLOCKSOURCE_H */ diff --git a/arch/sparc/include/asm/vdso/clocksource.h b/arch/sparc/include= /asm/vdso/clocksource.h new file mode 100644 index 0000000000000000000000000000000000000000..007aa8ceaf522ebc11b05dd46df= cdf72a328822f --- /dev/null +++ b/arch/sparc/include/asm/vdso/clocksource.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ASM_VDSO_CLOCKSOURCE_H +#define __ASM_VDSO_CLOCKSOURCE_H + +/* VDSO clocksources */ +#define VDSO_ARCH_CLOCKMODES \ + VDSO_CLOCKMODE_TICK, \ + VDSO_CLOCKMODE_STICK + +#endif /* __ASM_VDSO_CLOCKSOURCE_H */ diff --git a/arch/sparc/include/asm/vdso/gettimeofday.h b/arch/sparc/includ= e/asm/vdso/gettimeofday.h index 429dc080568f59145cc0bc696060adeb60ac177a..a35875fba45470ba961a7df3ae5= 2bc17d2a4a4a0 100644 --- a/arch/sparc/include/asm/vdso/gettimeofday.h +++ b/arch/sparc/include/asm/vdso/gettimeofday.h @@ -9,15 +9,14 @@ #include #include =20 +#include +#include +#include +#include + #include -#include =20 #ifdef CONFIG_SPARC64 -static __always_inline u64 vdso_shift_ns(u64 val, u32 amt) -{ - return val >> amt; -} - static __always_inline u64 vread_tick(void) { u64 ret; @@ -48,6 +47,7 @@ static __always_inline u64 vdso_shift_ns(u64 val, u32 amt) : "g1"); return ret; } +#define vdso_shift_ns vdso_shift_ns =20 static __always_inline u64 vread_tick(void) { @@ -70,9 +70,9 @@ static __always_inline u64 vread_tick_stick(void) } #endif =20 -static __always_inline u64 __arch_get_hw_counter(struct vvar_data *vvar) +static __always_inline u64 __arch_get_hw_counter(s32 clock_mode, const str= uct vdso_time_data *vd) { - if (likely(vvar->vclock_mode =3D=3D VCLOCK_STICK)) + if (likely(clock_mode =3D=3D VDSO_CLOCKMODE_STICK)) return vread_tick_stick(); else return vread_tick(); @@ -102,7 +102,20 @@ static __always_inline u64 __arch_get_hw_counter(struc= t vvar_data *vvar) "cc", "memory" =20 static __always_inline -long clock_gettime_fallback(clockid_t clock, struct __kernel_old_timespec = *ts) +long clock_gettime_fallback(clockid_t clock, struct __kernel_timespec *ts) +{ + register long num __asm__("g1") =3D __NR_clock_gettime; + register long o0 __asm__("o0") =3D clock; + register long o1 __asm__("o1") =3D (long) ts; + + __asm__ __volatile__(SYSCALL_STRING : "=3Dr" (o0) : "r" (num), + "0" (o0), "r" (o1) : SYSCALL_CLOBBERS); + return o0; +} + +#ifndef CONFIG_SPARC64 +static __always_inline +long clock_gettime32_fallback(clockid_t clock, struct old_timespec32 *ts) { register long num __asm__("g1") =3D __NR_clock_gettime; register long o0 __asm__("o0") =3D clock; @@ -112,6 +125,7 @@ long clock_gettime_fallback(clockid_t clock, struct __k= ernel_old_timespec *ts) "0" (o0), "r" (o1) : SYSCALL_CLOBBERS); return o0; } +#endif =20 static __always_inline long gettimeofday_fallback(struct __kernel_old_timeval *tv, struct timezon= e *tz) @@ -125,4 +139,30 @@ long gettimeofday_fallback(struct __kernel_old_timeval= *tv, struct timezone *tz) return o0; } =20 +static __always_inline const struct vdso_time_data *__arch_get_vdso_u_time= _data(void) +{ + unsigned long ret; + + /* + * SPARC does not support native PC-relative code relocations. + * Calculate the address manually, works for 32 and 64 bit code. + */ + __asm__ __volatile__( + "1:\n" + "call 3f\n" // Jump over the embedded data and set u= p %o7 + "nop\n" // Delay slot + "2:\n" + ".word vdso_u_time_data - .\n" // Embedded offset to external symbol + "3:\n" + "add %%o7, 2b - 1b, %%o7\n" // Point %o7 to the embedded offset + "ldsw [%%o7], %0\n" // Load the offset + "add %0, %%o7, %0\n" // Calculate the absolute address + : "=3Dr" (ret) + : + : "o7"); + + return (const struct vdso_time_data *)ret; +} +#define __arch_get_vdso_u_time_data __arch_get_vdso_u_time_data + #endif /* _ASM_SPARC_VDSO_GETTIMEOFDAY_H */ diff --git a/arch/sparc/include/asm/vdso/vsyscall.h b/arch/sparc/include/as= m/vdso/vsyscall.h new file mode 100644 index 0000000000000000000000000000000000000000..8bfe703fedc56f9334773b26b5e= 1ecec42781378 --- /dev/null +++ b/arch/sparc/include/asm/vdso/vsyscall.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _ASM_SPARC_VDSO_VSYSCALL_H +#define _ASM_SPARC_VDSO_VSYSCALL_H + +#define __VDSO_PAGES 4 + +#include + +#endif /* _ASM_SPARC_VDSO_VSYSCALL_H */ diff --git a/arch/sparc/include/asm/vvar.h b/arch/sparc/include/asm/vvar.h deleted file mode 100644 index 6eaf5cfcaae1319808e63884d624899895d9b6a5..000000000000000000000000000= 0000000000000 --- a/arch/sparc/include/asm/vvar.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved. - */ - -#ifndef _ASM_SPARC_VVAR_DATA_H -#define _ASM_SPARC_VVAR_DATA_H - -#include -#include -#include -#include -#include - -struct vvar_data { - unsigned int seq; - - int vclock_mode; - struct { /* extract of a clocksource struct */ - u64 cycle_last; - u64 mask; - int mult; - int shift; - } clock; - /* open coded 'struct timespec' */ - u64 wall_time_sec; - u64 wall_time_snsec; - u64 monotonic_time_snsec; - u64 monotonic_time_sec; - u64 monotonic_time_coarse_sec; - u64 monotonic_time_coarse_nsec; - u64 wall_time_coarse_sec; - u64 wall_time_coarse_nsec; - - int tz_minuteswest; - int tz_dsttime; -}; - -extern struct vvar_data *vvar_data; -extern int vdso_fix_stick; - -static inline unsigned int vvar_read_begin(const struct vvar_data *s) -{ - unsigned int ret; - -repeat: - ret =3D READ_ONCE(s->seq); - if (unlikely(ret & 1)) { - cpu_relax(); - goto repeat; - } - smp_rmb(); /* Finish all reads before we return seq */ - return ret; -} - -static inline int vvar_read_retry(const struct vvar_data *s, - unsigned int start) -{ - smp_rmb(); /* Finish all reads before checking the value of seq */ - return unlikely(s->seq !=3D start); -} - -static inline void vvar_write_begin(struct vvar_data *s) -{ - ++s->seq; - smp_wmb(); /* Makes sure that increment of seq is reflected */ -} - -static inline void vvar_write_end(struct vvar_data *s) -{ - smp_wmb(); /* Makes the value of seq current before we increment */ - ++s->seq; -} - - -#endif /* _ASM_SPARC_VVAR_DATA_H */ diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 36f2727e1445d0ea6e1c1a9ed716e04338a0c9a6..7a063cd4b6d3600e8e77efad5d6= 9ac1d9fad2f75 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -43,7 +43,6 @@ obj-$(CONFIG_SPARC32) +=3D systbls_32.o obj-y +=3D time_$(BITS).o obj-$(CONFIG_SPARC32) +=3D windows.o obj-y +=3D cpu.o -obj-$(CONFIG_SPARC64) +=3D vdso.o obj-$(CONFIG_SPARC32) +=3D devices.o obj-y +=3D ptrace_$(BITS).o obj-y +=3D unaligned_$(BITS).o diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index b32f27f929d1ab49a5aa05cde60d3b88e90928ba..87b267043ccd21b9397e316b017= f0ae3ab8585c6 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c @@ -838,14 +838,14 @@ void __init time_init_early(void) if (tlb_type =3D=3D spitfire) { if (is_hummingbird()) { init_tick_ops(&hbtick_operations); - clocksource_tick.archdata.vclock_mode =3D VCLOCK_NONE; + clocksource_tick.vdso_clock_mode =3D VDSO_CLOCKMODE_NONE; } else { init_tick_ops(&tick_operations); - clocksource_tick.archdata.vclock_mode =3D VCLOCK_TICK; + clocksource_tick.vdso_clock_mode =3D VDSO_CLOCKMODE_TICK; } } else { init_tick_ops(&stick_operations); - clocksource_tick.archdata.vclock_mode =3D VCLOCK_STICK; + clocksource_tick.vdso_clock_mode =3D VDSO_CLOCKMODE_STICK; } } =20 diff --git a/arch/sparc/kernel/vdso.c b/arch/sparc/kernel/vdso.c deleted file mode 100644 index 0e27437eb97bff16aba53b1634c7e9fa7db20b46..000000000000000000000000000= 0000000000000 --- a/arch/sparc/kernel/vdso.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2001 Andrea Arcangeli SuSE - * Copyright 2003 Andi Kleen, SuSE Labs. - * - * Thanks to hpa@transmeta.com for some useful hint. - * Special thanks to Ingo Molnar for his early experience with - * a different vsyscall implementation for Linux/IA32 and for the name. - */ - -#include -#include - -#include - -void update_vsyscall_tz(void) -{ - if (unlikely(vvar_data =3D=3D NULL)) - return; - - vvar_data->tz_minuteswest =3D sys_tz.tz_minuteswest; - vvar_data->tz_dsttime =3D sys_tz.tz_dsttime; -} - -void update_vsyscall(struct timekeeper *tk) -{ - struct vvar_data *vdata =3D vvar_data; - - if (unlikely(vdata =3D=3D NULL)) - return; - - vvar_write_begin(vdata); - vdata->vclock_mode =3D tk->tkr_mono.clock->archdata.vclock_mode; - vdata->clock.cycle_last =3D tk->tkr_mono.cycle_last; - vdata->clock.mask =3D tk->tkr_mono.mask; - vdata->clock.mult =3D tk->tkr_mono.mult; - vdata->clock.shift =3D tk->tkr_mono.shift; - - vdata->wall_time_sec =3D tk->xtime_sec; - vdata->wall_time_snsec =3D tk->tkr_mono.xtime_nsec; - - vdata->monotonic_time_sec =3D tk->xtime_sec + - tk->wall_to_monotonic.tv_sec; - vdata->monotonic_time_snsec =3D tk->tkr_mono.xtime_nsec + - (tk->wall_to_monotonic.tv_nsec << - tk->tkr_mono.shift); - - while (vdata->monotonic_time_snsec >=3D - (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift)) { - vdata->monotonic_time_snsec -=3D - ((u64)NSEC_PER_SEC) << tk->tkr_mono.shift; - vdata->monotonic_time_sec++; - } - - vdata->wall_time_coarse_sec =3D tk->xtime_sec; - vdata->wall_time_coarse_nsec =3D - (long)(tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift); - - vdata->monotonic_time_coarse_sec =3D - vdata->wall_time_coarse_sec + tk->wall_to_monotonic.tv_sec; - vdata->monotonic_time_coarse_nsec =3D - vdata->wall_time_coarse_nsec + tk->wall_to_monotonic.tv_nsec; - - while (vdata->monotonic_time_coarse_nsec >=3D NSEC_PER_SEC) { - vdata->monotonic_time_coarse_nsec -=3D NSEC_PER_SEC; - vdata->monotonic_time_coarse_sec++; - } - - vvar_write_end(vdata); -} diff --git a/arch/sparc/vdso/Makefile b/arch/sparc/vdso/Makefile index 2e911ccc9db71b2888ffc432d75ac8815ecce0f7..1822676b4ebdc2dc55ea1a9fb83= be0e25ea2cfef 100644 --- a/arch/sparc/vdso/Makefile +++ b/arch/sparc/vdso/Makefile @@ -3,6 +3,9 @@ # Building vDSO images for sparc. # =20 +# Include the generic Makefile to check the built vDSO: +include $(srctree)/lib/vdso/Makefile.include + # files to link into the vdso vobjs-y :=3D vdso-note.o vclock_gettime.o =20 @@ -105,6 +108,7 @@ $(obj)/vdso32.so.dbg: FORCE \ quiet_cmd_vdso =3D VDSO $@ cmd_vdso =3D $(LD) -nostdlib -o $@ \ $(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \ - -T $(filter %.lds,$^) $(filter %.o,$^) + -T $(filter %.lds,$^) $(filter %.o,$^); \ + $(cmd_vdso_check) =20 VDSO_LDFLAGS =3D -shared --hash-style=3Dboth --build-id=3Dsha1 -Bsymbolic = --no-undefined -z noexecstack diff --git a/arch/sparc/vdso/vclock_gettime.c b/arch/sparc/vdso/vclock_gett= ime.c index e768c0b84b3420deab2f74335892d40a5b515ee7..093a7ff4dafce1cf0af5af4c303= bef86e159858a 100644 --- a/arch/sparc/vdso/vclock_gettime.c +++ b/arch/sparc/vdso/vclock_gettime.c @@ -12,169 +12,40 @@ * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved. */ =20 -#include -#include -#include -#include -#include -#include -#include +#include +#include =20 -/* - * Compute the vvar page's address in the process address space, and retur= n it - * as a pointer to the vvar_data. - */ -notrace static __always_inline struct vvar_data *get_vvar_data(void) -{ - unsigned long ret; +#include =20 - /* - * vdso data page is the first vDSO page so grab the PC - * and move up a page to get to the data page. - */ - __asm__("rd %%pc, %0" : "=3Dr" (ret)); - ret &=3D ~(8192 - 1); - ret -=3D 8192; +#include =20 - return (struct vvar_data *) ret; -} +#include "../../../../lib/vdso/gettimeofday.c" =20 -notrace static __always_inline u64 vgetsns(struct vvar_data *vvar) +int __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *= tz) { - u64 v; - u64 cycles =3D __arch_get_hw_counter(vvar); - - v =3D (cycles - vvar->clock.cycle_last) & vvar->clock.mask; - return v * vvar->clock.mult; + return __cvdso_gettimeofday(tv, tz); } =20 -notrace static __always_inline int do_realtime(struct vvar_data *vvar, - struct __kernel_old_timespec *ts) -{ - unsigned long seq; - u64 ns; - - do { - seq =3D vvar_read_begin(vvar); - ts->tv_sec =3D vvar->wall_time_sec; - ns =3D vvar->wall_time_snsec; - ns +=3D vgetsns(vvar); - ns =3D vdso_shift_ns(ns, vvar->clock.shift); - } while (unlikely(vvar_read_retry(vvar, seq))); - - ts->tv_sec +=3D __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns); - ts->tv_nsec =3D ns; +int gettimeofday(struct __kernel_old_timeval *, struct timezone *) + __weak __alias(__vdso_gettimeofday); =20 - return 0; -} - -notrace static __always_inline int do_monotonic(struct vvar_data *vvar, - struct __kernel_old_timespec *ts) +#if defined(CONFIG_SPARC64) +int __vdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts) { - unsigned long seq; - u64 ns; - - do { - seq =3D vvar_read_begin(vvar); - ts->tv_sec =3D vvar->monotonic_time_sec; - ns =3D vvar->monotonic_time_snsec; - ns +=3D vgetsns(vvar); - ns =3D vdso_shift_ns(ns, vvar->clock.shift); - } while (unlikely(vvar_read_retry(vvar, seq))); - - ts->tv_sec +=3D __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns); - ts->tv_nsec =3D ns; - - return 0; -} - -notrace static int do_realtime_coarse(struct vvar_data *vvar, - struct __kernel_old_timespec *ts) -{ - unsigned long seq; - - do { - seq =3D vvar_read_begin(vvar); - ts->tv_sec =3D vvar->wall_time_coarse_sec; - ts->tv_nsec =3D vvar->wall_time_coarse_nsec; - } while (unlikely(vvar_read_retry(vvar, seq))); - return 0; + return __cvdso_clock_gettime(clock, ts); } =20 -notrace static int do_monotonic_coarse(struct vvar_data *vvar, - struct __kernel_old_timespec *ts) -{ - unsigned long seq; - - do { - seq =3D vvar_read_begin(vvar); - ts->tv_sec =3D vvar->monotonic_time_coarse_sec; - ts->tv_nsec =3D vvar->monotonic_time_coarse_nsec; - } while (unlikely(vvar_read_retry(vvar, seq))); +int clock_gettime(clockid_t, struct __kernel_timespec *) + __weak __alias(__vdso_clock_gettime); =20 - return 0; -} +#else =20 -notrace int -__vdso_clock_gettime(clockid_t clock, struct __kernel_old_timespec *ts) +int __vdso_clock_gettime(clockid_t clock, struct old_timespec32 *ts) { - struct vvar_data *vvd =3D get_vvar_data(); - - switch (clock) { - case CLOCK_REALTIME: - if (unlikely(vvd->vclock_mode =3D=3D VCLOCK_NONE)) - break; - return do_realtime(vvd, ts); - case CLOCK_MONOTONIC: - if (unlikely(vvd->vclock_mode =3D=3D VCLOCK_NONE)) - break; - return do_monotonic(vvd, ts); - case CLOCK_REALTIME_COARSE: - return do_realtime_coarse(vvd, ts); - case CLOCK_MONOTONIC_COARSE: - return do_monotonic_coarse(vvd, ts); - } - /* - * Unknown clock ID ? Fall back to the syscall. - */ - return clock_gettime_fallback(clock, ts); + return __cvdso_clock_gettime32(clock, ts); } -int -clock_gettime(clockid_t, struct __kernel_old_timespec *) - __attribute__((weak, alias("__vdso_clock_gettime"))); =20 -notrace int -__vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz) -{ - struct vvar_data *vvd =3D get_vvar_data(); +int clock_gettime(clockid_t, struct old_timespec32 *) + __weak __alias(__vdso_clock_gettime); =20 - if (likely(vvd->vclock_mode !=3D VCLOCK_NONE)) { - if (likely(tv !=3D NULL)) { - union tstv_t { - struct __kernel_old_timespec ts; - struct __kernel_old_timeval tv; - } *tstv =3D (union tstv_t *) tv; - do_realtime(vvd, &tstv->ts); - /* - * Assign before dividing to ensure that the division is - * done in the type of tv_usec, not tv_nsec. - * - * There cannot be > 1 billion usec in a second: - * do_realtime() has already distributed such overflow - * into tv_sec. So we can assign it to an int safely. - */ - tstv->tv.tv_usec =3D tstv->ts.tv_nsec; - tstv->tv.tv_usec /=3D 1000; - } - if (unlikely(tz !=3D NULL)) { - /* Avoid memcpy. Some old compilers fail to inline it */ - tz->tz_minuteswest =3D vvd->tz_minuteswest; - tz->tz_dsttime =3D vvd->tz_dsttime; - } - return 0; - } - return gettimeofday_fallback(tv, tz); -} -int -gettimeofday(struct __kernel_old_timeval *, struct timezone *) - __attribute__((weak, alias("__vdso_gettimeofday"))); +#endif diff --git a/arch/sparc/vdso/vdso-layout.lds.S b/arch/sparc/vdso/vdso-layou= t.lds.S index 9e0804789d11696948f11be367480b530a1f18d9..180e5d0ee07170a5dec88016a30= 4a44f87eb8d88 100644 --- a/arch/sparc/vdso/vdso-layout.lds.S +++ b/arch/sparc/vdso/vdso-layout.lds.S @@ -4,6 +4,10 @@ * This script controls its layout. */ =20 +#include +#include +#include + SECTIONS { /* @@ -13,8 +17,7 @@ SECTIONS * segment. Page size is 8192 for both 64-bit and 32-bit vdso binaries */ =20 - vvar_start =3D . -8192; - vvar_data =3D vvar_start; + VDSO_VVAR_SYMS =20 . =3D SIZEOF_HEADERS; =20 diff --git a/arch/sparc/vdso/vma.c b/arch/sparc/vdso/vma.c index 582d84e2e5ba8932f39948bb0ca2678fc8f06a10..38a664d697829b8203f0c7cd9e6= d7cc8bed4796f 100644 --- a/arch/sparc/vdso/vma.c +++ b/arch/sparc/vdso/vma.c @@ -16,17 +16,16 @@ #include #include #include +#include #include #include #include -#include #include =20 -unsigned int __read_mostly vdso_enabled =3D 1; +#include +#include =20 -static struct vm_special_mapping vvar_mapping =3D { - .name =3D "[vvar]" -}; +unsigned int __read_mostly vdso_enabled =3D 1; =20 #ifdef CONFIG_SPARC64 static struct vm_special_mapping vdso_mapping64 =3D { @@ -40,10 +39,8 @@ static struct vm_special_mapping vdso_mapping32 =3D { }; #endif =20 -struct vvar_data *vvar_data; - /* - * Allocate pages for the vdso and vvar, and copy in the vdso text from the + * Allocate pages for the vdso and copy in the vdso text from the * kernel image. */ static int __init init_vdso_image(const struct vdso_image *image, @@ -51,9 +48,8 @@ static int __init init_vdso_image(const struct vdso_image= *image, bool elf64) { int cnpages =3D (image->size) / PAGE_SIZE; - struct page *dp, **dpp =3D NULL; struct page *cp, **cpp =3D NULL; - int i, dnpages =3D 0; + int i; =20 /* * First, the vdso text. This is initialied data, an integral number of @@ -76,31 +72,6 @@ static int __init init_vdso_image(const struct vdso_imag= e *image, copy_page(page_address(cp), image->data + i * PAGE_SIZE); } =20 - /* - * Now the vvar page. This is uninitialized data. - */ - - if (vvar_data =3D=3D NULL) { - dnpages =3D (sizeof(struct vvar_data) / PAGE_SIZE) + 1; - if (WARN_ON(dnpages !=3D 1)) - goto oom; - dpp =3D kcalloc(dnpages, sizeof(struct page *), GFP_KERNEL); - vvar_mapping.pages =3D dpp; - - if (!dpp) - goto oom; - - dp =3D alloc_page(GFP_KERNEL); - if (!dp) - goto oom; - - dpp[0] =3D dp; - vvar_data =3D page_address(dp); - memset(vvar_data, 0, PAGE_SIZE); - - vvar_data->seq =3D 0; - } - return 0; oom: if (cpp !=3D NULL) { @@ -112,15 +83,6 @@ static int __init init_vdso_image(const struct vdso_ima= ge *image, vdso_mapping->pages =3D NULL; } =20 - if (dpp !=3D NULL) { - for (i =3D 0; i < dnpages; i++) { - if (dpp[i] !=3D NULL) - __free_page(dpp[i]); - } - kfree(dpp); - vvar_mapping.pages =3D NULL; - } - pr_warn("Cannot allocate vdso\n"); vdso_enabled =3D 0; return -ENOMEM; @@ -155,9 +117,12 @@ static unsigned long vdso_addr(unsigned long start, un= signed int len) return start + (offset << PAGE_SHIFT); } =20 +static_assert(VDSO_NR_PAGES =3D=3D __VDSO_PAGES); + static int map_vdso(const struct vdso_image *image, struct vm_special_mapping *vdso_mapping) { + const size_t area_size =3D image->size + VDSO_NR_PAGES * PAGE_SIZE; struct mm_struct *mm =3D current->mm; struct vm_area_struct *vma; unsigned long text_start, addr =3D 0; @@ -170,23 +135,20 @@ static int map_vdso(const struct vdso_image *image, * region is free. */ if (current->flags & PF_RANDOMIZE) { - addr =3D get_unmapped_area(NULL, 0, - image->size - image->sym_vvar_start, - 0, 0); + addr =3D get_unmapped_area(NULL, 0, area_size, 0, 0); if (IS_ERR_VALUE(addr)) { ret =3D addr; goto up_fail; } - addr =3D vdso_addr(addr, image->size - image->sym_vvar_start); + addr =3D vdso_addr(addr, area_size); } - addr =3D get_unmapped_area(NULL, addr, - image->size - image->sym_vvar_start, 0, 0); + addr =3D get_unmapped_area(NULL, addr, area_size, 0, 0); if (IS_ERR_VALUE(addr)) { ret =3D addr; goto up_fail; } =20 - text_start =3D addr - image->sym_vvar_start; + text_start =3D addr + VDSO_NR_PAGES * PAGE_SIZE; current->mm->context.vdso =3D (void __user *)text_start; =20 /* @@ -204,11 +166,7 @@ static int map_vdso(const struct vdso_image *image, goto up_fail; } =20 - vma =3D _install_special_mapping(mm, - addr, - -image->sym_vvar_start, - VM_READ|VM_MAYREAD, - &vvar_mapping); + vma =3D vdso_install_vvar_mapping(mm, addr); =20 if (IS_ERR(vma)) { ret =3D PTR_ERR(vma); --=20 2.51.0