Messages in this thread Patch in this message | | | Date | Tue, 29 Sep 2009 14:56:28 -0700 (PDT) | From | Linus Torvalds <> | Subject | Re: Linux 2.6.32-rc1 |
| |
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; \
| |