aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/reboot.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2008-11-11 19:19:48 -0500
committerH. Peter Anvin <hpa@zytor.com>2008-11-11 19:19:48 -0500
commit14d7ca5c575853664d8fe4f225a77b8df1b7de7d (patch)
tree0d16169c5fde30712109c3a316652d0525646f4f /arch/x86/kernel/reboot.c
parentd3ec5cae0921611ceae06464ef6291012dd9849f (diff)
x86: attempt reboot via port CF9 if we have standard PCI ports
Impact: Changes reboot behavior. If port CF9 seems to be safe to touch, attempt it before trying the keyboard controller. Port CF9 is not available on all chipsets (a significant but decreasing number of modern chipsets don't implement it), but port CF9 itself should in general be safe to poke (no ill effects if unimplemented) on any system which has PCI Configuration Method #1 or #2, as it falls inside the PCI configuration port range in both cases. No chipset without PCI is known to have port CF9, either, although an explicit "pci=bios" would mean we miss this and therefore don't use port CF9. An explicit "reboot=pci" can be used to force the use of port CF9. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86/kernel/reboot.c')
-rw-r--r--arch/x86/kernel/reboot.c34
1 files changed, 27 insertions, 7 deletions
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 34f8d37ae3c5..ddc93891cdcd 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -29,14 +29,17 @@ EXPORT_SYMBOL(pm_power_off);
29 29
30static const struct desc_ptr no_idt = {}; 30static const struct desc_ptr no_idt = {};
31static int reboot_mode; 31static int reboot_mode;
32enum reboot_type reboot_type = BOOT_KBD; 32enum reboot_type reboot_type = BOOT_CF9_COND;
33int reboot_force; 33int reboot_force;
34 34
35#if defined(CONFIG_X86_32) && defined(CONFIG_SMP) 35#if defined(CONFIG_X86_32) && defined(CONFIG_SMP)
36static int reboot_cpu = -1; 36static int reboot_cpu = -1;
37#endif 37#endif
38 38
39/* reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old] 39/* This is set by the PCI code if either type 1 or type 2 PCI is detected */
40bool port_cf9_safe = false;
41
42/* reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old] | p[ci]
40 warm Don't set the cold reboot flag 43 warm Don't set the cold reboot flag
41 cold Set the cold reboot flag 44 cold Set the cold reboot flag
42 bios Reboot by jumping through the BIOS (only for X86_32) 45 bios Reboot by jumping through the BIOS (only for X86_32)
@@ -45,6 +48,7 @@ static int reboot_cpu = -1;
45 kbd Use the keyboard controller. cold reset (default) 48 kbd Use the keyboard controller. cold reset (default)
46 acpi Use the RESET_REG in the FADT 49 acpi Use the RESET_REG in the FADT
47 efi Use efi reset_system runtime service 50 efi Use efi reset_system runtime service
51 pci Use the so-called "PCI reset register", CF9
48 force Avoid anything that could hang. 52 force Avoid anything that could hang.
49 */ 53 */
50static int __init reboot_setup(char *str) 54static int __init reboot_setup(char *str)
@@ -79,6 +83,7 @@ static int __init reboot_setup(char *str)
79 case 'k': 83 case 'k':
80 case 't': 84 case 't':
81 case 'e': 85 case 'e':
86 case 'p':
82 reboot_type = *str; 87 reboot_type = *str;
83 break; 88 break;
84 89
@@ -379,28 +384,43 @@ static void native_machine_emergency_restart(void)
379 load_idt(&no_idt); 384 load_idt(&no_idt);
380 __asm__ __volatile__("int3"); 385 __asm__ __volatile__("int3");
381 386
382 reboot_type = BOOT_KBD; 387 reboot_type = BOOT_CF9_COND;
383 break; 388 break;
384 389
385#ifdef CONFIG_X86_32 390#ifdef CONFIG_X86_32
386 case BOOT_BIOS: 391 case BOOT_BIOS:
387 machine_real_restart(jump_to_bios, sizeof(jump_to_bios)); 392 machine_real_restart(jump_to_bios, sizeof(jump_to_bios));
388 393
389 reboot_type = BOOT_KBD; 394 reboot_type = BOOT_CF9_COND;
390 break; 395 break;
391#endif 396#endif
392 397
393 case BOOT_ACPI: 398 case BOOT_ACPI:
394 acpi_reboot(); 399 acpi_reboot();
395 reboot_type = BOOT_KBD; 400 reboot_type = BOOT_CF9_COND;
396 break; 401 break;
397 402
398
399 case BOOT_EFI: 403 case BOOT_EFI:
400 if (efi_enabled) 404 if (efi_enabled)
401 efi.reset_system(reboot_mode ? EFI_RESET_WARM : EFI_RESET_COLD, 405 efi.reset_system(reboot_mode ?
406 EFI_RESET_WARM :
407 EFI_RESET_COLD,
402 EFI_SUCCESS, 0, NULL); 408 EFI_SUCCESS, 0, NULL);
409 reboot_type = BOOT_CF9_COND;
410 break;
411
412 case BOOT_CF9:
413 port_cf9_safe = true;
414 /* fall through */
403 415
416 case BOOT_CF9_COND:
417 if (port_cf9_safe) {
418 u8 cf9 = inb(0xcf9) & ~6;
419 outb(cf9|2, 0xcf9); /* Request hard reset */
420 udelay(50);
421 outb(cf9|6, 0xcf9); /* Actually do the reset */
422 udelay(50);
423 }
404 reboot_type = BOOT_KBD; 424 reboot_type = BOOT_KBD;
405 break; 425 break;
406 } 426 }