aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir@xen.org>2010-12-15 10:31:08 +0000
committerKeir Fraser <keir@xen.org>2010-12-15 10:31:08 +0000
commit508a7e32395683585aa4e4c5cddb78c106c1dd66 (patch)
treef885d3e76b312d14e56fd5ae9d9a6eac69dd6f69
parentc0ba4702f351003bd1e7bd695751bcab0d8f71f2 (diff)
downloadxen-508a7e32395683585aa4e4c5cddb78c106c1dd66.tar.gz
xen-508a7e32395683585aa4e4c5cddb78c106c1dd66.tar.bz2
xen-508a7e32395683585aa4e4c5cddb78c106c1dd66.zip
x86 acpi: Follow Windows behaviour more closely during reset.
This follows some changes proposed for upstream Linux: 1. Do not check the FADT reset register size/offset 2. Try ACPI poking twice during our reset attempt sequence Hopefully this will help us reset reliably on a wider range of platforms. Signed-off-by: Keir Fraser <keir@xen.org> xen-unstable changeset: 22482:91e0556f4d46 xen-unstable date: Fri Dec 10 11:32:19 2010 +0000 x86: acpi: Fix reboot attempt sequence. Signed-off-by: Keir Fraser <keir@xen.org> xen-unstable changeset: 22483:901c118b363e xen-unstable date: Fri Dec 10 16:40:05 2010 +0000
-rw-r--r--xen/arch/x86/shutdown.c21
-rw-r--r--xen/drivers/acpi/reboot.c7
2 files changed, 20 insertions, 8 deletions
diff --git a/xen/arch/x86/shutdown.c b/xen/arch/x86/shutdown.c
index 43a008849f..135e6ebc63 100644
--- a/xen/arch/x86/shutdown.c
+++ b/xen/arch/x86/shutdown.c
@@ -301,7 +301,8 @@ static void __machine_restart(void *pdelay)
void machine_restart(unsigned int delay_millisecs)
{
- int i;
+ unsigned int i, attempt;
+ enum reboot_type orig_reboot_type = reboot_type;
watchdog_disable();
console_start_sync();
@@ -336,7 +337,7 @@ void machine_restart(unsigned int delay_millisecs)
/* Rebooting needs to touch the page at absolute address 0. */
*((unsigned short *)__va(0x472)) = reboot_mode;
- for ( ; ; )
+ for ( attempt = 0; ; attempt++ )
{
switch ( reboot_type )
{
@@ -349,19 +350,29 @@ void machine_restart(unsigned int delay_millisecs)
outb(0xfe,0x64); /* pulse reset low */
udelay(50);
}
- /* fall through */
+ /*
+ * If this platform supports ACPI reset, we follow a Windows-style
+ * reboot attempt sequence:
+ * ACPI -> KBD -> ACPI -> KBD
+ * After this we revert to our usual sequence:
+ * KBD -> TRIPLE -> KBD -> TRIPLE -> KBD -> ...
+ */
+ reboot_type = (((attempt == 1) && (orig_reboot_type == BOOT_ACPI))
+ ? BOOT_ACPI : BOOT_TRIPLE);
+ break;
case BOOT_TRIPLE:
asm volatile ( "lidt %0 ; int3" : "=m" (no_idt) );
+ reboot_type = BOOT_KBD;
break;
case BOOT_BIOS:
machine_real_restart(jump_to_bios, sizeof(jump_to_bios));
+ reboot_type = BOOT_KBD;
break;
case BOOT_ACPI:
acpi_reboot();
+ reboot_type = BOOT_KBD;
break;
}
-
- reboot_type = BOOT_KBD;
}
}
diff --git a/xen/drivers/acpi/reboot.c b/xen/drivers/acpi/reboot.c
index 69ea8afeea..744c500a76 100644
--- a/xen/drivers/acpi/reboot.c
+++ b/xen/drivers/acpi/reboot.c
@@ -10,9 +10,10 @@ void acpi_reboot(void)
rr = &acpi_gbl_FADT.reset_register;
- /* Is the reset register supported? */
- if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) ||
- (rr->bit_width != 8) || (rr->bit_offset != 0))
+ /* Is the reset register supported? The spec says we should be
+ * checking the bit width and bit offset, but Windows ignores
+ * these fields */
+ if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER))
return;
reset_value = acpi_gbl_FADT.reset_value;