]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/i386/kernel/cpu/amd.c
[PATCH] i386: Don't delete cpu_devs data to identify different x86 types in late_initcall
[linux-2.6-omap-h63xx.git] / arch / i386 / kernel / cpu / amd.c
index 333578a4e91afcf768a5dc35e10188a76c06591f..4fec702afd7e84b58c896b6f99becf7fad87932a 100644 (file)
 extern void vide(void);
 __asm__(".align 4\nvide: ret");
 
-static void __init init_amd(struct cpuinfo_x86 *c)
+#define ENABLE_C1E_MASK         0x18000000
+#define CPUID_PROCESSOR_SIGNATURE       1
+#define CPUID_XFAM              0x0ff00000
+#define CPUID_XFAM_K8           0x00000000
+#define CPUID_XFAM_10H          0x00100000
+#define CPUID_XFAM_11H          0x00200000
+#define CPUID_XMOD              0x000f0000
+#define CPUID_XMOD_REV_F        0x00040000
+
+/* AMD systems with C1E don't have a working lAPIC timer. Check for that. */
+static __cpuinit int amd_apic_timer_broken(void)
+{
+       u32 lo, hi;
+       u32 eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
+       switch (eax & CPUID_XFAM) {
+       case CPUID_XFAM_K8:
+               if ((eax & CPUID_XMOD) < CPUID_XMOD_REV_F)
+                       break;
+       case CPUID_XFAM_10H:
+       case CPUID_XFAM_11H:
+               rdmsr(MSR_K8_ENABLE_C1E, lo, hi);
+               if (lo & ENABLE_C1E_MASK)
+                       return 1;
+                break;
+        default:
+                /* err on the side of caution */
+               return 1;
+        }
+       return 0;
+}
+
+int force_mwait __cpuinitdata;
+
+static void __cpuinit init_amd(struct cpuinfo_x86 *c)
 {
        u32 l, h;
        int mbytes = num_physpages >> (20-PAGE_SHIFT);
@@ -104,10 +137,7 @@ static void __init init_amd(struct cpuinfo_x86 *c)
                                        f_vide();
                                rdtscl(d2);
                                d = d2-d;
-                               
-                               /* Knock these two lines out if it debugs out ok */
-                               printk(KERN_INFO "AMD K6 stepping B detected - ");
-                               /* -- cut here -- */
+
                                if (d > 20*K6_BUG_LOOP) 
                                        printk("system stability may be impaired when more than 32 MB are used.\n");
                                else 
@@ -207,13 +237,13 @@ static void __init init_amd(struct cpuinfo_x86 *c)
                set_bit(X86_FEATURE_K7, c->x86_capability); 
                break;
        }
+       if (c->x86 >= 6)
+               set_bit(X86_FEATURE_FXSAVE_LEAK, c->x86_capability);
 
        display_cacheinfo(c);
 
        if (cpuid_eax(0x80000000) >= 0x80000008) {
                c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
-               if (c->x86_max_cores & (c->x86_max_cores - 1))
-                       c->x86_max_cores = 1;
        }
 
        if (cpuid_eax(0x80000000) >= 0x80000007) {
@@ -224,25 +254,35 @@ static void __init init_amd(struct cpuinfo_x86 *c)
 
 #ifdef CONFIG_X86_HT
        /*
-        * On a AMD dual core setup the lower bits of the APIC id
-        * distingush the cores.  Assumes number of cores is a power
-        * of two.
+        * On a AMD multi core setup the lower bits of the APIC id
+        * distingush the cores.
         */
        if (c->x86_max_cores > 1) {
                int cpu = smp_processor_id();
-               unsigned bits = 0;
-               while ((1 << bits) < c->x86_max_cores)
-                       bits++;
-               cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<<bits)-1);
-               phys_proc_id[cpu] >>= bits;
+               unsigned bits = (cpuid_ecx(0x80000008) >> 12) & 0xf;
+
+               if (bits == 0) {
+                       while ((1 << bits) < c->x86_max_cores)
+                               bits++;
+               }
+               c->cpu_core_id = c->phys_proc_id & ((1<<bits)-1);
+               c->phys_proc_id >>= bits;
                printk(KERN_INFO "CPU %d(%d) -> Core %d\n",
-                      cpu, c->x86_max_cores, cpu_core_id[cpu]);
+                      cpu, c->x86_max_cores, c->cpu_core_id);
        }
 #endif
 
+       if (cpuid_eax(0x80000000) >= 0x80000006)
+               num_cache_leaves = 3;
+
+       if (amd_apic_timer_broken())
+               set_bit(X86_FEATURE_LAPIC_TIMER_BROKEN, c->x86_capability);
+
+       if (c->x86 == 0x10 && !force_mwait)
+               clear_bit(X86_FEATURE_MWAIT, c->x86_capability);
 }
 
-static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
+static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
 {
        /* AMD errata T13 (order #21922) */
        if ((c->x86 == 6)) {
@@ -255,7 +295,7 @@ static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
        return size;
 }
 
-static struct cpu_dev amd_cpu_dev __initdata = {
+static struct cpu_dev amd_cpu_dev __cpuinitdata = {
        .c_vendor       = "AMD",
        .c_ident        = { "AuthenticAMD" },
        .c_models = {
@@ -271,7 +311,6 @@ static struct cpu_dev amd_cpu_dev __initdata = {
                },
        },
        .c_init         = init_amd,
-       .c_identify     = generic_identify,
        .c_size_cache   = amd_size_cache,
 };
 
@@ -280,5 +319,3 @@ int __init amd_init_cpu(void)
        cpu_devs[X86_VENDOR_AMD] = &amd_cpu_dev;
        return 0;
 }
-
-//early_arch_initcall(amd_init_cpu);