From 10657660c16e689bfad204190e7031b9b1622a35 Mon Sep 17 00:00:00 2001 From: Huang Pei Date: Wed, 15 Dec 2021 16:44:59 +0800 Subject: MIPS: rework local_t operation on MIPS64 +. remove "asm/war.h" since R10000_LLSC_WAR became a config option +. clean up Suggested-by: Maciej W. Rozycki Signed-off-by: Huang Pei Signed-off-by: Thomas Bogendoerfer --- arch/mips/include/asm/asm.h | 18 +++++++++++++ arch/mips/include/asm/local.h | 59 ++++++++++--------------------------------- 2 files changed, 32 insertions(+), 45 deletions(-) diff --git a/arch/mips/include/asm/asm.h b/arch/mips/include/asm/asm.h index 2f8ce94ebaaf..f3302b13d3e0 100644 --- a/arch/mips/include/asm/asm.h +++ b/arch/mips/include/asm/asm.h @@ -19,6 +19,7 @@ #include #include +#include #ifndef __VDSO__ /* @@ -211,6 +212,8 @@ symbol = value #define LONG_SUB sub #define LONG_SUBU subu #define LONG_L lw +#define LONG_LL ll +#define LONG_SC sc #define LONG_S sw #define LONG_SP swp #define LONG_SLL sll @@ -236,6 +239,8 @@ symbol = value #define LONG_SUB dsub #define LONG_SUBU dsubu #define LONG_L ld +#define LONG_LL lld +#define LONG_SC scd #define LONG_S sd #define LONG_SP sdp #define LONG_SLL dsll @@ -320,6 +325,19 @@ symbol = value #define SSNOP sll zero, zero, 1 +/* + * Using a branch-likely instruction to check the result of an sc instruction + * works around a bug present in R10000 CPUs prior to revision 3.0 that could + * cause ll-sc sequences to execute non-atomically. + */ +#ifdef CONFIG_WAR_R10000_LLSC +# define SC_BEQZ beqzl +#elif MIPS_ISA_REV >= 6 +# define SC_BEQZ beqzc +#else +# define SC_BEQZ beqz +#endif + #ifdef CONFIG_SGI_IP28 /* Inhibit speculative stores to volatile (e.g.DMA) or invalid addresses. */ #include diff --git a/arch/mips/include/asm/local.h b/arch/mips/include/asm/local.h index 3fa634090388..d4d47c846bb2 100644 --- a/arch/mips/include/asm/local.h +++ b/arch/mips/include/asm/local.h @@ -8,7 +8,7 @@ #include #include #include -#include +#include typedef struct { @@ -32,34 +32,18 @@ static __inline__ long local_add_return(long i, local_t * l) { unsigned long result; - if (kernel_uses_llsc && IS_ENABLED(CONFIG_WAR_R10000_LLSC)) { - unsigned long temp; - - __asm__ __volatile__( - " .set push \n" - " .set arch=r4000 \n" - __SYNC(full, loongson3_war) " \n" - "1:" __LL "%1, %2 # local_add_return \n" - __stringify(LONG_ADDU) " %0, %1, %3 \n" - __SC "%0, %2 \n" - " beqzl %0, 1b \n" - " addu %0, %1, %3 \n" - " .set pop \n" - : "=&r" (result), "=&r" (temp), "=m" (l->a.counter) - : "Ir" (i), "m" (l->a.counter) - : "memory"); - } else if (kernel_uses_llsc) { + if (kernel_uses_llsc) { unsigned long temp; __asm__ __volatile__( " .set push \n" " .set "MIPS_ISA_ARCH_LEVEL" \n" - __SYNC(full, loongson3_war) " \n" - "1:" __LL "%1, %2 # local_add_return \n" + __SYNC(full, loongson3_war) " \n" + "1:" __stringify(LONG_LL) " %1, %2 \n" + __stringify(LONG_ADDU) " %0, %1, %3 \n" + __stringify(LONG_SC) " %0, %2 \n" + __stringify(SC_BEQZ) " %0, 1b \n" __stringify(LONG_ADDU) " %0, %1, %3 \n" - __SC "%0, %2 \n" - " beqz %0, 1b \n" - " addu %0, %1, %3 \n" " .set pop \n" : "=&r" (result), "=&r" (temp), "=m" (l->a.counter) : "Ir" (i), "m" (l->a.counter) @@ -81,34 +65,19 @@ static __inline__ long local_sub_return(long i, local_t * l) { unsigned long result; - if (kernel_uses_llsc && IS_ENABLED(CONFIG_WAR_R10000_LLSC)) { - unsigned long temp; - - __asm__ __volatile__( - " .set push \n" - " .set arch=r4000 \n" - __SYNC(full, loongson3_war) " \n" - "1:" __LL "%1, %2 # local_sub_return \n" - __stringify(LONG_SUBU) " %0, %1, %3 \n" - __SC "%0, %2 \n" - " beqzl %0, 1b \n" - " subu %0, %1, %3 \n" - " .set pop \n" - : "=&r" (result), "=&r" (temp), "=m" (l->a.counter) - : "Ir" (i), "m" (l->a.counter) - : "memory"); - } else if (kernel_uses_llsc) { + if (kernel_uses_llsc) { unsigned long temp; __asm__ __volatile__( " .set push \n" " .set "MIPS_ISA_ARCH_LEVEL" \n" - __SYNC(full, loongson3_war) " \n" - "1:" __LL "%1, %2 # local_sub_return \n" + __SYNC(full, loongson3_war) " \n" + "1:" __stringify(LONG_LL) " %1, %2 \n" + __stringify(LONG_SUBU) " %0, %1, %3 \n" + __stringify(LONG_SUBU) " %0, %1, %3 \n" + __stringify(LONG_SC) " %0, %2 \n" + __stringify(SC_BEQZ) " %0, 1b \n" __stringify(LONG_SUBU) " %0, %1, %3 \n" - __SC "%0, %2 \n" - " beqz %0, 1b \n" - " subu %0, %1, %3 \n" " .set pop \n" : "=&r" (result), "=&r" (temp), "=m" (l->a.counter) : "Ir" (i), "m" (l->a.counter) -- cgit v1.2.3