diff options
Diffstat (limited to 'arch/i386/kernel/smpboot.c')
-rw-r--r-- | arch/i386/kernel/smpboot.c | 73 |
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 */ |
73 | int cpu_core_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID}; | 73 | int cpu_core_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID}; |
74 | 74 | ||
75 | /* representing HT siblings of each logical CPU */ | ||
75 | cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; | 76 | cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; |
76 | EXPORT_SYMBOL(cpu_sibling_map); | 77 | EXPORT_SYMBOL(cpu_sibling_map); |
77 | 78 | ||
79 | /* representing HT and core siblings of each logical CPU */ | ||
78 | cpumask_t cpu_core_map[NR_CPUS] __read_mostly; | 80 | cpumask_t cpu_core_map[NR_CPUS] __read_mostly; |
79 | EXPORT_SYMBOL(cpu_core_map); | 81 | EXPORT_SYMBOL(cpu_core_map); |
80 | 82 | ||
@@ -442,35 +444,60 @@ static void __devinit smp_callin(void) | |||
442 | 444 | ||
443 | static int cpucount; | 445 | static int cpucount; |
444 | 446 | ||
447 | /* representing cpus for which sibling maps can be computed */ | ||
448 | static cpumask_t cpu_sibling_setup_map; | ||
449 | |||
445 | static inline void | 450 | static inline void |
446 | set_cpu_sibling_map(int cpu) | 451 | set_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 | |||
1278 | remove_siblinginfo(int cpu) | 1302 | remove_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 | ||
1292 | int __cpu_disable(void) | 1325 | int __cpu_disable(void) |