diff options
Diffstat (limited to 'arch/x86/kernel/reboot.c')
| -rw-r--r-- | arch/x86/kernel/reboot.c | 24 | 
1 files changed, 23 insertions, 1 deletions
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 08c44b08bf5..0c016f72769 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -36,7 +36,7 @@ EXPORT_SYMBOL(pm_power_off);  static const struct desc_ptr no_idt = {};  static int reboot_mode; -enum reboot_type reboot_type = BOOT_KBD; +enum reboot_type reboot_type = BOOT_ACPI;  int reboot_force;  #if defined(CONFIG_X86_32) && defined(CONFIG_SMP) @@ -478,9 +478,24 @@ void __attribute__((weak)) mach_reboot_fixups(void)  {  } +/* + * 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(); @@ -502,6 +517,13 @@ static void native_machine_emergency_restart(void)  				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);  |