[PATCH] MIPS: Fix delay slot bug in `atomic*_sub_if_positive' for R10000_LLSC_WAR
From: Joshua Kinard <hidden>
Date: 2017-11-19 03:33:05
Subsystem:
atomic infrastructure, mips, the rest · Maintainers:
Will Deacon, Peter Zijlstra, Boqun Feng, Thomas Bogendoerfer, Linus Torvalds
From: Joshua Kinard <redacted> This patch fixes an old bug in MIPS ll/sc atomics, in the `atomic_sub_if_positive' and `atomic64_sub_if_positive' functions, for the R10000_LLSC_WAR case where the result of the subu/dsubu instruction would potentially not be made available to the sc/scd instruction due to being in the delay-slot of the branch-likely (beqzl) instruction. This also removes the need for the `noreorder' directive, allowing GAS to use delay slot scheduling as needed. The same fix is also applied to the standard branch (beqz) case in preparation for a follow-up patch that will cleanup/merge the R10000_LLSC_WAR and non-R10K sections together. Cc: linux-mips@linux-mips.org Signed-off-by: Joshua Kinard <redacted> Tested-by: Joshua Kinard <redacted> --- arch/mips/include/asm/atomic.h | 32 +++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-)
diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
index 0ab176bdb8e8..0babf2775d8e 100644
--- a/arch/mips/include/asm/atomic.h
+++ b/arch/mips/include/asm/atomic.h@@ -225,12 +225,10 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v) " .set arch=r4000 \n" "1: ll %1, %2 # atomic_sub_if_positive\n" " subu %0, %1, %3 \n" + " move %1, %0 \n" " bltz %0, 1f \n" - " sc %0, %2 \n" - " .set noreorder \n" - " beqzl %0, 1b \n" - " subu %0, %1, %3 \n" - " .set reorder \n" + " sc %1, %2 \n" + " beqzl %1, 1b \n" "1: \n" " .set mips0 \n" : "=&r" (result), "=&r" (temp),
@@ -244,12 +242,10 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v) " .set "MIPS_ISA_LEVEL" \n" "1: ll %1, %2 # atomic_sub_if_positive\n" " subu %0, %1, %3 \n" + " move %1, %0 \n" " bltz %0, 1f \n" - " sc %0, %2 \n" - " .set noreorder \n" - " beqz %0, 1b \n" - " subu %0, %1, %3 \n" - " .set reorder \n" + " sc %1, %2 \n" + " beqz %1, 1b \n" "1: \n" " .set mips0 \n" : "=&r" (result), "=&r" (temp),
@@ -570,12 +566,10 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v) " .set arch=r4000 \n" "1: lld %1, %2 # atomic64_sub_if_positive\n" " dsubu %0, %1, %3 \n" + " move %1, %0 \n" " bltz %0, 1f \n" - " scd %0, %2 \n" - " .set noreorder \n" - " beqzl %0, 1b \n" - " dsubu %0, %1, %3 \n" - " .set reorder \n" + " scd %1, %2 \n" + " beqzl %1, 1b \n" "1: \n" " .set mips0 \n" : "=&r" (result), "=&r" (temp),
@@ -589,12 +583,10 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v) " .set "MIPS_ISA_LEVEL" \n" "1: lld %1, %2 # atomic64_sub_if_positive\n" " dsubu %0, %1, %3 \n" + " move %1, %0 \n" " bltz %0, 1f \n" - " scd %0, %2 \n" - " .set noreorder \n" - " beqz %0, 1b \n" - " dsubu %0, %1, %3 \n" - " .set reorder \n" + " scd %1, %2 \n" + " beqz %1, 1b \n" "1: \n" " .set mips0 \n" : "=&r" (result), "=&r" (temp),