diff options
Diffstat (limited to 'arch/x86/kernel/smpboot.c')
-rw-r--r-- | arch/x86/kernel/smpboot.c | 134 |
1 files changed, 31 insertions, 103 deletions
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 08776a953487..c2871d3c71b6 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -64,6 +64,7 @@ | |||
64 | #include <asm/mtrr.h> | 64 | #include <asm/mtrr.h> |
65 | #include <asm/mwait.h> | 65 | #include <asm/mwait.h> |
66 | #include <asm/apic.h> | 66 | #include <asm/apic.h> |
67 | #include <asm/io_apic.h> | ||
67 | #include <asm/setup.h> | 68 | #include <asm/setup.h> |
68 | #include <asm/uv/uv.h> | 69 | #include <asm/uv/uv.h> |
69 | #include <linux/mc146818rtc.h> | 70 | #include <linux/mc146818rtc.h> |
@@ -71,10 +72,6 @@ | |||
71 | #include <asm/smpboot_hooks.h> | 72 | #include <asm/smpboot_hooks.h> |
72 | #include <asm/i8259.h> | 73 | #include <asm/i8259.h> |
73 | 74 | ||
74 | #ifdef CONFIG_X86_32 | ||
75 | u8 apicid_2_node[MAX_APICID]; | ||
76 | #endif | ||
77 | |||
78 | /* State of each CPU */ | 75 | /* State of each CPU */ |
79 | DEFINE_PER_CPU(int, cpu_state) = { 0 }; | 76 | DEFINE_PER_CPU(int, cpu_state) = { 0 }; |
80 | 77 | ||
@@ -130,68 +127,14 @@ EXPORT_PER_CPU_SYMBOL(cpu_sibling_map); | |||
130 | DEFINE_PER_CPU(cpumask_var_t, cpu_core_map); | 127 | DEFINE_PER_CPU(cpumask_var_t, cpu_core_map); |
131 | EXPORT_PER_CPU_SYMBOL(cpu_core_map); | 128 | EXPORT_PER_CPU_SYMBOL(cpu_core_map); |
132 | 129 | ||
130 | DEFINE_PER_CPU(cpumask_var_t, cpu_llc_shared_map); | ||
131 | |||
133 | /* Per CPU bogomips and other parameters */ | 132 | /* Per CPU bogomips and other parameters */ |
134 | DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info); | 133 | DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info); |
135 | EXPORT_PER_CPU_SYMBOL(cpu_info); | 134 | EXPORT_PER_CPU_SYMBOL(cpu_info); |
136 | 135 | ||
137 | atomic_t init_deasserted; | 136 | atomic_t init_deasserted; |
138 | 137 | ||
139 | #if defined(CONFIG_NUMA) && defined(CONFIG_X86_32) | ||
140 | /* which node each logical CPU is on */ | ||
141 | int cpu_to_node_map[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = 0 }; | ||
142 | EXPORT_SYMBOL(cpu_to_node_map); | ||
143 | |||
144 | /* set up a mapping between cpu and node. */ | ||
145 | static void map_cpu_to_node(int cpu, int node) | ||
146 | { | ||
147 | printk(KERN_INFO "Mapping cpu %d to node %d\n", cpu, node); | ||
148 | cpumask_set_cpu(cpu, node_to_cpumask_map[node]); | ||
149 | cpu_to_node_map[cpu] = node; | ||
150 | } | ||
151 | |||
152 | /* undo a mapping between cpu and node. */ | ||
153 | static void unmap_cpu_to_node(int cpu) | ||
154 | { | ||
155 | int node; | ||
156 | |||
157 | printk(KERN_INFO "Unmapping cpu %d from all nodes\n", cpu); | ||
158 | for (node = 0; node < MAX_NUMNODES; node++) | ||
159 | cpumask_clear_cpu(cpu, node_to_cpumask_map[node]); | ||
160 | cpu_to_node_map[cpu] = 0; | ||
161 | } | ||
162 | #else /* !(CONFIG_NUMA && CONFIG_X86_32) */ | ||
163 | #define map_cpu_to_node(cpu, node) ({}) | ||
164 | #define unmap_cpu_to_node(cpu) ({}) | ||
165 | #endif | ||
166 | |||
167 | #ifdef CONFIG_X86_32 | ||
168 | static int boot_cpu_logical_apicid; | ||
169 | |||
170 | u8 cpu_2_logical_apicid[NR_CPUS] __read_mostly = | ||
171 | { [0 ... NR_CPUS-1] = BAD_APICID }; | ||
172 | |||
173 | static void map_cpu_to_logical_apicid(void) | ||
174 | { | ||
175 | int cpu = smp_processor_id(); | ||
176 | int apicid = logical_smp_processor_id(); | ||
177 | int node = apic->apicid_to_node(apicid); | ||
178 | |||
179 | if (!node_online(node)) | ||
180 | node = first_online_node; | ||
181 | |||
182 | cpu_2_logical_apicid[cpu] = apicid; | ||
183 | map_cpu_to_node(cpu, node); | ||
184 | } | ||
185 | |||
186 | void numa_remove_cpu(int cpu) | ||
187 | { | ||
188 | cpu_2_logical_apicid[cpu] = BAD_APICID; | ||
189 | unmap_cpu_to_node(cpu); | ||
190 | } | ||
191 | #else | ||
192 | #define map_cpu_to_logical_apicid() do {} while (0) | ||
193 | #endif | ||
194 | |||
195 | /* | 138 | /* |
196 | * Report back to the Boot Processor. | 139 | * Report back to the Boot Processor. |
197 | * Running on AP. | 140 | * Running on AP. |
@@ -259,7 +202,6 @@ static void __cpuinit smp_callin(void) | |||
259 | apic->smp_callin_clear_local_apic(); | 202 | apic->smp_callin_clear_local_apic(); |
260 | setup_local_APIC(); | 203 | setup_local_APIC(); |
261 | end_local_APIC_setup(); | 204 | end_local_APIC_setup(); |
262 | map_cpu_to_logical_apicid(); | ||
263 | 205 | ||
264 | /* | 206 | /* |
265 | * Need to setup vector mappings before we enable interrupts. | 207 | * Need to setup vector mappings before we enable interrupts. |
@@ -355,23 +297,6 @@ notrace static void __cpuinit start_secondary(void *unused) | |||
355 | cpu_idle(); | 297 | cpu_idle(); |
356 | } | 298 | } |
357 | 299 | ||
358 | #ifdef CONFIG_CPUMASK_OFFSTACK | ||
359 | /* In this case, llc_shared_map is a pointer to a cpumask. */ | ||
360 | static inline void copy_cpuinfo_x86(struct cpuinfo_x86 *dst, | ||
361 | const struct cpuinfo_x86 *src) | ||
362 | { | ||
363 | struct cpumask *llc = dst->llc_shared_map; | ||
364 | *dst = *src; | ||
365 | dst->llc_shared_map = llc; | ||
366 | } | ||
367 | #else | ||
368 | static inline void copy_cpuinfo_x86(struct cpuinfo_x86 *dst, | ||
369 | const struct cpuinfo_x86 *src) | ||
370 | { | ||
371 | *dst = *src; | ||
372 | } | ||
373 | #endif /* CONFIG_CPUMASK_OFFSTACK */ | ||
374 | |||
375 | /* | 300 | /* |
376 | * The bootstrap kernel entry code has set these up. Save them for | 301 | * The bootstrap kernel entry code has set these up. Save them for |
377 | * a given CPU | 302 | * a given CPU |
@@ -381,7 +306,7 @@ void __cpuinit smp_store_cpu_info(int id) | |||
381 | { | 306 | { |
382 | struct cpuinfo_x86 *c = &cpu_data(id); | 307 | struct cpuinfo_x86 *c = &cpu_data(id); |
383 | 308 | ||
384 | copy_cpuinfo_x86(c, &boot_cpu_data); | 309 | *c = boot_cpu_data; |
385 | c->cpu_index = id; | 310 | c->cpu_index = id; |
386 | if (id != 0) | 311 | if (id != 0) |
387 | identify_secondary_cpu(c); | 312 | identify_secondary_cpu(c); |
@@ -389,15 +314,12 @@ void __cpuinit smp_store_cpu_info(int id) | |||
389 | 314 | ||
390 | static void __cpuinit link_thread_siblings(int cpu1, int cpu2) | 315 | static void __cpuinit link_thread_siblings(int cpu1, int cpu2) |
391 | { | 316 | { |
392 | struct cpuinfo_x86 *c1 = &cpu_data(cpu1); | ||
393 | struct cpuinfo_x86 *c2 = &cpu_data(cpu2); | ||
394 | |||
395 | cpumask_set_cpu(cpu1, cpu_sibling_mask(cpu2)); | 317 | cpumask_set_cpu(cpu1, cpu_sibling_mask(cpu2)); |
396 | cpumask_set_cpu(cpu2, cpu_sibling_mask(cpu1)); | 318 | cpumask_set_cpu(cpu2, cpu_sibling_mask(cpu1)); |
397 | cpumask_set_cpu(cpu1, cpu_core_mask(cpu2)); | 319 | cpumask_set_cpu(cpu1, cpu_core_mask(cpu2)); |
398 | cpumask_set_cpu(cpu2, cpu_core_mask(cpu1)); | 320 | cpumask_set_cpu(cpu2, cpu_core_mask(cpu1)); |
399 | cpumask_set_cpu(cpu1, c2->llc_shared_map); | 321 | cpumask_set_cpu(cpu1, cpu_llc_shared_mask(cpu2)); |
400 | cpumask_set_cpu(cpu2, c1->llc_shared_map); | 322 | cpumask_set_cpu(cpu2, cpu_llc_shared_mask(cpu1)); |
401 | } | 323 | } |
402 | 324 | ||
403 | 325 | ||
@@ -414,6 +336,7 @@ void __cpuinit set_cpu_sibling_map(int cpu) | |||
414 | 336 | ||
415 | if (cpu_has(c, X86_FEATURE_TOPOEXT)) { | 337 | if (cpu_has(c, X86_FEATURE_TOPOEXT)) { |
416 | if (c->phys_proc_id == o->phys_proc_id && | 338 | if (c->phys_proc_id == o->phys_proc_id && |
339 | per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i) && | ||
417 | c->compute_unit_id == o->compute_unit_id) | 340 | c->compute_unit_id == o->compute_unit_id) |
418 | link_thread_siblings(cpu, i); | 341 | link_thread_siblings(cpu, i); |
419 | } else if (c->phys_proc_id == o->phys_proc_id && | 342 | } else if (c->phys_proc_id == o->phys_proc_id && |
@@ -425,7 +348,7 @@ void __cpuinit set_cpu_sibling_map(int cpu) | |||
425 | cpumask_set_cpu(cpu, cpu_sibling_mask(cpu)); | 348 | cpumask_set_cpu(cpu, cpu_sibling_mask(cpu)); |
426 | } | 349 | } |
427 | 350 | ||
428 | cpumask_set_cpu(cpu, c->llc_shared_map); | 351 | cpumask_set_cpu(cpu, cpu_llc_shared_mask(cpu)); |
429 | 352 | ||
430 | if (__this_cpu_read(cpu_info.x86_max_cores) == 1) { | 353 | if (__this_cpu_read(cpu_info.x86_max_cores) == 1) { |
431 | cpumask_copy(cpu_core_mask(cpu), cpu_sibling_mask(cpu)); | 354 | cpumask_copy(cpu_core_mask(cpu), cpu_sibling_mask(cpu)); |
@@ -436,8 +359,8 @@ void __cpuinit set_cpu_sibling_map(int cpu) | |||
436 | for_each_cpu(i, cpu_sibling_setup_mask) { | 359 | for_each_cpu(i, cpu_sibling_setup_mask) { |
437 | if (per_cpu(cpu_llc_id, cpu) != BAD_APICID && | 360 | if (per_cpu(cpu_llc_id, cpu) != BAD_APICID && |
438 | per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) { | 361 | per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) { |
439 | cpumask_set_cpu(i, c->llc_shared_map); | 362 | cpumask_set_cpu(i, cpu_llc_shared_mask(cpu)); |
440 | cpumask_set_cpu(cpu, cpu_data(i).llc_shared_map); | 363 | cpumask_set_cpu(cpu, cpu_llc_shared_mask(i)); |
441 | } | 364 | } |
442 | if (c->phys_proc_id == cpu_data(i).phys_proc_id) { | 365 | if (c->phys_proc_id == cpu_data(i).phys_proc_id) { |
443 | cpumask_set_cpu(i, cpu_core_mask(cpu)); | 366 | cpumask_set_cpu(i, cpu_core_mask(cpu)); |
@@ -476,7 +399,7 @@ const struct cpumask *cpu_coregroup_mask(int cpu) | |||
476 | !(cpu_has(c, X86_FEATURE_AMD_DCM))) | 399 | !(cpu_has(c, X86_FEATURE_AMD_DCM))) |
477 | return cpu_core_mask(cpu); | 400 | return cpu_core_mask(cpu); |
478 | else | 401 | else |
479 | return c->llc_shared_map; | 402 | return cpu_llc_shared_mask(cpu); |
480 | } | 403 | } |
481 | 404 | ||
482 | static void impress_friends(void) | 405 | static void impress_friends(void) |
@@ -788,7 +711,7 @@ do_rest: | |||
788 | stack_start = c_idle.idle->thread.sp; | 711 | stack_start = c_idle.idle->thread.sp; |
789 | 712 | ||
790 | /* start_ip had better be page-aligned! */ | 713 | /* start_ip had better be page-aligned! */ |
791 | start_ip = setup_trampoline(); | 714 | start_ip = trampoline_address(); |
792 | 715 | ||
793 | /* So we see what's up */ | 716 | /* So we see what's up */ |
794 | announce_cpu(cpu, apicid); | 717 | announce_cpu(cpu, apicid); |
@@ -798,6 +721,8 @@ do_rest: | |||
798 | * the targeted processor. | 721 | * the targeted processor. |
799 | */ | 722 | */ |
800 | 723 | ||
724 | printk(KERN_DEBUG "smpboot cpu %d: start_ip = %lx\n", cpu, start_ip); | ||
725 | |||
801 | atomic_set(&init_deasserted, 0); | 726 | atomic_set(&init_deasserted, 0); |
802 | 727 | ||
803 | if (get_uv_system_type() != UV_NON_UNIQUE_APIC) { | 728 | if (get_uv_system_type() != UV_NON_UNIQUE_APIC) { |
@@ -851,8 +776,8 @@ do_rest: | |||
851 | pr_debug("CPU%d: has booted.\n", cpu); | 776 | pr_debug("CPU%d: has booted.\n", cpu); |
852 | else { | 777 | else { |
853 | boot_error = 1; | 778 | boot_error = 1; |
854 | if (*((volatile unsigned char *)trampoline_base) | 779 | if (*(volatile u32 *)TRAMPOLINE_SYM(trampoline_status) |
855 | == 0xA5) | 780 | == 0xA5A5A5A5) |
856 | /* trampoline started but...? */ | 781 | /* trampoline started but...? */ |
857 | pr_err("CPU%d: Stuck ??\n", cpu); | 782 | pr_err("CPU%d: Stuck ??\n", cpu); |
858 | else | 783 | else |
@@ -878,7 +803,7 @@ do_rest: | |||
878 | } | 803 | } |
879 | 804 | ||
880 | /* mark "stuck" area as not stuck */ | 805 | /* mark "stuck" area as not stuck */ |
881 | *((volatile unsigned long *)trampoline_base) = 0; | 806 | *(volatile u32 *)TRAMPOLINE_SYM(trampoline_status) = 0; |
882 | 807 | ||
883 | if (get_uv_system_type() != UV_NON_UNIQUE_APIC) { | 808 | if (get_uv_system_type() != UV_NON_UNIQUE_APIC) { |
884 | /* | 809 | /* |
@@ -945,6 +870,14 @@ int __cpuinit native_cpu_up(unsigned int cpu) | |||
945 | return 0; | 870 | return 0; |
946 | } | 871 | } |
947 | 872 | ||
873 | /** | ||
874 | * arch_disable_smp_support() - disables SMP support for x86 at runtime | ||
875 | */ | ||
876 | void arch_disable_smp_support(void) | ||
877 | { | ||
878 | disable_ioapic_support(); | ||
879 | } | ||
880 | |||
948 | /* | 881 | /* |
949 | * Fall back to non SMP mode after errors. | 882 | * Fall back to non SMP mode after errors. |
950 | * | 883 | * |
@@ -960,7 +893,6 @@ static __init void disable_smp(void) | |||
960 | physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map); | 893 | physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map); |
961 | else | 894 | else |
962 | physid_set_mask_of_physid(0, &phys_cpu_present_map); | 895 | physid_set_mask_of_physid(0, &phys_cpu_present_map); |
963 | map_cpu_to_logical_apicid(); | ||
964 | cpumask_set_cpu(0, cpu_sibling_mask(0)); | 896 | cpumask_set_cpu(0, cpu_sibling_mask(0)); |
965 | cpumask_set_cpu(0, cpu_core_mask(0)); | 897 | cpumask_set_cpu(0, cpu_core_mask(0)); |
966 | } | 898 | } |
@@ -1045,7 +977,7 @@ static int __init smp_sanity_check(unsigned max_cpus) | |||
1045 | "(tell your hw vendor)\n"); | 977 | "(tell your hw vendor)\n"); |
1046 | } | 978 | } |
1047 | smpboot_clear_io_apic(); | 979 | smpboot_clear_io_apic(); |
1048 | arch_disable_smp_support(); | 980 | disable_ioapic_support(); |
1049 | return -1; | 981 | return -1; |
1050 | } | 982 | } |
1051 | 983 | ||
@@ -1089,21 +1021,19 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) | |||
1089 | 1021 | ||
1090 | preempt_disable(); | 1022 | preempt_disable(); |
1091 | smp_cpu_index_default(); | 1023 | smp_cpu_index_default(); |
1092 | memcpy(__this_cpu_ptr(&cpu_info), &boot_cpu_data, sizeof(cpu_info)); | 1024 | |
1093 | cpumask_copy(cpu_callin_mask, cpumask_of(0)); | ||
1094 | mb(); | ||
1095 | /* | 1025 | /* |
1096 | * Setup boot CPU information | 1026 | * Setup boot CPU information |
1097 | */ | 1027 | */ |
1098 | smp_store_cpu_info(0); /* Final full version of the data */ | 1028 | smp_store_cpu_info(0); /* Final full version of the data */ |
1099 | #ifdef CONFIG_X86_32 | 1029 | cpumask_copy(cpu_callin_mask, cpumask_of(0)); |
1100 | boot_cpu_logical_apicid = logical_smp_processor_id(); | 1030 | mb(); |
1101 | #endif | 1031 | |
1102 | current_thread_info()->cpu = 0; /* needed? */ | 1032 | current_thread_info()->cpu = 0; /* needed? */ |
1103 | for_each_possible_cpu(i) { | 1033 | for_each_possible_cpu(i) { |
1104 | zalloc_cpumask_var(&per_cpu(cpu_sibling_map, i), GFP_KERNEL); | 1034 | zalloc_cpumask_var(&per_cpu(cpu_sibling_map, i), GFP_KERNEL); |
1105 | zalloc_cpumask_var(&per_cpu(cpu_core_map, i), GFP_KERNEL); | 1035 | zalloc_cpumask_var(&per_cpu(cpu_core_map, i), GFP_KERNEL); |
1106 | zalloc_cpumask_var(&cpu_data(i).llc_shared_map, GFP_KERNEL); | 1036 | zalloc_cpumask_var(&per_cpu(cpu_llc_shared_map, i), GFP_KERNEL); |
1107 | } | 1037 | } |
1108 | set_cpu_sibling_map(0); | 1038 | set_cpu_sibling_map(0); |
1109 | 1039 | ||
@@ -1139,8 +1069,6 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) | |||
1139 | 1069 | ||
1140 | bsp_end_local_APIC_setup(); | 1070 | bsp_end_local_APIC_setup(); |
1141 | 1071 | ||
1142 | map_cpu_to_logical_apicid(); | ||
1143 | |||
1144 | if (apic->setup_portio_remap) | 1072 | if (apic->setup_portio_remap) |
1145 | apic->setup_portio_remap(); | 1073 | apic->setup_portio_remap(); |
1146 | 1074 | ||