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.c50
1 files changed, 45 insertions, 5 deletions
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index eba7f53f8b4a..a6969903f2d6 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -72,6 +72,9 @@ 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/* Last level cache ID of each logical CPU */
76int cpu_llc_id[NR_CPUS] __cpuinitdata = {[0 ... NR_CPUS-1] = BAD_APICID};
77
75/* representing HT siblings of each logical CPU */ 78/* representing HT siblings of each logical CPU */
76cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; 79cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
77EXPORT_SYMBOL(cpu_sibling_map); 80EXPORT_SYMBOL(cpu_sibling_map);
@@ -440,6 +443,18 @@ static void __devinit smp_callin(void)
440 443
441static int cpucount; 444static int cpucount;
442 445
446/* maps the cpu to the sched domain representing multi-core */
447cpumask_t cpu_coregroup_map(int cpu)
448{
449 struct cpuinfo_x86 *c = cpu_data + cpu;
450 /*
451 * For perf, we return last level cache shared map.
452 * TBD: when power saving sched policy is added, we will return
453 * cpu_core_map when power saving policy is enabled
454 */
455 return c->llc_shared_map;
456}
457
443/* representing cpus for which sibling maps can be computed */ 458/* representing cpus for which sibling maps can be computed */
444static cpumask_t cpu_sibling_setup_map; 459static cpumask_t cpu_sibling_setup_map;
445 460
@@ -459,12 +474,16 @@ set_cpu_sibling_map(int cpu)
459 cpu_set(cpu, cpu_sibling_map[i]); 474 cpu_set(cpu, cpu_sibling_map[i]);
460 cpu_set(i, cpu_core_map[cpu]); 475 cpu_set(i, cpu_core_map[cpu]);
461 cpu_set(cpu, cpu_core_map[i]); 476 cpu_set(cpu, cpu_core_map[i]);
477 cpu_set(i, c[cpu].llc_shared_map);
478 cpu_set(cpu, c[i].llc_shared_map);
462 } 479 }
463 } 480 }
464 } else { 481 } else {
465 cpu_set(cpu, cpu_sibling_map[cpu]); 482 cpu_set(cpu, cpu_sibling_map[cpu]);
466 } 483 }
467 484
485 cpu_set(cpu, c[cpu].llc_shared_map);
486
468 if (current_cpu_data.x86_max_cores == 1) { 487 if (current_cpu_data.x86_max_cores == 1) {
469 cpu_core_map[cpu] = cpu_sibling_map[cpu]; 488 cpu_core_map[cpu] = cpu_sibling_map[cpu];
470 c[cpu].booted_cores = 1; 489 c[cpu].booted_cores = 1;
@@ -472,6 +491,11 @@ set_cpu_sibling_map(int cpu)
472 } 491 }
473 492
474 for_each_cpu_mask(i, cpu_sibling_setup_map) { 493 for_each_cpu_mask(i, cpu_sibling_setup_map) {
494 if (cpu_llc_id[cpu] != BAD_APICID &&
495 cpu_llc_id[cpu] == cpu_llc_id[i]) {
496 cpu_set(i, c[cpu].llc_shared_map);
497 cpu_set(cpu, c[i].llc_shared_map);
498 }
475 if (phys_proc_id[cpu] == phys_proc_id[i]) { 499 if (phys_proc_id[cpu] == phys_proc_id[i]) {
476 cpu_set(i, cpu_core_map[cpu]); 500 cpu_set(i, cpu_core_map[cpu]);
477 cpu_set(cpu, cpu_core_map[i]); 501 cpu_set(cpu, cpu_core_map[i]);
@@ -899,6 +923,7 @@ static int __devinit do_boot_cpu(int apicid, int cpu)
899 unsigned short nmi_high = 0, nmi_low = 0; 923 unsigned short nmi_high = 0, nmi_low = 0;
900 924
901 ++cpucount; 925 ++cpucount;
926 alternatives_smp_switch(1);
902 927
903 /* 928 /*
904 * We can't use kernel_thread since we must avoid to 929 * We can't use kernel_thread since we must avoid to
@@ -1002,7 +1027,6 @@ void cpu_exit_clear(void)
1002 1027
1003 cpu_clear(cpu, cpu_callout_map); 1028 cpu_clear(cpu, cpu_callout_map);
1004 cpu_clear(cpu, cpu_callin_map); 1029 cpu_clear(cpu, cpu_callin_map);
1005 cpu_clear(cpu, cpu_present_map);
1006 1030
1007 cpu_clear(cpu, smp_commenced_mask); 1031 cpu_clear(cpu, smp_commenced_mask);
1008 unmap_cpu_to_logical_apicid(cpu); 1032 unmap_cpu_to_logical_apicid(cpu);
@@ -1014,21 +1038,20 @@ struct warm_boot_cpu_info {
1014 int cpu; 1038 int cpu;
1015}; 1039};
1016 1040
1017static void __devinit do_warm_boot_cpu(void *p) 1041static void __cpuinit do_warm_boot_cpu(void *p)
1018{ 1042{
1019 struct warm_boot_cpu_info *info = p; 1043 struct warm_boot_cpu_info *info = p;
1020 do_boot_cpu(info->apicid, info->cpu); 1044 do_boot_cpu(info->apicid, info->cpu);
1021 complete(info->complete); 1045 complete(info->complete);
1022} 1046}
1023 1047
1024int __devinit smp_prepare_cpu(int cpu) 1048static int __cpuinit __smp_prepare_cpu(int cpu)
1025{ 1049{
1026 DECLARE_COMPLETION(done); 1050 DECLARE_COMPLETION(done);
1027 struct warm_boot_cpu_info info; 1051 struct warm_boot_cpu_info info;
1028 struct work_struct task; 1052 struct work_struct task;
1029 int apicid, ret; 1053 int apicid, ret;
1030 1054
1031 lock_cpu_hotplug();
1032 apicid = x86_cpu_to_apicid[cpu]; 1055 apicid = x86_cpu_to_apicid[cpu];
1033 if (apicid == BAD_APICID) { 1056 if (apicid == BAD_APICID) {
1034 ret = -ENODEV; 1057 ret = -ENODEV;
@@ -1053,7 +1076,6 @@ int __devinit smp_prepare_cpu(int cpu)
1053 zap_low_mappings(); 1076 zap_low_mappings();
1054 ret = 0; 1077 ret = 0;
1055exit: 1078exit:
1056 unlock_cpu_hotplug();
1057 return ret; 1079 return ret;
1058} 1080}
1059#endif 1081#endif
@@ -1358,6 +1380,8 @@ void __cpu_die(unsigned int cpu)
1358 /* They ack this in play_dead by setting CPU_DEAD */ 1380 /* They ack this in play_dead by setting CPU_DEAD */
1359 if (per_cpu(cpu_state, cpu) == CPU_DEAD) { 1381 if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
1360 printk ("CPU %d is now offline\n", cpu); 1382 printk ("CPU %d is now offline\n", cpu);
1383 if (1 == num_online_cpus())
1384 alternatives_smp_switch(0);
1361 return; 1385 return;
1362 } 1386 }
1363 msleep(100); 1387 msleep(100);
@@ -1379,6 +1403,22 @@ void __cpu_die(unsigned int cpu)
1379 1403
1380int __devinit __cpu_up(unsigned int cpu) 1404int __devinit __cpu_up(unsigned int cpu)
1381{ 1405{
1406#ifdef CONFIG_HOTPLUG_CPU
1407 int ret=0;
1408
1409 /*
1410 * We do warm boot only on cpus that had booted earlier
1411 * Otherwise cold boot is all handled from smp_boot_cpus().
1412 * cpu_callin_map is set during AP kickstart process. Its reset
1413 * when a cpu is taken offline from cpu_exit_clear().
1414 */
1415 if (!cpu_isset(cpu, cpu_callin_map))
1416 ret = __smp_prepare_cpu(cpu);
1417
1418 if (ret)
1419 return -EIO;
1420#endif
1421
1382 /* In case one didn't come up */ 1422 /* In case one didn't come up */
1383 if (!cpu_isset(cpu, cpu_callin_map)) { 1423 if (!cpu_isset(cpu, cpu_callin_map)) {
1384 printk(KERN_DEBUG "skipping cpu%d, didn't come online\n", cpu); 1424 printk(KERN_DEBUG "skipping cpu%d, didn't come online\n", cpu);