Tian, Kevin
2007-Jun-27 13:30 UTC
[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@intel.com> Signed-off-by Kevin Tian <kevin.tian@intel.com> 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*/ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Keir Fraser
2007-Jul-11 14:58 UTC
Re: [Xen-devel] [PATCH 2/10] PM interface between dom0 and Xen
Patches 1 and 2 are now in with only very slight changes. However, I have not yet enabled the new platform hypercalls. I believe they can be slimmed down significantly. 1. We don''t need set_acpi_sleep() at all. The values it provides are all quite easily found in the fixed-format FADT and FACS structures. We don''t have the code for finding and parsing those tables in Xen currently, and we don''t want to pull in the whole Linux generic mechanism! *But* I expect it would not be hard to put together a small routine to discover waking_vector, waking_vector_length, pm1{a,b}_{evt,vnt}_port, based on the Linux code (which we want to crib from since it does all the right things for different ACPI versions) but written from scratch to be tailored for extracting just those values that we require for S-state support. 2. Enter_acpi_sleep() does not require the magic video_{flags,mode} fields. If this is just to support "acpi_sleep=" cmdline option, we can support that option directly in Xen and cut dom0 out entirely. I''ll carry on looking through the remainder of the patches, since I can apply those in parallel with any changes being made to this patch 2/10. -- Keir On 27/6/07 14:30, "Tian, Kevin" <kevin.tian@intel.com> wrote:> 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@intel.com> > Signed-off-by Kevin Tian <kevin.tian@intel.com>_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Tian, Kevin
2007-Jul-12 02:01 UTC
RE: [Xen-devel] [PATCH 2/10] PM interface between dom0 and Xen
>From: Keir Fraser [mailto:keir@xensource.com] >Sent: 2007年7月11日 22:58 > >Patches 1 and 2 are now in with only very slight changes. > >However, I have not yet enabled the new platform hypercalls. I believe >they >can be slimmed down significantly. > > 1. We don''t need set_acpi_sleep() at all. The values it provides are all >quite easily found in the fixed-format FADT and FACS structures. We >don''t >have the code for finding and parsing those tables in Xen currently, and >we >don''t want to pull in the whole Linux generic mechanism! *But* I expect it >would not be hard to put together a small routine to discover >waking_vector, >waking_vector_length, pm1{a,b}_{evt,vnt}_port, based on the Linux code >(which we want to crib from since it does all the right things for different >ACPI versions) but written from scratch to be tailored for extracting just >those values that we require for S-state support.Sounds fair. Actually our first version in house was in this direction, but gave up later due to lazy copy based on file level which brought too much unused stuff into xen.> > 2. Enter_acpi_sleep() does not require the magic video_{flags,mode} >fields. >If this is just to support "acpi_sleep=" cmdline option, we can support that >option directly in Xen and cut dom0 out entirely.Sure.> >I''ll carry on looking through the remainder of the patches, since I can >apply those in parallel with any changes being made to this patch 2/10. >Thanks, Kevin _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel