[PATCH v14 8/9] powerpc/vdso: Switch VDSO to generic C implementation.

Christophe Leroy christophe.leroy at csgroup.eu
Fri Nov 27 00:20:47 AEDT 2020



Le 26/11/2020 à 14:10, Michael Ellerman a écrit :
> From: Christophe Leroy <christophe.leroy at csgroup.eu>
> 
> For VDSO32 on PPC64, we create a fake 32 bits config, on the same
> principle as MIPS architecture, in order to get the correct parts of
> the different asm header files.

The above is not done anymore since v13.

Christophe

> 
> With the C VDSO, the performance is slightly lower, but it is worth
> it as it will ease maintenance and evolution, and also brings clocks
> that are not supported with the ASM VDSO.
> 
> On an 8xx at 132 MHz, vdsotest with the ASM VDSO:
> gettimeofday:    vdso: 828 nsec/call
> clock-getres-realtime-coarse:    vdso: 391 nsec/call
> clock-gettime-realtime-coarse:    vdso: 614 nsec/call
> clock-getres-realtime:    vdso: 460 nsec/call
> clock-gettime-realtime:    vdso: 876 nsec/call
> clock-getres-monotonic-coarse:    vdso: 399 nsec/call
> clock-gettime-monotonic-coarse:    vdso: 691 nsec/call
> clock-getres-monotonic:    vdso: 460 nsec/call
> clock-gettime-monotonic:    vdso: 1026 nsec/call
> 
> On an 8xx at 132 MHz, vdsotest with the C VDSO:
> gettimeofday:    vdso: 955 nsec/call
> clock-getres-realtime-coarse:    vdso: 545 nsec/call
> clock-gettime-realtime-coarse:    vdso: 592 nsec/call
> clock-getres-realtime:    vdso: 545 nsec/call
> clock-gettime-realtime:    vdso: 941 nsec/call
> clock-getres-monotonic-coarse:    vdso: 545 nsec/call
> clock-gettime-monotonic-coarse:    vdso: 591 nsec/call
> clock-getres-monotonic:    vdso: 545 nsec/call
> clock-gettime-monotonic:    vdso: 940 nsec/call
> 
> It is even better for gettime with monotonic clocks.
> 
> Unsupported clocks with ASM VDSO:
> clock-gettime-boottime:    vdso: 3851 nsec/call
> clock-gettime-tai:    vdso: 3852 nsec/call
> clock-gettime-monotonic-raw:    vdso: 3396 nsec/call
> 
> Same clocks with C VDSO:
> clock-gettime-tai:    vdso: 941 nsec/call
> clock-gettime-monotonic-raw:    vdso: 1001 nsec/call
> clock-gettime-monotonic-coarse:    vdso: 591 nsec/call
> 
> On an 8321E at 333 MHz, vdsotest with the ASM VDSO:
> gettimeofday:    vdso: 220 nsec/call
> clock-getres-realtime-coarse:    vdso: 102 nsec/call
> clock-gettime-realtime-coarse:    vdso: 178 nsec/call
> clock-getres-realtime:    vdso: 129 nsec/call
> clock-gettime-realtime:    vdso: 235 nsec/call
> clock-getres-monotonic-coarse:    vdso: 105 nsec/call
> clock-gettime-monotonic-coarse:    vdso: 208 nsec/call
> clock-getres-monotonic:    vdso: 129 nsec/call
> clock-gettime-monotonic:    vdso: 274 nsec/call
> 
> On an 8321E at 333 MHz, vdsotest with the C VDSO:
> gettimeofday:    vdso: 272 nsec/call
> clock-getres-realtime-coarse:    vdso: 160 nsec/call
> clock-gettime-realtime-coarse:    vdso: 184 nsec/call
> clock-getres-realtime:    vdso: 166 nsec/call
> clock-gettime-realtime:    vdso: 281 nsec/call
> clock-getres-monotonic-coarse:    vdso: 160 nsec/call
> clock-gettime-monotonic-coarse:    vdso: 184 nsec/call
> clock-getres-monotonic:    vdso: 169 nsec/call
> clock-gettime-monotonic:    vdso: 275 nsec/call
> 
> Signed-off-by: Christophe Leroy <christophe.leroy at csgroup.eu>
> [mpe: Tweak include guards]
> Signed-off-by: Michael Ellerman <mpe at ellerman.id.au>
> Link: https://lore.kernel.org/r/ef30ff8270a96c5c3b981523cd9b4e3d89049d3d.1604426550.git.christophe.leroy@csgroup.eu
> ---
>   arch/powerpc/Kconfig                      |   2 +
>   arch/powerpc/include/asm/vdso/vsyscall.h  |  25 ++
>   arch/powerpc/include/asm/vdso_datapage.h  |  40 +--
>   arch/powerpc/kernel/asm-offsets.c         |  49 +---
>   arch/powerpc/kernel/time.c                |  91 +------
>   arch/powerpc/kernel/vdso.c                |   5 +-
>   arch/powerpc/kernel/vdso32/Makefile       |  26 +-
>   arch/powerpc/kernel/vdso32/gettimeofday.S | 291 +---------------------
>   arch/powerpc/kernel/vdso32/vdso32.lds.S   |   1 +
>   arch/powerpc/kernel/vdso64/Makefile       |  23 +-
>   arch/powerpc/kernel/vdso64/gettimeofday.S | 242 +-----------------
>   arch/powerpc/kernel/vdso64/vdso64.lds.S   |   2 +-
>   12 files changed, 106 insertions(+), 691 deletions(-)
>   create mode 100644 arch/powerpc/include/asm/vdso/vsyscall.h
> 
> v14: unchanged
> 
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index 7f4995b245a3..aad8532a718e 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -176,6 +176,7 @@ config PPC
>   	select GENERIC_STRNCPY_FROM_USER
>   	select GENERIC_STRNLEN_USER
>   	select GENERIC_TIME_VSYSCALL
> +	select GENERIC_GETTIMEOFDAY
>   	select HAVE_ARCH_AUDITSYSCALL
>   	select HAVE_ARCH_HUGE_VMAP		if PPC_BOOK3S_64 && PPC_RADIX_MMU
>   	select HAVE_ARCH_JUMP_LABEL
> @@ -206,6 +207,7 @@ config PPC
>   	select HAVE_FUNCTION_GRAPH_TRACER
>   	select HAVE_FUNCTION_TRACER
>   	select HAVE_GCC_PLUGINS			if GCC_VERSION >= 50200   # plugin support on gcc <= 5.1 is buggy on PPC
> +	select HAVE_GENERIC_VDSO
>   	select HAVE_HW_BREAKPOINT		if PERF_EVENTS && (PPC_BOOK3S || PPC_8xx)
>   	select HAVE_IDE
>   	select HAVE_IOREMAP_PROT
> diff --git a/arch/powerpc/include/asm/vdso/vsyscall.h b/arch/powerpc/include/asm/vdso/vsyscall.h
> new file mode 100644
> index 000000000000..48cf23f1e273
> --- /dev/null
> +++ b/arch/powerpc/include/asm/vdso/vsyscall.h
> @@ -0,0 +1,25 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _ASM_POWERPC_VDSO_VSYSCALL_H
> +#define _ASM_POWERPC_VDSO_VSYSCALL_H
> +
> +#ifndef __ASSEMBLY__
> +
> +#include <linux/timekeeper_internal.h>
> +#include <asm/vdso_datapage.h>
> +
> +/*
> + * Update the vDSO data page to keep in sync with kernel timekeeping.
> + */
> +static __always_inline
> +struct vdso_data *__arch_get_k_vdso_data(void)
> +{
> +	return vdso_data->data;
> +}
> +#define __arch_get_k_vdso_data __arch_get_k_vdso_data
> +
> +/* The asm-generic header needs to be included after the definitions above */
> +#include <asm-generic/vdso/vsyscall.h>
> +
> +#endif /* !__ASSEMBLY__ */
> +
> +#endif /* _ASM_POWERPC_VDSO_VSYSCALL_H */
> diff --git a/arch/powerpc/include/asm/vdso_datapage.h b/arch/powerpc/include/asm/vdso_datapage.h
> index b9ef6cf50ea5..c4d320504d26 100644
> --- a/arch/powerpc/include/asm/vdso_datapage.h
> +++ b/arch/powerpc/include/asm/vdso_datapage.h
> @@ -36,6 +36,7 @@
>   
>   #include <linux/unistd.h>
>   #include <linux/time.h>
> +#include <vdso/datapage.h>
>   
>   #define SYSCALL_MAP_SIZE      ((NR_syscalls + 31) / 32)
>   
> @@ -45,7 +46,7 @@
>   
>   #ifdef CONFIG_PPC64
>   
> -struct vdso_data {
> +struct vdso_arch_data {
>   	__u8  eye_catcher[16];		/* Eyecatcher: SYSTEMCFG:PPC64	0x00 */
>   	struct {			/* Systemcfg version numbers	     */
>   		__u32 major;		/* Major number			0x10 */
> @@ -59,13 +60,13 @@ struct vdso_data {
>   	__u32 processor;		/* Processor type		0x1C */
>   	__u64 processorCount;		/* # of physical processors	0x20 */
>   	__u64 physicalMemorySize;	/* Size of real memory(B)	0x28 */
> -	__u64 tb_orig_stamp;		/* Timebase at boot		0x30 */
> +	__u64 tb_orig_stamp;		/* (NU) Timebase at boot	0x30 */
>   	__u64 tb_ticks_per_sec;		/* Timebase tics / sec		0x38 */
> -	__u64 tb_to_xs;			/* Inverse of TB to 2^20	0x40 */
> -	__u64 stamp_xsec;		/*				0x48 */
> -	__u64 tb_update_count;		/* Timebase atomicity ctr	0x50 */
> -	__u32 tz_minuteswest;		/* Minutes west of Greenwich	0x58 */
> -	__u32 tz_dsttime;		/* Type of dst correction	0x5C */
> +	__u64 tb_to_xs;			/* (NU) Inverse of TB to 2^20	0x40 */
> +	__u64 stamp_xsec;		/* (NU)				0x48 */
> +	__u64 tb_update_count;		/* (NU) Timebase atomicity ctr	0x50 */
> +	__u32 tz_minuteswest;		/* (NU) Min. west of Greenwich	0x58 */
> +	__u32 tz_dsttime;		/* (NU) Type of dst correction	0x5C */
>   	__u32 dcache_size;		/* L1 d-cache size		0x60 */
>   	__u32 dcache_line_size;		/* L1 d-cache line size		0x64 */
>   	__u32 icache_size;		/* L1 i-cache size		0x68 */
> @@ -78,14 +79,10 @@ struct vdso_data {
>   	__u32 icache_block_size;		/* L1 i-cache block size     */
>   	__u32 dcache_log_block_size;		/* L1 d-cache log block size */
>   	__u32 icache_log_block_size;		/* L1 i-cache log block size */
> -	__u32 stamp_sec_fraction;		/* fractional seconds of stamp_xtime */
> -	__s32 wtom_clock_nsec;			/* Wall to monotonic clock nsec */
> -	__s64 wtom_clock_sec;			/* Wall to monotonic clock sec */
> -	__s64 stamp_xtime_sec;			/* xtime secs as at tb_orig_stamp */
> -	__s64 stamp_xtime_nsec;			/* xtime nsecs as at tb_orig_stamp */
> -	__u32 hrtimer_res;			/* hrtimer resolution */
>      	__u32 syscall_map_64[SYSCALL_MAP_SIZE]; /* map of syscalls  */
>      	__u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */
> +
> +	struct vdso_data data[CS_BASES];
>   };
>   
>   #else /* CONFIG_PPC64 */
> @@ -93,26 +90,15 @@ struct vdso_data {
>   /*
>    * And here is the simpler 32 bits version
>    */
> -struct vdso_data {
> -	__u64 tb_orig_stamp;		/* Timebase at boot		0x30 */
> +struct vdso_arch_data {
>   	__u64 tb_ticks_per_sec;		/* Timebase tics / sec		0x38 */
> -	__u64 tb_to_xs;			/* Inverse of TB to 2^20	0x40 */
> -	__u64 stamp_xsec;		/*				0x48 */
> -	__u32 tb_update_count;		/* Timebase atomicity ctr	0x50 */
> -	__u32 tz_minuteswest;		/* Minutes west of Greenwich	0x58 */
> -	__u32 tz_dsttime;		/* Type of dst correction	0x5C */
> -	__s32 wtom_clock_sec;			/* Wall to monotonic clock */
> -	__s32 wtom_clock_nsec;
> -	__s32 stamp_xtime_sec;		/* xtime seconds as at tb_orig_stamp */
> -	__s32 stamp_xtime_nsec;		/* xtime nsecs as at tb_orig_stamp */
> -	__u32 stamp_sec_fraction;	/* fractional seconds of stamp_xtime */
> -	__u32 hrtimer_res;		/* hrtimer resolution */
>      	__u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */
> +	struct vdso_data data[CS_BASES];
>   };
>   
>   #endif /* CONFIG_PPC64 */
>   
> -extern struct vdso_data *vdso_data;
> +extern struct vdso_arch_data *vdso_data;
>   
>   #else /* __ASSEMBLY__ */
>   
> diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
> index c2722ff36e98..a2dcb8ed79b9 100644
> --- a/arch/powerpc/kernel/asm-offsets.c
> +++ b/arch/powerpc/kernel/asm-offsets.c
> @@ -398,47 +398,16 @@ int main(void)
>   #endif /* ! CONFIG_PPC64 */
>   
>   	/* datapage offsets for use by vdso */
> -	OFFSET(CFG_TB_ORIG_STAMP, vdso_data, tb_orig_stamp);
> -	OFFSET(CFG_TB_TICKS_PER_SEC, vdso_data, tb_ticks_per_sec);
> -	OFFSET(CFG_TB_TO_XS, vdso_data, tb_to_xs);
> -	OFFSET(CFG_TB_UPDATE_COUNT, vdso_data, tb_update_count);
> -	OFFSET(CFG_TZ_MINUTEWEST, vdso_data, tz_minuteswest);
> -	OFFSET(CFG_TZ_DSTTIME, vdso_data, tz_dsttime);
> -	OFFSET(CFG_SYSCALL_MAP32, vdso_data, syscall_map_32);
> -	OFFSET(WTOM_CLOCK_SEC, vdso_data, wtom_clock_sec);
> -	OFFSET(WTOM_CLOCK_NSEC, vdso_data, wtom_clock_nsec);
> -	OFFSET(STAMP_XTIME_SEC, vdso_data, stamp_xtime_sec);
> -	OFFSET(STAMP_XTIME_NSEC, vdso_data, stamp_xtime_nsec);
> -	OFFSET(STAMP_SEC_FRAC, vdso_data, stamp_sec_fraction);
> -	OFFSET(CLOCK_HRTIMER_RES, vdso_data, hrtimer_res);
> +	OFFSET(VDSO_DATA_OFFSET, vdso_arch_data, data);
> +	OFFSET(CFG_TB_TICKS_PER_SEC, vdso_arch_data, tb_ticks_per_sec);
> +	OFFSET(CFG_SYSCALL_MAP32, vdso_arch_data, syscall_map_32);
>   #ifdef CONFIG_PPC64
> -	OFFSET(CFG_ICACHE_BLOCKSZ, vdso_data, icache_block_size);
> -	OFFSET(CFG_DCACHE_BLOCKSZ, vdso_data, dcache_block_size);
> -	OFFSET(CFG_ICACHE_LOGBLOCKSZ, vdso_data, icache_log_block_size);
> -	OFFSET(CFG_DCACHE_LOGBLOCKSZ, vdso_data, dcache_log_block_size);
> -	OFFSET(CFG_SYSCALL_MAP64, vdso_data, syscall_map_64);
> -	OFFSET(TVAL64_TV_SEC, __kernel_old_timeval, tv_sec);
> -	OFFSET(TVAL64_TV_USEC, __kernel_old_timeval, tv_usec);
> -#endif
> -	OFFSET(TSPC64_TV_SEC, __kernel_timespec, tv_sec);
> -	OFFSET(TSPC64_TV_NSEC, __kernel_timespec, tv_nsec);
> -	OFFSET(TVAL32_TV_SEC, old_timeval32, tv_sec);
> -	OFFSET(TVAL32_TV_USEC, old_timeval32, tv_usec);
> -	OFFSET(TSPC32_TV_SEC, old_timespec32, tv_sec);
> -	OFFSET(TSPC32_TV_NSEC, old_timespec32, tv_nsec);
> -	/* timeval/timezone offsets for use by vdso */
> -	OFFSET(TZONE_TZ_MINWEST, timezone, tz_minuteswest);
> -	OFFSET(TZONE_TZ_DSTTIME, timezone, tz_dsttime);
> -
> -	/* Other bits used by the vdso */
> -	DEFINE(CLOCK_REALTIME, CLOCK_REALTIME);
> -	DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC);
> -	DEFINE(CLOCK_REALTIME_COARSE, CLOCK_REALTIME_COARSE);
> -	DEFINE(CLOCK_MONOTONIC_COARSE, CLOCK_MONOTONIC_COARSE);
> -	DEFINE(CLOCK_MAX, CLOCK_TAI);
> -	DEFINE(NSEC_PER_SEC, NSEC_PER_SEC);
> -	DEFINE(EINVAL, EINVAL);
> -	DEFINE(KTIME_LOW_RES, KTIME_LOW_RES);
> +	OFFSET(CFG_ICACHE_BLOCKSZ, vdso_arch_data, icache_block_size);
> +	OFFSET(CFG_DCACHE_BLOCKSZ, vdso_arch_data, dcache_block_size);
> +	OFFSET(CFG_ICACHE_LOGBLOCKSZ, vdso_arch_data, icache_log_block_size);
> +	OFFSET(CFG_DCACHE_LOGBLOCKSZ, vdso_arch_data, dcache_log_block_size);
> +	OFFSET(CFG_SYSCALL_MAP64, vdso_arch_data, syscall_map_64);
> +#endif
>   
>   #ifdef CONFIG_BUG
>   	DEFINE(BUG_ENTRY_SIZE, sizeof(struct bug_entry));
> diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
> index 74efe46f5532..92481463f9dc 100644
> --- a/arch/powerpc/kernel/time.c
> +++ b/arch/powerpc/kernel/time.c
> @@ -82,6 +82,7 @@ static struct clocksource clocksource_timebase = {
>   	.flags        = CLOCK_SOURCE_IS_CONTINUOUS,
>   	.mask         = CLOCKSOURCE_MASK(64),
>   	.read         = timebase_read,
> +	.vdso_clock_mode	= VDSO_CLOCKMODE_ARCHTIMER,
>   };
>   
>   #define DECREMENTER_DEFAULT_MAX 0x7FFFFFFF
> @@ -831,95 +832,6 @@ static notrace u64 timebase_read(struct clocksource *cs)
>   	return (u64)get_tb();
>   }
>   
> -
> -void update_vsyscall(struct timekeeper *tk)
> -{
> -	struct timespec64 xt;
> -	struct clocksource *clock = tk->tkr_mono.clock;
> -	u32 mult = tk->tkr_mono.mult;
> -	u32 shift = tk->tkr_mono.shift;
> -	u64 cycle_last = tk->tkr_mono.cycle_last;
> -	u64 new_tb_to_xs, new_stamp_xsec;
> -	u64 frac_sec;
> -
> -	if (clock != &clocksource_timebase)
> -		return;
> -
> -	xt.tv_sec = tk->xtime_sec;
> -	xt.tv_nsec = (long)(tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift);
> -
> -	/* Make userspace gettimeofday spin until we're done. */
> -	++vdso_data->tb_update_count;
> -	smp_mb();
> -
> -	/*
> -	 * This computes ((2^20 / 1e9) * mult) >> shift as a
> -	 * 0.64 fixed-point fraction.
> -	 * The computation in the else clause below won't overflow
> -	 * (as long as the timebase frequency is >= 1.049 MHz)
> -	 * but loses precision because we lose the low bits of the constant
> -	 * in the shift.  Note that 19342813113834067 ~= 2^(20+64) / 1e9.
> -	 * For a shift of 24 the error is about 0.5e-9, or about 0.5ns
> -	 * over a second.  (Shift values are usually 22, 23 or 24.)
> -	 * For high frequency clocks such as the 512MHz timebase clock
> -	 * on POWER[6789], the mult value is small (e.g. 32768000)
> -	 * and so we can shift the constant by 16 initially
> -	 * (295147905179 ~= 2^(20+64-16) / 1e9) and then do the
> -	 * remaining shifts after the multiplication, which gives a
> -	 * more accurate result (e.g. with mult = 32768000, shift = 24,
> -	 * the error is only about 1.2e-12, or 0.7ns over 10 minutes).
> -	 */
> -	if (mult <= 62500000 && clock->shift >= 16)
> -		new_tb_to_xs = ((u64) mult * 295147905179ULL) >> (clock->shift - 16);
> -	else
> -		new_tb_to_xs = (u64) mult * (19342813113834067ULL >> clock->shift);
> -
> -	/*
> -	 * Compute the fractional second in units of 2^-32 seconds.
> -	 * The fractional second is tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift
> -	 * in nanoseconds, so multiplying that by 2^32 / 1e9 gives
> -	 * it in units of 2^-32 seconds.
> -	 * We assume shift <= 32 because clocks_calc_mult_shift()
> -	 * generates shift values in the range 0 - 32.
> -	 */
> -	frac_sec = tk->tkr_mono.xtime_nsec << (32 - shift);
> -	do_div(frac_sec, NSEC_PER_SEC);
> -
> -	/*
> -	 * Work out new stamp_xsec value for any legacy users of systemcfg.
> -	 * stamp_xsec is in units of 2^-20 seconds.
> -	 */
> -	new_stamp_xsec = frac_sec >> 12;
> -	new_stamp_xsec += tk->xtime_sec * XSEC_PER_SEC;
> -
> -	/*
> -	 * tb_update_count is used to allow the userspace gettimeofday code
> -	 * to assure itself that it sees a consistent view of the tb_to_xs and
> -	 * stamp_xsec variables.  It reads the tb_update_count, then reads
> -	 * tb_to_xs and stamp_xsec and then reads tb_update_count again.  If
> -	 * the two values of tb_update_count match and are even then the
> -	 * tb_to_xs and stamp_xsec values are consistent.  If not, then it
> -	 * loops back and reads them again until this criteria is met.
> -	 */
> -	vdso_data->tb_orig_stamp = cycle_last;
> -	vdso_data->stamp_xsec = new_stamp_xsec;
> -	vdso_data->tb_to_xs = new_tb_to_xs;
> -	vdso_data->wtom_clock_sec = tk->wall_to_monotonic.tv_sec;
> -	vdso_data->wtom_clock_nsec = tk->wall_to_monotonic.tv_nsec;
> -	vdso_data->stamp_xtime_sec = xt.tv_sec;
> -	vdso_data->stamp_xtime_nsec = xt.tv_nsec;
> -	vdso_data->stamp_sec_fraction = frac_sec;
> -	vdso_data->hrtimer_res = hrtimer_resolution;
> -	smp_wmb();
> -	++(vdso_data->tb_update_count);
> -}
> -
> -void update_vsyscall_tz(void)
> -{
> -	vdso_data->tz_minuteswest = sys_tz.tz_minuteswest;
> -	vdso_data->tz_dsttime = sys_tz.tz_dsttime;
> -}
> -
>   static void __init clocksource_init(void)
>   {
>   	struct clocksource *clock = &clocksource_timebase;
> @@ -1079,7 +991,6 @@ void __init time_init(void)
>   		sys_tz.tz_dsttime = 0;
>   	}
>   
> -	vdso_data->tb_update_count = 0;
>   	vdso_data->tb_ticks_per_sec = tb_ticks_per_sec;
>   
>   	/* initialise and enable the large decrementer (if we have one) */
> diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
> index 8dad44262e75..23208a051af5 100644
> --- a/arch/powerpc/kernel/vdso.c
> +++ b/arch/powerpc/kernel/vdso.c
> @@ -17,6 +17,7 @@
>   #include <linux/elf.h>
>   #include <linux/security.h>
>   #include <linux/memblock.h>
> +#include <vdso/datapage.h>
>   
>   #include <asm/processor.h>
>   #include <asm/mmu.h>
> @@ -70,10 +71,10 @@ static int vdso_ready;
>    * with it, it will become dynamically allocated
>    */
>   static union {
> -	struct vdso_data	data;
> +	struct vdso_arch_data	data;
>   	u8			page[PAGE_SIZE];
>   } vdso_data_store __page_aligned_data;
> -struct vdso_data *vdso_data = &vdso_data_store.data;
> +struct vdso_arch_data *vdso_data = &vdso_data_store.data;
>   
>   /* Format of the patch table */
>   struct vdso_patch_def
> diff --git a/arch/powerpc/kernel/vdso32/Makefile b/arch/powerpc/kernel/vdso32/Makefile
> index 73eada6bc8cd..853545a19a1e 100644
> --- a/arch/powerpc/kernel/vdso32/Makefile
> +++ b/arch/powerpc/kernel/vdso32/Makefile
> @@ -2,8 +2,20 @@
>   
>   # List of files in the vdso, has to be asm only for now
>   
> +ARCH_REL_TYPE_ABS := R_PPC_JUMP_SLOT|R_PPC_GLOB_DAT|R_PPC_ADDR32|R_PPC_ADDR24|R_PPC_ADDR16|R_PPC_ADDR16_LO|R_PPC_ADDR16_HI|R_PPC_ADDR16_HA|R_PPC_ADDR14|R_PPC_ADDR14_BRTAKEN|R_PPC_ADDR14_BRNTAKEN
> +include $(srctree)/lib/vdso/Makefile
> +
>   obj-vdso32 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o getcpu.o
>   
> +ifneq ($(c-gettimeofday-y),)
> +  CFLAGS_vgettimeofday.o += -include $(c-gettimeofday-y)
> +  CFLAGS_vgettimeofday.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
> +  CFLAGS_vgettimeofday.o += $(call cc-option, -fno-stack-protector)
> +  CFLAGS_vgettimeofday.o += -DDISABLE_BRANCH_PROFILING
> +  CFLAGS_vgettimeofday.o += -ffreestanding -fasynchronous-unwind-tables
> +  CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE)
> +endif
> +
>   # Build rules
>   
>   ifdef CROSS32_COMPILE
> @@ -15,6 +27,7 @@ endif
>   CC32FLAGS :=
>   ifdef CONFIG_PPC64
>   CC32FLAGS += -m32
> +KBUILD_CFLAGS := $(filter-out -mcmodel=medium,$(KBUILD_CFLAGS))
>   endif
>   
>   targets := $(obj-vdso32) vdso32.so vdso32.so.dbg
> @@ -23,6 +36,7 @@ obj-vdso32 := $(addprefix $(obj)/, $(obj-vdso32))
>   GCOV_PROFILE := n
>   KCOV_INSTRUMENT := n
>   UBSAN_SANITIZE := n
> +KASAN_SANITIZE := n
>   
>   ccflags-y := -shared -fno-common -fno-builtin -nostdlib \
>   	-Wl,-soname=linux-vdso32.so.1 -Wl,--hash-style=both
> @@ -36,8 +50,8 @@ CPPFLAGS_vdso32.lds += -P -C -Upowerpc
>   $(obj)/vdso32_wrapper.o : $(obj)/vdso32.so
>   
>   # link rule for the .so file, .lds has to be first
> -$(obj)/vdso32.so.dbg: $(src)/vdso32.lds $(obj-vdso32) FORCE
> -	$(call if_changed,vdso32ld)
> +$(obj)/vdso32.so.dbg: $(src)/vdso32.lds $(obj-vdso32) $(obj)/vgettimeofday.o FORCE
> +	$(call if_changed,vdso32ld_and_check)
>   
>   # strip rule for the .so file
>   $(obj)/%.so: OBJCOPYFLAGS := -S
> @@ -47,12 +61,16 @@ $(obj)/%.so: $(obj)/%.so.dbg FORCE
>   # assembly rules for the .S files
>   $(obj-vdso32): %.o: %.S FORCE
>   	$(call if_changed_dep,vdso32as)
> +$(obj)/vgettimeofday.o: %.o: %.c FORCE
> +	$(call if_changed_dep,vdso32cc)
>   
>   # actual build commands
> -quiet_cmd_vdso32ld = VDSO32L $@
> -      cmd_vdso32ld = $(VDSOCC) $(c_flags) $(CC32FLAGS) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^)
> +quiet_cmd_vdso32ld_and_check = VDSO32L $@
> +      cmd_vdso32ld_and_check = $(VDSOCC) $(c_flags) $(CC32FLAGS) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^) ; $(cmd_vdso_check)
>   quiet_cmd_vdso32as = VDSO32A $@
>         cmd_vdso32as = $(VDSOCC) $(a_flags) $(CC32FLAGS) -c -o $@ $<
> +quiet_cmd_vdso32cc = VDSO32C $@
> +      cmd_vdso32cc = $(VDSOCC) $(c_flags) $(CC32FLAGS) -c -o $@ $<
>   
>   # install commands for the unstripped file
>   quiet_cmd_vdso_install = INSTALL $@
> diff --git a/arch/powerpc/kernel/vdso32/gettimeofday.S b/arch/powerpc/kernel/vdso32/gettimeofday.S
> index e7f8f9f1b3f4..fd7b01c51281 100644
> --- a/arch/powerpc/kernel/vdso32/gettimeofday.S
> +++ b/arch/powerpc/kernel/vdso32/gettimeofday.S
> @@ -12,13 +12,7 @@
>   #include <asm/vdso_datapage.h>
>   #include <asm/asm-offsets.h>
>   #include <asm/unistd.h>
> -
> -/* Offset for the low 32-bit part of a field of long type */
> -#ifdef CONFIG_PPC64
> -#define LOPART	4
> -#else
> -#define LOPART	0
> -#endif
> +#include <asm/vdso/gettimeofday.h>
>   
>   	.text
>   /*
> @@ -28,32 +22,7 @@
>    *
>    */
>   V_FUNCTION_BEGIN(__kernel_gettimeofday)
> -  .cfi_startproc
> -	mflr	r12
> -  .cfi_register lr,r12
> -
> -	mr.	r10,r3			/* r10 saves tv */
> -	mr	r11,r4			/* r11 saves tz */
> -	get_datapage	r9, r0
> -	beq	3f
> -	LOAD_REG_IMMEDIATE(r7, 1000000)	/* load up USEC_PER_SEC */
> -	bl	__do_get_tspec at local	/* get sec/usec from tb & kernel */
> -	stw	r3,TVAL32_TV_SEC(r10)
> -	stw	r4,TVAL32_TV_USEC(r10)
> -
> -3:	cmplwi	r11,0			/* check if tz is NULL */
> -	mtlr	r12
> -	crclr	cr0*4+so
> -	li	r3,0
> -	beqlr
> -
> -	lwz	r4,CFG_TZ_MINUTEWEST(r9)/* fill tz */
> -	lwz	r5,CFG_TZ_DSTTIME(r9)
> -	stw	r4,TZONE_TZ_MINWEST(r11)
> -	stw	r5,TZONE_TZ_DSTTIME(r11)
> -
> -	blr
> -  .cfi_endproc
> +	cvdso_call __c_kernel_gettimeofday
>   V_FUNCTION_END(__kernel_gettimeofday)
>   
>   /*
> @@ -63,127 +32,7 @@ V_FUNCTION_END(__kernel_gettimeofday)
>    *
>    */
>   V_FUNCTION_BEGIN(__kernel_clock_gettime)
> -  .cfi_startproc
> -	/* Check for supported clock IDs */
> -	cmpli	cr0,r3,CLOCK_REALTIME
> -	cmpli	cr1,r3,CLOCK_MONOTONIC
> -	cror	cr0*4+eq,cr0*4+eq,cr1*4+eq
> -
> -	cmpli	cr5,r3,CLOCK_REALTIME_COARSE
> -	cmpli	cr6,r3,CLOCK_MONOTONIC_COARSE
> -	cror	cr5*4+eq,cr5*4+eq,cr6*4+eq
> -
> -	cror	cr0*4+eq,cr0*4+eq,cr5*4+eq
> -	bne	cr0, .Lgettime_fallback
> -
> -	mflr	r12			/* r12 saves lr */
> -  .cfi_register lr,r12
> -	mr	r11,r4			/* r11 saves tp */
> -	get_datapage	r9, r0
> -	LOAD_REG_IMMEDIATE(r7, NSEC_PER_SEC)	/* load up NSEC_PER_SEC */
> -	beq	cr5, .Lcoarse_clocks
> -.Lprecise_clocks:
> -	bl	__do_get_tspec at local	/* get sec/nsec from tb & kernel */
> -	bne	cr1, .Lfinish		/* not monotonic -> all done */
> -
> -	/*
> -	 * CLOCK_MONOTONIC
> -	 */
> -
> -	/* now we must fixup using wall to monotonic. We need to snapshot
> -	 * that value and do the counter trick again. Fortunately, we still
> -	 * have the counter value in r8 that was returned by __do_get_xsec.
> -	 * At this point, r3,r4 contain our sec/nsec values, r5 and r6
> -	 * can be used, r7 contains NSEC_PER_SEC.
> -	 */
> -
> -	lwz	r5,(WTOM_CLOCK_SEC+LOPART)(r9)
> -	lwz	r6,WTOM_CLOCK_NSEC(r9)
> -
> -	/* We now have our offset in r5,r6. We create a fake dependency
> -	 * on that value and re-check the counter
> -	 */
> -	or	r0,r6,r5
> -	xor	r0,r0,r0
> -	add	r9,r9,r0
> -	lwz	r0,(CFG_TB_UPDATE_COUNT+LOPART)(r9)
> -        cmpl    cr0,r8,r0		/* check if updated */
> -	bne-	.Lprecise_clocks
> -	b	.Lfinish_monotonic
> -
> -	/*
> -	 * For coarse clocks we get data directly from the vdso data page, so
> -	 * we don't need to call __do_get_tspec, but we still need to do the
> -	 * counter trick.
> -	 */
> -.Lcoarse_clocks:
> -	lwz	r8,(CFG_TB_UPDATE_COUNT+LOPART)(r9)
> -	andi.	r0,r8,1                 /* pending update ? loop */
> -	bne-	.Lcoarse_clocks
> -	add	r9,r9,r0		/* r0 is already 0 */
> -
> -	/*
> -	 * CLOCK_REALTIME_COARSE, below values are needed for MONOTONIC_COARSE
> -	 * too
> -	 */
> -	lwz	r3,STAMP_XTIME_SEC+LOPART(r9)
> -	lwz	r4,STAMP_XTIME_NSEC+LOPART(r9)
> -	bne	cr6,1f
> -
> -	/* CLOCK_MONOTONIC_COARSE */
> -	lwz	r5,(WTOM_CLOCK_SEC+LOPART)(r9)
> -	lwz	r6,WTOM_CLOCK_NSEC(r9)
> -
> -	/* check if counter has updated */
> -	or	r0,r6,r5
> -1:	or	r0,r0,r3
> -	or	r0,r0,r4
> -	xor	r0,r0,r0
> -	add	r3,r3,r0
> -	lwz	r0,CFG_TB_UPDATE_COUNT+LOPART(r9)
> -	cmpl	cr0,r0,r8               /* check if updated */
> -	bne-	.Lcoarse_clocks
> -
> -	/* Counter has not updated, so continue calculating proper values for
> -	 * sec and nsec if monotonic coarse, or just return with the proper
> -	 * values for realtime.
> -	 */
> -	bne	cr6, .Lfinish
> -
> -	/* Calculate and store result. Note that this mimics the C code,
> -	 * which may cause funny results if nsec goes negative... is that
> -	 * possible at all ?
> -	 */
> -.Lfinish_monotonic:
> -	add	r3,r3,r5
> -	add	r4,r4,r6
> -	cmpw	cr0,r4,r7
> -	cmpwi	cr1,r4,0
> -	blt	1f
> -	subf	r4,r7,r4
> -	addi	r3,r3,1
> -1:	bge	cr1, .Lfinish
> -	addi	r3,r3,-1
> -	add	r4,r4,r7
> -
> -.Lfinish:
> -	stw	r3,TSPC32_TV_SEC(r11)
> -	stw	r4,TSPC32_TV_NSEC(r11)
> -
> -	mtlr	r12
> -	crclr	cr0*4+so
> -	li	r3,0
> -	blr
> -
> -	/*
> -	 * syscall fallback
> -	 */
> -.Lgettime_fallback:
> -	li	r0,__NR_clock_gettime
> -  .cfi_restore lr
> -	sc
> -	blr
> -  .cfi_endproc
> +	cvdso_call __c_kernel_clock_gettime
>   V_FUNCTION_END(__kernel_clock_gettime)
>   
>   
> @@ -194,37 +43,7 @@ V_FUNCTION_END(__kernel_clock_gettime)
>    *
>    */
>   V_FUNCTION_BEGIN(__kernel_clock_getres)
> -  .cfi_startproc
> -	/* Check for supported clock IDs */
> -	cmplwi	cr0, r3, CLOCK_MAX
> -	cmpwi	cr1, r3, CLOCK_REALTIME_COARSE
> -	cmpwi	cr7, r3, CLOCK_MONOTONIC_COARSE
> -	bgt	cr0, 99f
> -	LOAD_REG_IMMEDIATE(r5, KTIME_LOW_RES)
> -	beq	cr1, 1f
> -	beq	cr7, 1f
> -
> -	mflr	r12
> -  .cfi_register lr,r12
> -	get_datapage	r3, r0
> -	lwz	r5, CLOCK_HRTIMER_RES(r3)
> -	mtlr	r12
> -1:	li	r3,0
> -	cmpli	cr0,r4,0
> -	crclr	cr0*4+so
> -	beqlr
> -	stw	r3,TSPC32_TV_SEC(r4)
> -	stw	r5,TSPC32_TV_NSEC(r4)
> -	blr
> -
> -	/*
> -	 * syscall fallback
> -	 */
> -99:
> -	li	r0,__NR_clock_getres
> -	sc
> -	blr
> -  .cfi_endproc
> +	cvdso_call __c_kernel_clock_getres
>   V_FUNCTION_END(__kernel_clock_getres)
>   
>   
> @@ -235,105 +54,5 @@ V_FUNCTION_END(__kernel_clock_getres)
>    *
>    */
>   V_FUNCTION_BEGIN(__kernel_time)
> -  .cfi_startproc
> -	mflr	r12
> -  .cfi_register lr,r12
> -
> -	mr	r11,r3			/* r11 holds t */
> -	get_datapage	r9, r0
> -
> -	lwz	r3,STAMP_XTIME_SEC+LOPART(r9)
> -
> -	cmplwi	r11,0			/* check if t is NULL */
> -	mtlr	r12
> -	crclr	cr0*4+so
> -	beqlr
> -	stw	r3,0(r11)		/* store result at *t */
> -	blr
> -  .cfi_endproc
> +	cvdso_call_time __c_kernel_time
>   V_FUNCTION_END(__kernel_time)
> -
> -/*
> - * This is the core of clock_gettime() and gettimeofday(),
> - * it returns the current time in r3 (seconds) and r4.
> - * On entry, r7 gives the resolution of r4, either USEC_PER_SEC
> - * or NSEC_PER_SEC, giving r4 in microseconds or nanoseconds.
> - * It expects the datapage ptr in r9 and doesn't clobber it.
> - * It clobbers r0, r5 and r6.
> - * On return, r8 contains the counter value that can be reused.
> - * This clobbers cr0 but not any other cr field.
> - */
> -__do_get_tspec:
> -  .cfi_startproc
> -	/* Check for update count & load values. We use the low
> -	 * order 32 bits of the update count
> -	 */
> -1:	lwz	r8,(CFG_TB_UPDATE_COUNT+LOPART)(r9)
> -	andi.	r0,r8,1			/* pending update ? loop */
> -	bne-	1b
> -	xor	r0,r8,r8		/* create dependency */
> -	add	r9,r9,r0
> -
> -	/* Load orig stamp (offset to TB) */
> -	lwz	r5,CFG_TB_ORIG_STAMP(r9)
> -	lwz	r6,(CFG_TB_ORIG_STAMP+4)(r9)
> -
> -	/* Get a stable TB value */
> -2:	MFTBU(r3)
> -	MFTBL(r4)
> -	MFTBU(r0)
> -	cmplw	cr0,r3,r0
> -	bne-	2b
> -
> -	/* Subtract tb orig stamp and shift left 12 bits.
> -	 */
> -	subfc	r4,r6,r4
> -	subfe	r0,r5,r3
> -	slwi	r0,r0,12
> -	rlwimi.	r0,r4,12,20,31
> -	slwi	r4,r4,12
> -
> -	/*
> -	 * Load scale factor & do multiplication.
> -	 * We only use the high 32 bits of the tb_to_xs value.
> -	 * Even with a 1GHz timebase clock, the high 32 bits of
> -	 * tb_to_xs will be at least 4 million, so the error from
> -	 * ignoring the low 32 bits will be no more than 0.25ppm.
> -	 * The error will just make the clock run very very slightly
> -	 * slow until the next time the kernel updates the VDSO data,
> -	 * at which point the clock will catch up to the kernel's value,
> -	 * so there is no long-term error accumulation.
> -	 */
> -	lwz	r5,CFG_TB_TO_XS(r9)	/* load values */
> -	mulhwu	r4,r4,r5
> -	li	r3,0
> -
> -	beq+	4f			/* skip high part computation if 0 */
> -	mulhwu	r3,r0,r5
> -	mullw	r5,r0,r5
> -	addc	r4,r4,r5
> -	addze	r3,r3
> -4:
> -	/* At this point, we have seconds since the xtime stamp
> -	 * as a 32.32 fixed-point number in r3 and r4.
> -	 * Load & add the xtime stamp.
> -	 */
> -	lwz	r5,STAMP_XTIME_SEC+LOPART(r9)
> -	lwz	r6,STAMP_SEC_FRAC(r9)
> -	addc	r4,r4,r6
> -	adde	r3,r3,r5
> -
> -	/* We create a fake dependency on the result in r3/r4
> -	 * and re-check the counter
> -	 */
> -	or	r6,r4,r3
> -	xor	r0,r6,r6
> -	add	r9,r9,r0
> -	lwz	r0,(CFG_TB_UPDATE_COUNT+LOPART)(r9)
> -        cmplw	cr0,r8,r0		/* check if updated */
> -	bne-	1b
> -
> -	mulhwu	r4,r4,r7		/* convert to micro or nanoseconds */
> -
> -	blr
> -  .cfi_endproc
> diff --git a/arch/powerpc/kernel/vdso32/vdso32.lds.S b/arch/powerpc/kernel/vdso32/vdso32.lds.S
> index 7eadac74c7f9..51e9b3f3f88a 100644
> --- a/arch/powerpc/kernel/vdso32/vdso32.lds.S
> +++ b/arch/powerpc/kernel/vdso32/vdso32.lds.S
> @@ -111,6 +111,7 @@ SECTIONS
>   		*(.note.GNU-stack)
>   		*(.data .data.* .gnu.linkonce.d.* .sdata*)
>   		*(.bss .sbss .dynbss .dynsbss)
> +		*(.got1)
>   	}
>   }
>   
> diff --git a/arch/powerpc/kernel/vdso64/Makefile b/arch/powerpc/kernel/vdso64/Makefile
> index dfd34f68bfa1..4a8c5e4d25c0 100644
> --- a/arch/powerpc/kernel/vdso64/Makefile
> +++ b/arch/powerpc/kernel/vdso64/Makefile
> @@ -1,8 +1,20 @@
>   # SPDX-License-Identifier: GPL-2.0
>   # List of files in the vdso, has to be asm only for now
>   
> +ARCH_REL_TYPE_ABS := R_PPC_JUMP_SLOT|R_PPC_GLOB_DAT|R_PPC_ADDR32|R_PPC_ADDR24|R_PPC_ADDR16|R_PPC_ADDR16_LO|R_PPC_ADDR16_HI|R_PPC_ADDR16_HA|R_PPC_ADDR14|R_PPC_ADDR14_BRTAKEN|R_PPC_ADDR14_BRNTAKEN
> +include $(srctree)/lib/vdso/Makefile
> +
>   obj-vdso64 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o getcpu.o
>   
> +ifneq ($(c-gettimeofday-y),)
> +  CFLAGS_vgettimeofday.o += -include $(c-gettimeofday-y)
> +  CFLAGS_vgettimeofday.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
> +  CFLAGS_vgettimeofday.o += $(call cc-option, -fno-stack-protector)
> +  CFLAGS_vgettimeofday.o += -DDISABLE_BRANCH_PROFILING
> +  CFLAGS_vgettimeofday.o += -ffreestanding -fasynchronous-unwind-tables
> +  CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE)
> +endif
> +
>   # Build rules
>   
>   targets := $(obj-vdso64) vdso64.so vdso64.so.dbg
> @@ -11,6 +23,7 @@ obj-vdso64 := $(addprefix $(obj)/, $(obj-vdso64))
>   GCOV_PROFILE := n
>   KCOV_INSTRUMENT := n
>   UBSAN_SANITIZE := n
> +KASAN_SANITIZE := n
>   
>   ccflags-y := -shared -fno-common -fno-builtin -nostdlib \
>   	-Wl,-soname=linux-vdso64.so.1 -Wl,--hash-style=both
> @@ -20,12 +33,14 @@ obj-y += vdso64_wrapper.o
>   targets += vdso64.lds
>   CPPFLAGS_vdso64.lds += -P -C -U$(ARCH)
>   
> +$(obj)/vgettimeofday.o: %.o: %.c FORCE
> +
>   # Force dependency (incbin is bad)
>   $(obj)/vdso64_wrapper.o : $(obj)/vdso64.so
>   
>   # link rule for the .so file, .lds has to be first
> -$(obj)/vdso64.so.dbg: $(src)/vdso64.lds $(obj-vdso64) FORCE
> -	$(call if_changed,vdso64ld)
> +$(obj)/vdso64.so.dbg: $(src)/vdso64.lds $(obj-vdso64) $(obj)/vgettimeofday.o FORCE
> +	$(call if_changed,vdso64ld_and_check)
>   
>   # strip rule for the .so file
>   $(obj)/%.so: OBJCOPYFLAGS := -S
> @@ -33,8 +48,8 @@ $(obj)/%.so: $(obj)/%.so.dbg FORCE
>   	$(call if_changed,objcopy)
>   
>   # actual build commands
> -quiet_cmd_vdso64ld = VDSO64L $@
> -      cmd_vdso64ld = $(CC) $(c_flags) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^)
> +quiet_cmd_vdso64ld_and_check = VDSO64L $@
> +      cmd_vdso64ld_and_check = $(CC) $(c_flags) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^); $(cmd_vdso_check)
>   
>   # install commands for the unstripped file
>   quiet_cmd_vdso_install = INSTALL $@
> diff --git a/arch/powerpc/kernel/vdso64/gettimeofday.S b/arch/powerpc/kernel/vdso64/gettimeofday.S
> index 20f8be40c653..d7a7bfb51081 100644
> --- a/arch/powerpc/kernel/vdso64/gettimeofday.S
> +++ b/arch/powerpc/kernel/vdso64/gettimeofday.S
> @@ -12,6 +12,7 @@
>   #include <asm/vdso_datapage.h>
>   #include <asm/asm-offsets.h>
>   #include <asm/unistd.h>
> +#include <asm/vdso/gettimeofday.h>
>   
>   	.text
>   /*
> @@ -21,31 +22,7 @@
>    *
>    */
>   V_FUNCTION_BEGIN(__kernel_gettimeofday)
> -  .cfi_startproc
> -	mflr	r12
> -  .cfi_register lr,r12
> -
> -	mr	r11,r3			/* r11 holds tv */
> -	mr	r10,r4			/* r10 holds tz */
> -	get_datapage	r3, r0
> -	cmpldi	r11,0			/* check if tv is NULL */
> -	beq	2f
> -	lis	r7,1000000 at ha		/* load up USEC_PER_SEC */
> -	addi	r7,r7,1000000 at l
> -	bl	V_LOCAL_FUNC(__do_get_tspec) /* get sec/us from tb & kernel */
> -	std	r4,TVAL64_TV_SEC(r11)	/* store sec in tv */
> -	std	r5,TVAL64_TV_USEC(r11)	/* store usec in tv */
> -2:	cmpldi	r10,0			/* check if tz is NULL */
> -	beq	1f
> -	lwz	r4,CFG_TZ_MINUTEWEST(r3)/* fill tz */
> -	lwz	r5,CFG_TZ_DSTTIME(r3)
> -	stw	r4,TZONE_TZ_MINWEST(r10)
> -	stw	r5,TZONE_TZ_DSTTIME(r10)
> -1:	mtlr	r12
> -	crclr	cr0*4+so
> -	li	r3,0			/* always success */
> -	blr
> -  .cfi_endproc
> +	cvdso_call __c_kernel_gettimeofday
>   V_FUNCTION_END(__kernel_gettimeofday)
>   
>   
> @@ -56,120 +33,7 @@ V_FUNCTION_END(__kernel_gettimeofday)
>    *
>    */
>   V_FUNCTION_BEGIN(__kernel_clock_gettime)
> -  .cfi_startproc
> -	/* Check for supported clock IDs */
> -	cmpwi	cr0,r3,CLOCK_REALTIME
> -	cmpwi	cr1,r3,CLOCK_MONOTONIC
> -	cror	cr0*4+eq,cr0*4+eq,cr1*4+eq
> -
> -	cmpwi	cr5,r3,CLOCK_REALTIME_COARSE
> -	cmpwi	cr6,r3,CLOCK_MONOTONIC_COARSE
> -	cror	cr5*4+eq,cr5*4+eq,cr6*4+eq
> -
> -	cror	cr0*4+eq,cr0*4+eq,cr5*4+eq
> -	bne	cr0,99f
> -
> -	mflr	r12			/* r12 saves lr */
> -  .cfi_register lr,r12
> -	mr	r11,r4			/* r11 saves tp */
> -	get_datapage	r3, r0
> -	lis	r7,NSEC_PER_SEC at h	/* want nanoseconds */
> -	ori	r7,r7,NSEC_PER_SEC at l
> -	beq	cr5,70f
> -50:	bl	V_LOCAL_FUNC(__do_get_tspec)	/* get time from tb & kernel */
> -	bne	cr1,80f			/* if not monotonic, all done */
> -
> -	/*
> -	 * CLOCK_MONOTONIC
> -	 */
> -
> -	/* now we must fixup using wall to monotonic. We need to snapshot
> -	 * that value and do the counter trick again. Fortunately, we still
> -	 * have the counter value in r8 that was returned by __do_get_tspec.
> -	 * At this point, r4,r5 contain our sec/nsec values.
> -	 */
> -
> -	ld	r6,WTOM_CLOCK_SEC(r3)
> -	lwa	r9,WTOM_CLOCK_NSEC(r3)
> -
> -	/* We now have our result in r6,r9. We create a fake dependency
> -	 * on that result and re-check the counter
> -	 */
> -	or	r0,r6,r9
> -	xor	r0,r0,r0
> -	add	r3,r3,r0
> -	ld	r0,CFG_TB_UPDATE_COUNT(r3)
> -        cmpld   cr0,r0,r8		/* check if updated */
> -	bne-	50b
> -	b	78f
> -
> -	/*
> -	 * For coarse clocks we get data directly from the vdso data page, so
> -	 * we don't need to call __do_get_tspec, but we still need to do the
> -	 * counter trick.
> -	 */
> -70:	ld      r8,CFG_TB_UPDATE_COUNT(r3)
> -	andi.   r0,r8,1                 /* pending update ? loop */
> -	bne-    70b
> -	add     r3,r3,r0		/* r0 is already 0 */
> -
> -	/*
> -	 * CLOCK_REALTIME_COARSE, below values are needed for MONOTONIC_COARSE
> -	 * too
> -	 */
> -	ld      r4,STAMP_XTIME_SEC(r3)
> -	ld      r5,STAMP_XTIME_NSEC(r3)
> -	bne     cr6,75f
> -
> -	/* CLOCK_MONOTONIC_COARSE */
> -	ld	r6,WTOM_CLOCK_SEC(r3)
> -	lwa     r9,WTOM_CLOCK_NSEC(r3)
> -
> -	/* check if counter has updated */
> -	or      r0,r6,r9
> -75:	or	r0,r0,r4
> -	or	r0,r0,r5
> -	xor     r0,r0,r0
> -	add     r3,r3,r0
> -	ld      r0,CFG_TB_UPDATE_COUNT(r3)
> -	cmpld   cr0,r0,r8               /* check if updated */
> -	bne-    70b
> -
> -	/* Counter has not updated, so continue calculating proper values for
> -	 * sec and nsec if monotonic coarse, or just return with the proper
> -	 * values for realtime.
> -	 */
> -	bne     cr6,80f
> -
> -	/* Add wall->monotonic offset and check for overflow or underflow */
> -78:	add     r4,r4,r6
> -	add     r5,r5,r9
> -	cmpd    cr0,r5,r7
> -	cmpdi   cr1,r5,0
> -	blt     79f
> -	subf    r5,r7,r5
> -	addi    r4,r4,1
> -79:	bge     cr1,80f
> -	addi    r4,r4,-1
> -	add     r5,r5,r7
> -
> -80:	std	r4,TSPC64_TV_SEC(r11)
> -	std	r5,TSPC64_TV_NSEC(r11)
> -
> -	mtlr	r12
> -	crclr	cr0*4+so
> -	li	r3,0
> -	blr
> -
> -	/*
> -	 * syscall fallback
> -	 */
> -99:
> -	li	r0,__NR_clock_gettime
> -  .cfi_restore lr
> -	sc
> -	blr
> -  .cfi_endproc
> +	cvdso_call __c_kernel_clock_gettime
>   V_FUNCTION_END(__kernel_clock_gettime)
>   
>   
> @@ -180,34 +44,7 @@ V_FUNCTION_END(__kernel_clock_gettime)
>    *
>    */
>   V_FUNCTION_BEGIN(__kernel_clock_getres)
> -  .cfi_startproc
> -	/* Check for supported clock IDs */
> -	cmpwi	cr0,r3,CLOCK_REALTIME
> -	cmpwi	cr1,r3,CLOCK_MONOTONIC
> -	cror	cr0*4+eq,cr0*4+eq,cr1*4+eq
> -	bne	cr0,99f
> -
> -	mflr	r12
> -  .cfi_register lr,r12
> -	get_datapage	r3, r0
> -	lwz	r5, CLOCK_HRTIMER_RES(r3)
> -	mtlr	r12
> -	li	r3,0
> -	cmpldi	cr0,r4,0
> -	crclr	cr0*4+so
> -	beqlr
> -	std	r3,TSPC64_TV_SEC(r4)
> -	std	r5,TSPC64_TV_NSEC(r4)
> -	blr
> -
> -	/*
> -	 * syscall fallback
> -	 */
> -99:
> -	li	r0,__NR_clock_getres
> -	sc
> -	blr
> -  .cfi_endproc
> +	cvdso_call __c_kernel_clock_getres
>   V_FUNCTION_END(__kernel_clock_getres)
>   
>   /*
> @@ -217,74 +54,5 @@ V_FUNCTION_END(__kernel_clock_getres)
>    *
>    */
>   V_FUNCTION_BEGIN(__kernel_time)
> -  .cfi_startproc
> -	mflr	r12
> -  .cfi_register lr,r12
> -
> -	mr	r11,r3			/* r11 holds t */
> -	get_datapage	r3, r0
> -
> -	ld	r4,STAMP_XTIME_SEC(r3)
> -
> -	cmpldi	r11,0			/* check if t is NULL */
> -	beq	2f
> -	std	r4,0(r11)		/* store result at *t */
> -2:	mtlr	r12
> -	crclr	cr0*4+so
> -	mr	r3,r4
> -	blr
> -  .cfi_endproc
> +	cvdso_call_time __c_kernel_time
>   V_FUNCTION_END(__kernel_time)
> -
> -
> -/*
> - * This is the core of clock_gettime() and gettimeofday(),
> - * it returns the current time in r4 (seconds) and r5.
> - * On entry, r7 gives the resolution of r5, either USEC_PER_SEC
> - * or NSEC_PER_SEC, giving r5 in microseconds or nanoseconds.
> - * It expects the datapage ptr in r3 and doesn't clobber it.
> - * It clobbers r0, r6 and r9.
> - * On return, r8 contains the counter value that can be reused.
> - * This clobbers cr0 but not any other cr field.
> - */
> -V_FUNCTION_BEGIN(__do_get_tspec)
> -  .cfi_startproc
> -	/* check for update count & load values */
> -1:	ld	r8,CFG_TB_UPDATE_COUNT(r3)
> -	andi.	r0,r8,1			/* pending update ? loop */
> -	bne-	1b
> -	xor	r0,r8,r8		/* create dependency */
> -	add	r3,r3,r0
> -
> -	/* Get TB & offset it. We use the MFTB macro which will generate
> -	 * workaround code for Cell.
> -	 */
> -	MFTB(r6)
> -	ld	r9,CFG_TB_ORIG_STAMP(r3)
> -	subf	r6,r9,r6
> -
> -	/* Scale result */
> -	ld	r5,CFG_TB_TO_XS(r3)
> -	sldi	r6,r6,12		/* compute time since stamp_xtime */
> -	mulhdu	r6,r6,r5		/* in units of 2^-32 seconds */
> -
> -	/* Add stamp since epoch */
> -	ld	r4,STAMP_XTIME_SEC(r3)
> -	lwz	r5,STAMP_SEC_FRAC(r3)
> -	or	r0,r4,r5
> -	or	r0,r0,r6
> -	xor	r0,r0,r0
> -	add	r3,r3,r0
> -	ld	r0,CFG_TB_UPDATE_COUNT(r3)
> -	cmpld   r0,r8			/* check if updated */
> -	bne-	1b			/* reload if so */
> -
> -	/* convert to seconds & nanoseconds and add to stamp */
> -	add	r6,r6,r5		/* add on fractional seconds of xtime */
> -	mulhwu	r5,r6,r7		/* compute micro or nanoseconds and */
> -	srdi	r6,r6,32		/* seconds since stamp_xtime */
> -	clrldi	r5,r5,32
> -	add	r4,r4,r6
> -	blr
> -  .cfi_endproc
> -V_FUNCTION_END(__do_get_tspec)
> diff --git a/arch/powerpc/kernel/vdso64/vdso64.lds.S b/arch/powerpc/kernel/vdso64/vdso64.lds.S
> index 256fb9720298..71be083b24ed 100644
> --- a/arch/powerpc/kernel/vdso64/vdso64.lds.S
> +++ b/arch/powerpc/kernel/vdso64/vdso64.lds.S
> @@ -61,7 +61,6 @@ SECTIONS
>   	.gcc_except_table : { *(.gcc_except_table) }
>   	.rela.dyn ALIGN(8) : { *(.rela.dyn) }
>   
> -	.opd ALIGN(8)	: { KEEP (*(.opd)) }
>   	.got ALIGN(8)	: { *(.got .toc) }
>   
>   	_end = .;
> @@ -111,6 +110,7 @@ SECTIONS
>   		*(.branch_lt)
>   		*(.data .data.* .gnu.linkonce.d.* .sdata*)
>   		*(.bss .sbss .dynbss .dynsbss)
> +		*(.opd)
>   	}
>   }
>   
> 




More information about the Linuxppc-dev mailing list