aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/smpboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/smpboot.c')
-rw-r--r--arch/i386/kernel/smpboot.c73
1 files changed, 53 insertions, 20 deletions
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 01b618e73ecd..0a9c64655236 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -74,9 +74,11 @@ EXPORT_SYMBOL(phys_proc_id);
74int cpu_core_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID}; 74int cpu_core_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID};
75EXPORT_SYMBOL(cpu_core_id); 75EXPORT_SYMBOL(cpu_core_id);
76 76
77/* representing HT siblings of each logical CPU */
77cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; 78cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
78EXPORT_SYMBOL(cpu_sibling_map); 79EXPORT_SYMBOL(cpu_sibling_map);
79 80
81/* representing HT and core siblings of each logical CPU */
80cpumask_t cpu_core_map[NR_CPUS] __read_mostly; 82cpumask_t cpu_core_map[NR_CPUS] __read_mostly;
81EXPORT_SYMBOL(cpu_core_map); 83EXPORT_SYMBOL(cpu_core_map);
82 84
@@ -444,35 +446,60 @@ static void __devinit smp_callin(void)
444 446
445static int cpucount; 447static int cpucount;
446 448
449/* representing cpus for which sibling maps can be computed */
450static cpumask_t cpu_sibling_setup_map;
451
447static inline void 452static inline void
448set_cpu_sibling_map(int cpu) 453set_cpu_sibling_map(int cpu)
449{ 454{
450 int i; 455 int i;
456 struct cpuinfo_x86 *c = cpu_data;
457
458 cpu_set(cpu, cpu_sibling_setup_map);
451 459
452 if (smp_num_siblings > 1) { 460 if (smp_num_siblings > 1) {
453 for (i = 0; i < NR_CPUS; i++) { 461 for_each_cpu_mask(i, cpu_sibling_setup_map) {
454 if (!cpu_isset(i, cpu_callout_map)) 462 if (phys_proc_id[cpu] == phys_proc_id[i] &&
455 continue; 463 cpu_core_id[cpu] == cpu_core_id[i]) {
456 if (cpu_core_id[cpu] == cpu_core_id[i]) {
457 cpu_set(i, cpu_sibling_map[cpu]); 464 cpu_set(i, cpu_sibling_map[cpu]);
458 cpu_set(cpu, cpu_sibling_map[i]); 465 cpu_set(cpu, cpu_sibling_map[i]);
466 cpu_set(i, cpu_core_map[cpu]);
467 cpu_set(cpu, cpu_core_map[i]);
459 } 468 }
460 } 469 }
461 } else { 470 } else {
462 cpu_set(cpu, cpu_sibling_map[cpu]); 471 cpu_set(cpu, cpu_sibling_map[cpu]);
463 } 472 }
464 473
465 if (current_cpu_data.x86_num_cores > 1) { 474 if (current_cpu_data.x86_max_cores == 1) {
466 for (i = 0; i < NR_CPUS; i++) {
467 if (!cpu_isset(i, cpu_callout_map))
468 continue;
469 if (phys_proc_id[cpu] == phys_proc_id[i]) {
470 cpu_set(i, cpu_core_map[cpu]);
471 cpu_set(cpu, cpu_core_map[i]);
472 }
473 }
474 } else {
475 cpu_core_map[cpu] = cpu_sibling_map[cpu]; 475 cpu_core_map[cpu] = cpu_sibling_map[cpu];
476 c[cpu].booted_cores = 1;
477 return;
478 }
479
480 for_each_cpu_mask(i, cpu_sibling_setup_map) {
481 if (phys_proc_id[cpu] == phys_proc_id[i]) {
482 cpu_set(i, cpu_core_map[cpu]);
483 cpu_set(cpu, cpu_core_map[i]);
484 /*
485 * Does this new cpu bringup a new core?
486 */
487 if (cpus_weight(cpu_sibling_map[cpu]) == 1) {
488 /*
489 * for each core in package, increment
490 * the booted_cores for this new cpu
491 */
492 if (first_cpu(cpu_sibling_map[i]) == i)
493 c[cpu].booted_cores++;
494 /*
495 * increment the core count for all
496 * the other cpus in this package
497 */
498 if (i != cpu)
499 c[i].booted_cores++;
500 } else if (i != cpu && !c[cpu].booted_cores)
501 c[cpu].booted_cores = c[i].booted_cores;
502 }
476 } 503 }
477} 504}
478 505
@@ -1096,11 +1123,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
1096 1123
1097 current_thread_info()->cpu = 0; 1124 current_thread_info()->cpu = 0;
1098 smp_tune_scheduling(); 1125 smp_tune_scheduling();
1099 cpus_clear(cpu_sibling_map[0]);
1100 cpu_set(0, cpu_sibling_map[0]);
1101 1126
1102 cpus_clear(cpu_core_map[0]); 1127 set_cpu_sibling_map(0);
1103 cpu_set(0, cpu_core_map[0]);
1104 1128
1105 /* 1129 /*
1106 * If we couldn't find an SMP configuration at boot time, 1130 * If we couldn't find an SMP configuration at boot time,
@@ -1279,15 +1303,24 @@ static void
1279remove_siblinginfo(int cpu) 1303remove_siblinginfo(int cpu)
1280{ 1304{
1281 int sibling; 1305 int sibling;
1306 struct cpuinfo_x86 *c = cpu_data;
1282 1307
1308 for_each_cpu_mask(sibling, cpu_core_map[cpu]) {
1309 cpu_clear(cpu, cpu_core_map[sibling]);
1310 /*
1311 * last thread sibling in this cpu core going down
1312 */
1313 if (cpus_weight(cpu_sibling_map[cpu]) == 1)
1314 c[sibling].booted_cores--;
1315 }
1316
1283 for_each_cpu_mask(sibling, cpu_sibling_map[cpu]) 1317 for_each_cpu_mask(sibling, cpu_sibling_map[cpu])
1284 cpu_clear(cpu, cpu_sibling_map[sibling]); 1318 cpu_clear(cpu, cpu_sibling_map[sibling]);
1285 for_each_cpu_mask(sibling, cpu_core_map[cpu])
1286 cpu_clear(cpu, cpu_core_map[sibling]);
1287 cpus_clear(cpu_sibling_map[cpu]); 1319 cpus_clear(cpu_sibling_map[cpu]);
1288 cpus_clear(cpu_core_map[cpu]); 1320 cpus_clear(cpu_core_map[cpu]);
1289 phys_proc_id[cpu] = BAD_APICID; 1321 phys_proc_id[cpu] = BAD_APICID;
1290 cpu_core_id[cpu] = BAD_APICID; 1322 cpu_core_id[cpu] = BAD_APICID;
1323 cpu_clear(cpu, cpu_sibling_setup_map);
1291} 1324}
1292 1325
1293int __cpu_disable(void) 1326int __cpu_disable(void)