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