[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |