Force inlining of get_tb() in order to avoid getting following function in vdso32, leading to suboptimal performance in clock_gettime() 00000688 <.get_tb>: 688: 7c 6d 42 a6 mftbu r3 68c: 7c 8c 42 a6 mftb r4 690: 7d 2d 42 a6 mftbu r9 694: 7c 03 48 40 cmplw r3,r9 698: 40 e2 ff f0 bne+ 688 <.get_tb> 69c: 4e 80 00 20 blr Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/df05d53eed1210cf1aa76d1fb44aa0fab29c018e.1608488286.git.christophe.leroy@csgroup.eu
79 lines
2 KiB
C
79 lines
2 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
/*
|
|
* Common timebase prototypes and such for all ppc machines.
|
|
*/
|
|
|
|
#ifndef _ASM_POWERPC_VDSO_TIMEBASE_H
|
|
#define _ASM_POWERPC_VDSO_TIMEBASE_H
|
|
|
|
#include <asm/reg.h>
|
|
|
|
/*
|
|
* We use __powerpc64__ here because we want the compat VDSO to use the 32-bit
|
|
* version below in the else case of the ifdef.
|
|
*/
|
|
#if defined(__powerpc64__) && (defined(CONFIG_PPC_CELL) || defined(CONFIG_E500))
|
|
#define mftb() ({unsigned long rval; \
|
|
asm volatile( \
|
|
"90: mfspr %0, %2;\n" \
|
|
ASM_FTR_IFSET( \
|
|
"97: cmpwi %0,0;\n" \
|
|
" beq- 90b;\n", "", %1) \
|
|
: "=r" (rval) \
|
|
: "i" (CPU_FTR_CELL_TB_BUG), "i" (SPRN_TBRL) : "cr0"); \
|
|
rval;})
|
|
#elif defined(CONFIG_PPC_8xx)
|
|
#define mftb() ({unsigned long rval; \
|
|
asm volatile("mftbl %0" : "=r" (rval)); rval;})
|
|
#else
|
|
#define mftb() ({unsigned long rval; \
|
|
asm volatile("mfspr %0, %1" : \
|
|
"=r" (rval) : "i" (SPRN_TBRL)); rval;})
|
|
#endif /* !CONFIG_PPC_CELL */
|
|
|
|
#if defined(CONFIG_PPC_8xx)
|
|
#define mftbu() ({unsigned long rval; \
|
|
asm volatile("mftbu %0" : "=r" (rval)); rval;})
|
|
#else
|
|
#define mftbu() ({unsigned long rval; \
|
|
asm volatile("mfspr %0, %1" : "=r" (rval) : \
|
|
"i" (SPRN_TBRU)); rval;})
|
|
#endif
|
|
|
|
#define mttbl(v) asm volatile("mttbl %0":: "r"(v))
|
|
#define mttbu(v) asm volatile("mttbu %0":: "r"(v))
|
|
|
|
/* For compatibility, get_tbl() is defined as get_tb() on ppc64 */
|
|
static inline unsigned long get_tbl(void)
|
|
{
|
|
return mftb();
|
|
}
|
|
|
|
static __always_inline u64 get_tb(void)
|
|
{
|
|
unsigned int tbhi, tblo, tbhi2;
|
|
|
|
/*
|
|
* We use __powerpc64__ here not CONFIG_PPC64 because we want the compat
|
|
* VDSO to use the 32-bit compatible version in the while loop below.
|
|
*/
|
|
if (__is_defined(__powerpc64__))
|
|
return mftb();
|
|
|
|
do {
|
|
tbhi = mftbu();
|
|
tblo = mftb();
|
|
tbhi2 = mftbu();
|
|
} while (tbhi != tbhi2);
|
|
|
|
return ((u64)tbhi << 32) | tblo;
|
|
}
|
|
|
|
static inline void set_tb(unsigned int upper, unsigned int lower)
|
|
{
|
|
mtspr(SPRN_TBWL, 0);
|
|
mtspr(SPRN_TBWU, upper);
|
|
mtspr(SPRN_TBWL, lower);
|
|
}
|
|
|
|
#endif /* _ASM_POWERPC_VDSO_TIMEBASE_H */
|