aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/cpu
diff options
context:
space:
mode:
authorSiddha, Suresh B <suresh.b.siddha@intel.com>2005-11-05 11:25:54 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-14 22:55:16 -0500
commit94605eff572b727aaad9b4b29bc358b919096503 (patch)
tree657a848d8ef34d2f94bbad3aa4e5458d2d3f2d2b /arch/i386/kernel/cpu
parente90f22edf432512219cc2952f5811961abbd164f (diff)
[PATCH] x86-64/i386: Intel HT, Multi core detection fixes
Fields obtained through cpuid vector 0x1(ebx[16:23]) and vector 0x4(eax[14:25], eax[26:31]) indicate the maximum values and might not always be the same as what is available and what OS sees. So make sure "siblings" and "cpu cores" values in /proc/cpuinfo reflect the values as seen by OS instead of what cpuid instruction says. This will also fix the buggy BIOS cases (for example where cpuid on a single core cpu says there are "2" siblings, even when HT is disabled in the BIOS. http://bugzilla.kernel.org/show_bug.cgi?id=4359) Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/i386/kernel/cpu')
-rw-r--r--arch/i386/kernel/cpu/amd.c12
-rw-r--r--arch/i386/kernel/cpu/common.c36
-rw-r--r--arch/i386/kernel/cpu/intel.c2
-rw-r--r--arch/i386/kernel/cpu/intel_cacheinfo.c2
-rw-r--r--arch/i386/kernel/cpu/proc.c7
5 files changed, 25 insertions, 34 deletions
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
index 53a1681cd964..e344ef88cfcd 100644
--- a/arch/i386/kernel/cpu/amd.c
+++ b/arch/i386/kernel/cpu/amd.c
@@ -206,9 +206,9 @@ static void __init init_amd(struct cpuinfo_x86 *c)
206 display_cacheinfo(c); 206 display_cacheinfo(c);
207 207
208 if (cpuid_eax(0x80000000) >= 0x80000008) { 208 if (cpuid_eax(0x80000000) >= 0x80000008) {
209 c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1; 209 c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
210 if (c->x86_num_cores & (c->x86_num_cores - 1)) 210 if (c->x86_max_cores & (c->x86_max_cores - 1))
211 c->x86_num_cores = 1; 211 c->x86_max_cores = 1;
212 } 212 }
213 213
214#ifdef CONFIG_X86_HT 214#ifdef CONFIG_X86_HT
@@ -217,15 +217,15 @@ static void __init init_amd(struct cpuinfo_x86 *c)
217 * distingush the cores. Assumes number of cores is a power 217 * distingush the cores. Assumes number of cores is a power
218 * of two. 218 * of two.
219 */ 219 */
220 if (c->x86_num_cores > 1) { 220 if (c->x86_max_cores > 1) {
221 int cpu = smp_processor_id(); 221 int cpu = smp_processor_id();
222 unsigned bits = 0; 222 unsigned bits = 0;
223 while ((1 << bits) < c->x86_num_cores) 223 while ((1 << bits) < c->x86_max_cores)
224 bits++; 224 bits++;
225 cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<<bits)-1); 225 cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<<bits)-1);
226 phys_proc_id[cpu] >>= bits; 226 phys_proc_id[cpu] >>= bits;
227 printk(KERN_INFO "CPU %d(%d) -> Core %d\n", 227 printk(KERN_INFO "CPU %d(%d) -> Core %d\n",
228 cpu, c->x86_num_cores, cpu_core_id[cpu]); 228 cpu, c->x86_max_cores, cpu_core_id[cpu]);
229 } 229 }
230#endif 230#endif
231} 231}
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 35a67dab4a94..4e9c2e99b0a5 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -335,7 +335,7 @@ void __devinit identify_cpu(struct cpuinfo_x86 *c)
335 c->x86_model = c->x86_mask = 0; /* So far unknown... */ 335 c->x86_model = c->x86_mask = 0; /* So far unknown... */
336 c->x86_vendor_id[0] = '\0'; /* Unset */ 336 c->x86_vendor_id[0] = '\0'; /* Unset */
337 c->x86_model_id[0] = '\0'; /* Unset */ 337 c->x86_model_id[0] = '\0'; /* Unset */
338 c->x86_num_cores = 1; 338 c->x86_max_cores = 1;
339 memset(&c->x86_capability, 0, sizeof c->x86_capability); 339 memset(&c->x86_capability, 0, sizeof c->x86_capability);
340 340
341 if (!have_cpuid_p()) { 341 if (!have_cpuid_p()) {
@@ -446,52 +446,44 @@ void __devinit identify_cpu(struct cpuinfo_x86 *c)
446void __devinit detect_ht(struct cpuinfo_x86 *c) 446void __devinit detect_ht(struct cpuinfo_x86 *c)
447{ 447{
448 u32 eax, ebx, ecx, edx; 448 u32 eax, ebx, ecx, edx;
449 int index_msb, tmp; 449 int index_msb, core_bits;
450 int cpu = smp_processor_id(); 450 int cpu = smp_processor_id();
451 451
452 cpuid(1, &eax, &ebx, &ecx, &edx);
453
454 c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0);
455
452 if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY)) 456 if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
453 return; 457 return;
454 458
455 cpuid(1, &eax, &ebx, &ecx, &edx);
456 smp_num_siblings = (ebx & 0xff0000) >> 16; 459 smp_num_siblings = (ebx & 0xff0000) >> 16;
457 460
458 if (smp_num_siblings == 1) { 461 if (smp_num_siblings == 1) {
459 printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); 462 printk(KERN_INFO "CPU: Hyper-Threading is disabled\n");
460 } else if (smp_num_siblings > 1 ) { 463 } else if (smp_num_siblings > 1 ) {
461 index_msb = 31;
462 464
463 if (smp_num_siblings > NR_CPUS) { 465 if (smp_num_siblings > NR_CPUS) {
464 printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings); 466 printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);
465 smp_num_siblings = 1; 467 smp_num_siblings = 1;
466 return; 468 return;
467 } 469 }
468 tmp = smp_num_siblings; 470
469 while ((tmp & 0x80000000 ) == 0) { 471 index_msb = get_count_order(smp_num_siblings);
470 tmp <<=1 ;
471 index_msb--;
472 }
473 if (smp_num_siblings & (smp_num_siblings - 1))
474 index_msb++;
475 phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb); 472 phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);
476 473
477 printk(KERN_INFO "CPU: Physical Processor ID: %d\n", 474 printk(KERN_INFO "CPU: Physical Processor ID: %d\n",
478 phys_proc_id[cpu]); 475 phys_proc_id[cpu]);
479 476
480 smp_num_siblings = smp_num_siblings / c->x86_num_cores; 477 smp_num_siblings = smp_num_siblings / c->x86_max_cores;
481 478
482 tmp = smp_num_siblings; 479 index_msb = get_count_order(smp_num_siblings) ;
483 index_msb = 31;
484 while ((tmp & 0x80000000) == 0) {
485 tmp <<=1 ;
486 index_msb--;
487 }
488 480
489 if (smp_num_siblings & (smp_num_siblings - 1)) 481 core_bits = get_count_order(c->x86_max_cores);
490 index_msb++;
491 482
492 cpu_core_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb); 483 cpu_core_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb) &
484 ((1 << core_bits) - 1);
493 485
494 if (c->x86_num_cores > 1) 486 if (c->x86_max_cores > 1)
495 printk(KERN_INFO "CPU: Processor Core ID: %d\n", 487 printk(KERN_INFO "CPU: Processor Core ID: %d\n",
496 cpu_core_id[cpu]); 488 cpu_core_id[cpu]);
497 } 489 }
diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c
index 43601de0f633..8d603ba28126 100644
--- a/arch/i386/kernel/cpu/intel.c
+++ b/arch/i386/kernel/cpu/intel.c
@@ -157,7 +157,7 @@ static void __devinit init_intel(struct cpuinfo_x86 *c)
157 if ( p ) 157 if ( p )
158 strcpy(c->x86_model_id, p); 158 strcpy(c->x86_model_id, p);
159 159
160 c->x86_num_cores = num_cpu_cores(c); 160 c->x86_max_cores = num_cpu_cores(c);
161 161
162 detect_ht(c); 162 detect_ht(c);
163 163
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c
index 4dc42a189ae5..e66d14099564 100644
--- a/arch/i386/kernel/cpu/intel_cacheinfo.c
+++ b/arch/i386/kernel/cpu/intel_cacheinfo.c
@@ -307,7 +307,7 @@ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
307#ifdef CONFIG_X86_HT 307#ifdef CONFIG_X86_HT
308 else if (num_threads_sharing == smp_num_siblings) 308 else if (num_threads_sharing == smp_num_siblings)
309 this_leaf->shared_cpu_map = cpu_sibling_map[cpu]; 309 this_leaf->shared_cpu_map = cpu_sibling_map[cpu];
310 else if (num_threads_sharing == (c->x86_num_cores * smp_num_siblings)) 310 else if (num_threads_sharing == (c->x86_max_cores * smp_num_siblings))
311 this_leaf->shared_cpu_map = cpu_core_map[cpu]; 311 this_leaf->shared_cpu_map = cpu_core_map[cpu];
312 else 312 else
313 printk(KERN_DEBUG "Number of CPUs sharing cache didn't match " 313 printk(KERN_DEBUG "Number of CPUs sharing cache didn't match "
diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c
index 41b871ecf4b3..e7921315ae9d 100644
--- a/arch/i386/kernel/cpu/proc.c
+++ b/arch/i386/kernel/cpu/proc.c
@@ -94,12 +94,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
94 if (c->x86_cache_size >= 0) 94 if (c->x86_cache_size >= 0)
95 seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); 95 seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
96#ifdef CONFIG_X86_HT 96#ifdef CONFIG_X86_HT
97 if (c->x86_num_cores * smp_num_siblings > 1) { 97 if (c->x86_max_cores * smp_num_siblings > 1) {
98 seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]); 98 seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]);
99 seq_printf(m, "siblings\t: %d\n", 99 seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[n]));
100 c->x86_num_cores * smp_num_siblings);
101 seq_printf(m, "core id\t\t: %d\n", cpu_core_id[n]); 100 seq_printf(m, "core id\t\t: %d\n", cpu_core_id[n]);
102 seq_printf(m, "cpu cores\t: %d\n", c->x86_num_cores); 101 seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
103 } 102 }
104#endif 103#endif
105 104