Skip to content

Commit 93c8833

Browse files
Mark Rutlandksacilotto
Mark Rutland
authored andcommitted
arm64: xchg: hazard against entire exchange variable
BugLink: http://bugs.launchpad.net/bugs/1694621 commit fee960b upstream. The inline assembly in __XCHG_CASE() uses a +Q constraint to hazard against other accesses to the memory location being exchanged. However, the pointer passed to the constraint is a u8 pointer, and thus the hazard only applies to the first byte of the location. GCC can take advantage of this, assuming that other portions of the location are unchanged, as demonstrated with the following test case: union u { unsigned long l; unsigned int i[2]; }; unsigned long update_char_hazard(union u *u) { unsigned int a, b; a = u->i[1]; asm ("str %1, %0" : "+Q" (*(char *)&u->l) : "r" (0UL)); b = u->i[1]; return a ^ b; } unsigned long update_long_hazard(union u *u) { unsigned int a, b; a = u->i[1]; asm ("str %1, %0" : "+Q" (*(long *)&u->l) : "r" (0UL)); b = u->i[1]; return a ^ b; } The linaro 15.08 GCC 5.1.1 toolchain compiles the above as follows when using -O2 or above: 0000000000000000 <update_char_hazard>: 0: d2800001 mov x1, #0x0 // #0 4: f9000001 str x1, [x0] 8: d2800000 mov x0, #0x0 // #0 c: d65f03c0 ret 0000000000000010 <update_long_hazard>: 10: b9400401 ldr w1, [x0,#4] 14: d2800002 mov x2, #0x0 // #0 18: f9000002 str x2, [x0] 1c: b9400400 ldr w0, [x0,#4] 20: 4a000020 eor w0, w1, w0 24: d65f03c0 ret This patch fixes the issue by passing an unsigned long pointer into the +Q constraint, as we do for our cmpxchg code. This may hazard against more than is necessary, but this is better than missing a necessary hazard. Fixes: 305d454 ("arm64: atomics: implement native {relaxed, acquire, release} atomics") Acked-by: Will Deacon <[email protected]> Signed-off-by: Mark Rutland <[email protected]> Signed-off-by: Catalin Marinas <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> Signed-off-by: Stefan Bader <[email protected]> Signed-off-by: Thadeu Lima de Souza Cascardo <[email protected]>
1 parent 00cdb7e commit 93c8833

File tree

1 file changed

+1
-1
lines changed

1 file changed

+1
-1
lines changed

arch/arm64/include/asm/cmpxchg.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ static inline unsigned long __xchg_case_##name(unsigned long x, \
4949
" swp" #acq_lse #rel #sz "\t%" #w "3, %" #w "0, %2\n" \
5050
" nop\n" \
5151
" " #nop_lse) \
52-
: "=&r" (ret), "=&r" (tmp), "+Q" (*(u8 *)ptr) \
52+
: "=&r" (ret), "=&r" (tmp), "+Q" (*(unsigned long *)ptr) \
5353
: "r" (x) \
5454
: cl); \
5555
\

0 commit comments

Comments
 (0)