Re: Linux 2.6.32-rc1

Linus Torvalds
2009-09-29T21:57:22Z

On Tue, 29 Sep 2009, Arjan van de Ven wrote:
>
> can't we use alternatives() for this, to patch cmpxchg64 in ?
> I mean.. it'll be commonly supported nowadays.. the fallback to it not
> being supported could be a bit slower by now...

Yes, we could. It would limit us to some fixed address format, probably

cmpxchg8b (%esi)

or something. Use something like this as a starting point, perhaps?

NOTE! Totally untested! And you'd actually need to implement the
"cmpxchg8b_emu" function that takes it's arguments in %eax:%edx, %ebx:%ecx
and %esi and doesn't trash any other registers..

Linus

---
arch/x86/include/asm/cmpxchg_32.h | 27 ++++++++++++++-------------
1 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/arch/x86/include/asm/cmpxchg_32.h b/arch/x86/include/asm/cmpxchg_32.h
index 82ceb78..d16a486 100644
--- a/arch/x86/include/asm/cmpxchg_32.h
+++ b/arch/x86/include/asm/cmpxchg_32.h
@@ -312,19 +312,20 @@ static inline unsigned long cmpxchg_386(volatile void *ptr, unsigned long old,

extern unsigned long long cmpxchg_486_u64(volatile void *, u64, u64);

-#define cmpxchg64(ptr, o, n) \
-({ \
- __typeof__(*(ptr)) __ret; \
- if (likely(boot_cpu_data.x86 > 4)) \
- __ret = (__typeof__(*(ptr)))__cmpxchg64((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(ptr, o, n) \
+({ \
+ __typeof__(*(ptr)) __ret; \
+ __typeof__(*(ptr)) __old = (o); \
+ __typeof__(*(ptr)) __new = (n); \
+ alternative_io(LOCK_PREFIX "cmpxchg8b (%%esi)", \
+ "call cmpxchg8b_emu", \
+ X86_FEATURE_CMPXCHG8B, \
+ "=A" (__ret), \
+ "m" (*(ptr)), "0" (__old), \
+ "b" ((unsigned int)__new), \
+ "c" ((unsigned int)(__new>>32)) ); \
+ __ret; })
+
#define cmpxchg64_local(ptr, o, n) \
({ \
__typeof__(*(ptr)) __ret; \