Merge branch 'from-linus' into upstream
[powerpc.git] / arch / i386 / kernel / cpu / intel.c
index 8d603ba..5a2e270 100644 (file)
@@ -1,4 +1,3 @@
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 
@@ -6,6 +5,7 @@
 #include <linux/bitops.h>
 #include <linux/smp.h>
 #include <linux/thread_info.h>
+#include <linux/module.h>
 
 #include <asm/processor.h>
 #include <asm/msr.h>
@@ -28,7 +28,7 @@ extern int trap_init_f00f_bug(void);
 struct movsl_mask movsl_mask __read_mostly;
 #endif
 
-void __devinit early_intel_workaround(struct cpuinfo_x86 *c)
+void __cpuinit early_intel_workaround(struct cpuinfo_x86 *c)
 {
        if (c->x86_vendor != X86_VENDOR_INTEL)
                return;
@@ -43,7 +43,7 @@ void __devinit early_intel_workaround(struct cpuinfo_x86 *c)
  *     This is called before we do cpu ident work
  */
  
-int __devinit ppro_with_ram_bug(void)
+int __cpuinit ppro_with_ram_bug(void)
 {
        /* Uses data from early_cpu_detect now */
        if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
@@ -61,7 +61,7 @@ int __devinit ppro_with_ram_bug(void)
  * P4 Xeon errata 037 workaround.
  * Hardware prefetcher may cause stale data to be loaded into the cache.
  */
-static void __devinit Intel_errata_workarounds(struct cpuinfo_x86 *c)
+static void __cpuinit Intel_errata_workarounds(struct cpuinfo_x86 *c)
 {
        unsigned long lo, hi;
 
@@ -80,7 +80,7 @@ static void __devinit Intel_errata_workarounds(struct cpuinfo_x86 *c)
 /*
  * find out the number of processor cores on the die
  */
-static int __devinit num_cpu_cores(struct cpuinfo_x86 *c)
+static int __cpuinit num_cpu_cores(struct cpuinfo_x86 *c)
 {
        unsigned int eax, ebx, ecx, edx;
 
@@ -95,7 +95,7 @@ static int __devinit num_cpu_cores(struct cpuinfo_x86 *c)
                return 1;
 }
 
-static void __devinit init_intel(struct cpuinfo_x86 *c)
+static void __cpuinit init_intel(struct cpuinfo_x86 *c)
 {
        unsigned int l2 = 0;
        char *p = NULL;
@@ -121,6 +121,12 @@ static void __devinit init_intel(struct cpuinfo_x86 *c)
 
        select_idle_routine(c);
        l2 = init_intel_cacheinfo(c);
+       if (c->cpuid_level > 9 ) {
+               unsigned eax = cpuid_eax(10);
+               /* Check for version and the number of counters */
+               if ((eax & 0xff) && (((eax>>8) & 0xff) > 1))
+                       set_bit(X86_FEATURE_ARCH_PERFMON, c->x86_capability);
+       }
 
        /* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it until model 3 mask 3 */
        if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633)
@@ -182,10 +188,13 @@ static void __devinit init_intel(struct cpuinfo_x86 *c)
        }
 #endif
 
-       if (c->x86 == 15) 
+       if (c->x86 == 15)
                set_bit(X86_FEATURE_P4, c->x86_capability);
        if (c->x86 == 6) 
                set_bit(X86_FEATURE_P3, c->x86_capability);
+       if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
+               (c->x86 == 0x6 && c->x86_model >= 0x0e))
+               set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability);
 }
 
 
@@ -201,7 +210,7 @@ static unsigned int intel_size_cache(struct cpuinfo_x86 * c, unsigned int size)
        return size;
 }
 
-static struct cpu_dev intel_cpu_dev __devinitdata = {
+static struct cpu_dev intel_cpu_dev __cpuinitdata = {
        .c_vendor       = "Intel",
        .c_ident        = { "GenuineIntel" },
        .c_models = {
@@ -264,5 +273,52 @@ __init int intel_cpu_init(void)
        return 0;
 }
 
+#ifndef CONFIG_X86_CMPXCHG
+unsigned long cmpxchg_386_u8(volatile void *ptr, u8 old, u8 new)
+{
+       u8 prev;
+       unsigned long flags;
+
+       /* Poor man's cmpxchg for 386. Unsuitable for SMP */
+       local_irq_save(flags);
+       prev = *(u8 *)ptr;
+       if (prev == old)
+               *(u8 *)ptr = new;
+       local_irq_restore(flags);
+       return prev;
+}
+EXPORT_SYMBOL(cmpxchg_386_u8);
+
+unsigned long cmpxchg_386_u16(volatile void *ptr, u16 old, u16 new)
+{
+       u16 prev;
+       unsigned long flags;
+
+       /* Poor man's cmpxchg for 386. Unsuitable for SMP */
+       local_irq_save(flags);
+       prev = *(u16 *)ptr;
+       if (prev == old)
+               *(u16 *)ptr = new;
+       local_irq_restore(flags);
+       return prev;
+}
+EXPORT_SYMBOL(cmpxchg_386_u16);
+
+unsigned long cmpxchg_386_u32(volatile void *ptr, u32 old, u32 new)
+{
+       u32 prev;
+       unsigned long flags;
+
+       /* Poor man's cmpxchg for 386. Unsuitable for SMP */
+       local_irq_save(flags);
+       prev = *(u32 *)ptr;
+       if (prev == old)
+               *(u32 *)ptr = new;
+       local_irq_restore(flags);
+       return prev;
+}
+EXPORT_SYMBOL(cmpxchg_386_u32);
+#endif
+
 // arch_initcall(intel_cpu_init);