]> err.no Git - linux-2.6/blobdiff - arch/i386/kernel/cpu/intel_cacheinfo.c
[PATCH] x86: cpuid.4 doesn't need cpu level 5
[linux-2.6] / arch / i386 / kernel / cpu / intel_cacheinfo.c
index 4dc42a189ae5ebefc3b3f0595211a51a2182f8be..ce61921369e53aa5827e8262daece57cbe2fca2a 100644 (file)
@@ -43,13 +43,23 @@ static struct _cache_table cache_table[] __cpuinitdata =
        { 0x2c, LVL_1_DATA, 32 },       /* 8-way set assoc, 64 byte line size */
        { 0x30, LVL_1_INST, 32 },       /* 8-way set assoc, 64 byte line size */
        { 0x39, LVL_2,      128 },      /* 4-way set assoc, sectored cache, 64 byte line size */
+       { 0x3a, LVL_2,      192 },      /* 6-way set assoc, sectored cache, 64 byte line size */
        { 0x3b, LVL_2,      128 },      /* 2-way set assoc, sectored cache, 64 byte line size */
        { 0x3c, LVL_2,      256 },      /* 4-way set assoc, sectored cache, 64 byte line size */
+       { 0x3d, LVL_2,      384 },      /* 6-way set assoc, sectored cache, 64 byte line size */
+       { 0x3e, LVL_2,      512 },      /* 4-way set assoc, sectored cache, 64 byte line size */
        { 0x41, LVL_2,      128 },      /* 4-way set assoc, 32 byte line size */
        { 0x42, LVL_2,      256 },      /* 4-way set assoc, 32 byte line size */
        { 0x43, LVL_2,      512 },      /* 4-way set assoc, 32 byte line size */
        { 0x44, LVL_2,      1024 },     /* 4-way set assoc, 32 byte line size */
        { 0x45, LVL_2,      2048 },     /* 4-way set assoc, 32 byte line size */
+       { 0x46, LVL_3,      4096 },     /* 4-way set assoc, 64 byte line size */
+       { 0x47, LVL_3,      8192 },     /* 8-way set assoc, 64 byte line size */
+       { 0x49, LVL_3,      4096 },     /* 16-way set assoc, 64 byte line size */
+       { 0x4a, LVL_3,      6144 },     /* 12-way set assoc, 64 byte line size */
+       { 0x4b, LVL_3,      8192 },     /* 16-way set assoc, 64 byte line size */
+       { 0x4c, LVL_3,     12288 },     /* 12-way set assoc, 64 byte line size */
+       { 0x4d, LVL_3,     16384 },     /* 16-way set assoc, 64 byte line size */
        { 0x60, LVL_1_DATA, 16 },       /* 8-way set assoc, sectored cache, 64 byte line size */
        { 0x66, LVL_1_DATA, 8 },        /* 4-way set assoc, sectored cache, 64 byte line size */
        { 0x67, LVL_1_DATA, 16 },       /* 4-way set assoc, sectored cache, 64 byte line size */
@@ -57,6 +67,7 @@ static struct _cache_table cache_table[] __cpuinitdata =
        { 0x70, LVL_TRACE,  12 },       /* 8-way set assoc */
        { 0x71, LVL_TRACE,  16 },       /* 8-way set assoc */
        { 0x72, LVL_TRACE,  32 },       /* 8-way set assoc */
+       { 0x73, LVL_TRACE,  64 },       /* 8-way set assoc */
        { 0x78, LVL_2,    1024 },       /* 4-way set assoc, 64 byte line size */
        { 0x79, LVL_2,     128 },       /* 8-way set assoc, sectored cache, 64 byte line size */
        { 0x7a, LVL_2,     256 },       /* 8-way set assoc, sectored cache, 64 byte line size */
@@ -141,6 +152,7 @@ static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_le
        return 0;
 }
 
+/* will only be called once; __init is safe here */
 static int __init find_num_cache_leaves(void)
 {
        unsigned int            eax, ebx, ecx, edx;
@@ -162,7 +174,7 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
        unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */
        unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */
 
-       if (c->cpuid_level > 4) {
+       if (c->cpuid_level > 3) {
                static int is_initialized;
 
                if (is_initialized == 0) {
@@ -293,29 +305,45 @@ static struct _cpuid4_info *cpuid4_info[NR_CPUS];
 #ifdef CONFIG_SMP
 static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
 {
-       struct _cpuid4_info     *this_leaf;
+       struct _cpuid4_info     *this_leaf, *sibling_leaf;
        unsigned long num_threads_sharing;
-#ifdef CONFIG_X86_HT
-       struct cpuinfo_x86 *c = cpu_data + cpu;
-#endif
+       int index_msb, i;
+       struct cpuinfo_x86 *c = cpu_data;
 
        this_leaf = CPUID4_INFO_IDX(cpu, index);
        num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing;
 
        if (num_threads_sharing == 1)
                cpu_set(cpu, this_leaf->shared_cpu_map);
-#ifdef CONFIG_X86_HT
-       else if (num_threads_sharing == smp_num_siblings)
-               this_leaf->shared_cpu_map = cpu_sibling_map[cpu];
-       else if (num_threads_sharing == (c->x86_num_cores * smp_num_siblings))
-               this_leaf->shared_cpu_map = cpu_core_map[cpu];
-       else
-               printk(KERN_DEBUG "Number of CPUs sharing cache didn't match "
-                               "any known set of CPUs\n");
-#endif
+       else {
+               index_msb = get_count_order(num_threads_sharing);
+
+               for_each_online_cpu(i) {
+                       if (c[i].apicid >> index_msb ==
+                           c[cpu].apicid >> index_msb) {
+                               cpu_set(i, this_leaf->shared_cpu_map);
+                               if (i != cpu && cpuid4_info[i])  {
+                                       sibling_leaf = CPUID4_INFO_IDX(i, index);
+                                       cpu_set(cpu, sibling_leaf->shared_cpu_map);
+                               }
+                       }
+               }
+       }
+}
+static void __cpuinit cache_remove_shared_cpu_map(unsigned int cpu, int index)
+{
+       struct _cpuid4_info     *this_leaf, *sibling_leaf;
+       int sibling;
+
+       this_leaf = CPUID4_INFO_IDX(cpu, index);
+       for_each_cpu_mask(sibling, this_leaf->shared_cpu_map) {
+               sibling_leaf = CPUID4_INFO_IDX(sibling, index); 
+               cpu_clear(cpu, sibling_leaf->shared_cpu_map);
+       }
 }
 #else
 static void __init cache_shared_cpu_map_setup(unsigned int cpu, int index) {}
+static void __init cache_remove_shared_cpu_map(unsigned int cpu, int index) {}
 #endif
 
 static void free_cache_attributes(unsigned int cpu)
@@ -574,8 +602,10 @@ static void __cpuexit cache_remove_dev(struct sys_device * sys_dev)
        unsigned int cpu = sys_dev->id;
        unsigned long i;
 
-       for (i = 0; i < num_cache_leaves; i++)
+       for (i = 0; i < num_cache_leaves; i++) {
+               cache_remove_shared_cpu_map(cpu, i);
                kobject_unregister(&(INDEX_KOBJECT_PTR(cpu,i)->kobj));
+       }
        kobject_unregister(cache_kobject[cpu]);
        cpuid4_cache_sysfs_exit(cpu);
        return;