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>
diff -r e1f74a5a09cb xen/arch/x86/acpi/boot.c
--- a/xen/arch/x86/acpi/boot.c Wed Jul 18 13:56:21 2007 +0100
+++ b/xen/arch/x86/acpi/boot.c Thu Jul 19 14:35:45 2007 +0800
@@ -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 e1f74a5a09cb xen/arch/x86/acpi/power.c
--- a/xen/arch/x86/acpi/power.c Wed Jul 18 13:56:21 2007 +0100
+++ b/xen/arch/x86/acpi/power.c Thu Jul 19 14:34:37 2007 +0800
@@ -31,15 +31,7 @@ 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;
+struct acpi_sleep_info acpi_sinfo;
extern void do_suspend_lowlevel(void);
@@ -52,6 +44,7 @@ static char *acpi_states[ACPI_S_STATE_CO
unsigned long acpi_video_flags;
unsigned long saved_videomode;
+void *wakeup_vector_va;
/* XXX: Add suspend failure recover later */
static int device_power_down(void)
@@ -100,6 +93,23 @@ static void thaw_domains(void)
domain_unpause(d);
}
+static void acpi_sleep_prepare(u32 state)
+{
+ if (state == ACPI_STATE_S3)
+ {
+ 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)
{
@@ -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;
}
/*
diff -r e1f74a5a09cb xen/arch/x86/platform_hypercall.c
--- a/xen/arch/x86/platform_hypercall.c Wed Jul 18 13:56:21 2007 +0100
+++ b/xen/arch/x86/platform_hypercall.c Thu Jul 19 13:29:01 2007 +0800
@@ -248,21 +248,11 @@ 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
default:
ret = -ENOSYS;
diff -r e1f74a5a09cb xen/drivers/acpi/tables.c
--- a/xen/drivers/acpi/tables.c Wed Jul 18 13:56:21 2007 +0100
+++ b/xen/drivers/acpi/tables.c Thu Jul 19 13:29:01 2007 +0800
@@ -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 e1f74a5a09cb xen/include/asm-x86/acpi.h
--- a/xen/include/asm-x86/acpi.h Wed Jul 18 13:56:21 2007 +0100
+++ b/xen/include/asm-x86/acpi.h Thu Jul 19 13:29:01 2007 +0800
@@ -173,14 +173,29 @@ extern unsigned long acpi_wakeup_address
/* early initialization routine */
extern void acpi_reserve_bootmem(void);
+#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 struct acpi_sleep_info acpi_sinfo;
extern unsigned long acpi_video_flags;
extern unsigned long saved_videomode;
-struct xenpf_set_acpi_sleep;
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);
+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[];
diff -r e1f74a5a09cb xen/include/public/platform.h
--- a/xen/include/public/platform.h Wed Jul 18 13:56:21 2007 +0100
+++ b/xen/include/public/platform.h Thu Jul 19 13:29:01 2007 +0800
@@ -153,20 +153,7 @@ 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;
@@ -189,7 +176,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 e1f74a5a09cb xen/include/xen/acpi.h
--- a/xen/include/xen/acpi.h Wed Jul 18 13:56:21 2007 +0100
+++ b/xen/include/xen/acpi.h Thu Jul 19 13:29:01 2007 +0800
@@ -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*/
acpi_sx_info.patch
Description: acpi_sx_info.patch
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|