summaryrefslogtreecommitdiff
path: root/arch/s390/include
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2012-05-29 12:11:21 +0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2012-05-30 11:07:57 +0400
commitbf3db85311292eeacc9a9a8f38a0a4065a43a2fc (patch)
tree3061cba9ea7ba20905ebb202a81c6da76debfe6d /arch/s390/include
parent6b894a409e8c0fcbd0ea30f5b013e33b9c4b28a1 (diff)
downloadlinux-bf3db85311292eeacc9a9a8f38a0a4065a43a2fc.tar.xz
s390/cmpxchg: fix 1 and 2 byte memory accesses
When accessing a 1 or 2 byte memory operand we cannot use the passed address since the compare and swap instruction only works for 4 byte aligned memory operands. Hence we calculate an aligned address so that compare and swap works correctly. However we don't pass the calculated address to the inline assembly. This results in incorrect memory accesses and in a specification exception if used on non 4 byte aligned memory operands. Since this didn't happen until now, there don't seem to be too many users of cmpxchg on unaligned addresses. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/include')
-rw-r--r--arch/s390/include/asm/cmpxchg.h8
1 files changed, 4 insertions, 4 deletions
diff --git a/arch/s390/include/asm/cmpxchg.h b/arch/s390/include/asm/cmpxchg.h
index 13c8b2eb6983..26f2cb1aa9ff 100644
--- a/arch/s390/include/asm/cmpxchg.h
+++ b/arch/s390/include/asm/cmpxchg.h
@@ -113,9 +113,9 @@ static inline unsigned long __cmpxchg(void *ptr, unsigned long old,
" nr %1,%5\n"
" jnz 0b\n"
"1:"
- : "=&d" (prev), "=&d" (tmp), "=Q" (*(int *) ptr)
+ : "=&d" (prev), "=&d" (tmp), "+Q" (*(int *) addr)
: "d" (old << shift), "d" (new << shift),
- "d" (~(255 << shift)), "Q" (*(int *) ptr)
+ "d" (~(255 << shift))
: "memory", "cc");
return prev >> shift;
case 2:
@@ -134,9 +134,9 @@ static inline unsigned long __cmpxchg(void *ptr, unsigned long old,
" nr %1,%5\n"
" jnz 0b\n"
"1:"
- : "=&d" (prev), "=&d" (tmp), "=Q" (*(int *) ptr)
+ : "=&d" (prev), "=&d" (tmp), "+Q" (*(int *) addr)
: "d" (old << shift), "d" (new << shift),
- "d" (~(65535 << shift)), "Q" (*(int *) ptr)
+ "d" (~(65535 << shift))
: "memory", "cc");
return prev >> shift;
case 4: