[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] x86: Default ACPI reboot method.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1213105860 -3600
# Node ID c7d361cf579372b7b5e9168892beadc6304bb4c9
# Parent  57b8c74c35ef682838ad3c93974e740bea3ba40d
x86: Default ACPI reboot method.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/shutdown.c   |  219 ++++++++++++++++++++++++----------------------
 xen/drivers/acpi/Makefile |    1 
 xen/drivers/acpi/reboot.c |   37 +++++++
 xen/include/xen/acpi.h    |    2 
 4 files changed, 157 insertions(+), 102 deletions(-)

diff -r 57b8c74c35ef -r c7d361cf5793 xen/arch/x86/shutdown.c
--- a/xen/arch/x86/shutdown.c   Tue Jun 10 14:17:20 2008 +0100
+++ b/xen/arch/x86/shutdown.c   Tue Jun 10 14:51:00 2008 +0100
@@ -14,6 +14,7 @@
 #include <xen/irq.h>
 #include <xen/console.h>
 #include <xen/shutdown.h>
+#include <xen/acpi.h>
 #include <asm/msr.h>
 #include <asm/regs.h>
 #include <asm/mc146818rtc.h>
@@ -23,12 +24,53 @@
 #include <asm/mpspec.h>
 #include <asm/tboot.h>
 
-/* reboot_str: comma-separated list of reboot options. */
-static char __initdata reboot_str[10] = "";
-string_param("reboot", reboot_str);
+enum reboot_type {
+        BOOT_TRIPLE = 't',
+        BOOT_KBD = 'k',
+        BOOT_ACPI = 'a',
+#ifdef CONFIG_X86_32
+        BOOT_BIOS = 'b',
+#endif
+};
 
 static long no_idt[2];
 static int reboot_mode;
+
+/*
+ * reboot=b[ios] | t[riple] | k[bd] | [, [w]arm | [c]old]
+ * warm   Don't set the cold reboot flag
+ * cold   Set the cold reboot flag
+ * bios   Reboot by jumping through the BIOS (only for X86_32)
+ * triple Force a triple fault (init)
+ * kbd    Use the keyboard controller. cold reset (default)
+ * acpi   Use the RESET_REG in the FADT
+ */
+static enum reboot_type reboot_type = BOOT_ACPI;
+static void __init set_reboot_type(char *str)
+{
+    for ( ; ; )
+    {
+        switch ( *str )
+        {
+        case 'w': /* "warm" reboot (no memory testing etc) */
+            reboot_mode = 0x1234;
+            break;
+        case 'c': /* "cold" reboot (with memory testing etc) */
+            reboot_mode = 0x0;
+            break;
+        case 'b':
+        case 'a':
+        case 'k':
+        case 't':
+            reboot_type = *str;
+            break;
+        }
+        if ( (str = strchr(str, ',')) == NULL )
+            break;
+        str++;
+    }
+}
+custom_param("reboot", set_reboot_type);
 
 static inline void kb_wait(void)
 {
@@ -55,8 +97,6 @@ void machine_halt(void)
 }
 
 #ifdef __i386__
-
-static int reboot_thru_bios;
 
 /* The following code and data reboots the machine by switching to real
    mode and jumping to the BIOS reset entry point, as if the CPU has
@@ -192,10 +232,63 @@ static void machine_real_restart(const u
                                           MAX_LENGTH)));
 }
 
+static int __init set_bios_reboot(struct dmi_system_id *d)
+{
+    if ( reboot_type != BOOT_BIOS )
+    {
+        reboot_type = BOOT_BIOS;
+        printk("%s series board detected. "
+               "Selecting BIOS-method for reboots.\n", d->ident);
+    }
+    return 0;
+}
+
+static struct dmi_system_id __initdata reboot_dmi_table[] = {
+    {    /* Handle problems with rebooting on Dell 1300's */
+        .callback = set_bios_reboot,
+        .ident = "Dell PowerEdge 1300",
+        .matches = {
+            DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
+            DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"),
+        },
+    },
+    {    /* Handle problems with rebooting on Dell 300's */
+        .callback = set_bios_reboot,
+        .ident = "Dell PowerEdge 300",
+        .matches = {
+            DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
+            DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"),
+        },
+    },
+    {    /* Handle problems with rebooting on Dell 2400's */
+        .callback = set_bios_reboot,
+        .ident = "Dell PowerEdge 2400",
+        .matches = {
+            DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
+            DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"),
+        },
+    },
+    {    /* Handle problems with rebooting on HP laptops */
+        .callback = set_bios_reboot,
+        .ident = "HP Compaq Laptop",
+        .matches = {
+            DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+            DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"),
+        },
+    },
+    { }
+};
+
+static int __init reboot_init(void)
+{
+    dmi_check_system(reboot_dmi_table);
+    return 0;
+}
+__initcall(reboot_init);
+
 #else /* __x86_64__ */
 
 #define machine_real_restart(x, y)
-#define reboot_thru_bios 0
 
 #endif
 
@@ -226,10 +319,11 @@ void machine_restart(void)
     /* Rebooting needs to touch the page at absolute address 0. */
     *((unsigned short *)__va(0x472)) = reboot_mode;
 
-    if ( reboot_thru_bios <= 0 )
-    {
-        for ( ; ; )
+    for ( ; ; )
+    {
+        switch ( reboot_type )
         {
+        case BOOT_KBD:
             /* Pulse the keyboard reset line. */
             for ( i = 0; i < 100; i++ )
             {
@@ -238,100 +332,21 @@ void machine_restart(void)
                 outb(0xfe,0x64); /* pulse reset low */
                 udelay(50);
             }
-
-            /* That didn't work - force a triple fault.. */
-            __asm__ __volatile__("lidt %0": "=m" (no_idt));
-            __asm__ __volatile__("int3");
+            /* fall through */
+        case BOOT_TRIPLE:
+            asm volatile ( "lidt %0 ; int3" : "=m" (no_idt) );
+            break;
+        case BOOT_BIOS:
+            machine_real_restart(jump_to_bios, sizeof(jump_to_bios));
+            break;
+        case BOOT_ACPI:
+            acpi_reboot();
+            break;
         }
-    }
-    machine_real_restart(jump_to_bios, sizeof(jump_to_bios));
-}
-
-#ifndef reboot_thru_bios
-static int __init set_bios_reboot(struct dmi_system_id *d)
-{
-    if ( !reboot_thru_bios )
-    {
-        reboot_thru_bios = 1;
-        printk("%s series board detected. "
-               "Selecting BIOS-method for reboots.\n", d->ident);
-    }
-    return 0;
-}
-
-static struct dmi_system_id __initdata reboot_dmi_table[] = {
-    {    /* Handle problems with rebooting on Dell 1300's */
-        .callback = set_bios_reboot,
-        .ident = "Dell PowerEdge 1300",
-        .matches = {
-            DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
-            DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"),
-        },
-    },
-    {    /* Handle problems with rebooting on Dell 300's */
-        .callback = set_bios_reboot,
-        .ident = "Dell PowerEdge 300",
-        .matches = {
-            DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
-            DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"),
-        },
-    },
-    {    /* Handle problems with rebooting on Dell 2400's */
-        .callback = set_bios_reboot,
-        .ident = "Dell PowerEdge 2400",
-        .matches = {
-            DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
-            DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"),
-        },
-    },
-    {    /* Handle problems with rebooting on HP laptops */
-        .callback = set_bios_reboot,
-        .ident = "HP Compaq Laptop",
-        .matches = {
-            DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-            DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"),
-        },
-    },
-    { }
-};
-#endif
-
-static int __init reboot_init(void)
-{
-    const char *str;
-
-    for ( str = reboot_str; *str != '\0'; str++ )
-    {
-        switch ( *str )
-        {
-        case 'n': /* no reboot */
-            opt_noreboot = 1;
-            break;
-        case 'w': /* "warm" reboot (no memory testing etc) */
-            reboot_mode = 0x1234;
-            break;
-        case 'c': /* "cold" reboot (with memory testing etc) */
-            reboot_mode = 0x0;
-            break;
-#ifndef reboot_thru_bios
-        case 'b': /* "bios" reboot by jumping through the BIOS */
-            reboot_thru_bios = 1;
-            break;
-        case 'h': /* "hard" reboot by toggling RESET and/or crashing the CPU */
-            reboot_thru_bios = -1;
-            break;
-#endif
-        }
-        if ( (str = strchr(str, ',')) == NULL )
-            break;
-    }
-
-#ifndef reboot_thru_bios
-    dmi_check_system(reboot_dmi_table);
-#endif
-    return 0;
-}
-__initcall(reboot_init);
+
+        reboot_type = BOOT_KBD;
+    }
+}
 
 /*
  * Local variables:
diff -r 57b8c74c35ef -r c7d361cf5793 xen/drivers/acpi/Makefile
--- a/xen/drivers/acpi/Makefile Tue Jun 10 14:17:20 2008 +0100
+++ b/xen/drivers/acpi/Makefile Tue Jun 10 14:51:00 2008 +0100
@@ -6,3 +6,4 @@ obj-y += osl.o
 obj-y += osl.o
 
 obj-$(x86) += hwregs.o
+obj-$(x86) += reboot.o
diff -r 57b8c74c35ef -r c7d361cf5793 xen/drivers/acpi/reboot.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/drivers/acpi/reboot.c Tue Jun 10 14:51:00 2008 +0100
@@ -0,0 +1,37 @@
+#include <xen/config.h>
+#include <xen/pci.h>
+#include <acpi/acpi.h>
+
+void acpi_reboot(void)
+{
+       struct acpi_generic_address *rr;
+       u8 reset_value;
+
+       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))
+               return;
+
+       reset_value = acpi_gbl_FADT.reset_value;
+
+       /* The reset register can only exist in I/O, Memory or PCI config space
+        * on a device on bus 0. */
+       switch (rr->space_id) {
+       case ACPI_ADR_SPACE_PCI_CONFIG:
+               printk("Resetting with ACPI PCI RESET_REG.");
+               /* Write the value that resets us. */
+               pci_conf_write8(0,
+                               (rr->address >> 32) & 31,
+                               (rr->address >> 16) & 7,
+                               (rr->address & 255),
+                               reset_value);
+               break;
+       case ACPI_ADR_SPACE_SYSTEM_MEMORY:
+       case ACPI_ADR_SPACE_SYSTEM_IO:
+               printk("ACPI MEMORY or I/O RESET_REG.");
+               acpi_hw_low_level_write(8, reset_value, rr);
+               break;
+       }
+}
diff -r 57b8c74c35ef -r c7d361cf5793 xen/include/xen/acpi.h
--- a/xen/include/xen/acpi.h    Tue Jun 10 14:17:20 2008 +0100
+++ b/xen/include/xen/acpi.h    Tue Jun 10 14:51:00 2008 +0100
@@ -441,4 +441,6 @@ static inline int acpi_get_pxm(acpi_hand
 
 extern int pnpacpi_disabled;
 
+void acpi_reboot(void);
+
 #endif /*_LINUX_ACPI_H*/

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.