[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 1/4] ACPI sleep info and interface


  • To: "Keir Fraser" <keir@xxxxxxxxxxxxx>
  • From: "Tian, Kevin" <kevin.tian@xxxxxxxxx>
  • Date: Thu, 19 Jul 2007 18:02:40 +0800
  • Cc: xen-devel@xxxxxxxxxxxxxxxxxxx
  • Delivery-date: Thu, 19 Jul 2007 03:00:33 -0700
  • List-id: Xen developer discussion <xen-devel.lists.xensource.com>
  • Thread-index: AcfJ6/EfRrK+LYWqRo+BOP7gkJXlxA==
  • Thread-topic: [PATCH 1/4] ACPI sleep info and interface

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*/

Attachment: acpi_sx_info.patch
Description: acpi_sx_info.patch

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

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