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

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



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


 


Rackspace

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