[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 2/10] PM interface between dom0 and Xen
Define pm interfaces between dom0 and Xen, with one to register sleep info and the other for triggering sleep state. "acpi_sleep=s3_mode/s3_bios" option is also supported by piggybacking video flag/mode to xen at trigger point. Signed-off-by Ke Yu <ke.yu@xxxxxxxxx> Signed-off-by Kevin Tian <kevin.tian@xxxxxxxxx> diff -r 50e0cc2aee5e xen/arch/x86/acpi/power.c --- a/xen/arch/x86/acpi/power.c Tue Jun 26 20:28:13 2007 -0400 +++ b/xen/arch/x86/acpi/power.c Tue Jun 26 20:37:48 2007 -0400 @@ -10,6 +10,7 @@ * Slimmed with Xen specific support. */ +#include <xen/config.h> #include <asm/io.h> #define CONFIG_ACPI_SLEEP #include <asm/acpi.h> @@ -28,6 +29,16 @@ u8 sleep_states[ACPI_S_STATE_COUNT]; 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 *acpi_states[ACPI_S_STATE_COUNT] = @@ -129,6 +140,99 @@ int enter_state(u32 state) 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; +} + +/* + * Dom0 issues this hypercall in place of writing pm1a_cnt. Xen then + * takes over the control and put the system into sleep state really. + * Also video flags and mode are passed here, in case user may use + * "acpi_sleep=***" for video resume. + * + * Guest may issue a two-phases write to PM1x_CNT, to work + * around poorly implemented hardware. It's better to keep + * this logic here. Two writes can be differentiated by + * enable bit setting. + */ +int acpi_enter_sleep(struct xenpf_enter_acpi_sleep *sleep) +{ + 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)) + { + pmprintk(XENLOG_ERR, "Mismatched pm1a/pm1b setting\n"); + return -EINVAL; + } + + /* Write #1 */ + if (!(sleep->pm1a_cnt_val & ACPI_BITMASK_SLEEP_ENABLE)) + { + outw((u16)sleep->pm1a_cnt_val, acpi_sinfo.pm1a_cnt); + if (acpi_sinfo.pm1b_cnt) + outw((u16)sleep->pm1b_cnt_val, acpi_sinfo.pm1b_cnt); + return 0; + } + + /* Write #2 */ + 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); +} + +static int acpi_get_wake_status(void) +{ + uint16_t val; + + /* Wake status is the 15th bit of PM1 status register. (ACPI spec 3.0) */ + val = inw(acpi_sinfo.pm1a_evt) | inw(acpi_sinfo.pm1b_evt); + val &= ACPI_BITMASK_WAKE_STATUS; + val >>= ACPI_BITPOSITION_WAKE_STATUS; + return val; +} + +/* System is really put into sleep state by this stub */ +acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) +{ + ACPI_FLUSH_CPU_CACHE(); + + 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); } static int __init acpi_sleep_init(void) diff -r 50e0cc2aee5e xen/arch/x86/acpi/suspend.c --- a/xen/arch/x86/acpi/suspend.c Tue Jun 26 20:28:13 2007 -0400 +++ b/xen/arch/x86/acpi/suspend.c Tue Jun 26 20:37:48 2007 -0400 @@ -35,6 +35,9 @@ 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 50e0cc2aee5e xen/arch/x86/platform_hypercall.c --- a/xen/arch/x86/platform_hypercall.c Tue Jun 26 20:28:13 2007 -0400 +++ b/xen/arch/x86/platform_hypercall.c Tue Jun 26 20:37:48 2007 -0400 @@ -18,6 +18,7 @@ #include <xen/console.h> #include <xen/iocap.h> #include <xen/guest_access.h> +#include <xen/acpi.h> #include <asm/current.h> #include <public/platform.h> #include <asm/edd.h> @@ -247,6 +248,20 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe } break; + 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; + default: ret = -ENOSYS; break; diff -r 50e0cc2aee5e xen/include/asm-x86/config.h --- a/xen/include/asm-x86/config.h Tue Jun 26 20:28:13 2007 -0400 +++ b/xen/include/asm-x86/config.h Tue Jun 26 20:37:48 2007 -0400 @@ -96,6 +96,8 @@ extern char trampoline_realmode_entry[]; extern char trampoline_realmode_entry[]; extern unsigned int trampoline_xen_phys_start; extern unsigned char trampoline_cpu_started; +extern char wakeup_start[]; +extern unsigned int video_mode, video_flags; #endif #if defined(__x86_64__) diff -r 50e0cc2aee5e xen/include/public/platform.h --- a/xen/include/public/platform.h Tue Jun 26 20:28:13 2007 -0400 +++ b/xen/include/public/platform.h Tue Jun 26 20:38:34 2007 -0400 @@ -153,6 +153,31 @@ 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 +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 */ +}; +typedef struct xenpf_enter_acpi_sleep xenpf_enter_acpi_sleep_t; +DEFINE_XEN_GUEST_HANDLE(xenpf_enter_acpi_sleep_t); + struct xen_platform_op { uint32_t cmd; uint32_t interface_version; /* XENPF_INTERFACE_VERSION */ @@ -164,6 +189,8 @@ 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 50e0cc2aee5e xen/include/xen/acpi.h --- a/xen/include/xen/acpi.h Tue Jun 26 20:28:13 2007 -0400 +++ b/xen/include/xen/acpi.h Tue Jun 26 20:37:48 2007 -0400 @@ -535,4 +535,15 @@ static inline int acpi_get_pxm(acpi_hand extern int pnpacpi_disabled; +#include <public/platform.h> +#ifdef COMPAT +#define xenpf_set_acpi_sleep compat_pf_set_acpi_sleep +#define xenpf_enter_acpi_sleep compat_pf_enter_acpi_sleep +#endif /* COMPAT */ + +extern unsigned long acpi_video_flags; +extern unsigned long saved_videomode; +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 /*_LINUX_ACPI_H*/ Attachment:
acpi_sleep_interface.patch _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |