diff options
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/reboot.c | 34 |
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 | ||
30 | static const struct desc_ptr no_idt = {}; | 30 | static const struct desc_ptr no_idt = {}; |
31 | static int reboot_mode; | 31 | static int reboot_mode; |
32 | enum reboot_type reboot_type = BOOT_KBD; | 32 | enum reboot_type reboot_type = BOOT_CF9_COND; |
33 | int reboot_force; | 33 | int reboot_force; |
34 | 34 | ||
35 | #if defined(CONFIG_X86_32) && defined(CONFIG_SMP) | 35 | #if defined(CONFIG_X86_32) && defined(CONFIG_SMP) |
36 | static int reboot_cpu = -1; | 36 | static 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 */ |
40 | bool 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 | */ |
50 | static int __init reboot_setup(char *str) | 54 | static 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 | } |