From: Vineet Gupta <vgu...@synopsys.com>

This patch has been added to the 3.18 stable tree. If you have any
objections, please let us know.

===============

[ Upstream commit d57f727264f1425a94689bafc7e99e502cb135b5 ]

When auditing cmpxchg call sites, Chuck noted that gcc was optimizing
away some of the desired LDs.

|       do {
|               new = old = *ipi_data_ptr;
|               new |= 1U << msg;
|       } while (cmpxchg(ipi_data_ptr, old, new) != old);

was generating to below

| 8015cef8:     ld         r2,[r4,0]  <-- First LD
| 8015cefc:     bset       r1,r2,r1
|
| 8015cf00:     llock      r3,[r4]  <-- atomic op
| 8015cf04:     brne       r3,r2,8015cf10
| 8015cf08:     scond      r1,[r4]
| 8015cf0c:     bnz        8015cf00
|
| 8015cf10:     brne       r3,r2,8015cf00  <-- Branch doesn't go to orig LD

Although this was fixed by adding a ACCESS_ONCE in this call site, it
seems safer (for now at least) to add compiler barrier to LLSC based
cmpxchg

Reported-by: Chuck Jordan <cjordan@synopsys,com>
Cc: <stable@vger.kernel.org>
Acked-by: Peter Zijlstra (Intel) <pet...@infradead.org>
Signed-off-by: Vineet Gupta <vgu...@synopsys.com>
Signed-off-by: Sasha Levin <sasha.le...@oracle.com>
---
 arch/arc/include/asm/cmpxchg.h | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/arc/include/asm/cmpxchg.h b/arch/arc/include/asm/cmpxchg.h
index 03cd689..90de5c5 100644
--- a/arch/arc/include/asm/cmpxchg.h
+++ b/arch/arc/include/asm/cmpxchg.h
@@ -25,10 +25,11 @@ __cmpxchg(volatile void *ptr, unsigned long expected, 
unsigned long new)
        "       scond   %3, [%1]        \n"
        "       bnz     1b              \n"
        "2:                             \n"
-       : "=&r"(prev)
-       : "r"(ptr), "ir"(expected),
-         "r"(new) /* can't be "ir". scond can't take limm for "b" */
-       : "cc");
+       : "=&r"(prev)   /* Early clobber, to prevent reg reuse */
+       : "r"(ptr),     /* Not "m": llock only supports reg direct addr mode */
+         "ir"(expected),
+         "r"(new)      /* can't be "ir". scond can't take LIMM for "b" */
+       : "cc", "memory"); /* so that gcc knows memory is being written here */
 
        return prev;
 }
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to