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-devel

[Xen-devel] [PATCH 2/2] piix4acpi: change in ACPI to match the change in

To: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>, Xen Devel <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH 2/2] piix4acpi: change in ACPI to match the change in the BIOS.
From: anthony.perard@xxxxxxxxxx
Date: Tue, 9 Nov 2010 15:34:10 +0000
Cc: anthony.perard@xxxxxxxxxx
Delivery-date: Tue, 09 Nov 2010 07:36:35 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <19672.13711.636862.918627@xxxxxxxxxxxxxxxxxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <19672.13711.636862.918627@xxxxxxxxxxxxxxxxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
From: Anthony PERARD <anthony.perard@xxxxxxxxxx>

Some change have been introduced in the firmware to match QEMU's BIOS.
So this patch adds the new sleep state values and handle old and new
ACPI IOPort mapping.

QEMU-Xen uses new ioport by default, but if it's a saved state with old
firmware, it unmaps the new ioport and maps the old one.

Signed-off-by: Anthony PERARD <anthony.perard@xxxxxxxxxx>
---
 hw/piix4acpi.c |  121 +++++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 94 insertions(+), 27 deletions(-)

diff --git a/hw/piix4acpi.c b/hw/piix4acpi.c
index 1efa77d..fb1e5c3 100644
--- a/hw/piix4acpi.c
+++ b/hw/piix4acpi.c
@@ -52,9 +52,12 @@
 
 /* Sleep state type codes as defined by the \_Sx objects in the DSDT. */
 /* These must be kept in sync with the DSDT (hvmloader/acpi/dsdt.asl) */
-#define SLP_TYP_S4        (6 << 10)
-#define SLP_TYP_S3        (5 << 10)
-#define SLP_TYP_S5        (7 << 10)
+#define SLP_TYP_S4_V0     (6 << 10)
+#define SLP_TYP_S3_V0     (5 << 10)
+#define SLP_TYP_S5_V0     (7 << 10)
+#define SLP_TYP_S4_V1     (0 << 10)
+#define SLP_TYP_S3_V1     (1 << 10)
+#define SLP_TYP_S5_V1     (0 << 10)
 
 #define ACPI_DBG_IO_ADDR  0xb044
 #define ACPI_PHP_IO_ADDR  0x10c0
@@ -75,12 +78,14 @@
 typedef struct PCIAcpiState {
     PCIDevice dev;
     uint16_t pm1_control; /* pm1a_ECNT_BLK */
+
+    uint32_t pm1a_evt_blk_address;
 } PCIAcpiState;
 
 typedef struct GPEState {
     /* GPE0 block */
-    uint8_t gpe0_sts[ACPI_GPE0_BLK_LEN / 2];
-    uint8_t gpe0_en[ACPI_GPE0_BLK_LEN / 2];
+    uint8_t gpe0_sts[ACPI_GPE0_BLK_LEN_V0 / 2];
+    uint8_t gpe0_en[ACPI_GPE0_BLK_LEN_V0 / 2];
 
     /* CPU bitmap */
     uint8_t cpus_sts[32];
@@ -88,6 +93,8 @@ typedef struct GPEState {
     /* SCI IRQ level */
     uint8_t sci_asserted;
 
+    uint32_t gpe0_blk_address;
+    uint32_t gpe0_blk_half_len;
 } GPEState;
 
 static GPEState gpe_state;
@@ -100,6 +107,9 @@ typedef struct PHPDevFn {
                                       * PSTB in ASL */
 } PHPDevFn;
 
+static void acpi_map(PCIDevice *pci_dev, int region_num,
+                     uint32_t addr, uint32_t size, int type);
+
 static PHPDevFn php_devfn;
 int s3_shutdown_flag;
 static qemu_irq sci_irq;
@@ -138,18 +148,36 @@ static void piix4acpi_save(QEMUFile *f, void *opaque)
     PCIAcpiState *s = opaque;
     pci_device_save(&s->dev, f);
     qemu_put_be16s(f, &s->pm1_control);
+    qemu_put_be32s(f, &s->pm1a_evt_blk_address);
 }
 
 static int piix4acpi_load(QEMUFile *f, void *opaque, int version_id)
 {
     PCIAcpiState *s = opaque;
     int ret;
-    if (version_id > 1) 
+    uint32_t pm1a_evt_address_assigned;
+
+    if (version_id > 2)
         return -EINVAL;
     ret = pci_device_load(&s->dev, f);
     if (ret < 0)
         return ret;
     qemu_get_be16s(f, &s->pm1_control);
+
+    pm1a_evt_address_assigned = s->pm1a_evt_blk_address;
+    if (version_id <= 1) {
+        /* map to old ioport instead of the new one */
+        s->pm1a_evt_blk_address = ACPI_PM1A_EVT_BLK_ADDRESS_V0;
+    } else {
+        qemu_get_be32s(f, &s->pm1a_evt_blk_address);
+    }
+
+    if (s->pm1a_evt_blk_address != pm1a_evt_address_assigned) {
+        PIIX4ACPI_LOG(PIIX4ACPI_LOG_DEBUG, "ACPI: Change firmware IOPorts 
mapping.\n");
+        /* unmap new ioport to use old ioport */
+        isa_unassign_ioport(pm1a_evt_address_assigned + 4, 2);
+        acpi_map((PCIDevice *)s, 0, s->pm1a_evt_blk_address, 0x10, 
PCI_ADDRESS_SPACE_IO);
+    }
     return 0;
 }
 
@@ -172,15 +200,17 @@ static void acpi_shutdown(uint32_t val)
         return;
 
     switch (val & SLP_TYP_Sx) {
-    case SLP_TYP_S3:
+    case SLP_TYP_S3_V0:
+    case SLP_TYP_S3_V1:
         s3_shutdown_flag = 1;
         qemu_system_reset();
         s3_shutdown_flag = 0;
         cmos_set_s3_resume();
         xc_set_hvm_param(xc_handle, domid, HVM_PARAM_ACPI_S_STATE, 3);
         break;
-    case SLP_TYP_S4:
-    case SLP_TYP_S5:
+    case SLP_TYP_S4_V0:
+    case SLP_TYP_S5_V0:
+    case SLP_TYP_S5_V1:
         qemu_system_shutdown_request();
         break;
     default:
@@ -403,7 +433,7 @@ static uint32_t gpe_sts_read(void *opaque, uint32_t addr)
 {
     GPEState *s = opaque;
 
-    return s->gpe0_sts[addr - ACPI_GPE0_BLK_ADDRESS];
+    return s->gpe0_sts[addr - s->gpe0_blk_address];
 }
 
 /* write 1 to clear specific GPE bits */
@@ -415,7 +445,7 @@ static void gpe_sts_write(void *opaque, uint32_t addr, 
uint32_t val)
     PIIX4ACPI_LOG(PIIX4ACPI_LOG_DEBUG, "gpe_sts_write: addr=0x%x, 
val=0x%x.\n", addr, val);
 
     hotplugged = test_bit(&s->gpe0_sts[0], ACPI_PHP_GPE_BIT);
-    s->gpe0_sts[addr - ACPI_GPE0_BLK_ADDRESS] &= ~val;
+    s->gpe0_sts[addr - s->gpe0_blk_address] &= ~val;
     if ( s->sci_asserted &&
          hotplugged &&
          !test_bit(&s->gpe0_sts[0], ACPI_PHP_GPE_BIT)) {
@@ -429,7 +459,7 @@ static uint32_t gpe_en_read(void *opaque, uint32_t addr)
 {
     GPEState *s = opaque;
 
-    return s->gpe0_en[addr - (ACPI_GPE0_BLK_ADDRESS + ACPI_GPE0_BLK_LEN / 2)];
+    return s->gpe0_en[addr - (s->gpe0_blk_address + s->gpe0_blk_half_len)];
 }
 
 /* write 0 to clear en bit */
@@ -439,7 +469,7 @@ static void gpe_en_write(void *opaque, uint32_t addr, 
uint32_t val)
     int reg_count;
 
     PIIX4ACPI_LOG(PIIX4ACPI_LOG_DEBUG, "gpe_en_write: addr=0x%x, val=0x%x.\n", 
addr, val);
-    reg_count = addr - (ACPI_GPE0_BLK_ADDRESS + ACPI_GPE0_BLK_LEN / 2);
+    reg_count = addr - (s->gpe0_blk_address + s->gpe0_blk_half_len);
     s->gpe0_en[reg_count] = val;
     /* If disable GPE bit right after generating SCI on it, 
      * need deassert the intr to avoid redundant intrs
@@ -459,7 +489,7 @@ static void gpe_save(QEMUFile* f, void* opaque)
     GPEState *s = (GPEState*)opaque;
     int i;
 
-    for ( i = 0; i < ACPI_GPE0_BLK_LEN / 2; i++ ) {
+    for ( i = 0; i < ACPI_GPE0_BLK_LEN_V0 / 2; i++ ) {
         qemu_put_8s(f, &s->gpe0_sts[i]);
         qemu_put_8s(f, &s->gpe0_en[i]);
     }
@@ -468,21 +498,54 @@ static void gpe_save(QEMUFile* f, void* opaque)
     if ( s->sci_asserted ) {
         PIIX4ACPI_LOG(PIIX4ACPI_LOG_INFO, "gpe_save with sci asserted!\n");
     }
+
+    qemu_put_be32s(f, &s->gpe0_blk_address);
+    qemu_put_be32s(f, &s->gpe0_blk_half_len);
 }
 
 static int gpe_load(QEMUFile* f, void* opaque, int version_id)
 {
     GPEState *s = (GPEState*)opaque;
     int i;
-    if (version_id != 1)
+    uint32_t gpe0_addr_assigned;
+    uint32_t gpe0_half_len_assigned;
+
+    if (version_id > 2)
         return -EINVAL;
 
-    for ( i = 0; i < ACPI_GPE0_BLK_LEN / 2; i++ ) {
+    for ( i = 0; i < ACPI_GPE0_BLK_LEN_V0 / 2; i++ ) {
         qemu_get_8s(f, &s->gpe0_sts[i]);
         qemu_get_8s(f, &s->gpe0_en[i]);
     }
 
     qemu_get_8s(f, &s->sci_asserted);
+
+    gpe0_addr_assigned = s->gpe0_blk_address;
+    gpe0_half_len_assigned = s->gpe0_blk_half_len;
+
+    if (version_id <= 1) {
+        s->gpe0_blk_address = ACPI_GPE0_BLK_ADDRESS_V0;
+        s->gpe0_blk_half_len = ACPI_GPE0_BLK_LEN_V0 / 2;
+    } else {
+        qemu_get_be32s(f, &s->gpe0_blk_address);
+        qemu_get_be32s(f, &s->gpe0_blk_half_len);
+    }
+
+    if (gpe0_addr_assigned != s->gpe0_blk_address ||
+        gpe0_half_len_assigned != s->gpe0_blk_half_len) {
+        isa_unassign_ioport(gpe0_addr_assigned, gpe0_half_len_assigned * 2);
+
+        register_ioport_read(s->gpe0_blk_address, s->gpe0_blk_half_len,
+                             1, gpe_sts_read, s);
+        register_ioport_read(s->gpe0_blk_address + s->gpe0_blk_half_len,
+                             s->gpe0_blk_half_len, 1, gpe_en_read, s);
+
+        register_ioport_write(s->gpe0_blk_address, s->gpe0_blk_half_len,
+                              1, gpe_sts_write, s);
+        register_ioport_write(s->gpe0_blk_address + s->gpe0_blk_half_len,
+                              s->gpe0_blk_half_len, 1, gpe_en_write, s);
+    }
+
     return 0;
 }
 
@@ -529,29 +592,32 @@ static void gpe_acpi_init(void)
     register_ioport_read(PROC_BASE, 32, 1,  gpe_cpus_readb, s);
     register_ioport_write(PROC_BASE, 32, 1, gpe_cpus_writeb, s);
 
-    register_ioport_read(ACPI_GPE0_BLK_ADDRESS,
-                         ACPI_GPE0_BLK_LEN / 2,
+    s->gpe0_blk_address = ACPI_GPE0_BLK_ADDRESS_V1;
+    s->gpe0_blk_half_len = ACPI_GPE0_BLK_LEN_V1 / 2;
+
+    register_ioport_read(s->gpe0_blk_address,
+                         s->gpe0_blk_half_len,
                          1,
                          gpe_sts_read,
                          s);
-    register_ioport_read(ACPI_GPE0_BLK_ADDRESS + ACPI_GPE0_BLK_LEN / 2,
-                         ACPI_GPE0_BLK_LEN / 2,
+    register_ioport_read(s->gpe0_blk_address + s->gpe0_blk_half_len,
+                         s->gpe0_blk_half_len,
                          1,
                          gpe_en_read,
                          s);
 
-    register_ioport_write(ACPI_GPE0_BLK_ADDRESS,
-                          ACPI_GPE0_BLK_LEN / 2,
+    register_ioport_write(s->gpe0_blk_address,
+                          s->gpe0_blk_half_len,
                           1,
                           gpe_sts_write,
                           s);
-    register_ioport_write(ACPI_GPE0_BLK_ADDRESS + ACPI_GPE0_BLK_LEN / 2,
-                          ACPI_GPE0_BLK_LEN / 2,
+    register_ioport_write(s->gpe0_blk_address + s->gpe0_blk_half_len,
+                          s->gpe0_blk_half_len,
                           1,
                           gpe_en_write,
                           s);
 
-    register_savevm("gpe", 0, 1, gpe_save, gpe_load, s);
+    register_savevm("gpe", 0, 2, gpe_save, gpe_load, s);
 }
 
 #ifdef CONFIG_PASSTHROUGH
@@ -703,7 +769,8 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t 
smb_io_base,
     pci_conf[0x43] = 0x00;
     d->pm1_control = SCI_EN;
 
-    acpi_map((PCIDevice *)d, 0, 0x1f40, 0x10, PCI_ADDRESS_SPACE_IO);
+    d->pm1a_evt_blk_address = ACPI_PM1A_EVT_BLK_ADDRESS_V1;
+    acpi_map((PCIDevice *)d, 0, d->pm1a_evt_blk_address, 0x10, 
PCI_ADDRESS_SPACE_IO);
 
     gpe_acpi_init();
 #ifdef CONFIG_PASSTHROUGH
@@ -711,7 +778,7 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t 
smb_io_base,
 #endif
     register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, d);
 
-    register_savevm("piix4acpi", 0, 1, piix4acpi_save, piix4acpi_load, d);
+    register_savevm("piix4acpi", 0, 2, piix4acpi_save, piix4acpi_load, d);
 
     return NULL;
 }
-- 
1.7.1


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