Fixes x86 spinlocks with new gcc
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 14 Jan 2015 21:21:26 +0000 (13:21 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 14 Jan 2015 21:29:29 +0000 (13:29 -0800)
Newer versions of GCC screw up our ancient spinlocks.

The issue was that "m" can include (%rax) implicitly, and GCC does not give us
a way to tell it to not use that register.  Previously, putting "eax" in the
clobber list was enough (maybe!) to tell GCC to not mess with it.  But it
really only tells GCC not to use it afterwards.  There is no way to tell it to
not use it during.  And we don't know which register they picked.  The fix is
to use a dummy variable, to force GCC to give us a register to play with.

To make things fun to track down, the location of the KMSG immediate lock in
pcpui mattered for this, since the clobber of rax's lower byte made a
diffference with how this would show up.

If we have any other inline asm with "m" in the input:output, we'll need to
take a look.

For a similar horror story, check out:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58758

Note the answer was basically "don't use inline asm."

kern/arch/x86/atomic.h

index eaaa761..ad4e066 100644 (file)
@@ -127,6 +127,7 @@ static inline bool spin_locked(spinlock_t *lock)
 
 static inline void __spin_lock_raw(volatile uint32_t *rlock)
 {
+       uint8_t dicks = 0;
        asm volatile(
                        "1:                       "
                        "       cmpb $0, %0;          "
@@ -134,11 +135,11 @@ static inline void __spin_lock_raw(volatile uint32_t *rlock)
                        "       pause;                "
                        "       jmp 1b;               "
                        "2:                       " 
-                       "       movb $1, %%al;        "
-                       "       xchgb %%al, %0;       "
-                       "       cmpb $0, %%al;        "
+                       "       movb $1, %1;          "
+                       "       xchgb %1, %0;         "
+                       "       cmpb $0, %1;          "
                        "       jne 1b;               "
-               : : "m"(*rlock) : "eax", "cc");
+               : : "m"(*rlock), "r"(dicks) : "cc");
        cmb();  /* need cmb(), the CPU mb() was handled by the xchg */
 }