1 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 2 3 #include <linux/module.h> 4 #include <linux/reboot.h> 5 #include <linux/init.h> 6 #include <linux/pm.h> 7 #include <linux/efi.h> 8 #include <linux/dmi.h> 9 #include <linux/sched.h> 10 #include <linux/tboot.h> 11 #include <linux/delay.h> 12 #include <acpi/reboot.h> 13 #include <asm/io.h> 14 #include <asm/apic.h> 15 #include <asm/desc.h> 16 #include <asm/hpet.h> 17 #include <asm/pgtable.h> 18 #include <asm/proto.h> 19 #include <asm/reboot_fixups.h> 20 #include <asm/reboot.h> 21 #include <asm/pci_x86.h> 22 #include <asm/virtext.h> 23 #include <asm/cpu.h> 24 #include <asm/nmi.h> 25 #include <asm/smp.h> 26 27 #include <linux/ctype.h> 28 #include <linux/mc146818rtc.h> 29 #include <asm/realmode.h> 30 #include <asm/x86_init.h> 31 32 /* 33 * Power off function, if any 34 */ 35 void (*pm_power_off)(void); 36 EXPORT_SYMBOL(pm_power_off); 37 38 static const struct desc_ptr no_idt = {}; 39 40 /* 41 * This is set if we need to go through the 'emergency' path. 42 * When machine_emergency_restart() is called, we may be on 43 * an inconsistent state and won't be able to do a clean cleanup 44 */ 45 static int reboot_emergency; 46 47 /* This is set by the PCI code if either type 1 or type 2 PCI is detected */ 48 bool port_cf9_safe = false; 49 50 /* 51 * Reboot options and system auto-detection code provided by 52 * Dell Inc. so their systems "just work". :-) 53 */ 54 55 /* 56 * Some machines require the "reboot=b" or "reboot=k" commandline options, 57 * this quirk makes that automatic. 58 */ 59 static int __init set_bios_reboot(const struct dmi_system_id *d) 60 { 61 if (reboot_type != BOOT_BIOS) { 62 reboot_type = BOOT_BIOS; 63 pr_info("%s series board detected. Selecting %s-method for reboots.\n", 64 "BIOS", d->ident); 65 } 66 return 0; 67 } 68 69 void __noreturn machine_real_restart(unsigned int type) 70 { 71 local_irq_disable(); 72 73 /* 74 * Write zero to CMOS register number 0x0f, which the BIOS POST 75 * routine will recognize as telling it to do a proper reboot. (Well 76 * that's what this book in front of me says -- it may only apply to 77 * the Phoenix BIOS though, it's not clear). At the same time, 78 * disable NMIs by setting the top bit in the CMOS address register, 79 * as we're about to do peculiar things to the CPU. I'm not sure if 80 * `outb_p' is needed instead of just `outb'. Use it to be on the 81 * safe side. (Yes, CMOS_WRITE does outb_p's. - Paul G.) 82 */ 83 spin_lock(&rtc_lock); 84 CMOS_WRITE(0x00, 0x8f); 85 spin_unlock(&rtc_lock); 86 87 /* 88 * Switch back to the initial page table. 89 */ 90 #ifdef CONFIG_X86_32 91 load_cr3(initial_page_table); 92 #else 93 write_cr3(real_mode_header->trampoline_pgd); 94 #endif 95 96 /* Jump to the identity-mapped low memory code */ 97 #ifdef CONFIG_X86_32 98 asm volatile("jmpl *%0" : : 99 "rm" (real_mode_header->machine_real_restart_asm), 100 "a" (type)); 101 #else 102 asm volatile("ljmpl *%0" : : 103 "m" (real_mode_header->machine_real_restart_asm), 104 "D" (type)); 105 #endif 106 unreachable(); 107 } 108 #ifdef CONFIG_APM_MODULE 109 EXPORT_SYMBOL(machine_real_restart); 110 #endif 111 112 /* 113 * Some Apple MacBook and MacBookPro's needs reboot=p to be able to reboot 114 */ 115 static int __init set_pci_reboot(const struct dmi_system_id *d) 116 { 117 if (reboot_type != BOOT_CF9) { 118 reboot_type = BOOT_CF9; 119 pr_info("%s series board detected. Selecting %s-method for reboots.\n", 120 "PCI", d->ident); 121 } 122 return 0; 123 } 124 125 static int __init set_kbd_reboot(const struct dmi_system_id *d) 126 { 127 if (reboot_type != BOOT_KBD) { 128 reboot_type = BOOT_KBD; 129 pr_info("%s series board detected. Selecting %s-method for reboot.\n", 130 "KBD", d->ident); 131 } 132 return 0; 133 } 134 135 /* 136 * This is a single dmi_table handling all reboot quirks. 137 */ 138 static struct dmi_system_id __initdata reboot_dmi_table[] = { 139 { /* Handle problems with rebooting on Dell E520's */ 140 .callback = set_bios_reboot, 141 .ident = "Dell E520", 142 .matches = { 143 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 144 DMI_MATCH(DMI_PRODUCT_NAME, "Dell DM061"), 145 }, 146 }, 147 { /* Handle problems with rebooting on Dell 1300's */ 148 .callback = set_bios_reboot, 149 .ident = "Dell PowerEdge 1300", 150 .matches = { 151 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), 152 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"), 153 }, 154 }, 155 { /* Handle problems with rebooting on Dell 300's */ 156 .callback = set_bios_reboot, 157 .ident = "Dell PowerEdge 300", 158 .matches = { 159 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), 160 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"), 161 }, 162 }, 163 { /* Handle problems with rebooting on Dell Optiplex 745's SFF */ 164 .callback = set_bios_reboot, 165 .ident = "Dell OptiPlex 745", 166 .matches = { 167 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 168 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"), 169 }, 170 }, 171 { /* Handle problems with rebooting on Dell Optiplex 745's DFF */ 172 .callback = set_bios_reboot, 173 .ident = "Dell OptiPlex 745", 174 .matches = { 175 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 176 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"), 177 DMI_MATCH(DMI_BOARD_NAME, "0MM599"), 178 }, 179 }, 180 { /* Handle problems with rebooting on Dell Optiplex 745 with 0KW626 */ 181 .callback = set_bios_reboot, 182 .ident = "Dell OptiPlex 745", 183 .matches = { 184 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 185 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"), 186 DMI_MATCH(DMI_BOARD_NAME, "0KW626"), 187 }, 188 }, 189 { /* Handle problems with rebooting on Dell Optiplex 330 with 0KP561 */ 190 .callback = set_bios_reboot, 191 .ident = "Dell OptiPlex 330", 192 .matches = { 193 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 194 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 330"), 195 DMI_MATCH(DMI_BOARD_NAME, "0KP561"), 196 }, 197 }, 198 { /* Handle problems with rebooting on Dell Optiplex 360 with 0T656F */ 199 .callback = set_bios_reboot, 200 .ident = "Dell OptiPlex 360", 201 .matches = { 202 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 203 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 360"), 204 DMI_MATCH(DMI_BOARD_NAME, "0T656F"), 205 }, 206 }, 207 { /* Handle problems with rebooting on Dell OptiPlex 760 with 0G919G */ 208 .callback = set_bios_reboot, 209 .ident = "Dell OptiPlex 760", 210 .matches = { 211 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 212 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 760"), 213 DMI_MATCH(DMI_BOARD_NAME, "0G919G"), 214 }, 215 }, 216 { /* Handle problems with rebooting on Dell 2400's */ 217 .callback = set_bios_reboot, 218 .ident = "Dell PowerEdge 2400", 219 .matches = { 220 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), 221 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"), 222 }, 223 }, 224 { /* Handle problems with rebooting on Dell T5400's */ 225 .callback = set_bios_reboot, 226 .ident = "Dell Precision T5400", 227 .matches = { 228 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 229 DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T5400"), 230 }, 231 }, 232 { /* Handle problems with rebooting on Dell T7400's */ 233 .callback = set_bios_reboot, 234 .ident = "Dell Precision T7400", 235 .matches = { 236 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 237 DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T7400"), 238 }, 239 }, 240 { /* Handle problems with rebooting on HP laptops */ 241 .callback = set_bios_reboot, 242 .ident = "HP Compaq Laptop", 243 .matches = { 244 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 245 DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"), 246 }, 247 }, 248 { /* Handle problems with rebooting on Dell XPS710 */ 249 .callback = set_bios_reboot, 250 .ident = "Dell XPS710", 251 .matches = { 252 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 253 DMI_MATCH(DMI_PRODUCT_NAME, "Dell XPS710"), 254 }, 255 }, 256 { /* Handle problems with rebooting on Dell DXP061 */ 257 .callback = set_bios_reboot, 258 .ident = "Dell DXP061", 259 .matches = { 260 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 261 DMI_MATCH(DMI_PRODUCT_NAME, "Dell DXP061"), 262 }, 263 }, 264 { /* Handle problems with rebooting on Sony VGN-Z540N */ 265 .callback = set_bios_reboot, 266 .ident = "Sony VGN-Z540N", 267 .matches = { 268 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), 269 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-Z540N"), 270 }, 271 }, 272 { /* Handle problems with rebooting on ASUS P4S800 */ 273 .callback = set_bios_reboot, 274 .ident = "ASUS P4S800", 275 .matches = { 276 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), 277 DMI_MATCH(DMI_BOARD_NAME, "P4S800"), 278 }, 279 }, 280 281 { /* Handle reboot issue on Acer Aspire one */ 282 .callback = set_kbd_reboot, 283 .ident = "Acer Aspire One A110", 284 .matches = { 285 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 286 DMI_MATCH(DMI_PRODUCT_NAME, "AOA110"), 287 }, 288 }, 289 { /* Handle problems with rebooting on Apple MacBook5 */ 290 .callback = set_pci_reboot, 291 .ident = "Apple MacBook5", 292 .matches = { 293 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), 294 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5"), 295 }, 296 }, 297 { /* Handle problems with rebooting on Apple MacBookPro5 */ 298 .callback = set_pci_reboot, 299 .ident = "Apple MacBookPro5", 300 .matches = { 301 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), 302 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5"), 303 }, 304 }, 305 { /* Handle problems with rebooting on Apple Macmini3,1 */ 306 .callback = set_pci_reboot, 307 .ident = "Apple Macmini3,1", 308 .matches = { 309 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), 310 DMI_MATCH(DMI_PRODUCT_NAME, "Macmini3,1"), 311 }, 312 }, 313 { /* Handle problems with rebooting on the iMac9,1. */ 314 .callback = set_pci_reboot, 315 .ident = "Apple iMac9,1", 316 .matches = { 317 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), 318 DMI_MATCH(DMI_PRODUCT_NAME, "iMac9,1"), 319 }, 320 }, 321 { /* Handle problems with rebooting on the Latitude E6320. */ 322 .callback = set_pci_reboot, 323 .ident = "Dell Latitude E6320", 324 .matches = { 325 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 326 DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6320"), 327 }, 328 }, 329 { /* Handle problems with rebooting on the Latitude E5410. */ 330 .callback = set_pci_reboot, 331 .ident = "Dell Latitude E5410", 332 .matches = { 333 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 334 DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E5410"), 335 }, 336 }, 337 { /* Handle problems with rebooting on the Latitude E5420. */ 338 .callback = set_pci_reboot, 339 .ident = "Dell Latitude E5420", 340 .matches = { 341 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 342 DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E5420"), 343 }, 344 }, 345 { /* Handle problems with rebooting on the Latitude E6420. */ 346 .callback = set_pci_reboot, 347 .ident = "Dell Latitude E6420", 348 .matches = { 349 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 350 DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6420"), 351 }, 352 }, 353 { /* Handle problems with rebooting on the OptiPlex 990. */ 354 .callback = set_pci_reboot, 355 .ident = "Dell OptiPlex 990", 356 .matches = { 357 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 358 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 990"), 359 }, 360 }, 361 { /* Handle problems with rebooting on the Precision M6600. */ 362 .callback = set_pci_reboot, 363 .ident = "Dell Precision M6600", 364 .matches = { 365 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 366 DMI_MATCH(DMI_PRODUCT_NAME, "Precision M6600"), 367 }, 368 }, 369 { /* Handle problems with rebooting on the Dell PowerEdge C6100. */ 370 .callback = set_pci_reboot, 371 .ident = "Dell PowerEdge C6100", 372 .matches = { 373 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 374 DMI_MATCH(DMI_PRODUCT_NAME, "C6100"), 375 }, 376 }, 377 { /* Some C6100 machines were shipped with vendor being 'Dell'. */ 378 .callback = set_pci_reboot, 379 .ident = "Dell PowerEdge C6100", 380 .matches = { 381 DMI_MATCH(DMI_SYS_VENDOR, "Dell"), 382 DMI_MATCH(DMI_PRODUCT_NAME, "C6100"), 383 }, 384 }, 385 { } 386 }; 387 388 static int __init reboot_init(void) 389 { 390 /* 391 * Only do the DMI check if reboot_type hasn't been overridden 392 * on the command line 393 */ 394 if (reboot_default) 395 dmi_check_system(reboot_dmi_table); 396 return 0; 397 } 398 core_initcall(reboot_init); 399 400 static inline void kb_wait(void) 401 { 402 int i; 403 404 for (i = 0; i < 0x10000; i++) { 405 if ((inb(0x64) & 0x02) == 0) 406 break; 407 udelay(2); 408 } 409 } 410 411 static void vmxoff_nmi(int cpu, struct pt_regs *regs) 412 { 413 cpu_emergency_vmxoff(); 414 } 415 416 /* Use NMIs as IPIs to tell all CPUs to disable virtualization */ 417 static void emergency_vmx_disable_all(void) 418 { 419 /* Just make sure we won't change CPUs while doing this */ 420 local_irq_disable(); 421 422 /* 423 * We need to disable VMX on all CPUs before rebooting, otherwise 424 * we risk hanging up the machine, because the CPU ignore INIT 425 * signals when VMX is enabled. 426 * 427 * We can't take any locks and we may be on an inconsistent 428 * state, so we use NMIs as IPIs to tell the other CPUs to disable 429 * VMX and halt. 430 * 431 * For safety, we will avoid running the nmi_shootdown_cpus() 432 * stuff unnecessarily, but we don't have a way to check 433 * if other CPUs have VMX enabled. So we will call it only if the 434 * CPU we are running on has VMX enabled. 435 * 436 * We will miss cases where VMX is not enabled on all CPUs. This 437 * shouldn't do much harm because KVM always enable VMX on all 438 * CPUs anyway. But we can miss it on the small window where KVM 439 * is still enabling VMX. 440 */ 441 if (cpu_has_vmx() && cpu_vmx_enabled()) { 442 /* Disable VMX on this CPU. */ 443 cpu_vmxoff(); 444 445 /* Halt and disable VMX on the other CPUs */ 446 nmi_shootdown_cpus(vmxoff_nmi); 447 448 } 449 } 450 451 452 void __attribute__((weak)) mach_reboot_fixups(void) 453 { 454 } 455 456 /* 457 * Windows compatible x86 hardware expects the following on reboot: 458 * 459 * 1) If the FADT has the ACPI reboot register flag set, try it 460 * 2) If still alive, write to the keyboard controller 461 * 3) If still alive, write to the ACPI reboot register again 462 * 4) If still alive, write to the keyboard controller again 463 * 464 * If the machine is still alive at this stage, it gives up. We default to 465 * following the same pattern, except that if we're still alive after (4) we'll 466 * try to force a triple fault and then cycle between hitting the keyboard 467 * controller and doing that 468 */ 469 static void native_machine_emergency_restart(void) 470 { 471 int i; 472 int attempt = 0; 473 int orig_reboot_type = reboot_type; 474 unsigned short mode; 475 476 if (reboot_emergency) 477 emergency_vmx_disable_all(); 478 479 tboot_shutdown(TB_SHUTDOWN_REBOOT); 480 481 /* Tell the BIOS if we want cold or warm reboot */ 482 mode = reboot_mode == REBOOT_WARM ? 0x1234 : 0; 483 *((unsigned short *)__va(0x472)) = mode; 484 485 for (;;) { 486 /* Could also try the reset bit in the Hammer NB */ 487 switch (reboot_type) { 488 case BOOT_KBD: 489 mach_reboot_fixups(); /* For board specific fixups */ 490 491 for (i = 0; i < 10; i++) { 492 kb_wait(); 493 udelay(50); 494 outb(0xfe, 0x64); /* Pulse reset low */ 495 udelay(50); 496 } 497 if (attempt == 0 && orig_reboot_type == BOOT_ACPI) { 498 attempt = 1; 499 reboot_type = BOOT_ACPI; 500 } else { 501 reboot_type = BOOT_TRIPLE; 502 } 503 break; 504 505 case BOOT_TRIPLE: 506 load_idt(&no_idt); 507 __asm__ __volatile__("int3"); 508 509 reboot_type = BOOT_KBD; 510 break; 511 512 case BOOT_BIOS: 513 machine_real_restart(MRR_BIOS); 514 515 reboot_type = BOOT_KBD; 516 break; 517 518 case BOOT_ACPI: 519 acpi_reboot(); 520 reboot_type = BOOT_KBD; 521 break; 522 523 case BOOT_EFI: 524 if (efi_enabled(EFI_RUNTIME_SERVICES)) 525 efi.reset_system(reboot_mode == REBOOT_WARM ? 526 EFI_RESET_WARM : 527 EFI_RESET_COLD, 528 EFI_SUCCESS, 0, NULL); 529 reboot_type = BOOT_KBD; 530 break; 531 532 case BOOT_CF9: 533 port_cf9_safe = true; 534 /* Fall through */ 535 536 case BOOT_CF9_COND: 537 if (port_cf9_safe) { 538 u8 cf9 = inb(0xcf9) & ~6; 539 outb(cf9|2, 0xcf9); /* Request hard reset */ 540 udelay(50); 541 outb(cf9|6, 0xcf9); /* Actually do the reset */ 542 udelay(50); 543 } 544 reboot_type = BOOT_KBD; 545 break; 546 } 547 } 548 } 549 550 void native_machine_shutdown(void) 551 { 552 /* Stop the cpus and apics */ 553 #ifdef CONFIG_SMP 554 /* 555 * Stop all of the others. Also disable the local irq to 556 * not receive the per-cpu timer interrupt which may trigger 557 * scheduler's load balance. 558 */ 559 local_irq_disable(); 560 stop_other_cpus(); 561 #endif 562 563 lapic_shutdown(); 564 565 #ifdef CONFIG_X86_IO_APIC 566 disable_IO_APIC(); 567 #endif 568 569 #ifdef CONFIG_HPET_TIMER 570 hpet_disable(); 571 #endif 572 573 #ifdef CONFIG_X86_64 574 x86_platform.iommu_shutdown(); 575 #endif 576 } 577 578 static void __machine_emergency_restart(int emergency) 579 { 580 reboot_emergency = emergency; 581 machine_ops.emergency_restart(); 582 } 583 584 static void native_machine_restart(char *__unused) 585 { 586 pr_notice("machine restart\n"); 587 588 if (!reboot_force) 589 machine_shutdown(); 590 __machine_emergency_restart(0); 591 } 592 593 static void native_machine_halt(void) 594 { 595 /* Stop other cpus and apics */ 596 machine_shutdown(); 597 598 tboot_shutdown(TB_SHUTDOWN_HALT); 599 600 stop_this_cpu(NULL); 601 } 602 603 static void native_machine_power_off(void) 604 { 605 if (pm_power_off) { 606 if (!reboot_force) 607 machine_shutdown(); 608 pm_power_off(); 609 } 610 /* A fallback in case there is no PM info available */ 611 tboot_shutdown(TB_SHUTDOWN_HALT); 612 } 613 614 struct machine_ops machine_ops = { 615 .power_off = native_machine_power_off, 616 .shutdown = native_machine_shutdown, 617 .emergency_restart = native_machine_emergency_restart, 618 .restart = native_machine_restart, 619 .halt = native_machine_halt, 620 #ifdef CONFIG_KEXEC 621 .crash_shutdown = native_machine_crash_shutdown, 622 #endif 623 }; 624 625 void machine_power_off(void) 626 { 627 machine_ops.power_off(); 628 } 629 630 void machine_shutdown(void) 631 { 632 machine_ops.shutdown(); 633 } 634 635 void machine_emergency_restart(void) 636 { 637 __machine_emergency_restart(1); 638 } 639 640 void machine_restart(char *cmd) 641 { 642 machine_ops.restart(cmd); 643 } 644 645 void machine_halt(void) 646 { 647 machine_ops.halt(); 648 } 649 650 #ifdef CONFIG_KEXEC 651 void machine_crash_shutdown(struct pt_regs *regs) 652 { 653 machine_ops.crash_shutdown(regs); 654 } 655 #endif 656 657 658 #if defined(CONFIG_SMP) 659 660 /* This keeps a track of which one is crashing cpu. */ 661 static int crashing_cpu; 662 static nmi_shootdown_cb shootdown_callback; 663 664 static atomic_t waiting_for_crash_ipi; 665 666 static int crash_nmi_callback(unsigned int val, struct pt_regs *regs) 667 { 668 int cpu; 669 670 cpu = raw_smp_processor_id(); 671 672 /* 673 * Don't do anything if this handler is invoked on crashing cpu. 674 * Otherwise, system will completely hang. Crashing cpu can get 675 * an NMI if system was initially booted with nmi_watchdog parameter. 676 */ 677 if (cpu == crashing_cpu) 678 return NMI_HANDLED; 679 local_irq_disable(); 680 681 shootdown_callback(cpu, regs); 682 683 atomic_dec(&waiting_for_crash_ipi); 684 /* Assume hlt works */ 685 halt(); 686 for (;;) 687 cpu_relax(); 688 689 return NMI_HANDLED; 690 } 691 692 static void smp_send_nmi_allbutself(void) 693 { 694 apic->send_IPI_allbutself(NMI_VECTOR); 695 } 696 697 /* 698 * Halt all other CPUs, calling the specified function on each of them 699 * 700 * This function can be used to halt all other CPUs on crash 701 * or emergency reboot time. The function passed as parameter 702 * will be called inside a NMI handler on all CPUs. 703 */ 704 void nmi_shootdown_cpus(nmi_shootdown_cb callback) 705 { 706 unsigned long msecs; 707 local_irq_disable(); 708 709 /* Make a note of crashing cpu. Will be used in NMI callback. */ 710 crashing_cpu = safe_smp_processor_id(); 711 712 shootdown_callback = callback; 713 714 atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); 715 /* Would it be better to replace the trap vector here? */ 716 if (register_nmi_handler(NMI_LOCAL, crash_nmi_callback, 717 NMI_FLAG_FIRST, "crash")) 718 return; /* Return what? */ 719 /* 720 * Ensure the new callback function is set before sending 721 * out the NMI 722 */ 723 wmb(); 724 725 smp_send_nmi_allbutself(); 726 727 msecs = 1000; /* Wait at most a second for the other cpus to stop */ 728 while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) { 729 mdelay(1); 730 msecs--; 731 } 732 733 /* Leave the nmi callback set */ 734 } 735 #else /* !CONFIG_SMP */ 736 void nmi_shootdown_cpus(nmi_shootdown_cb callback) 737 { 738 /* No other CPUs to shoot down */ 739 } 740 #endif 741