aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-23 14:31:22 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-23 14:31:22 -0400
commit2335a8366f63a5191b5a2b3c5a05d90fe814654c (patch)
tree20b2da7333a5003a22466895338e7734aa40f784
parent44bc40e1489622234169786b0ad5a1f4a01e1090 (diff)
parent3aac27aba79b7c52e709ef6de0f7d8139caedc01 (diff)
Merge branch 'x86-reboot-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 reboot changes from Ingo Molnar: "The biggest change is a gentler method of rebooting/stopping via IRQs first and then via NMIs. There are several cleanups in the tree as well." * 'x86-reboot-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/reboot: Update nonmi_ipi parameter x86/reboot: Use NMI to assist in shutting down if IRQ fails Revert "x86, reboot: Use NMI instead of REBOOT_VECTOR to stop cpus" x86/reboot: Clean up coding style x86/reboot: Reduce to a single DMI table for reboot quirks
-rw-r--r--arch/x86/kernel/reboot.c277
-rw-r--r--arch/x86/kernel/smp.c100
2 files changed, 185 insertions, 192 deletions
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index d840e69a853c..77215c23fba1 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -39,7 +39,8 @@ static int reboot_mode;
39enum reboot_type reboot_type = BOOT_ACPI; 39enum reboot_type reboot_type = BOOT_ACPI;
40int reboot_force; 40int reboot_force;
41 41
42/* This variable is used privately to keep track of whether or not 42/*
43 * This variable is used privately to keep track of whether or not
43 * reboot_type is still set to its default value (i.e., reboot= hasn't 44 * reboot_type is still set to its default value (i.e., reboot= hasn't
44 * been set on the command line). This is needed so that we can 45 * been set on the command line). This is needed so that we can
45 * suppress DMI scanning for reboot quirks. Without it, it's 46 * suppress DMI scanning for reboot quirks. Without it, it's
@@ -51,7 +52,8 @@ static int reboot_default = 1;
51static int reboot_cpu = -1; 52static int reboot_cpu = -1;
52#endif 53#endif
53 54
54/* This is set if we need to go through the 'emergency' path. 55/*
56 * This is set if we need to go through the 'emergency' path.
55 * When machine_emergency_restart() is called, we may be on 57 * When machine_emergency_restart() is called, we may be on
56 * an inconsistent state and won't be able to do a clean cleanup 58 * an inconsistent state and won't be able to do a clean cleanup
57 */ 59 */
@@ -60,22 +62,24 @@ static int reboot_emergency;
60/* This is set by the PCI code if either type 1 or type 2 PCI is detected */ 62/* This is set by the PCI code if either type 1 or type 2 PCI is detected */
61bool port_cf9_safe = false; 63bool port_cf9_safe = false;
62 64
63/* reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old] | p[ci] 65/*
64 warm Don't set the cold reboot flag 66 * reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old] | p[ci]
65 cold Set the cold reboot flag 67 * warm Don't set the cold reboot flag
66 bios Reboot by jumping through the BIOS (only for X86_32) 68 * cold Set the cold reboot flag
67 smp Reboot by executing reset on BSP or other CPU (only for X86_32) 69 * bios Reboot by jumping through the BIOS (only for X86_32)
68 triple Force a triple fault (init) 70 * smp Reboot by executing reset on BSP or other CPU (only for X86_32)
69 kbd Use the keyboard controller. cold reset (default) 71 * triple Force a triple fault (init)
70 acpi Use the RESET_REG in the FADT 72 * kbd Use the keyboard controller. cold reset (default)
71 efi Use efi reset_system runtime service 73 * acpi Use the RESET_REG in the FADT
72 pci Use the so-called "PCI reset register", CF9 74 * efi Use efi reset_system runtime service
73 force Avoid anything that could hang. 75 * pci Use the so-called "PCI reset register", CF9
76 * force Avoid anything that could hang.
74 */ 77 */
75static int __init reboot_setup(char *str) 78static int __init reboot_setup(char *str)
76{ 79{
77 for (;;) { 80 for (;;) {
78 /* Having anything passed on the command line via 81 /*
82 * Having anything passed on the command line via
79 * reboot= will cause us to disable DMI checking 83 * reboot= will cause us to disable DMI checking
80 * below. 84 * below.
81 */ 85 */
@@ -98,9 +102,11 @@ static int __init reboot_setup(char *str)
98 if (isdigit(*(str+2))) 102 if (isdigit(*(str+2)))
99 reboot_cpu = reboot_cpu*10 + (int)(*(str+2) - '0'); 103 reboot_cpu = reboot_cpu*10 + (int)(*(str+2) - '0');
100 } 104 }
101 /* we will leave sorting out the final value 105 /*
102 when we are ready to reboot, since we might not 106 * We will leave sorting out the final value
103 have detected BSP APIC ID or smp_num_cpu */ 107 * when we are ready to reboot, since we might not
108 * have detected BSP APIC ID or smp_num_cpu
109 */
104 break; 110 break;
105#endif /* CONFIG_SMP */ 111#endif /* CONFIG_SMP */
106 112
@@ -150,6 +156,82 @@ static int __init set_bios_reboot(const struct dmi_system_id *d)
150 return 0; 156 return 0;
151} 157}
152 158
159extern const unsigned char machine_real_restart_asm[];
160extern const u64 machine_real_restart_gdt[3];
161
162void machine_real_restart(unsigned int type)
163{
164 void *restart_va;
165 unsigned long restart_pa;
166 void (*restart_lowmem)(unsigned int);
167 u64 *lowmem_gdt;
168
169 local_irq_disable();
170
171 /*
172 * Write zero to CMOS register number 0x0f, which the BIOS POST
173 * routine will recognize as telling it to do a proper reboot. (Well
174 * that's what this book in front of me says -- it may only apply to
175 * the Phoenix BIOS though, it's not clear). At the same time,
176 * disable NMIs by setting the top bit in the CMOS address register,
177 * as we're about to do peculiar things to the CPU. I'm not sure if
178 * `outb_p' is needed instead of just `outb'. Use it to be on the
179 * safe side. (Yes, CMOS_WRITE does outb_p's. - Paul G.)
180 */
181 spin_lock(&rtc_lock);
182 CMOS_WRITE(0x00, 0x8f);
183 spin_unlock(&rtc_lock);
184
185 /*
186 * Switch back to the initial page table.
187 */
188 load_cr3(initial_page_table);
189
190 /*
191 * Write 0x1234 to absolute memory location 0x472. The BIOS reads
192 * this on booting to tell it to "Bypass memory test (also warm
193 * boot)". This seems like a fairly standard thing that gets set by
194 * REBOOT.COM programs, and the previous reset routine did this
195 * too. */
196 *((unsigned short *)0x472) = reboot_mode;
197
198 /* Patch the GDT in the low memory trampoline */
199 lowmem_gdt = TRAMPOLINE_SYM(machine_real_restart_gdt);
200
201 restart_va = TRAMPOLINE_SYM(machine_real_restart_asm);
202 restart_pa = virt_to_phys(restart_va);
203 restart_lowmem = (void (*)(unsigned int))restart_pa;
204
205 /* GDT[0]: GDT self-pointer */
206 lowmem_gdt[0] =
207 (u64)(sizeof(machine_real_restart_gdt) - 1) +
208 ((u64)virt_to_phys(lowmem_gdt) << 16);
209 /* GDT[1]: 64K real mode code segment */
210 lowmem_gdt[1] =
211 GDT_ENTRY(0x009b, restart_pa, 0xffff);
212
213 /* Jump to the identity-mapped low memory code */
214 restart_lowmem(type);
215}
216#ifdef CONFIG_APM_MODULE
217EXPORT_SYMBOL(machine_real_restart);
218#endif
219
220#endif /* CONFIG_X86_32 */
221
222/*
223 * Some Apple MacBook and MacBookPro's needs reboot=p to be able to reboot
224 */
225static int __init set_pci_reboot(const struct dmi_system_id *d)
226{
227 if (reboot_type != BOOT_CF9) {
228 reboot_type = BOOT_CF9;
229 printk(KERN_INFO "%s series board detected. "
230 "Selecting PCI-method for reboots.\n", d->ident);
231 }
232 return 0;
233}
234
153static int __init set_kbd_reboot(const struct dmi_system_id *d) 235static int __init set_kbd_reboot(const struct dmi_system_id *d)
154{ 236{
155 if (reboot_type != BOOT_KBD) { 237 if (reboot_type != BOOT_KBD) {
@@ -159,7 +241,12 @@ static int __init set_kbd_reboot(const struct dmi_system_id *d)
159 return 0; 241 return 0;
160} 242}
161 243
244/*
245 * This is a single dmi_table handling all reboot quirks. Note that
246 * REBOOT_BIOS is only available for 32bit
247 */
162static struct dmi_system_id __initdata reboot_dmi_table[] = { 248static struct dmi_system_id __initdata reboot_dmi_table[] = {
249#ifdef CONFIG_X86_32
163 { /* Handle problems with rebooting on Dell E520's */ 250 { /* Handle problems with rebooting on Dell E520's */
164 .callback = set_bios_reboot, 251 .callback = set_bios_reboot,
165 .ident = "Dell E520", 252 .ident = "Dell E520",
@@ -184,7 +271,7 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
184 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"), 271 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"),
185 }, 272 },
186 }, 273 },
187 { /* Handle problems with rebooting on Dell Optiplex 745's SFF*/ 274 { /* Handle problems with rebooting on Dell Optiplex 745's SFF */
188 .callback = set_bios_reboot, 275 .callback = set_bios_reboot,
189 .ident = "Dell OptiPlex 745", 276 .ident = "Dell OptiPlex 745",
190 .matches = { 277 .matches = {
@@ -192,7 +279,7 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
192 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"), 279 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"),
193 }, 280 },
194 }, 281 },
195 { /* Handle problems with rebooting on Dell Optiplex 745's DFF*/ 282 { /* Handle problems with rebooting on Dell Optiplex 745's DFF */
196 .callback = set_bios_reboot, 283 .callback = set_bios_reboot,
197 .ident = "Dell OptiPlex 745", 284 .ident = "Dell OptiPlex 745",
198 .matches = { 285 .matches = {
@@ -201,7 +288,7 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
201 DMI_MATCH(DMI_BOARD_NAME, "0MM599"), 288 DMI_MATCH(DMI_BOARD_NAME, "0MM599"),
202 }, 289 },
203 }, 290 },
204 { /* Handle problems with rebooting on Dell Optiplex 745 with 0KW626 */ 291 { /* Handle problems with rebooting on Dell Optiplex 745 with 0KW626 */
205 .callback = set_bios_reboot, 292 .callback = set_bios_reboot,
206 .ident = "Dell OptiPlex 745", 293 .ident = "Dell OptiPlex 745",
207 .matches = { 294 .matches = {
@@ -210,7 +297,7 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
210 DMI_MATCH(DMI_BOARD_NAME, "0KW626"), 297 DMI_MATCH(DMI_BOARD_NAME, "0KW626"),
211 }, 298 },
212 }, 299 },
213 { /* Handle problems with rebooting on Dell Optiplex 330 with 0KP561 */ 300 { /* Handle problems with rebooting on Dell Optiplex 330 with 0KP561 */
214 .callback = set_bios_reboot, 301 .callback = set_bios_reboot,
215 .ident = "Dell OptiPlex 330", 302 .ident = "Dell OptiPlex 330",
216 .matches = { 303 .matches = {
@@ -219,7 +306,7 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
219 DMI_MATCH(DMI_BOARD_NAME, "0KP561"), 306 DMI_MATCH(DMI_BOARD_NAME, "0KP561"),
220 }, 307 },
221 }, 308 },
222 { /* Handle problems with rebooting on Dell Optiplex 360 with 0T656F */ 309 { /* Handle problems with rebooting on Dell Optiplex 360 with 0T656F */
223 .callback = set_bios_reboot, 310 .callback = set_bios_reboot,
224 .ident = "Dell OptiPlex 360", 311 .ident = "Dell OptiPlex 360",
225 .matches = { 312 .matches = {
@@ -228,7 +315,7 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
228 DMI_MATCH(DMI_BOARD_NAME, "0T656F"), 315 DMI_MATCH(DMI_BOARD_NAME, "0T656F"),
229 }, 316 },
230 }, 317 },
231 { /* Handle problems with rebooting on Dell OptiPlex 760 with 0G919G*/ 318 { /* Handle problems with rebooting on Dell OptiPlex 760 with 0G919G */
232 .callback = set_bios_reboot, 319 .callback = set_bios_reboot,
233 .ident = "Dell OptiPlex 760", 320 .ident = "Dell OptiPlex 760",
234 .matches = { 321 .matches = {
@@ -301,7 +388,7 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
301 DMI_MATCH(DMI_PRODUCT_NAME, "SBC-FITPC2"), 388 DMI_MATCH(DMI_PRODUCT_NAME, "SBC-FITPC2"),
302 }, 389 },
303 }, 390 },
304 { /* Handle problems with rebooting on ASUS P4S800 */ 391 { /* Handle problems with rebooting on ASUS P4S800 */
305 .callback = set_bios_reboot, 392 .callback = set_bios_reboot,
306 .ident = "ASUS P4S800", 393 .ident = "ASUS P4S800",
307 .matches = { 394 .matches = {
@@ -309,7 +396,9 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
309 DMI_MATCH(DMI_BOARD_NAME, "P4S800"), 396 DMI_MATCH(DMI_BOARD_NAME, "P4S800"),
310 }, 397 },
311 }, 398 },
312 { /* Handle reboot issue on Acer Aspire one */ 399#endif /* CONFIG_X86_32 */
400
401 { /* Handle reboot issue on Acer Aspire one */
313 .callback = set_kbd_reboot, 402 .callback = set_kbd_reboot,
314 .ident = "Acer Aspire One A110", 403 .ident = "Acer Aspire One A110",
315 .matches = { 404 .matches = {
@@ -317,96 +406,6 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
317 DMI_MATCH(DMI_PRODUCT_NAME, "AOA110"), 406 DMI_MATCH(DMI_PRODUCT_NAME, "AOA110"),
318 }, 407 },
319 }, 408 },
320 { }
321};
322
323static int __init reboot_init(void)
324{
325 /* Only do the DMI check if reboot_type hasn't been overridden
326 * on the command line
327 */
328 if (reboot_default) {
329 dmi_check_system(reboot_dmi_table);
330 }
331 return 0;
332}
333core_initcall(reboot_init);
334
335extern const unsigned char machine_real_restart_asm[];
336extern const u64 machine_real_restart_gdt[3];
337
338void machine_real_restart(unsigned int type)
339{
340 void *restart_va;
341 unsigned long restart_pa;
342 void (*restart_lowmem)(unsigned int);
343 u64 *lowmem_gdt;
344
345 local_irq_disable();
346
347 /* Write zero to CMOS register number 0x0f, which the BIOS POST
348 routine will recognize as telling it to do a proper reboot. (Well
349 that's what this book in front of me says -- it may only apply to
350 the Phoenix BIOS though, it's not clear). At the same time,
351 disable NMIs by setting the top bit in the CMOS address register,
352 as we're about to do peculiar things to the CPU. I'm not sure if
353 `outb_p' is needed instead of just `outb'. Use it to be on the
354 safe side. (Yes, CMOS_WRITE does outb_p's. - Paul G.)
355 */
356 spin_lock(&rtc_lock);
357 CMOS_WRITE(0x00, 0x8f);
358 spin_unlock(&rtc_lock);
359
360 /*
361 * Switch back to the initial page table.
362 */
363 load_cr3(initial_page_table);
364
365 /* Write 0x1234 to absolute memory location 0x472. The BIOS reads
366 this on booting to tell it to "Bypass memory test (also warm
367 boot)". This seems like a fairly standard thing that gets set by
368 REBOOT.COM programs, and the previous reset routine did this
369 too. */
370 *((unsigned short *)0x472) = reboot_mode;
371
372 /* Patch the GDT in the low memory trampoline */
373 lowmem_gdt = TRAMPOLINE_SYM(machine_real_restart_gdt);
374
375 restart_va = TRAMPOLINE_SYM(machine_real_restart_asm);
376 restart_pa = virt_to_phys(restart_va);
377 restart_lowmem = (void (*)(unsigned int))restart_pa;
378
379 /* GDT[0]: GDT self-pointer */
380 lowmem_gdt[0] =
381 (u64)(sizeof(machine_real_restart_gdt) - 1) +
382 ((u64)virt_to_phys(lowmem_gdt) << 16);
383 /* GDT[1]: 64K real mode code segment */
384 lowmem_gdt[1] =
385 GDT_ENTRY(0x009b, restart_pa, 0xffff);
386
387 /* Jump to the identity-mapped low memory code */
388 restart_lowmem(type);
389}
390#ifdef CONFIG_APM_MODULE
391EXPORT_SYMBOL(machine_real_restart);
392#endif
393
394#endif /* CONFIG_X86_32 */
395
396/*
397 * Some Apple MacBook and MacBookPro's needs reboot=p to be able to reboot
398 */
399static int __init set_pci_reboot(const struct dmi_system_id *d)
400{
401 if (reboot_type != BOOT_CF9) {
402 reboot_type = BOOT_CF9;
403 printk(KERN_INFO "%s series board detected. "
404 "Selecting PCI-method for reboots.\n", d->ident);
405 }
406 return 0;
407}
408
409static struct dmi_system_id __initdata pci_reboot_dmi_table[] = {
410 { /* Handle problems with rebooting on Apple MacBook5 */ 409 { /* Handle problems with rebooting on Apple MacBook5 */
411 .callback = set_pci_reboot, 410 .callback = set_pci_reboot,
412 .ident = "Apple MacBook5", 411 .ident = "Apple MacBook5",
@@ -474,17 +473,17 @@ static struct dmi_system_id __initdata pci_reboot_dmi_table[] = {
474 { } 473 { }
475}; 474};
476 475
477static int __init pci_reboot_init(void) 476static int __init reboot_init(void)
478{ 477{
479 /* Only do the DMI check if reboot_type hasn't been overridden 478 /*
479 * Only do the DMI check if reboot_type hasn't been overridden
480 * on the command line 480 * on the command line
481 */ 481 */
482 if (reboot_default) { 482 if (reboot_default)
483 dmi_check_system(pci_reboot_dmi_table); 483 dmi_check_system(reboot_dmi_table);
484 }
485 return 0; 484 return 0;
486} 485}
487core_initcall(pci_reboot_init); 486core_initcall(reboot_init);
488 487
489static inline void kb_wait(void) 488static inline void kb_wait(void)
490{ 489{
@@ -502,14 +501,14 @@ static void vmxoff_nmi(int cpu, struct pt_regs *regs)
502 cpu_emergency_vmxoff(); 501 cpu_emergency_vmxoff();
503} 502}
504 503
505/* Use NMIs as IPIs to tell all CPUs to disable virtualization 504/* Use NMIs as IPIs to tell all CPUs to disable virtualization */
506 */
507static void emergency_vmx_disable_all(void) 505static void emergency_vmx_disable_all(void)
508{ 506{
509 /* Just make sure we won't change CPUs while doing this */ 507 /* Just make sure we won't change CPUs while doing this */
510 local_irq_disable(); 508 local_irq_disable();
511 509
512 /* We need to disable VMX on all CPUs before rebooting, otherwise 510 /*
511 * We need to disable VMX on all CPUs before rebooting, otherwise
513 * we risk hanging up the machine, because the CPU ignore INIT 512 * we risk hanging up the machine, because the CPU ignore INIT
514 * signals when VMX is enabled. 513 * signals when VMX is enabled.
515 * 514 *
@@ -528,8 +527,7 @@ static void emergency_vmx_disable_all(void)
528 * is still enabling VMX. 527 * is still enabling VMX.
529 */ 528 */
530 if (cpu_has_vmx() && cpu_vmx_enabled()) { 529 if (cpu_has_vmx() && cpu_vmx_enabled()) {
531 /* Disable VMX on this CPU. 530 /* Disable VMX on this CPU. */
532 */
533 cpu_vmxoff(); 531 cpu_vmxoff();
534 532
535 /* Halt and disable VMX on the other CPUs */ 533 /* Halt and disable VMX on the other CPUs */
@@ -574,12 +572,12 @@ static void native_machine_emergency_restart(void)
574 /* Could also try the reset bit in the Hammer NB */ 572 /* Could also try the reset bit in the Hammer NB */
575 switch (reboot_type) { 573 switch (reboot_type) {
576 case BOOT_KBD: 574 case BOOT_KBD:
577 mach_reboot_fixups(); /* for board specific fixups */ 575 mach_reboot_fixups(); /* For board specific fixups */
578 576
579 for (i = 0; i < 10; i++) { 577 for (i = 0; i < 10; i++) {
580 kb_wait(); 578 kb_wait();
581 udelay(50); 579 udelay(50);
582 outb(0xfe, 0x64); /* pulse reset low */ 580 outb(0xfe, 0x64); /* Pulse reset low */
583 udelay(50); 581 udelay(50);
584 } 582 }
585 if (attempt == 0 && orig_reboot_type == BOOT_ACPI) { 583 if (attempt == 0 && orig_reboot_type == BOOT_ACPI) {
@@ -621,7 +619,7 @@ static void native_machine_emergency_restart(void)
621 619
622 case BOOT_CF9: 620 case BOOT_CF9:
623 port_cf9_safe = true; 621 port_cf9_safe = true;
624 /* fall through */ 622 /* Fall through */
625 623
626 case BOOT_CF9_COND: 624 case BOOT_CF9_COND:
627 if (port_cf9_safe) { 625 if (port_cf9_safe) {
@@ -659,7 +657,8 @@ void native_machine_shutdown(void)
659 /* Make certain I only run on the appropriate processor */ 657 /* Make certain I only run on the appropriate processor */
660 set_cpus_allowed_ptr(current, cpumask_of(reboot_cpu_id)); 658 set_cpus_allowed_ptr(current, cpumask_of(reboot_cpu_id));
661 659
662 /* O.K Now that I'm on the appropriate processor, 660 /*
661 * O.K Now that I'm on the appropriate processor,
663 * stop all of the others. 662 * stop all of the others.
664 */ 663 */
665 stop_other_cpus(); 664 stop_other_cpus();
@@ -697,12 +696,11 @@ static void native_machine_restart(char *__unused)
697 696
698static void native_machine_halt(void) 697static void native_machine_halt(void)
699{ 698{
700 /* stop other cpus and apics */ 699 /* Stop other cpus and apics */
701 machine_shutdown(); 700 machine_shutdown();
702 701
703 tboot_shutdown(TB_SHUTDOWN_HALT); 702 tboot_shutdown(TB_SHUTDOWN_HALT);
704 703
705 /* stop this cpu */
706 stop_this_cpu(NULL); 704 stop_this_cpu(NULL);
707} 705}
708 706
@@ -713,7 +711,7 @@ static void native_machine_power_off(void)
713 machine_shutdown(); 711 machine_shutdown();
714 pm_power_off(); 712 pm_power_off();
715 } 713 }
716 /* a fallback in case there is no PM info available */ 714 /* A fallback in case there is no PM info available */
717 tboot_shutdown(TB_SHUTDOWN_HALT); 715 tboot_shutdown(TB_SHUTDOWN_HALT);
718} 716}
719 717
@@ -775,7 +773,8 @@ static int crash_nmi_callback(unsigned int val, struct pt_regs *regs)
775 773
776 cpu = raw_smp_processor_id(); 774 cpu = raw_smp_processor_id();
777 775
778 /* Don't do anything if this handler is invoked on crashing cpu. 776 /*
777 * Don't do anything if this handler is invoked on crashing cpu.
779 * Otherwise, system will completely hang. Crashing cpu can get 778 * Otherwise, system will completely hang. Crashing cpu can get
780 * an NMI if system was initially booted with nmi_watchdog parameter. 779 * an NMI if system was initially booted with nmi_watchdog parameter.
781 */ 780 */
@@ -799,7 +798,8 @@ static void smp_send_nmi_allbutself(void)
799 apic->send_IPI_allbutself(NMI_VECTOR); 798 apic->send_IPI_allbutself(NMI_VECTOR);
800} 799}
801 800
802/* Halt all other CPUs, calling the specified function on each of them 801/*
802 * Halt all other CPUs, calling the specified function on each of them
803 * 803 *
804 * This function can be used to halt all other CPUs on crash 804 * This function can be used to halt all other CPUs on crash
805 * or emergency reboot time. The function passed as parameter 805 * or emergency reboot time. The function passed as parameter
@@ -810,7 +810,7 @@ void nmi_shootdown_cpus(nmi_shootdown_cb callback)
810 unsigned long msecs; 810 unsigned long msecs;
811 local_irq_disable(); 811 local_irq_disable();
812 812
813 /* Make a note of crashing cpu. Will be used in NMI callback.*/ 813 /* Make a note of crashing cpu. Will be used in NMI callback. */
814 crashing_cpu = safe_smp_processor_id(); 814 crashing_cpu = safe_smp_processor_id();
815 815
816 shootdown_callback = callback; 816 shootdown_callback = callback;
@@ -819,8 +819,9 @@ void nmi_shootdown_cpus(nmi_shootdown_cb callback)
819 /* Would it be better to replace the trap vector here? */ 819 /* Would it be better to replace the trap vector here? */
820 if (register_nmi_handler(NMI_LOCAL, crash_nmi_callback, 820 if (register_nmi_handler(NMI_LOCAL, crash_nmi_callback,
821 NMI_FLAG_FIRST, "crash")) 821 NMI_FLAG_FIRST, "crash"))
822 return; /* return what? */ 822 return; /* Return what? */
823 /* Ensure the new callback function is set before sending 823 /*
824 * Ensure the new callback function is set before sending
824 * out the NMI 825 * out the NMI
825 */ 826 */
826 wmb(); 827 wmb();
diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c
index 66c74f481cab..48d2b7ded422 100644
--- a/arch/x86/kernel/smp.c
+++ b/arch/x86/kernel/smp.c
@@ -109,6 +109,9 @@
109 * about nothing of note with C stepping upwards. 109 * about nothing of note with C stepping upwards.
110 */ 110 */
111 111
112static atomic_t stopping_cpu = ATOMIC_INIT(-1);
113static bool smp_no_nmi_ipi = false;
114
112/* 115/*
113 * this function sends a 'reschedule' IPI to another CPU. 116 * this function sends a 'reschedule' IPI to another CPU.
114 * it goes straight through and wastes no time serializing 117 * it goes straight through and wastes no time serializing
@@ -149,8 +152,6 @@ void native_send_call_func_ipi(const struct cpumask *mask)
149 free_cpumask_var(allbutself); 152 free_cpumask_var(allbutself);
150} 153}
151 154
152static atomic_t stopping_cpu = ATOMIC_INIT(-1);
153
154static int smp_stop_nmi_callback(unsigned int val, struct pt_regs *regs) 155static int smp_stop_nmi_callback(unsigned int val, struct pt_regs *regs)
155{ 156{
156 /* We are registered on stopping cpu too, avoid spurious NMI */ 157 /* We are registered on stopping cpu too, avoid spurious NMI */
@@ -162,7 +163,19 @@ static int smp_stop_nmi_callback(unsigned int val, struct pt_regs *regs)
162 return NMI_HANDLED; 163 return NMI_HANDLED;
163} 164}
164 165
165static void native_nmi_stop_other_cpus(int wait) 166/*
167 * this function calls the 'stop' function on all other CPUs in the system.
168 */
169
170asmlinkage void smp_reboot_interrupt(void)
171{
172 ack_APIC_irq();
173 irq_enter();
174 stop_this_cpu(NULL);
175 irq_exit();
176}
177
178static void native_stop_other_cpus(int wait)
166{ 179{
167 unsigned long flags; 180 unsigned long flags;
168 unsigned long timeout; 181 unsigned long timeout;
@@ -174,20 +187,25 @@ static void native_nmi_stop_other_cpus(int wait)
174 * Use an own vector here because smp_call_function 187 * Use an own vector here because smp_call_function
175 * does lots of things not suitable in a panic situation. 188 * does lots of things not suitable in a panic situation.
176 */ 189 */
190
191 /*
192 * We start by using the REBOOT_VECTOR irq.
193 * The irq is treated as a sync point to allow critical
194 * regions of code on other cpus to release their spin locks
195 * and re-enable irqs. Jumping straight to an NMI might
196 * accidentally cause deadlocks with further shutdown/panic
197 * code. By syncing, we give the cpus up to one second to
198 * finish their work before we force them off with the NMI.
199 */
177 if (num_online_cpus() > 1) { 200 if (num_online_cpus() > 1) {
178 /* did someone beat us here? */ 201 /* did someone beat us here? */
179 if (atomic_cmpxchg(&stopping_cpu, -1, safe_smp_processor_id()) != -1) 202 if (atomic_cmpxchg(&stopping_cpu, -1, safe_smp_processor_id()) != -1)
180 return; 203 return;
181 204
182 if (register_nmi_handler(NMI_LOCAL, smp_stop_nmi_callback, 205 /* sync above data before sending IRQ */
183 NMI_FLAG_FIRST, "smp_stop"))
184 /* Note: we ignore failures here */
185 return;
186
187 /* sync above data before sending NMI */
188 wmb(); 206 wmb();
189 207
190 apic->send_IPI_allbutself(NMI_VECTOR); 208 apic->send_IPI_allbutself(REBOOT_VECTOR);
191 209
192 /* 210 /*
193 * Don't wait longer than a second if the caller 211 * Don't wait longer than a second if the caller
@@ -197,63 +215,37 @@ static void native_nmi_stop_other_cpus(int wait)
197 while (num_online_cpus() > 1 && (wait || timeout--)) 215 while (num_online_cpus() > 1 && (wait || timeout--))
198 udelay(1); 216 udelay(1);
199 } 217 }
218
219 /* if the REBOOT_VECTOR didn't work, try with the NMI */
220 if ((num_online_cpus() > 1) && (!smp_no_nmi_ipi)) {
221 if (register_nmi_handler(NMI_LOCAL, smp_stop_nmi_callback,
222 NMI_FLAG_FIRST, "smp_stop"))
223 /* Note: we ignore failures here */
224 /* Hope the REBOOT_IRQ is good enough */
225 goto finish;
200 226
201 local_irq_save(flags); 227 /* sync above data before sending IRQ */
202 disable_local_APIC(); 228 wmb();
203 local_irq_restore(flags);
204}
205
206/*
207 * this function calls the 'stop' function on all other CPUs in the system.
208 */
209
210asmlinkage void smp_reboot_interrupt(void)
211{
212 ack_APIC_irq();
213 irq_enter();
214 stop_this_cpu(NULL);
215 irq_exit();
216}
217
218static void native_irq_stop_other_cpus(int wait)
219{
220 unsigned long flags;
221 unsigned long timeout;
222 229
223 if (reboot_force) 230 pr_emerg("Shutting down cpus with NMI\n");
224 return;
225 231
226 /* 232 apic->send_IPI_allbutself(NMI_VECTOR);
227 * Use an own vector here because smp_call_function
228 * does lots of things not suitable in a panic situation.
229 * On most systems we could also use an NMI here,
230 * but there are a few systems around where NMI
231 * is problematic so stay with an non NMI for now
232 * (this implies we cannot stop CPUs spinning with irq off
233 * currently)
234 */
235 if (num_online_cpus() > 1) {
236 apic->send_IPI_allbutself(REBOOT_VECTOR);
237 233
238 /* 234 /*
239 * Don't wait longer than a second if the caller 235 * Don't wait longer than a 10 ms if the caller
240 * didn't ask us to wait. 236 * didn't ask us to wait.
241 */ 237 */
242 timeout = USEC_PER_SEC; 238 timeout = USEC_PER_MSEC * 10;
243 while (num_online_cpus() > 1 && (wait || timeout--)) 239 while (num_online_cpus() > 1 && (wait || timeout--))
244 udelay(1); 240 udelay(1);
245 } 241 }
246 242
243finish:
247 local_irq_save(flags); 244 local_irq_save(flags);
248 disable_local_APIC(); 245 disable_local_APIC();
249 local_irq_restore(flags); 246 local_irq_restore(flags);
250} 247}
251 248
252static void native_smp_disable_nmi_ipi(void)
253{
254 smp_ops.stop_other_cpus = native_irq_stop_other_cpus;
255}
256
257/* 249/*
258 * Reschedule call back. 250 * Reschedule call back.
259 */ 251 */
@@ -287,8 +279,8 @@ void smp_call_function_single_interrupt(struct pt_regs *regs)
287 279
288static int __init nonmi_ipi_setup(char *str) 280static int __init nonmi_ipi_setup(char *str)
289{ 281{
290 native_smp_disable_nmi_ipi(); 282 smp_no_nmi_ipi = true;
291 return 1; 283 return 1;
292} 284}
293 285
294__setup("nonmi_ipi", nonmi_ipi_setup); 286__setup("nonmi_ipi", nonmi_ipi_setup);
@@ -298,7 +290,7 @@ struct smp_ops smp_ops = {
298 .smp_prepare_cpus = native_smp_prepare_cpus, 290 .smp_prepare_cpus = native_smp_prepare_cpus,
299 .smp_cpus_done = native_smp_cpus_done, 291 .smp_cpus_done = native_smp_cpus_done,
300 292
301 .stop_other_cpus = native_nmi_stop_other_cpus, 293 .stop_other_cpus = native_stop_other_cpus,
302 .smp_send_reschedule = native_smp_send_reschedule, 294 .smp_send_reschedule = native_smp_send_reschedule,
303 295
304 .cpu_up = native_cpu_up, 296 .cpu_up = native_cpu_up,