WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] [host s3] Retrieve necessary sleep inform

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [host s3] Retrieve necessary sleep information from plain-text ACPI
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 27 Jul 2007 03:12:05 -0700
Delivery-date: Fri, 27 Jul 2007 03:10:07 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [host s3] Retrieve necessary sleep information from plain-text ACPI, Xen patchbot-unstable <=