Matthew Garrett 0988eed
Improve our reboot handling for compatibility with Windows. Upstream in .38?
Matthew Garrett 0988eed
Matthew Garrett 0988eed
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
Matthew Garrett 0988eed
index c495aa8..c770e66 100644
Matthew Garrett 0988eed
--- a/arch/x86/kernel/reboot.c
Matthew Garrett 0988eed
+++ b/arch/x86/kernel/reboot.c
Matthew Garrett 0988eed
@@ -34,7 +34,7 @@ EXPORT_SYMBOL(pm_power_off);
Matthew Garrett 0988eed
 
Matthew Garrett 0988eed
 static const struct desc_ptr no_idt = {};
Matthew Garrett 0988eed
 static int reboot_mode;
Matthew Garrett 0988eed
-enum reboot_type reboot_type = BOOT_KBD;
Matthew Garrett 0988eed
+enum reboot_type reboot_type = BOOT_ACPI;
Matthew Garrett 0988eed
 int reboot_force;
Matthew Garrett 0988eed
 
Matthew Garrett 0988eed
 #if defined(CONFIG_X86_32) && defined(CONFIG_SMP)
Matthew Garrett 0988eed
@@ -538,9 +538,23 @@ void __attribute__((weak)) mach_reboot_fixups(void)
Matthew Garrett 0988eed
 {
Matthew Garrett 0988eed
 }
Matthew Garrett 0988eed
 
Matthew Garrett 0988eed
+/*
Matthew Garrett 0988eed
+ * Windows does the following on reboot:
Matthew Garrett 0988eed
+ * 1) If the FADT has the ACPI reboot register flag set, try it
Matthew Garrett 0988eed
+ * 2) If still alive, write to the keyboard controller
Matthew Garrett 0988eed
+ * 3) If still alive, write to the ACPI reboot register again
Kyle McMartin db49e9e
+ * 4) If still alive, write to the keyboard controller again
Matthew Garrett 0988eed
+ *
Matthew Garrett 0988eed
+ * If the machine is still alive at this stage, it gives up. We default to
Matthew Garrett 0988eed
+ * following the same pattern, except that if we're still alive after (4) we'll
Matthew Garrett 0988eed
+ * try to force a triple fault and then cycle between hitting the keyboard
Matthew Garrett 0988eed
+ * controller and doing that
Matthew Garrett 0988eed
+ */
Matthew Garrett 0988eed
 static void native_machine_emergency_restart(void)
Matthew Garrett 0988eed
 {
Matthew Garrett 0988eed
 	int i;
Matthew Garrett 0988eed
+	int attempt = 0;
Matthew Garrett 0988eed
+	int orig_reboot_type = reboot_type;
Matthew Garrett 0988eed
 
Matthew Garrett 0988eed
 	if (reboot_emergency)
Matthew Garrett 0988eed
 		emergency_vmx_disable_all();
Matthew Garrett 0988eed
@@ -562,6 +576,13 @@ static void native_machine_emergency_restart(void)
Matthew Garrett 0988eed
 				outb(0xfe, 0x64); /* pulse reset low */
Matthew Garrett 0988eed
 				udelay(50);
Matthew Garrett 0988eed
 			}
Matthew Garrett 0988eed
+			if (attempt == 0 && orig_reboot_type == BOOT_ACPI) {
Matthew Garrett 0988eed
+				attempt = 1;
Matthew Garrett 0988eed
+				reboot_type = BOOT_ACPI;
Matthew Garrett 0988eed
+			} else {
Matthew Garrett 0988eed
+				reboot_type = BOOT_TRIPLE;
Matthew Garrett 0988eed
+			}
Matthew Garrett 0988eed
+			break;
Matthew Garrett 0988eed
 
Matthew Garrett 0988eed
 		case BOOT_TRIPLE:
Matthew Garrett 0988eed
 			load_idt(&no_idt);