diff options
author | Siddha, Suresh B <suresh.b.siddha@intel.com> | 2005-11-05 11:25:54 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-14 22:55:16 -0500 |
commit | 94605eff572b727aaad9b4b29bc358b919096503 (patch) | |
tree | 657a848d8ef34d2f94bbad3aa4e5458d2d3f2d2b /arch/i386/kernel/cpu | |
parent | e90f22edf432512219cc2952f5811961abbd164f (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.c | 12 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/common.c | 36 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/intel.c | 2 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/intel_cacheinfo.c | 2 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/proc.c | 7 |
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) | |||
446 | void __devinit detect_ht(struct cpuinfo_x86 *c) | 446 | void __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 | ||