aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/reboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/reboot.c')
-rw-r--r--arch/x86/kernel/reboot.c116
1 files changed, 103 insertions, 13 deletions
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index c3cd512484e5..32e8f0af292c 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -12,6 +12,9 @@
12#include <asm/proto.h> 12#include <asm/proto.h>
13#include <asm/reboot_fixups.h> 13#include <asm/reboot_fixups.h>
14#include <asm/reboot.h> 14#include <asm/reboot.h>
15#include <asm/pci_x86.h>
16#include <asm/virtext.h>
17#include <asm/cpu.h>
15 18
16#ifdef CONFIG_X86_32 19#ifdef CONFIG_X86_32
17# include <linux/dmi.h> 20# include <linux/dmi.h>
@@ -21,8 +24,7 @@
21# include <asm/iommu.h> 24# include <asm/iommu.h>
22#endif 25#endif
23 26
24#include <mach_ipi.h> 27#include <asm/genapic.h>
25
26 28
27/* 29/*
28 * Power off function, if any 30 * Power off function, if any
@@ -39,7 +41,16 @@ int reboot_force;
39static int reboot_cpu = -1; 41static int reboot_cpu = -1;
40#endif 42#endif
41 43
42/* reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old] 44/* This is set if we need to go through the 'emergency' path.
45 * When machine_emergency_restart() is called, we may be on
46 * an inconsistent state and won't be able to do a clean cleanup
47 */
48static int reboot_emergency;
49
50/* This is set by the PCI code if either type 1 or type 2 PCI is detected */
51bool port_cf9_safe = false;
52
53/* reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old] | p[ci]
43 warm Don't set the cold reboot flag 54 warm Don't set the cold reboot flag
44 cold Set the cold reboot flag 55 cold Set the cold reboot flag
45 bios Reboot by jumping through the BIOS (only for X86_32) 56 bios Reboot by jumping through the BIOS (only for X86_32)
@@ -48,6 +59,7 @@ static int reboot_cpu = -1;
48 kbd Use the keyboard controller. cold reset (default) 59 kbd Use the keyboard controller. cold reset (default)
49 acpi Use the RESET_REG in the FADT 60 acpi Use the RESET_REG in the FADT
50 efi Use efi reset_system runtime service 61 efi Use efi reset_system runtime service
62 pci Use the so-called "PCI reset register", CF9
51 force Avoid anything that could hang. 63 force Avoid anything that could hang.
52 */ 64 */
53static int __init reboot_setup(char *str) 65static int __init reboot_setup(char *str)
@@ -82,6 +94,7 @@ static int __init reboot_setup(char *str)
82 case 'k': 94 case 'k':
83 case 't': 95 case 't':
84 case 'e': 96 case 'e':
97 case 'p':
85 reboot_type = *str; 98 reboot_type = *str;
86 break; 99 break;
87 100
@@ -172,6 +185,15 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
172 DMI_MATCH(DMI_BOARD_NAME, "0KW626"), 185 DMI_MATCH(DMI_BOARD_NAME, "0KW626"),
173 }, 186 },
174 }, 187 },
188 { /* Handle problems with rebooting on Dell Optiplex 330 with 0KP561 */
189 .callback = set_bios_reboot,
190 .ident = "Dell OptiPlex 330",
191 .matches = {
192 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
193 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 330"),
194 DMI_MATCH(DMI_BOARD_NAME, "0KP561"),
195 },
196 },
175 { /* Handle problems with rebooting on Dell 2400's */ 197 { /* Handle problems with rebooting on Dell 2400's */
176 .callback = set_bios_reboot, 198 .callback = set_bios_reboot,
177 .ident = "Dell PowerEdge 2400", 199 .ident = "Dell PowerEdge 2400",
@@ -354,6 +376,48 @@ static inline void kb_wait(void)
354 } 376 }
355} 377}
356 378
379static void vmxoff_nmi(int cpu, struct die_args *args)
380{
381 cpu_emergency_vmxoff();
382}
383
384/* Use NMIs as IPIs to tell all CPUs to disable virtualization
385 */
386static void emergency_vmx_disable_all(void)
387{
388 /* Just make sure we won't change CPUs while doing this */
389 local_irq_disable();
390
391 /* We need to disable VMX on all CPUs before rebooting, otherwise
392 * we risk hanging up the machine, because the CPU ignore INIT
393 * signals when VMX is enabled.
394 *
395 * We can't take any locks and we may be on an inconsistent
396 * state, so we use NMIs as IPIs to tell the other CPUs to disable
397 * VMX and halt.
398 *
399 * For safety, we will avoid running the nmi_shootdown_cpus()
400 * stuff unnecessarily, but we don't have a way to check
401 * if other CPUs have VMX enabled. So we will call it only if the
402 * CPU we are running on has VMX enabled.
403 *
404 * We will miss cases where VMX is not enabled on all CPUs. This
405 * shouldn't do much harm because KVM always enable VMX on all
406 * CPUs anyway. But we can miss it on the small window where KVM
407 * is still enabling VMX.
408 */
409 if (cpu_has_vmx() && cpu_vmx_enabled()) {
410 /* Disable VMX on this CPU.
411 */
412 cpu_vmxoff();
413
414 /* Halt and disable VMX on the other CPUs */
415 nmi_shootdown_cpus(vmxoff_nmi);
416
417 }
418}
419
420
357void __attribute__((weak)) mach_reboot_fixups(void) 421void __attribute__((weak)) mach_reboot_fixups(void)
358{ 422{
359} 423}
@@ -362,6 +426,9 @@ static void native_machine_emergency_restart(void)
362{ 426{
363 int i; 427 int i;
364 428
429 if (reboot_emergency)
430 emergency_vmx_disable_all();
431
365 /* Tell the BIOS if we want cold or warm reboot */ 432 /* Tell the BIOS if we want cold or warm reboot */
366 *((unsigned short *)__va(0x472)) = reboot_mode; 433 *((unsigned short *)__va(0x472)) = reboot_mode;
367 434
@@ -398,12 +465,27 @@ static void native_machine_emergency_restart(void)
398 reboot_type = BOOT_KBD; 465 reboot_type = BOOT_KBD;
399 break; 466 break;
400 467
401
402 case BOOT_EFI: 468 case BOOT_EFI:
403 if (efi_enabled) 469 if (efi_enabled)
404 efi.reset_system(reboot_mode ? EFI_RESET_WARM : EFI_RESET_COLD, 470 efi.reset_system(reboot_mode ?
471 EFI_RESET_WARM :
472 EFI_RESET_COLD,
405 EFI_SUCCESS, 0, NULL); 473 EFI_SUCCESS, 0, NULL);
474 reboot_type = BOOT_KBD;
475 break;
476
477 case BOOT_CF9:
478 port_cf9_safe = true;
479 /* fall through */
406 480
481 case BOOT_CF9_COND:
482 if (port_cf9_safe) {
483 u8 cf9 = inb(0xcf9) & ~6;
484 outb(cf9|2, 0xcf9); /* Request hard reset */
485 udelay(50);
486 outb(cf9|6, 0xcf9); /* Actually do the reset */
487 udelay(50);
488 }
407 reboot_type = BOOT_KBD; 489 reboot_type = BOOT_KBD;
408 break; 490 break;
409 } 491 }
@@ -420,7 +502,7 @@ void native_machine_shutdown(void)
420 502
421#ifdef CONFIG_X86_32 503#ifdef CONFIG_X86_32
422 /* See if there has been given a command line override */ 504 /* See if there has been given a command line override */
423 if ((reboot_cpu != -1) && (reboot_cpu < NR_CPUS) && 505 if ((reboot_cpu != -1) && (reboot_cpu < nr_cpu_ids) &&
424 cpu_online(reboot_cpu)) 506 cpu_online(reboot_cpu))
425 reboot_cpu_id = reboot_cpu; 507 reboot_cpu_id = reboot_cpu;
426#endif 508#endif
@@ -430,7 +512,7 @@ void native_machine_shutdown(void)
430 reboot_cpu_id = smp_processor_id(); 512 reboot_cpu_id = smp_processor_id();
431 513
432 /* Make certain I only run on the appropriate processor */ 514 /* Make certain I only run on the appropriate processor */
433 set_cpus_allowed_ptr(current, &cpumask_of_cpu(reboot_cpu_id)); 515 set_cpus_allowed_ptr(current, cpumask_of(reboot_cpu_id));
434 516
435 /* O.K Now that I'm on the appropriate processor, 517 /* O.K Now that I'm on the appropriate processor,
436 * stop all of the others. 518 * stop all of the others.
@@ -453,17 +535,28 @@ void native_machine_shutdown(void)
453#endif 535#endif
454} 536}
455 537
538static void __machine_emergency_restart(int emergency)
539{
540 reboot_emergency = emergency;
541 machine_ops.emergency_restart();
542}
543
456static void native_machine_restart(char *__unused) 544static void native_machine_restart(char *__unused)
457{ 545{
458 printk("machine restart\n"); 546 printk("machine restart\n");
459 547
460 if (!reboot_force) 548 if (!reboot_force)
461 machine_shutdown(); 549 machine_shutdown();
462 machine_emergency_restart(); 550 __machine_emergency_restart(0);
463} 551}
464 552
465static void native_machine_halt(void) 553static void native_machine_halt(void)
466{ 554{
555 /* stop other cpus and apics */
556 machine_shutdown();
557
558 /* stop this cpu */
559 stop_this_cpu(NULL);
467} 560}
468 561
469static void native_machine_power_off(void) 562static void native_machine_power_off(void)
@@ -498,7 +591,7 @@ void machine_shutdown(void)
498 591
499void machine_emergency_restart(void) 592void machine_emergency_restart(void)
500{ 593{
501 machine_ops.emergency_restart(); 594 __machine_emergency_restart(1);
502} 595}
503 596
504void machine_restart(char *cmd) 597void machine_restart(char *cmd)
@@ -558,10 +651,7 @@ static int crash_nmi_callback(struct notifier_block *self,
558 651
559static void smp_send_nmi_allbutself(void) 652static void smp_send_nmi_allbutself(void)
560{ 653{
561 cpumask_t mask = cpu_online_map; 654 apic->send_IPI_allbutself(NMI_VECTOR);
562 cpu_clear(safe_smp_processor_id(), mask);
563 if (!cpus_empty(mask))
564 send_IPI_mask(mask, NMI_VECTOR);
565} 655}
566 656
567static struct notifier_block crash_nmi_nb = { 657static struct notifier_block crash_nmi_nb = {