[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [host s3] Retrieve necessary sleep information from plain-text ACPI
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Date 1184846012 -3600 # Node ID 0d291a7c8c1f4a77a01c49f2e8cc90271ed19d37 # Parent f191aa8ac8ea52c3858202993b15f89dedc2e90c [host s3] Retrieve necessary sleep information from plain-text ACPI tables (FADT/FACS), and keep one hypercall remained for sleep notification. Signed-off-by: Ke Yu <ke.yu@xxxxxxxxx> Signed-off-by: Kevin Tian <kevin.tian@xxxxxxxxx> Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- xen/arch/x86/acpi/boot.c | 93 +++++++++++++++++++++++++++++++ xen/arch/x86/acpi/power.c | 114 +++++++++++++++++++------------------- xen/arch/x86/acpi/suspend.c | 3 - xen/arch/x86/platform_hypercall.c | 14 ---- xen/drivers/acpi/tables.c | 3 + xen/include/asm-x86/acpi.h | 20 +++++- xen/include/public/platform.h | 25 +------- xen/include/xen/acpi.h | 1 8 files changed, 177 insertions(+), 96 deletions(-) diff -r f191aa8ac8ea -r 0d291a7c8c1f xen/arch/x86/acpi/boot.c --- a/xen/arch/x86/acpi/boot.c Thu Jul 19 10:59:05 2007 +0100 +++ b/xen/arch/x86/acpi/boot.c Thu Jul 19 12:53:32 2007 +0100 @@ -369,6 +369,95 @@ extern u32 pmtmr_ioport; extern u32 pmtmr_ioport; #endif +#ifdef CONFIG_ACPI_SLEEP +/* Get pm1x_cnt and pm1x_evt information for ACPI sleep */ +static int __init +acpi_fadt_parse_sleep_info(struct fadt_descriptor_rev2 *fadt) +{ + struct facs_descriptor_rev2 *facs = NULL; + uint64_t facs_pa; + + if (fadt->revision >= FADT2_REVISION_ID) { + /* Sanity check on FADT Rev. 2 */ + if ((fadt->xpm1a_cnt_blk.address_space_id != + ACPI_ADR_SPACE_SYSTEM_IO) || + (fadt->xpm1b_cnt_blk.address_space_id != + ACPI_ADR_SPACE_SYSTEM_IO) || + (fadt->xpm1a_evt_blk.address_space_id != + ACPI_ADR_SPACE_SYSTEM_IO) || + (fadt->xpm1b_evt_blk.address_space_id != + ACPI_ADR_SPACE_SYSTEM_IO)) + goto bad; + + acpi_sinfo.pm1a_cnt = (uint16_t)fadt->xpm1a_cnt_blk.address; + acpi_sinfo.pm1b_cnt = (uint16_t)fadt->xpm1b_cnt_blk.address; + acpi_sinfo.pm1a_evt = (uint16_t)fadt->xpm1a_evt_blk.address; + acpi_sinfo.pm1b_evt = (uint16_t)fadt->xpm1b_evt_blk.address; + } + + if (!acpi_sinfo.pm1a_cnt) + acpi_sinfo.pm1a_cnt = (uint16_t)fadt->V1_pm1a_cnt_blk; + if (!acpi_sinfo.pm1b_cnt) + acpi_sinfo.pm1b_cnt = (uint16_t)fadt->V1_pm1b_cnt_blk; + if (!acpi_sinfo.pm1a_evt) + acpi_sinfo.pm1a_evt = (uint16_t)fadt->V1_pm1a_evt_blk; + if (!acpi_sinfo.pm1b_evt) + acpi_sinfo.pm1b_evt = (uint16_t)fadt->V1_pm1b_evt_blk; + + /* Now FACS... */ + if (fadt->revision >= FADT2_REVISION_ID) + facs_pa = fadt->xfirmware_ctrl; + else + facs_pa = (uint64_t)fadt->V1_firmware_ctrl; + + facs = (struct facs_descriptor_rev2 *) + __acpi_map_table(facs_pa, sizeof(struct facs_descriptor_rev2)); + if (!facs) + goto bad; + + if (strncmp(facs->signature, "FACS", 4)) { + printk(KERN_ERR PREFIX "Invalid FACS signature %s\n", + facs->signature); + goto bad; + } + + if (facs->length < 24) { + printk(KERN_ERR PREFIX "Invalid FACS table length: 0x%x", + facs->length); + goto bad; + } + + if (facs->length < 64) + printk(KERN_WARNING PREFIX + "FACS is shorter than ACPI spec allow: 0x%x", + facs->length); + + if ((acpi_rsdp_rev < 2) || + (facs->length < 32)) { + acpi_sinfo.wakeup_vector = facs_pa + + offsetof(struct facs_descriptor_rev2, + firmware_waking_vector); + acpi_sinfo.vector_width = 32; + } else { + acpi_sinfo.wakeup_vector = facs_pa + + offsetof(struct facs_descriptor_rev2, + xfirmware_waking_vector); + acpi_sinfo.vector_width = 64; + } + + printk (KERN_INFO PREFIX + "ACPI SLEEP INFO: pm1x_cnt[%x,%x], pm1x_evt[%x,%x]\n" + " wakeup_vec[%"PRIx64"], vec_size[%x]\n", + acpi_sinfo.pm1a_cnt, acpi_sinfo.pm1b_cnt, + acpi_sinfo.pm1a_evt, acpi_sinfo.pm1b_cnt, + acpi_sinfo.wakeup_vector, acpi_sinfo.vector_width); + return 0; +bad: + memset(&acpi_sinfo, 0, sizeof(acpi_sinfo)); + return 0; +} +#endif + static int __init acpi_parse_fadt(unsigned long phys, unsigned long size) { struct fadt_descriptor_rev2 *fadt = NULL; @@ -412,6 +501,10 @@ static int __init acpi_parse_fadt(unsign if (pmtmr_ioport) printk(KERN_INFO PREFIX "PM-Timer IO Port: %#x\n", pmtmr_ioport); +#endif + +#ifdef CONFIG_ACPI_SLEEP + acpi_fadt_parse_sleep_info(fadt); #endif return 0; } diff -r f191aa8ac8ea -r 0d291a7c8c1f xen/arch/x86/acpi/power.c --- a/xen/arch/x86/acpi/power.c Thu Jul 19 10:59:05 2007 +0100 +++ b/xen/arch/x86/acpi/power.c Thu Jul 19 12:53:32 2007 +0100 @@ -28,20 +28,15 @@ #define pmprintk(_l, _f, _a...) printk(_l "<PM>" _f, ## _a ) -u8 sleep_states[ACPI_S_STATE_COUNT]; -DEFINE_SPINLOCK(pm_lock); - -struct acpi_sleep_info { - uint16_t pm1a_cnt; - uint16_t pm1b_cnt; - uint16_t pm1a_evt; - uint16_t pm1b_evt; - uint16_t pm1a_cnt_val; - uint16_t pm1b_cnt_val; - uint32_t sleep_state; -} acpi_sinfo; - -extern void do_suspend_lowlevel(void); +static char opt_acpi_sleep[20]; +string_param("acpi_sleep", opt_acpi_sleep); + +static u8 sleep_states[ACPI_S_STATE_COUNT]; +static DEFINE_SPINLOCK(pm_lock); + +struct acpi_sleep_info acpi_sinfo; + +void do_suspend_lowlevel(void); static char *acpi_states[ACPI_S_STATE_COUNT] = { @@ -50,10 +45,6 @@ static char *acpi_states[ACPI_S_STATE_CO [ACPI_STATE_S4] = "disk", }; -unsigned long acpi_video_flags; -unsigned long saved_videomode; - -/* XXX: Add suspend failure recover later */ static int device_power_down(void) { console_suspend(); @@ -100,8 +91,27 @@ static void thaw_domains(void) domain_unpause(d); } +static void acpi_sleep_prepare(u32 state) +{ + void *wakeup_vector_va; + + if ( state != ACPI_STATE_S3 ) + return; + + wakeup_vector_va = __acpi_map_table( + acpi_sinfo.wakeup_vector, sizeof(uint64_t)); + if (acpi_sinfo.vector_width == 32) + *(uint32_t *)wakeup_vector_va = + (uint32_t)bootsym_phys(wakeup_start); + else + *(uint64_t *)wakeup_vector_va = + (uint64_t)bootsym_phys(wakeup_start); +} + +static void acpi_sleep_post(u32 state) {} + /* Main interface to do xen specific suspend/resume */ -int enter_state(u32 state) +static int enter_state(u32 state) { unsigned long flags; int error; @@ -122,6 +132,8 @@ int enter_state(u32 state) pmprintk(XENLOG_INFO, "PM: Preparing system for %s sleep\n", acpi_states[state]); + + acpi_sleep_prepare(state); local_irq_save(flags); @@ -152,36 +164,14 @@ int enter_state(u32 state) Done: local_irq_restore(flags); + acpi_sleep_post(state); + if ( !hvm_cpu_up() ) BUG(); thaw_domains(); spin_unlock(&pm_lock); return error; -} - -/* - * Xen just requires address of pm1x_cnt, and ACPI interpreter - * is still kept in dom0. Address of xen wakeup stub will be - * returned, and then dom0 writes that address to FACS. - */ -int set_acpi_sleep_info(struct xenpf_set_acpi_sleep *info) -{ - if (acpi_sinfo.pm1a_cnt) - pmprintk(XENLOG_WARNING, "Multiple setting on acpi sleep info\n"); - - acpi_sinfo.pm1a_cnt = info->pm1a_cnt_port; - acpi_sinfo.pm1b_cnt = info->pm1b_cnt_port; - acpi_sinfo.pm1a_evt = info->pm1a_evt_port; - acpi_sinfo.pm1b_evt = info->pm1b_evt_port; - info->xen_waking_vec = (uint64_t)bootsym_phys(wakeup_start); - - pmprintk(XENLOG_INFO, "pm1a[%x],pm1b[%x],pm1a_e[%x],pm1b_e[%x]" - "wake[%"PRIx64"]", - acpi_sinfo.pm1a_cnt, acpi_sinfo.pm1b_cnt, - acpi_sinfo.pm1a_evt, acpi_sinfo.pm1b_evt, - info->xen_waking_vec); - return 0; } /* @@ -197,20 +187,23 @@ int set_acpi_sleep_info(struct xenpf_set */ int acpi_enter_sleep(struct xenpf_enter_acpi_sleep *sleep) { - if (!IS_PRIV(current->domain) || !acpi_sinfo.pm1a_cnt) + if ( !IS_PRIV(current->domain) || !acpi_sinfo.pm1a_cnt ) return -EPERM; /* Sanity check */ - if (acpi_sinfo.pm1b_cnt_val && - ((sleep->pm1a_cnt_val ^ sleep->pm1b_cnt_val) & - ACPI_BITMASK_SLEEP_ENABLE)) + if ( acpi_sinfo.pm1b_cnt_val && + ((sleep->pm1a_cnt_val ^ sleep->pm1b_cnt_val) & + ACPI_BITMASK_SLEEP_ENABLE) ) { pmprintk(XENLOG_ERR, "Mismatched pm1a/pm1b setting\n"); return -EINVAL; } + if ( sleep->flags ) + return -EINVAL; + /* Write #1 */ - if (!(sleep->pm1a_cnt_val & ACPI_BITMASK_SLEEP_ENABLE)) + if ( !(sleep->pm1a_cnt_val & ACPI_BITMASK_SLEEP_ENABLE) ) { outw((u16)sleep->pm1a_cnt_val, acpi_sinfo.pm1a_cnt); if (acpi_sinfo.pm1b_cnt) @@ -222,8 +215,6 @@ int acpi_enter_sleep(struct xenpf_enter_ acpi_sinfo.pm1a_cnt_val = sleep->pm1a_cnt_val; acpi_sinfo.pm1b_cnt_val = sleep->pm1b_cnt_val; acpi_sinfo.sleep_state = sleep->sleep_state; - acpi_video_flags = sleep->video_flags; - saved_videomode = sleep->video_mode; return enter_state(acpi_sinfo.sleep_state); } @@ -247,7 +238,7 @@ acpi_status asmlinkage acpi_enter_sleep_ outw((u16)acpi_sinfo.pm1a_cnt_val, acpi_sinfo.pm1a_cnt); if (acpi_sinfo.pm1b_cnt) outw((u16)acpi_sinfo.pm1b_cnt_val, acpi_sinfo.pm1b_cnt); - + /* Wait until we enter sleep state, and spin until we wake */ while (!acpi_get_wake_status()); return_ACPI_STATUS(AE_OK); @@ -255,12 +246,24 @@ acpi_status asmlinkage acpi_enter_sleep_ static int __init acpi_sleep_init(void) { - int i = 0; + int i; + char *p = opt_acpi_sleep; + + while ( (p != NULL) && (*p != '\0') ) + { + if ( !strncmp(p, "s3_bios", 7) ) + acpi_video_flags |= 1; + if ( !strncmp(p, "s3_mode", 7) ) + acpi_video_flags |= 2; + p = strchr(p, ','); + if ( p != NULL ) + p += strspn(p, ", \t"); + } pmprintk(XENLOG_INFO, "ACPI (supports"); - for (i = 0; i < ACPI_S_STATE_COUNT; i++) - { - if (i == ACPI_STATE_S3) + for ( i = 0; i < ACPI_S_STATE_COUNT; i++ ) + { + if ( i == ACPI_STATE_S3 ) { sleep_states[i] = 1; printk(" S%d", i); @@ -269,6 +272,7 @@ static int __init acpi_sleep_init(void) sleep_states[i] = 0; } printk(")\n"); + return 0; } __initcall(acpi_sleep_init); diff -r f191aa8ac8ea -r 0d291a7c8c1f xen/arch/x86/acpi/suspend.c --- a/xen/arch/x86/acpi/suspend.c Thu Jul 19 10:59:05 2007 +0100 +++ b/xen/arch/x86/acpi/suspend.c Thu Jul 19 12:53:32 2007 +0100 @@ -35,9 +35,6 @@ void save_rest_processor_state(void) rdmsrl(MSR_CSTAR, saved_cstar); rdmsrl(MSR_LSTAR, saved_lstar); #endif - - bootsym(video_flags) = acpi_video_flags; - bootsym(video_mode) = saved_videomode; } #define loaddebug(_v,_reg) \ diff -r f191aa8ac8ea -r 0d291a7c8c1f xen/arch/x86/platform_hypercall.c --- a/xen/arch/x86/platform_hypercall.c Thu Jul 19 10:59:05 2007 +0100 +++ b/xen/arch/x86/platform_hypercall.c Thu Jul 19 12:53:32 2007 +0100 @@ -248,21 +248,9 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe } break; -#if 0 - case XENPF_set_acpi_sleep: - { - ret = set_acpi_sleep_info(&op->u.set_acpi_sleep); - if (!ret && copy_to_guest(u_xenpf_op, op, 1)) - ret = -EFAULT; - } - break; - case XENPF_enter_acpi_sleep: - { ret = acpi_enter_sleep(&op->u.enter_acpi_sleep); - } - break; -#endif + break; default: ret = -ENOSYS; diff -r f191aa8ac8ea -r 0d291a7c8c1f xen/drivers/acpi/tables.c --- a/xen/drivers/acpi/tables.c Thu Jul 19 10:59:05 2007 +0100 +++ b/xen/drivers/acpi/tables.c Thu Jul 19 12:53:32 2007 +0100 @@ -73,6 +73,7 @@ struct acpi_table_sdt { static unsigned long sdt_pa; /* Physical Address */ static unsigned long sdt_count; /* Table count */ +unsigned char acpi_rsdp_rev; static struct acpi_table_sdt sdt_entry[ACPI_MAX_TABLES] __initdata; @@ -598,6 +599,8 @@ int __init acpi_table_init(void) "RSDP (v%3.3d %6.6s ) @ 0x%p\n", rsdp->revision, rsdp->oem_id, (void *)rsdp_phys); + acpi_rsdp_rev = rsdp->revision; + if (rsdp->revision < 2) result = acpi_table_compute_checksum(rsdp, diff -r f191aa8ac8ea -r 0d291a7c8c1f xen/include/asm-x86/acpi.h --- a/xen/include/asm-x86/acpi.h Thu Jul 19 10:59:05 2007 +0100 +++ b/xen/include/asm-x86/acpi.h Thu Jul 19 12:53:32 2007 +0100 @@ -173,15 +173,25 @@ extern unsigned long acpi_wakeup_address /* early initialization routine */ extern void acpi_reserve_bootmem(void); -extern unsigned long acpi_video_flags; -extern unsigned long saved_videomode; -struct xenpf_set_acpi_sleep; +extern struct acpi_sleep_info acpi_sinfo; +#define acpi_video_flags bootsym(video_flags) struct xenpf_enter_acpi_sleep; -extern int set_acpi_sleep_info(struct xenpf_set_acpi_sleep *info); extern int acpi_enter_sleep(struct xenpf_enter_acpi_sleep *sleep); extern int acpi_enter_state(u32 state); -#endif /*CONFIG_ACPI_SLEEP*/ +struct acpi_sleep_info { + uint16_t pm1a_cnt; + uint16_t pm1b_cnt; + uint16_t pm1a_evt; + uint16_t pm1b_evt; + uint16_t pm1a_cnt_val; + uint16_t pm1b_cnt_val; + uint32_t sleep_state; + uint64_t wakeup_vector; + uint32_t vector_width; +}; + +#endif /* CONFIG_ACPI_SLEEP */ extern u8 x86_acpiid_to_apicid[]; #define MAX_LOCAL_APIC 256 diff -r f191aa8ac8ea -r 0d291a7c8c1f xen/include/public/platform.h --- a/xen/include/public/platform.h Thu Jul 19 10:59:05 2007 +0100 +++ b/xen/include/public/platform.h Thu Jul 19 12:53:32 2007 +0100 @@ -153,27 +153,13 @@ typedef struct xenpf_firmware_info xenpf typedef struct xenpf_firmware_info xenpf_firmware_info_t; DEFINE_XEN_GUEST_HANDLE(xenpf_firmware_info_t); -#define XENPF_set_acpi_sleep 51 -struct xenpf_set_acpi_sleep { - /* IN variables. */ - uint16_t pm1a_cnt_port; - uint16_t pm1b_cnt_port; - uint16_t pm1a_evt_port; - uint16_t pm1b_evt_port; - /* OUT variables */ - uint64_t xen_waking_vec; /* Tell dom0 to set FACS waking vector */ -}; -typedef struct xenpf_set_acpi_sleep xenpf_set_acpi_sleep_t; -DEFINE_XEN_GUEST_HANDLE(xenpf_set_acpi_sleep_t); - -#define XENPF_enter_acpi_sleep 52 +#define XENPF_enter_acpi_sleep 51 struct xenpf_enter_acpi_sleep { /* IN variables */ - uint16_t pm1a_cnt_val; - uint16_t pm1b_cnt_val; - uint32_t sleep_state; /* Which state to enter */ - uint32_t video_flags; /* S3_bios or s3_mode */ - uint32_t video_mode; /* Mode setting for s3_mode */ + uint16_t pm1a_cnt_val; /* PM1a control value. */ + uint16_t pm1b_cnt_val; /* PM1b control value. */ + uint32_t sleep_state; /* Which state to enter (Sn). */ + uint32_t flags; /* Must be zero. */ }; typedef struct xenpf_enter_acpi_sleep xenpf_enter_acpi_sleep_t; DEFINE_XEN_GUEST_HANDLE(xenpf_enter_acpi_sleep_t); @@ -189,7 +175,6 @@ struct xen_platform_op { struct xenpf_microcode_update microcode; struct xenpf_platform_quirk platform_quirk; struct xenpf_firmware_info firmware_info; - struct xenpf_set_acpi_sleep set_acpi_sleep; struct xenpf_enter_acpi_sleep enter_acpi_sleep; uint8_t pad[128]; } u; diff -r f191aa8ac8ea -r 0d291a7c8c1f xen/include/xen/acpi.h --- a/xen/include/xen/acpi.h Thu Jul 19 10:59:05 2007 +0100 +++ b/xen/include/xen/acpi.h Thu Jul 19 12:53:32 2007 +0100 @@ -534,5 +534,6 @@ static inline int acpi_get_pxm(acpi_hand #endif extern int pnpacpi_disabled; +extern unsigned char acpi_rsdp_rev; #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 |