aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/reboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/reboot.c')
-rw-r--r--arch/x86/kernel/reboot.c82
1 files changed, 47 insertions, 35 deletions
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 654b46574b91..52b1157c53eb 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -114,8 +114,8 @@ EXPORT_SYMBOL(machine_real_restart);
114 */ 114 */
115static int __init set_pci_reboot(const struct dmi_system_id *d) 115static int __init set_pci_reboot(const struct dmi_system_id *d)
116{ 116{
117 if (reboot_type != BOOT_CF9) { 117 if (reboot_type != BOOT_CF9_FORCE) {
118 reboot_type = BOOT_CF9; 118 reboot_type = BOOT_CF9_FORCE;
119 pr_info("%s series board detected. Selecting %s-method for reboots.\n", 119 pr_info("%s series board detected. Selecting %s-method for reboots.\n",
120 d->ident, "PCI"); 120 d->ident, "PCI");
121 } 121 }
@@ -191,6 +191,16 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
191 }, 191 },
192 }, 192 },
193 193
194 /* Certec */
195 { /* Handle problems with rebooting on Certec BPC600 */
196 .callback = set_pci_reboot,
197 .ident = "Certec BPC600",
198 .matches = {
199 DMI_MATCH(DMI_SYS_VENDOR, "Certec"),
200 DMI_MATCH(DMI_PRODUCT_NAME, "BPC600"),
201 },
202 },
203
194 /* Dell */ 204 /* Dell */
195 { /* Handle problems with rebooting on Dell DXP061 */ 205 { /* Handle problems with rebooting on Dell DXP061 */
196 .callback = set_bios_reboot, 206 .callback = set_bios_reboot,
@@ -458,20 +468,23 @@ void __attribute__((weak)) mach_reboot_fixups(void)
458} 468}
459 469
460/* 470/*
461 * Windows compatible x86 hardware expects the following on reboot: 471 * To the best of our knowledge Windows compatible x86 hardware expects
472 * the following on reboot:
462 * 473 *
463 * 1) If the FADT has the ACPI reboot register flag set, try it 474 * 1) If the FADT has the ACPI reboot register flag set, try it
464 * 2) If still alive, write to the keyboard controller 475 * 2) If still alive, write to the keyboard controller
465 * 3) If still alive, write to the ACPI reboot register again 476 * 3) If still alive, write to the ACPI reboot register again
466 * 4) If still alive, write to the keyboard controller again 477 * 4) If still alive, write to the keyboard controller again
467 * 5) If still alive, call the EFI runtime service to reboot 478 * 5) If still alive, call the EFI runtime service to reboot
468 * 6) If still alive, write to the PCI IO port 0xCF9 to reboot 479 * 6) If no EFI runtime service, call the BIOS to do a reboot
469 * 7) If still alive, inform BIOS to do a proper reboot 480 *
481 * We default to following the same pattern. We also have
482 * two other reboot methods: 'triple fault' and 'PCI', which
483 * can be triggered via the reboot= kernel boot option or
484 * via quirks.
470 * 485 *
471 * If the machine is still alive at this stage, it gives up. We default to 486 * This means that this function can never return, it can misbehave
472 * following the same pattern, except that if we're still alive after (7) we'll 487 * by not rebooting properly and hanging.
473 * try to force a triple fault and then cycle between hitting the keyboard
474 * controller and doing that
475 */ 488 */
476static void native_machine_emergency_restart(void) 489static void native_machine_emergency_restart(void)
477{ 490{
@@ -492,6 +505,11 @@ static void native_machine_emergency_restart(void)
492 for (;;) { 505 for (;;) {
493 /* Could also try the reset bit in the Hammer NB */ 506 /* Could also try the reset bit in the Hammer NB */
494 switch (reboot_type) { 507 switch (reboot_type) {
508 case BOOT_ACPI:
509 acpi_reboot();
510 reboot_type = BOOT_KBD;
511 break;
512
495 case BOOT_KBD: 513 case BOOT_KBD:
496 mach_reboot_fixups(); /* For board specific fixups */ 514 mach_reboot_fixups(); /* For board specific fixups */
497 515
@@ -509,43 +527,29 @@ static void native_machine_emergency_restart(void)
509 } 527 }
510 break; 528 break;
511 529
512 case BOOT_TRIPLE:
513 load_idt(&no_idt);
514 __asm__ __volatile__("int3");
515
516 /* We're probably dead after this, but... */
517 reboot_type = BOOT_KBD;
518 break;
519
520 case BOOT_BIOS:
521 machine_real_restart(MRR_BIOS);
522
523 /* We're probably dead after this, but... */
524 reboot_type = BOOT_TRIPLE;
525 break;
526
527 case BOOT_ACPI:
528 acpi_reboot();
529 reboot_type = BOOT_KBD;
530 break;
531
532 case BOOT_EFI: 530 case BOOT_EFI:
533 if (efi_enabled(EFI_RUNTIME_SERVICES)) 531 if (efi_enabled(EFI_RUNTIME_SERVICES))
534 efi.reset_system(reboot_mode == REBOOT_WARM ? 532 efi.reset_system(reboot_mode == REBOOT_WARM ?
535 EFI_RESET_WARM : 533 EFI_RESET_WARM :
536 EFI_RESET_COLD, 534 EFI_RESET_COLD,
537 EFI_SUCCESS, 0, NULL); 535 EFI_SUCCESS, 0, NULL);
538 reboot_type = BOOT_CF9_COND; 536 reboot_type = BOOT_BIOS;
537 break;
538
539 case BOOT_BIOS:
540 machine_real_restart(MRR_BIOS);
541
542 /* We're probably dead after this, but... */
543 reboot_type = BOOT_CF9_SAFE;
539 break; 544 break;
540 545
541 case BOOT_CF9: 546 case BOOT_CF9_FORCE:
542 port_cf9_safe = true; 547 port_cf9_safe = true;
543 /* Fall through */ 548 /* Fall through */
544 549
545 case BOOT_CF9_COND: 550 case BOOT_CF9_SAFE:
546 if (port_cf9_safe) { 551 if (port_cf9_safe) {
547 u8 reboot_code = reboot_mode == REBOOT_WARM ? 552 u8 reboot_code = reboot_mode == REBOOT_WARM ? 0x06 : 0x0E;
548 0x06 : 0x0E;
549 u8 cf9 = inb(0xcf9) & ~reboot_code; 553 u8 cf9 = inb(0xcf9) & ~reboot_code;
550 outb(cf9|2, 0xcf9); /* Request hard reset */ 554 outb(cf9|2, 0xcf9); /* Request hard reset */
551 udelay(50); 555 udelay(50);
@@ -553,7 +557,15 @@ static void native_machine_emergency_restart(void)
553 outb(cf9|reboot_code, 0xcf9); 557 outb(cf9|reboot_code, 0xcf9);
554 udelay(50); 558 udelay(50);
555 } 559 }
556 reboot_type = BOOT_BIOS; 560 reboot_type = BOOT_TRIPLE;
561 break;
562
563 case BOOT_TRIPLE:
564 load_idt(&no_idt);
565 __asm__ __volatile__("int3");
566
567 /* We're probably dead after this, but... */
568 reboot_type = BOOT_KBD;
557 break; 569 break;
558 } 570 }
559 } 571 }