arm64: cmpxchg_dbl: fix return value type
authorLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Thu, 5 Nov 2015 14:00:56 +0000 (14:00 +0000)
committerCatalin Marinas <catalin.marinas@arm.com>
Thu, 5 Nov 2015 17:29:40 +0000 (17:29 +0000)
The current arm64 __cmpxchg_double{_mb} implementations carry out the
compare exchange by first comparing the old values passed in to the
values read from the pointer provided and by stashing the cumulative
bitwise difference in a 64-bit register.

By comparing the register content against 0, it is possible to detect if
the values read differ from the old values passed in, so that the compare
exchange detects whether it has to bail out or carry on completing the
operation with the exchange.

Given the current implementation, to detect the cmpxchg operation
status, the __cmpxchg_double{_mb} functions should return the 64-bit
stashed bitwise difference so that the caller can detect cmpxchg failure
by comparing the return value content against 0. The current implementation
declares the return value as an int, which means that the 64-bit
value stashing the bitwise difference is truncated before being
returned to the __cmpxchg_double{_mb} callers, which means that
any bitwise difference present in the top 32 bits goes undetected,
triggering false positives and subsequent kernel failures.

This patch fixes the issue by declaring the arm64 __cmpxchg_double{_mb}
return values as a long, so that the bitwise difference is
properly propagated on failure, restoring the expected behaviour.

Fixes: e9a4b795652f ("arm64: cmpxchg_dbl: patch in lse instructions when supported by the CPU")
Cc: <stable@vger.kernel.org> # 4.3+
Cc: Marc Zyngier <marc.zyngier@arm.com>
Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
arch/arm64/include/asm/atomic_ll_sc.h
arch/arm64/include/asm/atomic_lse.h

index 74d0b8eb0799cb6635b999f7afb1c7e7c0a361bf..f61c84f6ba021aa9cd149c8b927680d86f6328b7 100644 (file)
@@ -233,7 +233,7 @@ __CMPXCHG_CASE( ,  ,  mb_8, dmb ish,  , l, "memory")
 #undef __CMPXCHG_CASE
 
 #define __CMPXCHG_DBL(name, mb, rel, cl)                               \
-__LL_SC_INLINE int                                                     \
+__LL_SC_INLINE long                                                    \
 __LL_SC_PREFIX(__cmpxchg_double##name(unsigned long old1,              \
                                      unsigned long old2,               \
                                      unsigned long new1,               \
index 1fce7908e6904a43791a385b5df76ef080ebefa2..197e06afbf71947eb505a893e53b73be73543be9 100644 (file)
@@ -387,7 +387,7 @@ __CMPXCHG_CASE(x,  ,  mb_8, al, "memory")
 #define __LL_SC_CMPXCHG_DBL(op)        __LL_SC_CALL(__cmpxchg_double##op)
 
 #define __CMPXCHG_DBL(name, mb, cl...)                                 \
-static inline int __cmpxchg_double##name(unsigned long old1,           \
+static inline long __cmpxchg_double##name(unsigned long old1,          \
                                         unsigned long old2,            \
                                         unsigned long new1,            \
                                         unsigned long new2,            \