diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2013-12-04 17:31:28 -0500 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2013-12-04 17:31:28 -0500 |
commit | e0f6dec35f9286e78879fe1ac92803fd69fc4fdc (patch) | |
tree | e24a09b061bbb0c7d6f6da371e277324ea034e38 | |
parent | 5551a34e5aeab868f8d37f70d8754868921b4ee5 (diff) |
x86, bitops: Correct the assembly constraints to testing bitops
In checkin:
0c44c2d0f459 x86: Use asm goto to implement better modify_and_test() functions
the various functions which do modify and test were unified and
optimized using "asm goto". However, this change missed the detail
that the bitops require an "Ir" constraint rather than an "er"
constraint ("I" = integer constant from 0-31, "e" = signed 32-bit
integer constant). This would cause code to miscompile if these
functions were used on constant bit positions 32-255 and the build to
fail if used on constant bit positions above 255.
Add the constraints as a parameter to the GEN_BINARY_RMWcc() macro to
avoid this problem.
Reported-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/529E8719.4070202@zytor.com
-rw-r--r-- | arch/x86/include/asm/atomic.h | 4 | ||||
-rw-r--r-- | arch/x86/include/asm/atomic64_64.h | 4 | ||||
-rw-r--r-- | arch/x86/include/asm/bitops.h | 6 | ||||
-rw-r--r-- | arch/x86/include/asm/local.h | 4 | ||||
-rw-r--r-- | arch/x86/include/asm/rmwcc.h | 8 |
5 files changed, 13 insertions, 13 deletions
diff --git a/arch/x86/include/asm/atomic.h b/arch/x86/include/asm/atomic.h index da31c8b8a92d..b17f4f48ecd7 100644 --- a/arch/x86/include/asm/atomic.h +++ b/arch/x86/include/asm/atomic.h | |||
@@ -77,7 +77,7 @@ static inline void atomic_sub(int i, atomic_t *v) | |||
77 | */ | 77 | */ |
78 | static inline int atomic_sub_and_test(int i, atomic_t *v) | 78 | static inline int atomic_sub_and_test(int i, atomic_t *v) |
79 | { | 79 | { |
80 | GEN_BINARY_RMWcc(LOCK_PREFIX "subl", v->counter, i, "%0", "e"); | 80 | GEN_BINARY_RMWcc(LOCK_PREFIX "subl", v->counter, "er", i, "%0", "e"); |
81 | } | 81 | } |
82 | 82 | ||
83 | /** | 83 | /** |
@@ -141,7 +141,7 @@ static inline int atomic_inc_and_test(atomic_t *v) | |||
141 | */ | 141 | */ |
142 | static inline int atomic_add_negative(int i, atomic_t *v) | 142 | static inline int atomic_add_negative(int i, atomic_t *v) |
143 | { | 143 | { |
144 | GEN_BINARY_RMWcc(LOCK_PREFIX "addl", v->counter, i, "%0", "s"); | 144 | GEN_BINARY_RMWcc(LOCK_PREFIX "addl", v->counter, "er", i, "%0", "s"); |
145 | } | 145 | } |
146 | 146 | ||
147 | /** | 147 | /** |
diff --git a/arch/x86/include/asm/atomic64_64.h b/arch/x86/include/asm/atomic64_64.h index 3f065c985aee..46e9052bbd28 100644 --- a/arch/x86/include/asm/atomic64_64.h +++ b/arch/x86/include/asm/atomic64_64.h | |||
@@ -72,7 +72,7 @@ static inline void atomic64_sub(long i, atomic64_t *v) | |||
72 | */ | 72 | */ |
73 | static inline int atomic64_sub_and_test(long i, atomic64_t *v) | 73 | static inline int atomic64_sub_and_test(long i, atomic64_t *v) |
74 | { | 74 | { |
75 | GEN_BINARY_RMWcc(LOCK_PREFIX "subq", v->counter, i, "%0", "e"); | 75 | GEN_BINARY_RMWcc(LOCK_PREFIX "subq", v->counter, "er", i, "%0", "e"); |
76 | } | 76 | } |
77 | 77 | ||
78 | /** | 78 | /** |
@@ -138,7 +138,7 @@ static inline int atomic64_inc_and_test(atomic64_t *v) | |||
138 | */ | 138 | */ |
139 | static inline int atomic64_add_negative(long i, atomic64_t *v) | 139 | static inline int atomic64_add_negative(long i, atomic64_t *v) |
140 | { | 140 | { |
141 | GEN_BINARY_RMWcc(LOCK_PREFIX "addq", v->counter, i, "%0", "s"); | 141 | GEN_BINARY_RMWcc(LOCK_PREFIX "addq", v->counter, "er", i, "%0", "s"); |
142 | } | 142 | } |
143 | 143 | ||
144 | /** | 144 | /** |
diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h index 6d76d0935989..9fc1af74dc83 100644 --- a/arch/x86/include/asm/bitops.h +++ b/arch/x86/include/asm/bitops.h | |||
@@ -205,7 +205,7 @@ static inline void change_bit(long nr, volatile unsigned long *addr) | |||
205 | */ | 205 | */ |
206 | static inline int test_and_set_bit(long nr, volatile unsigned long *addr) | 206 | static inline int test_and_set_bit(long nr, volatile unsigned long *addr) |
207 | { | 207 | { |
208 | GEN_BINARY_RMWcc(LOCK_PREFIX "bts", *addr, nr, "%0", "c"); | 208 | GEN_BINARY_RMWcc(LOCK_PREFIX "bts", *addr, "Ir", nr, "%0", "c"); |
209 | } | 209 | } |
210 | 210 | ||
211 | /** | 211 | /** |
@@ -251,7 +251,7 @@ static inline int __test_and_set_bit(long nr, volatile unsigned long *addr) | |||
251 | */ | 251 | */ |
252 | static inline int test_and_clear_bit(long nr, volatile unsigned long *addr) | 252 | static inline int test_and_clear_bit(long nr, volatile unsigned long *addr) |
253 | { | 253 | { |
254 | GEN_BINARY_RMWcc(LOCK_PREFIX "btr", *addr, nr, "%0", "c"); | 254 | GEN_BINARY_RMWcc(LOCK_PREFIX "btr", *addr, "Ir", nr, "%0", "c"); |
255 | } | 255 | } |
256 | 256 | ||
257 | /** | 257 | /** |
@@ -304,7 +304,7 @@ static inline int __test_and_change_bit(long nr, volatile unsigned long *addr) | |||
304 | */ | 304 | */ |
305 | static inline int test_and_change_bit(long nr, volatile unsigned long *addr) | 305 | static inline int test_and_change_bit(long nr, volatile unsigned long *addr) |
306 | { | 306 | { |
307 | GEN_BINARY_RMWcc(LOCK_PREFIX "btc", *addr, nr, "%0", "c"); | 307 | GEN_BINARY_RMWcc(LOCK_PREFIX "btc", *addr, "Ir", nr, "%0", "c"); |
308 | } | 308 | } |
309 | 309 | ||
310 | static __always_inline int constant_test_bit(long nr, const volatile unsigned long *addr) | 310 | static __always_inline int constant_test_bit(long nr, const volatile unsigned long *addr) |
diff --git a/arch/x86/include/asm/local.h b/arch/x86/include/asm/local.h index 5b23e605e707..4ad6560847b1 100644 --- a/arch/x86/include/asm/local.h +++ b/arch/x86/include/asm/local.h | |||
@@ -52,7 +52,7 @@ static inline void local_sub(long i, local_t *l) | |||
52 | */ | 52 | */ |
53 | static inline int local_sub_and_test(long i, local_t *l) | 53 | static inline int local_sub_and_test(long i, local_t *l) |
54 | { | 54 | { |
55 | GEN_BINARY_RMWcc(_ASM_SUB, l->a.counter, i, "%0", "e"); | 55 | GEN_BINARY_RMWcc(_ASM_SUB, l->a.counter, "er", i, "%0", "e"); |
56 | } | 56 | } |
57 | 57 | ||
58 | /** | 58 | /** |
@@ -92,7 +92,7 @@ static inline int local_inc_and_test(local_t *l) | |||
92 | */ | 92 | */ |
93 | static inline int local_add_negative(long i, local_t *l) | 93 | static inline int local_add_negative(long i, local_t *l) |
94 | { | 94 | { |
95 | GEN_BINARY_RMWcc(_ASM_ADD, l->a.counter, i, "%0", "s"); | 95 | GEN_BINARY_RMWcc(_ASM_ADD, l->a.counter, "er", i, "%0", "s"); |
96 | } | 96 | } |
97 | 97 | ||
98 | /** | 98 | /** |
diff --git a/arch/x86/include/asm/rmwcc.h b/arch/x86/include/asm/rmwcc.h index 1ff990f1de8e..8f7866a5b9a4 100644 --- a/arch/x86/include/asm/rmwcc.h +++ b/arch/x86/include/asm/rmwcc.h | |||
@@ -16,8 +16,8 @@ cc_label: \ | |||
16 | #define GEN_UNARY_RMWcc(op, var, arg0, cc) \ | 16 | #define GEN_UNARY_RMWcc(op, var, arg0, cc) \ |
17 | __GEN_RMWcc(op " " arg0, var, cc) | 17 | __GEN_RMWcc(op " " arg0, var, cc) |
18 | 18 | ||
19 | #define GEN_BINARY_RMWcc(op, var, val, arg0, cc) \ | 19 | #define GEN_BINARY_RMWcc(op, var, vcon, val, arg0, cc) \ |
20 | __GEN_RMWcc(op " %1, " arg0, var, cc, "er" (val)) | 20 | __GEN_RMWcc(op " %1, " arg0, var, cc, vcon (val)) |
21 | 21 | ||
22 | #else /* !CC_HAVE_ASM_GOTO */ | 22 | #else /* !CC_HAVE_ASM_GOTO */ |
23 | 23 | ||
@@ -33,8 +33,8 @@ do { \ | |||
33 | #define GEN_UNARY_RMWcc(op, var, arg0, cc) \ | 33 | #define GEN_UNARY_RMWcc(op, var, arg0, cc) \ |
34 | __GEN_RMWcc(op " " arg0, var, cc) | 34 | __GEN_RMWcc(op " " arg0, var, cc) |
35 | 35 | ||
36 | #define GEN_BINARY_RMWcc(op, var, val, arg0, cc) \ | 36 | #define GEN_BINARY_RMWcc(op, var, vcon, val, arg0, cc) \ |
37 | __GEN_RMWcc(op " %2, " arg0, var, cc, "er" (val)) | 37 | __GEN_RMWcc(op " %2, " arg0, var, cc, vcon (val)) |
38 | 38 | ||
39 | #endif /* CC_HAVE_ASM_GOTO */ | 39 | #endif /* CC_HAVE_ASM_GOTO */ |
40 | 40 | ||