diff options
Diffstat (limited to 'arch/i386/kernel/smpboot.c')
-rw-r--r-- | arch/i386/kernel/smpboot.c | 50 |
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 */ |
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 | /* Last level cache ID of each logical CPU */ | ||
76 | int 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 */ |
76 | cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; | 79 | cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; |
77 | EXPORT_SYMBOL(cpu_sibling_map); | 80 | EXPORT_SYMBOL(cpu_sibling_map); |
@@ -440,6 +443,18 @@ static void __devinit smp_callin(void) | |||
440 | 443 | ||
441 | static int cpucount; | 444 | static int cpucount; |
442 | 445 | ||
446 | /* maps the cpu to the sched domain representing multi-core */ | ||
447 | cpumask_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 */ |
444 | static cpumask_t cpu_sibling_setup_map; | 459 | static 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 | ||
1017 | static void __devinit do_warm_boot_cpu(void *p) | 1041 | static 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 | ||
1024 | int __devinit smp_prepare_cpu(int cpu) | 1048 | static 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; |
1055 | exit: | 1078 | exit: |
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 | ||
1380 | int __devinit __cpu_up(unsigned int cpu) | 1404 | int __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); |