[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH V2 3/3] 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 | 97 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 80 insertions(+), 17 deletions(-) diff --git a/hw/piix4acpi.c b/hw/piix4acpi.c index 1efa77d..589d4a4 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,34 @@ 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_INFO, "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); + } return 0; } @@ -172,6 +199,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 +207,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 +432,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 +447,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 +464,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 +477,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 +500,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 +509,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 +614,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 +766,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 +774,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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |