Michal Suchanek bed401
From 552263456215ada7ee8700ce022d12b0cffe4802 Mon Sep 17 00:00:00 2001
Michal Suchanek bed401
From: Vincenzo Frascino <vincenzo.frascino@arm.com>
Michal Suchanek bed401
Date: Mon, 2 Dec 2019 07:57:29 +0000
Michal Suchanek bed401
Subject: [PATCH] powerpc: Fix vDSO clock_getres()
Michal Suchanek bed401
Michal Suchanek bed401
References: bsc#1065729
Michal Suchanek bed401
Patch-mainline: v5.5-rc1
Michal Suchanek bed401
Git-commit: 552263456215ada7ee8700ce022d12b0cffe4802
Michal Suchanek bed401
Michal Suchanek bed401
clock_getres in the vDSO library has to preserve the same behaviour
Michal Suchanek bed401
of posix_get_hrtimer_res().
Michal Suchanek bed401
Michal Suchanek bed401
In particular, posix_get_hrtimer_res() does:
Michal Suchanek bed401
    sec = 0;
Michal Suchanek bed401
    ns = hrtimer_resolution;
Michal Suchanek bed401
and hrtimer_resolution depends on the enablement of the high
Michal Suchanek bed401
resolution timers that can happen either at compile or at run time.
Michal Suchanek bed401
Michal Suchanek bed401
Fix the powerpc vdso implementation of clock_getres keeping a copy of
Michal Suchanek bed401
hrtimer_resolution in vdso data and using that directly.
Michal Suchanek bed401
Michal Suchanek bed401
Fixes: a7f290dad32e ("[PATCH] powerpc: Merge vdso's and add vdso support to 32 bits kernel")
Michal Suchanek bed401
Cc: stable@vger.kernel.org
Michal Suchanek bed401
Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Michal Suchanek bed401
Reviewed-by: Christophe Leroy <christophe.leroy@c-s.fr>
Michal Suchanek bed401
Acked-by: Shuah Khan <skhan@linuxfoundation.org>
Michal Suchanek bed401
[chleroy: changed CLOCK_REALTIME_RES to CLOCK_HRTIMER_RES]
Michal Suchanek bed401
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Michal Suchanek bed401
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Michal Suchanek bed401
Link: https://lore.kernel.org/r/a55eca3a5e85233838c2349783bcb5164dae1d09.1575273217.git.christophe.leroy@c-s.fr
Michal Suchanek bed401
Acked-by: Michal Suchanek <msuchanek@suse.de>
Michal Suchanek bed401
---
Michal Suchanek bed401
 arch/powerpc/include/asm/vdso_datapage.h  | 2 ++
Michal Suchanek bed401
 arch/powerpc/kernel/asm-offsets.c         | 2 +-
Michal Suchanek bed401
 arch/powerpc/kernel/time.c                | 1 +
Michal Suchanek bed401
 arch/powerpc/kernel/vdso32/gettimeofday.S | 7 +++++--
Michal Suchanek bed401
 arch/powerpc/kernel/vdso64/gettimeofday.S | 7 +++++--
Michal Suchanek bed401
 5 files changed, 14 insertions(+), 5 deletions(-)
Michal Suchanek bed401
Michal Suchanek bed401
--- a/arch/powerpc/include/asm/vdso_datapage.h
Michal Suchanek bed401
+++ b/arch/powerpc/include/asm/vdso_datapage.h
Michal Suchanek bed401
@@ -86,6 +86,7 @@ struct vdso_data {
Michal Suchanek bed401
 	__s32 wtom_clock_nsec;			/* Wall to monotonic clock nsec */
Michal Suchanek bed401
 	__s64 wtom_clock_sec;			/* Wall to monotonic clock sec */
Michal Suchanek bed401
 	struct timespec stamp_xtime;		/* xtime as at tb_orig_stamp */
Michal Suchanek bed401
+	__u32 hrtimer_res;			/* hrtimer resolution */
Michal Suchanek bed401
    	__u32 syscall_map_64[SYSCALL_MAP_SIZE]; /* map of syscalls  */
Michal Suchanek bed401
    	__u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */
Michal Suchanek bed401
 };
Michal Suchanek bed401
@@ -107,6 +108,7 @@ struct vdso_data {
Michal Suchanek bed401
 	__s32 wtom_clock_nsec;
Michal Suchanek bed401
 	struct timespec stamp_xtime;	/* xtime as at tb_orig_stamp */
Michal Suchanek bed401
 	__u32 stamp_sec_fraction;	/* fractional seconds of stamp_xtime */
Michal Suchanek bed401
+	__u32 hrtimer_res;		/* hrtimer resolution */
Michal Suchanek bed401
    	__u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */
Michal Suchanek bed401
 	__u32 dcache_block_size;	/* L1 d-cache block size     */
Michal Suchanek bed401
 	__u32 icache_block_size;	/* L1 i-cache block size     */
Michal Suchanek bed401
--- a/arch/powerpc/kernel/asm-offsets.c
Michal Suchanek bed401
+++ b/arch/powerpc/kernel/asm-offsets.c
Michal Suchanek bed401
@@ -374,6 +374,7 @@ int main(void)
Michal Suchanek bed401
 	OFFSET(WTOM_CLOCK_NSEC, vdso_data, wtom_clock_nsec);
Michal Suchanek bed401
 	OFFSET(STAMP_XTIME, vdso_data, stamp_xtime);
Michal Suchanek bed401
 	OFFSET(STAMP_SEC_FRAC, vdso_data, stamp_sec_fraction);
Michal Suchanek bed401
+	OFFSET(CLOCK_HRTIMER_RES, vdso_data, hrtimer_res);
Michal Suchanek bed401
 	OFFSET(CFG_ICACHE_BLOCKSZ, vdso_data, icache_block_size);
Michal Suchanek bed401
 	OFFSET(CFG_DCACHE_BLOCKSZ, vdso_data, dcache_block_size);
Michal Suchanek bed401
 	OFFSET(CFG_ICACHE_LOGBLOCKSZ, vdso_data, icache_log_block_size);
Michal Suchanek bed401
@@ -402,7 +403,6 @@ int main(void)
Michal Suchanek bed401
 	DEFINE(CLOCK_REALTIME, CLOCK_REALTIME);
Michal Suchanek bed401
 	DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC);
Michal Suchanek bed401
 	DEFINE(NSEC_PER_SEC, NSEC_PER_SEC);
Michal Suchanek bed401
-	DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC);
Michal Suchanek bed401
 
Michal Suchanek bed401
 #ifdef CONFIG_BUG
Michal Suchanek bed401
 	DEFINE(BUG_ENTRY_SIZE, sizeof(struct bug_entry));
Michal Suchanek bed401
--- a/arch/powerpc/kernel/time.c
Michal Suchanek bed401
+++ b/arch/powerpc/kernel/time.c
Michal Suchanek bed401
@@ -876,6 +876,7 @@ void update_vsyscall_old(struct timespec
Michal Suchanek bed401
 	vdso_data->wtom_clock_nsec = wtm->tv_nsec;
Michal Suchanek bed401
 	vdso_data->stamp_xtime = *wall_time;
Michal Suchanek bed401
 	vdso_data->stamp_sec_fraction = frac_sec;
Michal Suchanek bed401
+	vdso_data->hrtimer_res = hrtimer_resolution;
Michal Suchanek bed401
 	smp_wmb();
Michal Suchanek bed401
 	++(vdso_data->tb_update_count);
Michal Suchanek bed401
 }
Michal Suchanek bed401
diff --git a/arch/powerpc/kernel/vdso32/gettimeofday.S b/arch/powerpc/kernel/vdso32/gettimeofday.S
Michal Suchanek bed401
index c8e6902cb01b..3306672f57a9 100644
Michal Suchanek bed401
--- a/arch/powerpc/kernel/vdso32/gettimeofday.S
Michal Suchanek bed401
+++ b/arch/powerpc/kernel/vdso32/gettimeofday.S
Michal Suchanek bed401
@@ -154,12 +154,15 @@ V_FUNCTION_BEGIN(__kernel_clock_getres)
Michal Suchanek bed401
 	cror	cr0*4+eq,cr0*4+eq,cr1*4+eq
Michal Suchanek bed401
 	bne	cr0,99f
Michal Suchanek bed401
 
Michal Suchanek bed401
+	mflr	r12
Michal Suchanek bed401
+  .cfi_register lr,r12
Michal Suchanek bed401
+	bl	__get_datapage@local	/* get data page */
Michal Suchanek bed401
+	lwz	r5, CLOCK_HRTIMER_RES(r3)
Michal Suchanek bed401
+	mtlr	r12
Michal Suchanek bed401
 	li	r3,0
Michal Suchanek bed401
 	cmpli	cr0,r4,0
Michal Suchanek bed401
 	crclr	cr0*4+so
Michal Suchanek bed401
 	beqlr
Michal Suchanek bed401
-	lis	r5,CLOCK_REALTIME_RES@h
Michal Suchanek bed401
-	ori	r5,r5,CLOCK_REALTIME_RES@l
Michal Suchanek bed401
 	stw	r3,TSPC32_TV_SEC(r4)
Michal Suchanek bed401
 	stw	r5,TSPC32_TV_NSEC(r4)
Michal Suchanek bed401
 	blr
Michal Suchanek bed401
diff --git a/arch/powerpc/kernel/vdso64/gettimeofday.S b/arch/powerpc/kernel/vdso64/gettimeofday.S
Michal Suchanek bed401
index 1f24e411af80..1c9a04703250 100644
Michal Suchanek bed401
--- a/arch/powerpc/kernel/vdso64/gettimeofday.S
Michal Suchanek bed401
+++ b/arch/powerpc/kernel/vdso64/gettimeofday.S
Michal Suchanek bed401
@@ -186,12 +186,15 @@ V_FUNCTION_BEGIN(__kernel_clock_getres)
Michal Suchanek bed401
 	cror	cr0*4+eq,cr0*4+eq,cr1*4+eq
Michal Suchanek bed401
 	bne	cr0,99f
Michal Suchanek bed401
 
Michal Suchanek bed401
+	mflr	r12
Michal Suchanek bed401
+  .cfi_register lr,r12
Michal Suchanek bed401
+	bl	V_LOCAL_FUNC(__get_datapage)
Michal Suchanek bed401
+	lwz	r5, CLOCK_HRTIMER_RES(r3)
Michal Suchanek bed401
+	mtlr	r12
Michal Suchanek bed401
 	li	r3,0
Michal Suchanek bed401
 	cmpldi	cr0,r4,0
Michal Suchanek bed401
 	crclr	cr0*4+so
Michal Suchanek bed401
 	beqlr
Michal Suchanek bed401
-	lis	r5,CLOCK_REALTIME_RES@h
Michal Suchanek bed401
-	ori	r5,r5,CLOCK_REALTIME_RES@l
Michal Suchanek bed401
 	std	r3,TSPC64_TV_SEC(r4)
Michal Suchanek bed401
 	std	r5,TSPC64_TV_NSEC(r4)
Michal Suchanek bed401
 	blr