diff options
Diffstat (limited to 'arch/x86/kernel/smpboot.c')
-rw-r--r-- | arch/x86/kernel/smpboot.c | 125 |
1 files changed, 80 insertions, 45 deletions
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 7985c5b3f916..76b6f50978f7 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #include <asm/desc.h> | 52 | #include <asm/desc.h> |
53 | #include <asm/nmi.h> | 53 | #include <asm/nmi.h> |
54 | #include <asm/irq.h> | 54 | #include <asm/irq.h> |
55 | #include <asm/idle.h> | ||
55 | #include <asm/smp.h> | 56 | #include <asm/smp.h> |
56 | #include <asm/trampoline.h> | 57 | #include <asm/trampoline.h> |
57 | #include <asm/cpu.h> | 58 | #include <asm/cpu.h> |
@@ -88,7 +89,7 @@ static DEFINE_PER_CPU(struct task_struct *, idle_thread_array); | |||
88 | #define get_idle_for_cpu(x) (per_cpu(idle_thread_array, x)) | 89 | #define get_idle_for_cpu(x) (per_cpu(idle_thread_array, x)) |
89 | #define set_idle_for_cpu(x, p) (per_cpu(idle_thread_array, x) = (p)) | 90 | #define set_idle_for_cpu(x, p) (per_cpu(idle_thread_array, x) = (p)) |
90 | #else | 91 | #else |
91 | struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ; | 92 | static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ; |
92 | #define get_idle_for_cpu(x) (idle_thread_array[(x)]) | 93 | #define get_idle_for_cpu(x) (idle_thread_array[(x)]) |
93 | #define set_idle_for_cpu(x, p) (idle_thread_array[(x)] = (p)) | 94 | #define set_idle_for_cpu(x, p) (idle_thread_array[(x)] = (p)) |
94 | #endif | 95 | #endif |
@@ -123,13 +124,12 @@ EXPORT_PER_CPU_SYMBOL(cpu_info); | |||
123 | 124 | ||
124 | static atomic_t init_deasserted; | 125 | static atomic_t init_deasserted; |
125 | 126 | ||
126 | static int boot_cpu_logical_apicid; | ||
127 | 127 | ||
128 | /* representing cpus for which sibling maps can be computed */ | 128 | /* representing cpus for which sibling maps can be computed */ |
129 | static cpumask_t cpu_sibling_setup_map; | 129 | static cpumask_t cpu_sibling_setup_map; |
130 | 130 | ||
131 | /* Set if we find a B stepping CPU */ | 131 | /* Set if we find a B stepping CPU */ |
132 | int __cpuinitdata smp_b_stepping; | 132 | static int __cpuinitdata smp_b_stepping; |
133 | 133 | ||
134 | #if defined(CONFIG_NUMA) && defined(CONFIG_X86_32) | 134 | #if defined(CONFIG_NUMA) && defined(CONFIG_X86_32) |
135 | 135 | ||
@@ -165,6 +165,8 @@ static void unmap_cpu_to_node(int cpu) | |||
165 | #endif | 165 | #endif |
166 | 166 | ||
167 | #ifdef CONFIG_X86_32 | 167 | #ifdef CONFIG_X86_32 |
168 | static int boot_cpu_logical_apicid; | ||
169 | |||
168 | u8 cpu_2_logical_apicid[NR_CPUS] __read_mostly = | 170 | u8 cpu_2_logical_apicid[NR_CPUS] __read_mostly = |
169 | { [0 ... NR_CPUS-1] = BAD_APICID }; | 171 | { [0 ... NR_CPUS-1] = BAD_APICID }; |
170 | 172 | ||
@@ -210,7 +212,7 @@ static void __cpuinit smp_callin(void) | |||
210 | /* | 212 | /* |
211 | * (This works even if the APIC is not enabled.) | 213 | * (This works even if the APIC is not enabled.) |
212 | */ | 214 | */ |
213 | phys_id = GET_APIC_ID(read_apic_id()); | 215 | phys_id = read_apic_id(); |
214 | cpuid = smp_processor_id(); | 216 | cpuid = smp_processor_id(); |
215 | if (cpu_isset(cpuid, cpu_callin_map)) { | 217 | if (cpu_isset(cpuid, cpu_callin_map)) { |
216 | panic("%s: phys CPU#%d, CPU#%d already present??\n", __func__, | 218 | panic("%s: phys CPU#%d, CPU#%d already present??\n", __func__, |
@@ -257,6 +259,7 @@ static void __cpuinit smp_callin(void) | |||
257 | end_local_APIC_setup(); | 259 | end_local_APIC_setup(); |
258 | map_cpu_to_logical_apicid(); | 260 | map_cpu_to_logical_apicid(); |
259 | 261 | ||
262 | notify_cpu_starting(cpuid); | ||
260 | /* | 263 | /* |
261 | * Get our bogomips. | 264 | * Get our bogomips. |
262 | * | 265 | * |
@@ -550,8 +553,7 @@ static inline void __inquire_remote_apic(int apicid) | |||
550 | printk(KERN_CONT | 553 | printk(KERN_CONT |
551 | "a previous APIC delivery may have failed\n"); | 554 | "a previous APIC delivery may have failed\n"); |
552 | 555 | ||
553 | apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); | 556 | apic_icr_write(APIC_DM_REMRD | regs[i], apicid); |
554 | apic_write(APIC_ICR, APIC_DM_REMRD | regs[i]); | ||
555 | 557 | ||
556 | timeout = 0; | 558 | timeout = 0; |
557 | do { | 559 | do { |
@@ -583,11 +585,9 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip) | |||
583 | int maxlvt; | 585 | int maxlvt; |
584 | 586 | ||
585 | /* Target chip */ | 587 | /* Target chip */ |
586 | apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(logical_apicid)); | ||
587 | |||
588 | /* Boot on the stack */ | 588 | /* Boot on the stack */ |
589 | /* Kick the second */ | 589 | /* Kick the second */ |
590 | apic_write(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL); | 590 | apic_icr_write(APIC_DM_NMI | APIC_DEST_LOGICAL, logical_apicid); |
591 | 591 | ||
592 | pr_debug("Waiting for send to finish...\n"); | 592 | pr_debug("Waiting for send to finish...\n"); |
593 | send_status = safe_apic_wait_icr_idle(); | 593 | send_status = safe_apic_wait_icr_idle(); |
@@ -640,13 +640,11 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) | |||
640 | /* | 640 | /* |
641 | * Turn INIT on target chip | 641 | * Turn INIT on target chip |
642 | */ | 642 | */ |
643 | apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid)); | ||
644 | |||
645 | /* | 643 | /* |
646 | * Send IPI | 644 | * Send IPI |
647 | */ | 645 | */ |
648 | apic_write(APIC_ICR, | 646 | apic_icr_write(APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT, |
649 | APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT); | 647 | phys_apicid); |
650 | 648 | ||
651 | pr_debug("Waiting for send to finish...\n"); | 649 | pr_debug("Waiting for send to finish...\n"); |
652 | send_status = safe_apic_wait_icr_idle(); | 650 | send_status = safe_apic_wait_icr_idle(); |
@@ -656,10 +654,8 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) | |||
656 | pr_debug("Deasserting INIT.\n"); | 654 | pr_debug("Deasserting INIT.\n"); |
657 | 655 | ||
658 | /* Target chip */ | 656 | /* Target chip */ |
659 | apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid)); | ||
660 | |||
661 | /* Send IPI */ | 657 | /* Send IPI */ |
662 | apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT); | 658 | apic_icr_write(APIC_INT_LEVELTRIG | APIC_DM_INIT, phys_apicid); |
663 | 659 | ||
664 | pr_debug("Waiting for send to finish...\n"); | 660 | pr_debug("Waiting for send to finish...\n"); |
665 | send_status = safe_apic_wait_icr_idle(); | 661 | send_status = safe_apic_wait_icr_idle(); |
@@ -702,11 +698,10 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) | |||
702 | */ | 698 | */ |
703 | 699 | ||
704 | /* Target chip */ | 700 | /* Target chip */ |
705 | apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid)); | ||
706 | |||
707 | /* Boot on the stack */ | 701 | /* Boot on the stack */ |
708 | /* Kick the second */ | 702 | /* Kick the second */ |
709 | apic_write(APIC_ICR, APIC_DM_STARTUP | (start_eip >> 12)); | 703 | apic_icr_write(APIC_DM_STARTUP | (start_eip >> 12), |
704 | phys_apicid); | ||
710 | 705 | ||
711 | /* | 706 | /* |
712 | * Give the other CPU some time to accept the IPI. | 707 | * Give the other CPU some time to accept the IPI. |
@@ -1175,10 +1170,17 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) | |||
1175 | * Setup boot CPU information | 1170 | * Setup boot CPU information |
1176 | */ | 1171 | */ |
1177 | smp_store_cpu_info(0); /* Final full version of the data */ | 1172 | smp_store_cpu_info(0); /* Final full version of the data */ |
1173 | #ifdef CONFIG_X86_32 | ||
1178 | boot_cpu_logical_apicid = logical_smp_processor_id(); | 1174 | boot_cpu_logical_apicid = logical_smp_processor_id(); |
1175 | #endif | ||
1179 | current_thread_info()->cpu = 0; /* needed? */ | 1176 | current_thread_info()->cpu = 0; /* needed? */ |
1180 | set_cpu_sibling_map(0); | 1177 | set_cpu_sibling_map(0); |
1181 | 1178 | ||
1179 | #ifdef CONFIG_X86_64 | ||
1180 | enable_IR_x2apic(); | ||
1181 | setup_apic_routing(); | ||
1182 | #endif | ||
1183 | |||
1182 | if (smp_sanity_check(max_cpus) < 0) { | 1184 | if (smp_sanity_check(max_cpus) < 0) { |
1183 | printk(KERN_INFO "SMP disabled\n"); | 1185 | printk(KERN_INFO "SMP disabled\n"); |
1184 | disable_smp(); | 1186 | disable_smp(); |
@@ -1186,9 +1188,9 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) | |||
1186 | } | 1188 | } |
1187 | 1189 | ||
1188 | preempt_disable(); | 1190 | preempt_disable(); |
1189 | if (GET_APIC_ID(read_apic_id()) != boot_cpu_physical_apicid) { | 1191 | if (read_apic_id() != boot_cpu_physical_apicid) { |
1190 | panic("Boot APIC ID in local APIC unexpected (%d vs %d)", | 1192 | panic("Boot APIC ID in local APIC unexpected (%d vs %d)", |
1191 | GET_APIC_ID(read_apic_id()), boot_cpu_physical_apicid); | 1193 | read_apic_id(), boot_cpu_physical_apicid); |
1192 | /* Or can we switch back to PIC here? */ | 1194 | /* Or can we switch back to PIC here? */ |
1193 | } | 1195 | } |
1194 | preempt_enable(); | 1196 | preempt_enable(); |
@@ -1313,16 +1315,13 @@ __init void prefill_possible_map(void) | |||
1313 | if (!num_processors) | 1315 | if (!num_processors) |
1314 | num_processors = 1; | 1316 | num_processors = 1; |
1315 | 1317 | ||
1316 | #ifdef CONFIG_HOTPLUG_CPU | ||
1317 | if (additional_cpus == -1) { | 1318 | if (additional_cpus == -1) { |
1318 | if (disabled_cpus > 0) | 1319 | if (disabled_cpus > 0) |
1319 | additional_cpus = disabled_cpus; | 1320 | additional_cpus = disabled_cpus; |
1320 | else | 1321 | else |
1321 | additional_cpus = 0; | 1322 | additional_cpus = 0; |
1322 | } | 1323 | } |
1323 | #else | 1324 | |
1324 | additional_cpus = 0; | ||
1325 | #endif | ||
1326 | possible = num_processors + additional_cpus; | 1325 | possible = num_processors + additional_cpus; |
1327 | if (possible > NR_CPUS) | 1326 | if (possible > NR_CPUS) |
1328 | possible = NR_CPUS; | 1327 | possible = NR_CPUS; |
@@ -1346,25 +1345,9 @@ static void __ref remove_cpu_from_maps(int cpu) | |||
1346 | numa_remove_cpu(cpu); | 1345 | numa_remove_cpu(cpu); |
1347 | } | 1346 | } |
1348 | 1347 | ||
1349 | int __cpu_disable(void) | 1348 | void cpu_disable_common(void) |
1350 | { | 1349 | { |
1351 | int cpu = smp_processor_id(); | 1350 | int cpu = smp_processor_id(); |
1352 | |||
1353 | /* | ||
1354 | * Perhaps use cpufreq to drop frequency, but that could go | ||
1355 | * into generic code. | ||
1356 | * | ||
1357 | * We won't take down the boot processor on i386 due to some | ||
1358 | * interrupts only being able to be serviced by the BSP. | ||
1359 | * Especially so if we're not using an IOAPIC -zwane | ||
1360 | */ | ||
1361 | if (cpu == 0) | ||
1362 | return -EBUSY; | ||
1363 | |||
1364 | if (nmi_watchdog == NMI_LOCAL_APIC) | ||
1365 | stop_apic_nmi_watchdog(NULL); | ||
1366 | clear_local_APIC(); | ||
1367 | |||
1368 | /* | 1351 | /* |
1369 | * HACK: | 1352 | * HACK: |
1370 | * Allow any queued timer interrupts to get serviced | 1353 | * Allow any queued timer interrupts to get serviced |
@@ -1382,10 +1365,32 @@ int __cpu_disable(void) | |||
1382 | remove_cpu_from_maps(cpu); | 1365 | remove_cpu_from_maps(cpu); |
1383 | unlock_vector_lock(); | 1366 | unlock_vector_lock(); |
1384 | fixup_irqs(cpu_online_map); | 1367 | fixup_irqs(cpu_online_map); |
1368 | } | ||
1369 | |||
1370 | int native_cpu_disable(void) | ||
1371 | { | ||
1372 | int cpu = smp_processor_id(); | ||
1373 | |||
1374 | /* | ||
1375 | * Perhaps use cpufreq to drop frequency, but that could go | ||
1376 | * into generic code. | ||
1377 | * | ||
1378 | * We won't take down the boot processor on i386 due to some | ||
1379 | * interrupts only being able to be serviced by the BSP. | ||
1380 | * Especially so if we're not using an IOAPIC -zwane | ||
1381 | */ | ||
1382 | if (cpu == 0) | ||
1383 | return -EBUSY; | ||
1384 | |||
1385 | if (nmi_watchdog == NMI_LOCAL_APIC) | ||
1386 | stop_apic_nmi_watchdog(NULL); | ||
1387 | clear_local_APIC(); | ||
1388 | |||
1389 | cpu_disable_common(); | ||
1385 | return 0; | 1390 | return 0; |
1386 | } | 1391 | } |
1387 | 1392 | ||
1388 | void __cpu_die(unsigned int cpu) | 1393 | void native_cpu_die(unsigned int cpu) |
1389 | { | 1394 | { |
1390 | /* We don't do anything here: idle task is faking death itself. */ | 1395 | /* We don't do anything here: idle task is faking death itself. */ |
1391 | unsigned int i; | 1396 | unsigned int i; |
@@ -1402,15 +1407,45 @@ void __cpu_die(unsigned int cpu) | |||
1402 | } | 1407 | } |
1403 | printk(KERN_ERR "CPU %u didn't die...\n", cpu); | 1408 | printk(KERN_ERR "CPU %u didn't die...\n", cpu); |
1404 | } | 1409 | } |
1410 | |||
1411 | void play_dead_common(void) | ||
1412 | { | ||
1413 | idle_task_exit(); | ||
1414 | reset_lazy_tlbstate(); | ||
1415 | irq_ctx_exit(raw_smp_processor_id()); | ||
1416 | c1e_remove_cpu(raw_smp_processor_id()); | ||
1417 | |||
1418 | mb(); | ||
1419 | /* Ack it */ | ||
1420 | __get_cpu_var(cpu_state) = CPU_DEAD; | ||
1421 | |||
1422 | /* | ||
1423 | * With physical CPU hotplug, we should halt the cpu | ||
1424 | */ | ||
1425 | local_irq_disable(); | ||
1426 | } | ||
1427 | |||
1428 | void native_play_dead(void) | ||
1429 | { | ||
1430 | play_dead_common(); | ||
1431 | wbinvd_halt(); | ||
1432 | } | ||
1433 | |||
1405 | #else /* ... !CONFIG_HOTPLUG_CPU */ | 1434 | #else /* ... !CONFIG_HOTPLUG_CPU */ |
1406 | int __cpu_disable(void) | 1435 | int native_cpu_disable(void) |
1407 | { | 1436 | { |
1408 | return -ENOSYS; | 1437 | return -ENOSYS; |
1409 | } | 1438 | } |
1410 | 1439 | ||
1411 | void __cpu_die(unsigned int cpu) | 1440 | void native_cpu_die(unsigned int cpu) |
1412 | { | 1441 | { |
1413 | /* We said "no" in __cpu_disable */ | 1442 | /* We said "no" in __cpu_disable */ |
1414 | BUG(); | 1443 | BUG(); |
1415 | } | 1444 | } |
1445 | |||
1446 | void native_play_dead(void) | ||
1447 | { | ||
1448 | BUG(); | ||
1449 | } | ||
1450 | |||
1416 | #endif | 1451 | #endif |