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

[Xen-devel] [PATCH V3 6/6] 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 |   99 ++++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 82 insertions(+), 17 deletions(-)

diff --git a/hw/piix4acpi.c b/hw/piix4acpi.c
index 1efa77d..92e728e 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_OLD    (6 << 10)
+#define SLP_TYP_S3_OLD    (5 << 10)
+#define SLP_TYP_S5_OLD    (7 << 10)
+#define SLP_TYP_S4        (0 << 10)
+#define SLP_TYP_S3        (1 << 10)
+#define SLP_TYP_S5        (0 << 10)
 
 #define ACPI_DBG_IO_ADDR  0xb044
 #define ACPI_PHP_IO_ADDR  0x10c0
@@ -75,12 +78,15 @@
 typedef struct PCIAcpiState {
     PCIDevice dev;
     uint16_t pm1_control; /* pm1a_ECNT_BLK */
+
+    /* if true, use old ioport of the firmware. */
+    uint8_t use_old_ioport;
 } 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_OLD / 2];
+    uint8_t gpe0_en[ACPI_GPE0_BLK_LEN_OLD / 2];
 
     /* CPU bitmap */
     uint8_t cpus_sts[32];
@@ -88,6 +94,8 @@ typedef struct GPEState {
     /* SCI IRQ level */
     uint8_t sci_asserted;
 
+    /* if true, use old ioport of the firmware. */
+    uint8_t use_old_ioport;
 } GPEState;
 
 static GPEState gpe_state;
@@ -100,6 +108,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 +149,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_8s(f, &s->use_old_ioport);
 }
 
 static int piix4acpi_load(QEMUFile *f, void *opaque, int version_id)
 {
     PCIAcpiState *s = opaque;
     int ret;
-    if (version_id > 1) 
+
+    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);
+
+    if (version_id <= 1) {
+        /* map to old ioport instead of the new one */
+        s->use_old_ioport = 1;
+    } else {
+        qemu_get_8s(f, &s->use_old_ioport);
+    }
+
+    if (s->use_old_ioport) {
+        PIIX4ACPI_LOG(PIIX4ACPI_LOG_DEBUG, "ACPI: Use old firmware 
IOPorts.\n");
+        /* unmap new ioport to use old ioport */
+        isa_unassign_ioport(ACPI_PM1A_EVT_BLK_ADDRESS + 4, 2);
+        acpi_map((PCIDevice *)s, 0, ACPI_PM1A_EVT_BLK_ADDRESS_OLD, 0x10, 
PCI_ADDRESS_SPACE_IO);
+    } else {
+        PIIX4ACPI_LOG(PIIX4ACPI_LOG_DEBUG, "ACPI: Keep new firmware 
IOPorts.\n");
+    }
     return 0;
 }
 
@@ -172,6 +201,7 @@ static void acpi_shutdown(uint32_t val)
         return;
 
     switch (val & SLP_TYP_Sx) {
+    case SLP_TYP_S3_OLD:
     case SLP_TYP_S3:
         s3_shutdown_flag = 1;
         qemu_system_reset();
@@ -179,7 +209,8 @@ static void acpi_shutdown(uint32_t val)
         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_S4_OLD:
+    case SLP_TYP_S5_OLD:
     case SLP_TYP_S5:
         qemu_system_shutdown_request();
         break;
@@ -403,7 +434,10 @@ static uint32_t gpe_sts_read(void *opaque, uint32_t addr)
 {
     GPEState *s = opaque;
 
-    return s->gpe0_sts[addr - ACPI_GPE0_BLK_ADDRESS];
+    if (s->use_old_ioport)
+        return s->gpe0_sts[addr - ACPI_GPE0_BLK_ADDRESS_OLD];
+    else
+        return s->gpe0_sts[addr - ACPI_GPE0_BLK_ADDRESS];
 }
 
 /* write 1 to clear specific GPE bits */
@@ -415,7 +449,10 @@ 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;
+    if (s->use_old_ioport)
+        s->gpe0_sts[addr - ACPI_GPE0_BLK_ADDRESS_OLD] &= ~val;
+    else
+        s->gpe0_sts[addr - ACPI_GPE0_BLK_ADDRESS] &= ~val;
     if ( s->sci_asserted &&
          hotplugged &&
          !test_bit(&s->gpe0_sts[0], ACPI_PHP_GPE_BIT)) {
@@ -429,7 +466,10 @@ 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)];
+    if (s->use_old_ioport)
+        return s->gpe0_en[addr - (ACPI_GPE0_BLK_ADDRESS_OLD + 
ACPI_GPE0_BLK_LEN_OLD / 2)];
+    else
+        return s->gpe0_en[addr - (ACPI_GPE0_BLK_ADDRESS + ACPI_GPE0_BLK_LEN / 
2)];
 }
 
 /* write 0 to clear en bit */
@@ -439,7 +479,10 @@ 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);
+    if (s->use_old_ioport)
+        reg_count = addr - (ACPI_GPE0_BLK_ADDRESS_OLD + ACPI_GPE0_BLK_LEN_OLD 
/ 2);
+    else
+        reg_count = addr - (ACPI_GPE0_BLK_ADDRESS + ACPI_GPE0_BLK_LEN / 2);
     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 +502,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_OLD / 2; i++ ) {
         qemu_put_8s(f, &s->gpe0_sts[i]);
         qemu_put_8s(f, &s->gpe0_en[i]);
     }
@@ -468,21 +511,43 @@ 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_8s(f, &s->use_old_ioport);
 }
 
 static int gpe_load(QEMUFile* f, void* opaque, int version_id)
 {
     GPEState *s = (GPEState*)opaque;
     int i;
-    if (version_id != 1)
+    if (version_id > 2)
         return -EINVAL;
 
-    for ( i = 0; i < ACPI_GPE0_BLK_LEN / 2; i++ ) {
+    for ( i = 0; i < ACPI_GPE0_BLK_LEN_OLD / 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);
+
+    if (version_id <= 1) {
+        s->use_old_ioport = 1;
+    } else {
+        qemu_get_8s(f, &s->use_old_ioport);
+    }
+
+    if (s->use_old_ioport) {
+        isa_unassign_ioport(ACPI_GPE0_BLK_ADDRESS, ACPI_GPE0_BLK_LEN);
+
+        register_ioport_read(ACPI_GPE0_BLK_ADDRESS_OLD, ACPI_GPE0_BLK_LEN_OLD 
/ 2,
+                             1, gpe_sts_read, s);
+        register_ioport_read(ACPI_GPE0_BLK_ADDRESS_OLD + ACPI_GPE0_BLK_LEN_OLD 
/ 2,
+                             ACPI_GPE0_BLK_LEN_OLD / 2, 1, gpe_en_read, s);
+        register_ioport_write(ACPI_GPE0_BLK_ADDRESS_OLD, ACPI_GPE0_BLK_LEN_OLD 
/ 2,
+                              1, gpe_sts_write, s);
+        register_ioport_write(ACPI_GPE0_BLK_ADDRESS_OLD + 
ACPI_GPE0_BLK_LEN_OLD / 2,
+                              ACPI_GPE0_BLK_LEN_OLD / 2, 1, gpe_en_write, s);
+    }
+
     return 0;
 }
 
@@ -551,7 +616,7 @@ static void gpe_acpi_init(void)
                           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 +768,7 @@ 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);
+    acpi_map((PCIDevice *)d, 0, ACPI_PM1A_EVT_BLK_ADDRESS, 0x10, 
PCI_ADDRESS_SPACE_IO);
 
     gpe_acpi_init();
 #ifdef CONFIG_PASSTHROUGH
@@ -711,7 +776,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®.