[PATCH] cmpxchg(8b) fixes.

From: Paweł Sikora
Date: Sat Aug 07 2004 - 13:32:55 EST


Could someone look at this and fix/apply?

--
/* Copyright (C) 2003, SCO, Inc. This is valuable Intellectual Property. */

#define say(x) lie(x)
--- linux-2.6.8-rc3/arch/i386/Kconfig.orig 2004-08-07 07:52:57.000000000 +0200
+++ linux-2.6.8-rc3/arch/i386/Kconfig 2004-08-07 10:37:33.204220304 +0200
@@ -342,6 +342,11 @@
depends on !M386
default y

+config X86_CMPXCHG8B
+ bool
+ depends on !M386 && !M486
+ default y
+
config X86_XADD
bool
depends on !M386
--- linux-2.6.8-rc3/arch/x86_64/Kconfig.orig 2004-08-07 14:22:20.000000000 +0200
+++ linux-2.6.8-rc3/arch/x86_64/Kconfig 2004-08-07 14:42:35.503414192 +0200
@@ -45,6 +45,10 @@
bool
default y

+config X86_CMPXCHG8B
+ bool
+ default y
+
config EARLY_PRINTK
bool
default y
--- linux-2.6.8-rc3/drivers/acpi/Kconfig.orig 2004-08-03 23:28:51.000000000 +0200
+++ linux-2.6.8-rc3/drivers/acpi/Kconfig 2004-08-07 14:45:14.718209864 +0200
@@ -5,11 +5,11 @@
menu "ACPI (Advanced Configuration and Power Interface) Support"
depends on !X86_VISWS
depends on !IA64_HP_SIM
- depends on IA64 || X86
+ depends on IA64 || X86_CMPXCHG

config ACPI
bool "ACPI Support"
- depends on IA64 || X86
+ depends on IA64 || X86_CMPXCHG

default y
---help---
--- linux-2.6.8-rc3/drivers/char/drm/Kconfig.orig 2004-08-03 23:28:30.000000000 +0200
+++ linux-2.6.8-rc3/drivers/char/drm/Kconfig 2004-08-07 12:49:55.413820920 +0200
@@ -6,6 +6,7 @@
#
config DRM
bool "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
+ depends on !X86 || X86_CMPXCHG
help
Kernel-level support for the Direct Rendering Infrastructure (DRI)
introduced in XFree86 4.0. If you say Y here, you need to select
--- linux-2.6.8-rc3/include/asm-i386/system.h.orig 2004-08-07 20:13:02.385439072 +0200
+++ linux-2.6.8-rc3/include/asm-i386/system.h 2004-08-07 20:19:48.638679192 +0200
@@ -5,7 +5,6 @@
#include <linux/kernel.h>
#include <asm/segment.h>
#include <asm/cpufeature.h>
-#include <linux/bitops.h> /* for LOCK_PREFIX */

#ifdef __KERNEL__

@@ -149,8 +148,14 @@
#define __xg(x) ((struct __xchg_dummy *)(x))


+#ifdef CONFIG_X86_CMPXCHG8B
+#define __HAVE_ARCH_CMPXCHG8B 1
+
/*
- * The semantics of XCHGCMP8B are a bit strange, this is why
+ * CMPXCHG8B isn't supported on Intel processors earlier
+ * than the Pentium processors.
+ *
+ * The semantics of CMPXCHG8B are a bit strange, this is why
* there is a loop and the loading of %%eax and %%edx has to
* be inside. This inlines well in most cases, the cached
* cost is around ~38 cycles. (in the future we might want
@@ -163,8 +168,9 @@
* of the instruction set reference 24319102.pdf. We need
* the reader side to see the coherent 64bit value.
*/
-static inline void __set_64bit (unsigned long long * ptr,
- unsigned int low, unsigned int high)
+static __inline__ void __set_64bit(unsigned long long * ptr,
+ const unsigned int low,
+ const unsigned int high)
{
__asm__ __volatile__ (
"\n1:\t"
@@ -179,29 +185,19 @@
: "ax","dx","memory");
}

-static inline void __set_64bit_constant (unsigned long long *ptr,
- unsigned long long value)
-{
- __set_64bit(ptr,(unsigned int)(value), (unsigned int)((value)>>32ULL));
-}
-#define ll_low(x) *(((unsigned int*)&(x))+0)
-#define ll_high(x) *(((unsigned int*)&(x))+1)
-
-static inline void __set_64bit_var (unsigned long long *ptr,
- unsigned long long value)
-{
- __set_64bit(ptr,ll_low(value), ll_high(value));
-}
+#define set_64bit(ptr, value) \
+ (__builtin_constant_p(value) ? \
+ __set_64bit(ptr, \
+ (const unsigned int)(value), \
+ (const unsigned int)(value >> 32ULL) \
+ ) : \
+ __set_64bit(ptr, \
+ *(((const unsigned int *)&value) + 0), \
+ *(((const unsigned int *)&value) + 1) \
+ ) \
+ )

-#define set_64bit(ptr,value) \
-(__builtin_constant_p(value) ? \
- __set_64bit_constant(ptr, value) : \
- __set_64bit_var(ptr, value) )
-
-#define _set_64bit(ptr,value) \
-(__builtin_constant_p(value) ? \
- __set_64bit(ptr, (unsigned int)(value), (unsigned int)((value)>>32ULL) ) : \
- __set_64bit(ptr, ll_low(value), ll_high(value)) )
+#endif

/*
* Note: no "lock" prefix even on SMP: xchg always implies lock anyway
@@ -233,35 +229,38 @@
return x;
}

+#ifdef CONFIG_X86_CMPXCHG
+#define __HAVE_ARCH_CMPXCHG 1
+
/*
* Atomic compare and exchange. Compare OLD with MEM, if identical,
* store NEW in MEM. Return the initial value in MEM. Success is
* indicated by comparing RETURN with OLD.
+ *
+ * CMPXCHG isn't supported on Intel processors earlier than
+ * the Intel486 processors.
*/
-
-#ifdef CONFIG_X86_CMPXCHG
-#define __HAVE_ARCH_CMPXCHG 1
-#endif
-
-static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
- unsigned long new, int size)
+static __inline__ unsigned long __cmpxchg(volatile void *ptr,
+ const unsigned long old,
+ const unsigned long new,
+ const int size)
{
unsigned long prev;
switch (size) {
case 1:
- __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
+ __asm__ __volatile__(LOCK "cmpxchgb %b1,%2"
: "=a"(prev)
: "q"(new), "m"(*__xg(ptr)), "0"(old)
: "memory");
return prev;
case 2:
- __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
+ __asm__ __volatile__(LOCK "cmpxchgw %w1,%2"
: "=a"(prev)
: "q"(new), "m"(*__xg(ptr)), "0"(old)
: "memory");
return prev;
case 4:
- __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
+ __asm__ __volatile__(LOCK "cmpxchgl %1,%2"
: "=a"(prev)
: "q"(new), "m"(*__xg(ptr)), "0"(old)
: "memory");
@@ -270,10 +269,14 @@
return old;
}

-#define cmpxchg(ptr,o,n)\
- ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
- (unsigned long)(n),sizeof(*(ptr))))
-
+#define cmpxchg(ptr, o, n) \
+ ((__typeof__(*(ptr)))__cmpxchg((ptr), \
+ (unsigned long)(o), \
+ (unsigned long)(n), \
+ sizeof(*(ptr))))
+
+#endif
+
#ifdef __KERNEL__
struct alt_instr {
__u8 *instr; /* original instruction */