static UINT32 acpi_power_button (void *ctxt) { DLOG ("ACPI: acpi_power_button\n"); printf ("REBOOTING...\n"); DLOG_COM1 ("REBOOTING...\n"); tsc_delay_usec (100000); /* avoid race between COM1 and Reboot */ acpi_reboot (); asm volatile ("hlt"); return 0; }
/* * Windows compatible x86 hardware expects the following on reboot: * * 1) If the FADT has the ACPI reboot register flag set, try it * 2) If still alive, write to the keyboard controller * 3) If still alive, write to the ACPI reboot register again * 4) If still alive, write to the keyboard controller again * * If the machine is still alive at this stage, it gives up. We default to * following the same pattern, except that if we're still alive after (4) we'll * try to force a triple fault and then cycle between hitting the keyboard * controller and doing that */ static void native_machine_emergency_restart(void) { int i; int attempt = 0; int orig_reboot_type = reboot_type; if (reboot_emergency) emergency_vmx_disable_all(); tboot_shutdown(TB_SHUTDOWN_REBOOT); /* Tell the BIOS if we want cold or warm reboot */ *((unsigned short *)__va(0x472)) = reboot_mode; for (;;) { /* Could also try the reset bit in the Hammer NB */ switch (reboot_type) { case BOOT_KBD: mach_reboot_fixups(); /* For board specific fixups */ for (i = 0; i < 10; i++) { kb_wait(); udelay(50); outb(0xfe, 0x64); /* Pulse reset low */ udelay(50); } if (attempt == 0 && orig_reboot_type == BOOT_ACPI) { attempt = 1; reboot_type = BOOT_ACPI; } else { reboot_type = BOOT_TRIPLE; } break; case BOOT_TRIPLE: load_idt(&no_idt); __asm__ __volatile__("int3"); reboot_type = BOOT_KBD; break; case BOOT_BIOS: machine_real_restart(MRR_BIOS); reboot_type = BOOT_KBD; break; case BOOT_ACPI: acpi_reboot(); reboot_type = BOOT_KBD; break; case BOOT_EFI: if (efi_enabled(EFI_RUNTIME_SERVICES)) efi.reset_system(reboot_mode ? EFI_RESET_WARM : EFI_RESET_COLD, EFI_SUCCESS, 0, NULL); reboot_type = BOOT_KBD; break; case BOOT_CF9: port_cf9_safe = true; /* Fall through */ case BOOT_CF9_COND: if (port_cf9_safe) { u8 cf9 = inb(0xcf9) & ~6; outb(cf9|2, 0xcf9); /* Request hard reset */ udelay(50); outb(cf9|6, 0xcf9); /* Actually do the reset */ udelay(50); } reboot_type = BOOT_KBD; break; } } }
/* * To the best of our knowledge Windows compatible x86 hardware expects * the following on reboot: * * 1) If the FADT has the ACPI reboot register flag set, try it * 2) If still alive, write to the keyboard controller * 3) If still alive, write to the ACPI reboot register again * 4) If still alive, write to the keyboard controller again * 5) If still alive, call the EFI runtime service to reboot * 6) If no EFI runtime service, call the BIOS to do a reboot * * We default to following the same pattern. We also have * two other reboot methods: 'triple fault' and 'PCI', which * can be triggered via the reboot= kernel boot option or * via quirks. * * This means that this function can never return, it can misbehave * by not rebooting properly and hanging. */ static void native_machine_emergency_restart(void) { int i; int attempt = 0; int orig_reboot_type = reboot_type; unsigned short mode; if (reboot_emergency) emergency_vmx_disable_all(); tboot_shutdown(TB_SHUTDOWN_REBOOT); /* Tell the BIOS if we want cold or warm reboot */ mode = reboot_mode == REBOOT_WARM ? 0x1234 : 0; *((unsigned short *)__va(0x472)) = mode; /* * If an EFI capsule has been registered with the firmware then * override the reboot= parameter. */ if (efi_capsule_pending(NULL)) { pr_info("EFI capsule is pending, forcing EFI reboot.\n"); reboot_type = BOOT_EFI; } for (;;) { /* Could also try the reset bit in the Hammer NB */ switch (reboot_type) { case BOOT_ACPI: acpi_reboot(); reboot_type = BOOT_KBD; break; case BOOT_KBD: mach_reboot_fixups(); /* For board specific fixups */ for (i = 0; i < 10; i++) { kb_wait(); udelay(50); outb(0xfe, 0x64); /* Pulse reset low */ udelay(50); } if (attempt == 0 && orig_reboot_type == BOOT_ACPI) { attempt = 1; reboot_type = BOOT_ACPI; } else { reboot_type = BOOT_EFI; } break; case BOOT_EFI: efi_reboot(reboot_mode, NULL); reboot_type = BOOT_BIOS; break; case BOOT_BIOS: machine_real_restart(MRR_BIOS); /* We're probably dead after this, but... */ reboot_type = BOOT_CF9_SAFE; break; case BOOT_CF9_FORCE: port_cf9_safe = true; /* Fall through */ case BOOT_CF9_SAFE: if (port_cf9_safe) { u8 reboot_code = reboot_mode == REBOOT_WARM ? 0x06 : 0x0E; u8 cf9 = inb(0xcf9) & ~reboot_code; outb(cf9|2, 0xcf9); /* Request hard reset */ udelay(50); /* Actually do the reset */ outb(cf9|reboot_code, 0xcf9); udelay(50); } reboot_type = BOOT_TRIPLE; break; case BOOT_TRIPLE: load_idt(&no_idt); __asm__ __volatile__("int3"); /* We're probably dead after this, but... */ reboot_type = BOOT_KBD; break; } } }