x86, asm: Merge cmpxchg_486_u64() and cmpxchg8b_emu()
H. Peter Anvin [Thu, 29 Jul 2010 00:05:11 +0000 (17:05 -0700)]
We have two functions for doing exactly the same thing -- emulating
cmpxchg8b on 486 and older hardware -- with different calling
conventions, and yet doing the same thing.  Drop the C version and use
the assembly version, via alternatives, for both the local and
non-local versions of cmpxchg8b.

Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
LKML-Reference: <AANLkTikAmaDPji-TVDarmG1yD=fwbffcsmEU=YEuP+8r@mail.gmail.com>

arch/x86/include/asm/cmpxchg_32.h
arch/x86/lib/cmpxchg.c

index f5bd1fd..284a6e8 100644 (file)
@@ -246,8 +246,6 @@ static inline unsigned long cmpxchg_386(volatile void *ptr, unsigned long old,
  * to simulate the cmpxchg8b on the 80386 and 80486 CPU.
  */
 
-extern unsigned long long cmpxchg_486_u64(volatile void *, u64, u64);
-
 #define cmpxchg64(ptr, o, n)                                   \
 ({                                                             \
        __typeof__(*(ptr)) __ret;                               \
@@ -265,20 +263,20 @@ extern unsigned long long cmpxchg_486_u64(volatile void *, u64, u64);
        __ret; })
 
 
-
-#define cmpxchg64_local(ptr, o, n)                                     \
-({                                                                     \
-       __typeof__(*(ptr)) __ret;                                       \
-       if (likely(boot_cpu_data.x86 > 4))                              \
-               __ret = (__typeof__(*(ptr)))__cmpxchg64_local((ptr),    \
-                               (unsigned long long)(o),                \
-                               (unsigned long long)(n));               \
-       else                                                            \
-               __ret = (__typeof__(*(ptr)))cmpxchg_486_u64((ptr),      \
-                               (unsigned long long)(o),                \
-                               (unsigned long long)(n));               \
-       __ret;                                                          \
-})
+#define cmpxchg64_local(ptr, o, n)                             \
+({                                                             \
+       __typeof__(*(ptr)) __ret;                               \
+       __typeof__(*(ptr)) __old = (o);                         \
+       __typeof__(*(ptr)) __new = (n);                         \
+       alternative_io("call cmpxchg8b_emu",                    \
+                      "cmpxchg8b (%%esi)" ,                    \
+                      X86_FEATURE_CX8,                         \
+                      "=A" (__ret),                            \
+                      "S" ((ptr)), "0" (__old),                \
+                      "b" ((unsigned int)__new),               \
+                      "c" ((unsigned int)(__new>>32))          \
+                      : "memory");                             \
+       __ret; })
 
 #endif
 
index 2056ccf..5d619f6 100644 (file)
@@ -52,21 +52,3 @@ unsigned long cmpxchg_386_u32(volatile void *ptr, u32 old, u32 new)
 }
 EXPORT_SYMBOL(cmpxchg_386_u32);
 #endif
-
-#ifndef CONFIG_X86_CMPXCHG64
-unsigned long long cmpxchg_486_u64(volatile void *ptr, u64 old, u64 new)
-{
-       u64 prev;
-       unsigned long flags;
-
-       /* Poor man's cmpxchg8b for 386 and 486. Unsuitable for SMP */
-       local_irq_save(flags);
-       prev = *(u64 *)ptr;
-       if (prev == old)
-               *(u64 *)ptr = new;
-       local_irq_restore(flags);
-       return prev;
-}
-EXPORT_SYMBOL(cmpxchg_486_u64);
-#endif
-