public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC] x86: bitops asm constraint fixes
@ 2008-03-13  9:08 Jan Beulich
  2008-03-14  7:51 ` H. Peter Anvin
                   ` (3 more replies)
  0 siblings, 4 replies; 16+ messages in thread
From: Jan Beulich @ 2008-03-13  9:08 UTC (permalink / raw)
  To: mingo, tglx, hpa; +Cc: linux-kernel

This (simplified) piece of code didn't behave as expected due to
incorrect constraints in some of the bitops functions, when
X86_FEATURE_xxx is referring to other than the first long:

int test(struct cpuinfo_x86 *c) {
	if (cpu_has(c, X86_FEATURE_xxx))
		clear_cpu_cap(c, X86_FEATURE_xxx);
	return cpu_has(c, X86_FEATURE_xxx);
}

I'd really like understand, though, what the policy of (not) having a
"memory" clobber in these operations is - currently, this appears to
be totally inconsistent. Also, many comments of the non-atomic
functions say those may also be re-ordered - this contradicts the use
of "asm volatile" in there, which again I'd like to understand.

As much as all of these, using 'int' for the 'nr' parameter and
'void *' for the 'addr' one is in conflict with
Documentation/atomic_ops.txt, especially because bt{,c,r,s} indeed
take the bit index as signed (which hence would really need special
precaution) and access the full 32 bits (if 'unsigned long' was used
properly here, 64 bits for x86-64) pointed at, so invalid uses like
referencing a 'char' array cannot currently be caught.

Finally, the code with and without this patch relies heavily on the
-fno-strict-aliasing compiler switch and I'm not certain this really
is a good idea.

In the light of all of this I'm sending this as RFC, as fixing the
above might warrant a much bigger patch...

Signed-off-by: Jan Beulich <jbeulich@novell.com>

---
 include/asm-x86/bitops.h |   43 ++++++++++++++++++++++++-------------------
 1 file changed, 24 insertions(+), 19 deletions(-)

--- linux-2.6.25-rc5/include/asm-x86/bitops.h	2008-03-10 13:24:33.000000000 +0100
+++ 2.6.25-rc5-x86-clear-bit/include/asm-x86/bitops.h	2008-03-13 08:45:40.000000000 +0100
@@ -24,9 +24,12 @@
 /* Technically wrong, but this avoids compilation errors on some gcc
    versions. */
 #define ADDR "=m" (*(volatile long *) addr)
+#define BIT_ADDR "=m" (((volatile int *) addr)[nr >> 5])
 #else
 #define ADDR "+m" (*(volatile long *) addr)
+#define BIT_ADDR "+m" (((volatile int *) addr)[nr >> 5])
 #endif
+#define BASE_ADDR "m" (*(volatile int *) addr)
 
 /**
  * set_bit - Atomically set a bit in memory
@@ -79,9 +82,8 @@ static inline void __set_bit(int nr, vol
  */
 static inline void clear_bit(int nr, volatile void *addr)
 {
-	asm volatile(LOCK_PREFIX "btr %1,%0"
-		     : ADDR
-		     : "Ir" (nr));
+	asm volatile(LOCK_PREFIX "btr %1,%2"
+		     : BIT_ADDR : "Ir" (nr), BASE_ADDR);
 }
 
 /*
@@ -100,7 +102,7 @@ static inline void clear_bit_unlock(unsi
 
 static inline void __clear_bit(int nr, volatile void *addr)
 {
-	asm volatile("btr %1,%0" : ADDR : "Ir" (nr));
+	asm volatile("btr %1,%2" : BIT_ADDR : "Ir" (nr), BASE_ADDR);
 }
 
 /*
@@ -135,7 +137,7 @@ static inline void __clear_bit_unlock(un
  */
 static inline void __change_bit(int nr, volatile void *addr)
 {
-	asm volatile("btc %1,%0" : ADDR : "Ir" (nr));
+	asm volatile("btc %1,%2" : BIT_ADDR : "Ir" (nr), BASE_ADDR);
 }
 
 /**
@@ -149,8 +151,8 @@ static inline void __change_bit(int nr, 
  */
 static inline void change_bit(int nr, volatile void *addr)
 {
-	asm volatile(LOCK_PREFIX "btc %1,%0"
-		     : ADDR : "Ir" (nr));
+	asm volatile(LOCK_PREFIX "btc %1,%2"
+		     : BIT_ADDR : "Ir" (nr), BASE_ADDR);
 }
 
 /**
@@ -198,10 +200,10 @@ static inline int __test_and_set_bit(int
 {
 	int oldbit;
 
-	asm("bts %2,%1\n\t"
-	    "sbb %0,%0"
-	    : "=r" (oldbit), ADDR
-	    : "Ir" (nr));
+	asm volatile("bts %2,%3\n\t"
+		     "sbb %0,%0"
+		     : "=r" (oldbit), BIT_ADDR
+		     : "Ir" (nr), BASE_ADDR);
 	return oldbit;
 }
 
@@ -238,10 +240,10 @@ static inline int __test_and_clear_bit(i
 {
 	int oldbit;
 
-	asm volatile("btr %2,%1\n\t"
+	asm volatile("btr %2,%3\n\t"
 		     "sbb %0,%0"
-		     : "=r" (oldbit), ADDR
-		     : "Ir" (nr));
+		     : "=r" (oldbit), BIT_ADDR
+		     : "Ir" (nr), BASE_ADDR);
 	return oldbit;
 }
 
@@ -250,10 +252,10 @@ static inline int __test_and_change_bit(
 {
 	int oldbit;
 
-	asm volatile("btc %2,%1\n\t"
+	asm volatile("btc %2,%3\n\t"
 		     "sbb %0,%0"
-		     : "=r" (oldbit), ADDR
-		     : "Ir" (nr) : "memory");
+		     : "=r" (oldbit), BIT_ADDR
+		     : "Ir" (nr), BASE_ADDR);
 
 	return oldbit;
 }
@@ -288,10 +290,11 @@ static inline int variable_test_bit(int 
 {
 	int oldbit;
 
-	asm volatile("bt %2,%1\n\t"
+	asm volatile("bt %2,%3\n\t"
 		     "sbb %0,%0"
 		     : "=r" (oldbit)
-		     : "m" (*(unsigned long *)addr), "Ir" (nr));
+		     : "m" (((volatile const int *)addr)[nr >> 5]),
+		       "Ir" (nr), BASE_ADDR);
 
 	return oldbit;
 }
@@ -310,6 +313,8 @@ static int test_bit(int nr, const volati
 	 constant_test_bit((nr),(addr)) :	\
 	 variable_test_bit((nr),(addr)))
 
+#undef BASE_ADDR
+#undef BIT_ADDR
 #undef ADDR
 
 #ifdef CONFIG_X86_32



^ permalink raw reply	[flat|nested] 16+ messages in thread
* Re: [RFC] x86: bitops asm constraint fixes
@ 2008-03-27  8:12 Jan Beulich
  2008-03-27  8:41 ` Ingo Molnar
  0 siblings, 1 reply; 16+ messages in thread
From: Jan Beulich @ 2008-03-27  8:12 UTC (permalink / raw)
  To: mingo; +Cc: tglx, linux-kernel, hpa

Please revert it for the time being, I've got a better version (i.e.
without extra dead code being generated) that I intended to
submit once I know whether the other issues pointed out in the
description on the original patch also should be adjusted. Of
course, that could also be done incrementally, but I would think
overhauling the whole file at once wouldn't be a bad thing...

Jan

>>> Ingo Molnar <mingo@elte.hu> 03/21/08 2:54 PM >>>

thanks Jan, i've applied your patch.

	Ingo


^ permalink raw reply	[flat|nested] 16+ messages in thread
* Re: [RFC] x86: bitops asm constraint fixes
@ 2008-03-28 19:55 Jan Beulich
  0 siblings, 0 replies; 16+ messages in thread
From: Jan Beulich @ 2008-03-28 19:55 UTC (permalink / raw)
  To: mingo; +Cc: tglx, linux-kernel, hpa

>>> Ingo Molnar <mingo@elte.hu> 03/27/08 9:41 AM >>>
>
>* Jan Beulich <jbeulich@novell.com> wrote:
>
>> Please revert it for the time being, I've got a better version (i.e. 
>> without extra dead code being generated) that I intended to submit 
>> once I know whether the other issues pointed out in the description on 
>> the original patch also should be adjusted. Of course, that could also 
>> be done incrementally, but I would think overhauling the whole file at 
>> once wouldn't be a bad thing...
>
>since it appears to cause no problems in x86.git (it passed a lot of 
>testing already) i'd prefer to keep it (so that we can see any other 
>side-effects of touching this code) - could you send your improvements 
>as a delta against x86.git/latest? [or is there any outright bug caused 
>by your changes that necessiates a revert?]

That's fine with me (and no, there's no bug in there other than the
mentioned dead code generation).

Jan

^ permalink raw reply	[flat|nested] 16+ messages in thread
* Re: [RFC] x86: bitops asm constraint fixes
@ 2008-04-14 13:31 Jan Beulich
  2008-04-14 16:21 ` Jeremy Fitzhardinge
  0 siblings, 1 reply; 16+ messages in thread
From: Jan Beulich @ 2008-04-14 13:31 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: tglx, linux-kernel, hpa

>>> Ingo Molnar <mingo@elte.hu> 27.03.08 09:41 >>>
>
>* Jan Beulich <jbeulich@novell.com> wrote:
>
>> Please revert it for the time being, I've got a better version (i.e. 
>> without extra dead code being generated) that I intended to submit 
>> once I know whether the other issues pointed out in the description on 
>> the original patch also should be adjusted. Of course, that could also 
>> be done incrementally, but I would think overhauling the whole file at 
>> once wouldn't be a bad thing...
>
>since it appears to cause no problems in x86.git (it passed a lot of 
>testing already) i'd prefer to keep it (so that we can see any other 
>side-effects of touching this code) - could you send your improvements 
>as a delta against x86.git/latest? [or is there any outright bug caused 
>by your changes that necessiates a revert?]

(Sorry, need to resend, previous version was lacking a refresh.)

For those bitops that don't have a memory clobber, make the asm
constraints more precise. It still remains questionable whether the
inconsistencies in the use of memory clobbers shouldn't be addressed.

Signed-off-by: Jan Beulich <jbeulich@novell.com>

--- x86.git/include/asm-x86/bitops.h
+++ x86.git/include/asm-x86/bitops.h
@@ -20,16 +20,20 @@
  * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
  */
 
+struct __bits { int _[1UL << (32 - 3 - sizeof(int))]; };
+
 #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1)
 /* Technically wrong, but this avoids compilation errors on some gcc
    versions. */
-#define ADDR "=m" (*(volatile long *)addr)
-#define BIT_ADDR "=m" (((volatile int *)addr)[nr >> 5])
+#define ADDR "=m" (*(volatile long *) addr)
+#define BIT_ADDR "=m" (((volatile int *) addr)[nr >> 5])
+#define FULL_ADDR "=m" (*(volatile struct __bits *) addr)
 #else
 #define ADDR "+m" (*(volatile long *) addr)
-#define BIT_ADDR "+m" (((volatile int *)addr)[nr >> 5])
+#define BIT_ADDR "+m" (((volatile int *) addr)[nr >> 5])
+#define FULL_ADDR "+m" (*(volatile struct __bits *) addr)
 #endif
-#define BASE_ADDR "m" (*(volatile int *)addr)
+#define BASE_ADDR "m" (*(volatile int *) addr)
 
 /**
  * set_bit - Atomically set a bit in memory
@@ -62,7 +68,10 @@ static inline void set_bit(int nr, volat
  */
 static inline void __set_bit(int nr, volatile void *addr)
 {
-	asm volatile("bts %1,%0" : ADDR : "Ir" (nr) : "memory");
+	if (__builtin_constant_p(nr))
+		asm volatile("bts %1,%2" : BIT_ADDR : "Ir" (nr), BASE_ADDR);
+	else
+		asm volatile("bts %1,%0" : FULL_ADDR : "r" (nr));
 }
 
 /**
@@ -77,7 +87,11 @@ static inline void __set_bit(int nr, vol
  */
 static inline void clear_bit(int nr, volatile void *addr)
 {
-	asm volatile(LOCK_PREFIX "btr %1,%2" : BIT_ADDR : "Ir" (nr), BASE_ADDR);
+	if (__builtin_constant_p(nr))
+		asm volatile(LOCK_PREFIX "btr %1,%2"
+			     : BIT_ADDR : "Ir" (nr), BASE_ADDR);
+	else
+		asm volatile(LOCK_PREFIX "btr %1,%0" : FULL_ADDR : "r" (nr));
 }
 
 /*
@@ -96,7 +110,10 @@ static inline void clear_bit_unlock(unsi
 
 static inline void __clear_bit(int nr, volatile void *addr)
 {
-	asm volatile("btr %1,%2" : BIT_ADDR : "Ir" (nr), BASE_ADDR);
+	if (__builtin_constant_p(nr))
+		asm volatile("btr %1,%2" : BIT_ADDR : "Ir" (nr), BASE_ADDR);
+	else
+		asm volatile("btr %1,%0" : FULL_ADDR : "r" (nr));
 }
 
 /*
@@ -131,7 +148,10 @@ static inline void __clear_bit_unlock(un
  */
 static inline void __change_bit(int nr, volatile void *addr)
 {
-	asm volatile("btc %1,%2" : BIT_ADDR : "Ir" (nr), BASE_ADDR);
+	if (__builtin_constant_p(nr))
+		asm volatile("btc %1,%2" : BIT_ADDR : "Ir" (nr), BASE_ADDR);
+	else
+		asm volatile("btc %1,%0" : FULL_ADDR : "r" (nr));
 }
 
 /**
@@ -145,7 +165,11 @@ static inline void __change_bit(int nr, 
  */
 static inline void change_bit(int nr, volatile void *addr)
 {
-	asm volatile(LOCK_PREFIX "btc %1,%2" : BIT_ADDR : "Ir" (nr), BASE_ADDR);
+	if (__builtin_constant_p(nr))
+		asm volatile(LOCK_PREFIX "btc %1,%2"
+			     : BIT_ADDR : "Ir" (nr), BASE_ADDR);
+	else
+		asm volatile(LOCK_PREFIX "btc %1,%0" : FULL_ADDR : "r" (nr));
 }
 
 /**
@@ -191,9 +217,15 @@ static inline int __test_and_set_bit(int
 {
 	int oldbit;
 
-	asm volatile("bts %2,%3\n\t"
-		     "sbb %0,%0"
-		     : "=r" (oldbit), BIT_ADDR : "Ir" (nr), BASE_ADDR);
+	if (__builtin_constant_p(nr))
+		asm volatile("bts %2,%3\n\t"
+			     "sbb %0,%0"
+			     : "=r" (oldbit), BIT_ADDR : "Ir" (nr), BASE_ADDR);
+	else
+		asm volatile("bts %2,%1\n\t"
+			     "sbb %0,%0"
+			     : "=r" (oldbit), FULL_ADDR : "r" (nr));
+
 	return oldbit;
 }
 
@@ -229,9 +262,15 @@ static inline int __test_and_clear_bit(i
 {
 	int oldbit;
 
-	asm volatile("btr %2,%3\n\t"
-		     "sbb %0,%0"
-		     : "=r" (oldbit), BIT_ADDR : "Ir" (nr), BASE_ADDR);
+	if (__builtin_constant_p(nr))
+		asm volatile("btr %2,%3\n\t"
+			     "sbb %0,%0"
+			     : "=r" (oldbit), BIT_ADDR : "Ir" (nr), BASE_ADDR);
+	else
+		asm volatile("btr %2,%1\n\t"
+			     "sbb %0,%0"
+			     : "=r" (oldbit), FULL_ADDR : "r" (nr));
+
 	return oldbit;
 }
 
@@ -240,9 +279,14 @@ static inline int __test_and_change_bit(
 {
 	int oldbit;
 
-	asm volatile("btc %2,%3\n\t"
-		     "sbb %0,%0"
-		     : "=r" (oldbit), BIT_ADDR : "Ir" (nr), BASE_ADDR);
+	if (__builtin_constant_p(nr))
+		asm volatile("btc %2,%3\n\t"
+			     "sbb %0,%0"
+			     : "=r" (oldbit), BIT_ADDR : "Ir" (nr), BASE_ADDR);
+	else
+		asm volatile("btc %2,%1\n\t"
+			     "sbb %0,%0"
+			     : "=r" (oldbit), FULL_ADDR : "r" (nr));
 
 	return oldbit;
 }
@@ -276,11 +321,10 @@ static inline int variable_test_bit(int 
 {
 	int oldbit;
 
-	asm volatile("bt %2,%3\n\t"
+	asm volatile("bt %2,%1\n\t"
 		     "sbb %0,%0"
 		     : "=r" (oldbit)
-		     : "m" (((volatile const int *)addr)[nr >> 5]),
-		       "Ir" (nr), BASE_ADDR);
+		     : "m" (*(volatile struct __bits *) addr), "Ir" (nr));
 
 	return oldbit;
 }
@@ -398,6 +431,7 @@ static int test_bit(int nr, const volati
 #endif /* __KERNEL__ */
 
 #undef BASE_ADDR
+#undef FULL_ADDR
 #undef BIT_ADDR
 #undef ADDR
 



^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2008-04-15  7:02 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-03-13  9:08 [RFC] x86: bitops asm constraint fixes Jan Beulich
2008-03-14  7:51 ` H. Peter Anvin
2008-03-14  8:09   ` Jan Beulich
2008-03-14 18:56 ` Jeremy Fitzhardinge
2008-03-17  9:08   ` Jan Beulich
2008-03-14 21:07 ` Chuck Ebbert
2008-03-17  9:16   ` Jan Beulich
2008-03-19 13:19     ` H. Peter Anvin
2008-03-21 13:54 ` Ingo Molnar
  -- strict thread matches above, loose matches on Subject: below --
2008-03-27  8:12 Jan Beulich
2008-03-27  8:41 ` Ingo Molnar
2008-04-14 12:53   ` Jan Beulich
2008-03-28 19:55 Jan Beulich
2008-04-14 13:31 Jan Beulich
2008-04-14 16:21 ` Jeremy Fitzhardinge
2008-04-15  7:03   ` Jan Beulich

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox