[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.