Commit 56813262 authored by H. Peter Anvin's avatar H. Peter Anvin Committed by Greg Kroah-Hartman

x86: Add memory modify constraints to xchg() and cmpxchg()

commit 113fc5a6 upstream.

xchg() and cmpxchg() modify their memory operands, not merely read
them.  For some versions of gcc the "memory" clobber has apparently
dealt with the situation, but not for all.
Originally-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: default avatarH. Peter Anvin <hpa@zytor.com>
Cc: Glauber Costa <glommer@redhat.com>
Cc: Avi Kivity <avi@redhat.com>
Cc: Peter Palfrader <peter@palfrader.org>
Cc: Greg KH <gregkh@suse.de>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Zachary Amsden <zamsden@redhat.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
LKML-Reference: <4C4F7277.8050306@zytor.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 203824be
...@@ -27,20 +27,20 @@ struct __xchg_dummy { ...@@ -27,20 +27,20 @@ struct __xchg_dummy {
switch (size) { \ switch (size) { \
case 1: \ case 1: \
asm volatile("xchgb %b0,%1" \ asm volatile("xchgb %b0,%1" \
: "=q" (__x) \ : "=q" (__x), "+m" (*__xg(ptr)) \
: "m" (*__xg(ptr)), "0" (__x) \ : "0" (__x) \
: "memory"); \ : "memory"); \
break; \ break; \
case 2: \ case 2: \
asm volatile("xchgw %w0,%1" \ asm volatile("xchgw %w0,%1" \
: "=r" (__x) \ : "=r" (__x), "+m" (*__xg(ptr)) \
: "m" (*__xg(ptr)), "0" (__x) \ : "0" (__x) \
: "memory"); \ : "memory"); \
break; \ break; \
case 4: \ case 4: \
asm volatile("xchgl %0,%1" \ asm volatile("xchgl %0,%1" \
: "=r" (__x) \ : "=r" (__x), "+m" (*__xg(ptr)) \
: "m" (*__xg(ptr)), "0" (__x) \ : "0" (__x) \
: "memory"); \ : "memory"); \
break; \ break; \
default: \ default: \
...@@ -70,14 +70,14 @@ static inline void __set_64bit(unsigned long long *ptr, ...@@ -70,14 +70,14 @@ static inline void __set_64bit(unsigned long long *ptr,
unsigned int low, unsigned int high) unsigned int low, unsigned int high)
{ {
asm volatile("\n1:\t" asm volatile("\n1:\t"
"movl (%0), %%eax\n\t" "movl (%1), %%eax\n\t"
"movl 4(%0), %%edx\n\t" "movl 4(%1), %%edx\n\t"
LOCK_PREFIX "cmpxchg8b (%0)\n\t" LOCK_PREFIX "cmpxchg8b (%1)\n\t"
"jnz 1b" "jnz 1b"
: /* no outputs */ : "=m" (*ptr)
: "D"(ptr), : "D" (ptr),
"b"(low), "b" (low),
"c"(high) "c" (high)
: "ax", "dx", "memory"); : "ax", "dx", "memory");
} }
...@@ -121,21 +121,21 @@ extern void __cmpxchg_wrong_size(void); ...@@ -121,21 +121,21 @@ extern void __cmpxchg_wrong_size(void);
__typeof__(*(ptr)) __new = (new); \ __typeof__(*(ptr)) __new = (new); \
switch (size) { \ switch (size) { \
case 1: \ case 1: \
asm volatile(lock "cmpxchgb %b1,%2" \ asm volatile(lock "cmpxchgb %b2,%1" \
: "=a"(__ret) \ : "=a" (__ret), "+m" (*__xg(ptr)) \
: "q"(__new), "m"(*__xg(ptr)), "0"(__old) \ : "q" (__new), "0" (__old) \
: "memory"); \ : "memory"); \
break; \ break; \
case 2: \ case 2: \
asm volatile(lock "cmpxchgw %w1,%2" \ asm volatile(lock "cmpxchgw %w2,%1" \
: "=a"(__ret) \ : "=a" (__ret), "+m" (*__xg(ptr)) \
: "r"(__new), "m"(*__xg(ptr)), "0"(__old) \ : "r" (__new), "0" (__old) \
: "memory"); \ : "memory"); \
break; \ break; \
case 4: \ case 4: \
asm volatile(lock "cmpxchgl %1,%2" \ asm volatile(lock "cmpxchgl %2,%1" \
: "=a"(__ret) \ : "=a" (__ret), "+m" (*__xg(ptr)) \
: "r"(__new), "m"(*__xg(ptr)), "0"(__old) \ : "r" (__new), "0" (__old) \
: "memory"); \ : "memory"); \
break; \ break; \
default: \ default: \
...@@ -180,12 +180,12 @@ static inline unsigned long long __cmpxchg64(volatile void *ptr, ...@@ -180,12 +180,12 @@ static inline unsigned long long __cmpxchg64(volatile void *ptr,
unsigned long long new) unsigned long long new)
{ {
unsigned long long prev; unsigned long long prev;
asm volatile(LOCK_PREFIX "cmpxchg8b %3" asm volatile(LOCK_PREFIX "cmpxchg8b %1"
: "=A"(prev) : "=A" (prev),
: "b"((unsigned long)new), "+m" (*__xg(ptr))
"c"((unsigned long)(new >> 32)), : "b" ((unsigned long)new),
"m"(*__xg(ptr)), "c" ((unsigned long)(new >> 32)),
"0"(old) "0" (old)
: "memory"); : "memory");
return prev; return prev;
} }
...@@ -195,12 +195,12 @@ static inline unsigned long long __cmpxchg64_local(volatile void *ptr, ...@@ -195,12 +195,12 @@ static inline unsigned long long __cmpxchg64_local(volatile void *ptr,
unsigned long long new) unsigned long long new)
{ {
unsigned long long prev; unsigned long long prev;
asm volatile("cmpxchg8b %3" asm volatile("cmpxchg8b %1"
: "=A"(prev) : "=A" (prev),
: "b"((unsigned long)new), "+m" (*__xg(ptr))
"c"((unsigned long)(new >> 32)), : "b" ((unsigned long)new),
"m"(*__xg(ptr)), "c" ((unsigned long)(new >> 32)),
"0"(old) "0" (old)
: "memory"); : "memory");
return prev; return prev;
} }
......
...@@ -26,26 +26,26 @@ extern void __cmpxchg_wrong_size(void); ...@@ -26,26 +26,26 @@ extern void __cmpxchg_wrong_size(void);
switch (size) { \ switch (size) { \
case 1: \ case 1: \
asm volatile("xchgb %b0,%1" \ asm volatile("xchgb %b0,%1" \
: "=q" (__x) \ : "=q" (__x), "+m" (*__xg(ptr)) \
: "m" (*__xg(ptr)), "0" (__x) \ : "0" (__x) \
: "memory"); \ : "memory"); \
break; \ break; \
case 2: \ case 2: \
asm volatile("xchgw %w0,%1" \ asm volatile("xchgw %w0,%1" \
: "=r" (__x) \ : "=r" (__x), "+m" (*__xg(ptr)) \
: "m" (*__xg(ptr)), "0" (__x) \ : "0" (__x) \
: "memory"); \ : "memory"); \
break; \ break; \
case 4: \ case 4: \
asm volatile("xchgl %k0,%1" \ asm volatile("xchgl %k0,%1" \
: "=r" (__x) \ : "=r" (__x), "+m" (*__xg(ptr)) \
: "m" (*__xg(ptr)), "0" (__x) \ : "0" (__x) \
: "memory"); \ : "memory"); \
break; \ break; \
case 8: \ case 8: \
asm volatile("xchgq %0,%1" \ asm volatile("xchgq %0,%1" \
: "=r" (__x) \ : "=r" (__x), "+m" (*__xg(ptr)) \
: "m" (*__xg(ptr)), "0" (__x) \ : "0" (__x) \
: "memory"); \ : "memory"); \
break; \ break; \
default: \ default: \
...@@ -71,27 +71,27 @@ extern void __cmpxchg_wrong_size(void); ...@@ -71,27 +71,27 @@ extern void __cmpxchg_wrong_size(void);
__typeof__(*(ptr)) __new = (new); \ __typeof__(*(ptr)) __new = (new); \
switch (size) { \ switch (size) { \
case 1: \ case 1: \
asm volatile(lock "cmpxchgb %b1,%2" \ asm volatile(lock "cmpxchgb %b2,%1" \
: "=a"(__ret) \ : "=a" (__ret), "+m" (*__xg(ptr)) \
: "q"(__new), "m"(*__xg(ptr)), "0"(__old) \ : "q" (__new), "0" (__old) \
: "memory"); \ : "memory"); \
break; \ break; \
case 2: \ case 2: \
asm volatile(lock "cmpxchgw %w1,%2" \ asm volatile(lock "cmpxchgw %w2,%1" \
: "=a"(__ret) \ : "=a" (__ret), "+m" (*__xg(ptr)) \
: "r"(__new), "m"(*__xg(ptr)), "0"(__old) \ : "r" (__new), "0" (__old) \
: "memory"); \ : "memory"); \
break; \ break; \
case 4: \ case 4: \
asm volatile(lock "cmpxchgl %k1,%2" \ asm volatile(lock "cmpxchgl %k2,%1" \
: "=a"(__ret) \ : "=a" (__ret), "+m" (*__xg(ptr)) \
: "r"(__new), "m"(*__xg(ptr)), "0"(__old) \ : "r" (__new), "0" (__old) \
: "memory"); \ : "memory"); \
break; \ break; \
case 8: \ case 8: \
asm volatile(lock "cmpxchgq %1,%2" \ asm volatile(lock "cmpxchgq %2,%1" \
: "=a"(__ret) \ : "=a" (__ret), "+m" (*__xg(ptr)) \
: "r"(__new), "m"(*__xg(ptr)), "0"(__old) \ : "r" (__new), "0" (__old) \
: "memory"); \ : "memory"); \
break; \ break; \
default: \ default: \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment