acpi: set correct address of the control/event blocks in the FADT
authorRoger Pau Monne <roger.pau@citrix.com>
Tue, 29 Aug 2017 08:50:24 +0000 (09:50 +0100)
committerWei Liu <wei.liu2@citrix.com>
Tue, 29 Aug 2017 09:42:16 +0000 (10:42 +0100)
Commit 149c6b unmasked an issue long present in Xen: the control/event
block addresses provided in the ACPI FADT table where hardcoded to the
V1 version. This was papered over because hvmloader would also always
set HVM_PARAM_ACPI_IOPORTS_LOCATION to 1 regardless of the BIOS
version.

The most notable issue caused by the above bug was that the QEMU
traditional GPE0 block was out of sync: the address provided in the
FADT didn't match the address QEMU was using.

Note that PM1a and TMR worked fine because the V1 address was
hardcoded in the FADT and HVM_PARAM_ACPI_IOPORTS_LOCATION was
unconditionally set to 1 by hvmloader.

Fix this by passing the address of the control/event blocks to
acpi_build_tables, so the values can be properly set in the FADT table
provided to the guest.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
tools/firmware/hvmloader/ovmf.c
tools/firmware/hvmloader/rombios.c
tools/firmware/hvmloader/seabios.c
tools/firmware/hvmloader/util.c
tools/libacpi/build.c
tools/libacpi/libacpi.h

index 17bd0fe95f38c6ee7b8e79dcdd337f8095b0c0bf..64806b67641d178797a635cc08743c38c9470713 100644 (file)
@@ -121,7 +121,12 @@ static void ovmf_acpi_build_tables(void)
         .dsdt_anycpu = dsdt_anycpu_qemu_xen,
         .dsdt_anycpu_len = dsdt_anycpu_qemu_xen_len,
         .dsdt_15cpu = NULL, 
-        .dsdt_15cpu_len = 0
+        .dsdt_15cpu_len = 0,
+        .pm1a_evt = ACPI_PM1A_EVT_BLK_ADDRESS_V1,
+        .pm1a_cnt = ACPI_PM1A_CNT_BLK_ADDRESS_V1,
+        .pm_tmr = ACPI_PM_TMR_BLK_ADDRESS_V1,
+        .gpe0 = ACPI_GPE0_BLK_ADDRESS_V1,
+        .gpe0_len = ACPI_GPE0_BLK_LEN_V1,
     };
 
     hvm_param_set(HVM_PARAM_ACPI_IOPORTS_LOCATION, 1);
index b14d1f2af3f82829c5a296c644a6730ed560126e..9591bbb0aa1858467eee09cc81d5c6e5ee94aa2a 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <libacpi.h>
 #include <xen/hvm/params.h>
+#include <xen/hvm/ioreq.h>
 
 #define ROM_INCLUDE_ROMBIOS
 #define ROM_INCLUDE_VGABIOS
@@ -176,6 +177,11 @@ static void rombios_acpi_build_tables(void)
         .dsdt_anycpu_len = dsdt_anycpu_len,
         .dsdt_15cpu = dsdt_15cpu,
         .dsdt_15cpu_len = dsdt_15cpu_len,
+        .pm1a_evt = ACPI_PM1A_EVT_BLK_ADDRESS_V0,
+        .pm1a_cnt = ACPI_PM1A_CNT_BLK_ADDRESS_V0,
+        .pm_tmr = ACPI_PM_TMR_BLK_ADDRESS_V0,
+        .gpe0 = ACPI_GPE0_BLK_ADDRESS_V0,
+        .gpe0_len = ACPI_GPE0_BLK_LEN_V0,
     };
 
     hvm_param_set(HVM_PARAM_ACPI_IOPORTS_LOCATION, 0);
index c8792cd42b49df70312278d2f0435f664427d70c..0375407ca7f4777a39df3cfd1938cbe39b789a87 100644 (file)
@@ -95,6 +95,11 @@ static void seabios_acpi_build_tables(void)
         .dsdt_anycpu_len = dsdt_anycpu_qemu_xen_len,
         .dsdt_15cpu = NULL,
         .dsdt_15cpu_len = 0,
+        .pm1a_evt = ACPI_PM1A_EVT_BLK_ADDRESS_V1,
+        .pm1a_cnt = ACPI_PM1A_CNT_BLK_ADDRESS_V1,
+        .pm_tmr = ACPI_PM_TMR_BLK_ADDRESS_V1,
+        .gpe0 = ACPI_GPE0_BLK_ADDRESS_V1,
+        .gpe0_len = ACPI_GPE0_BLK_LEN_V1,
     };
 
     hvm_param_set(HVM_PARAM_ACPI_IOPORTS_LOCATION, 1);
index 934b566a5dbb7f360d7cda14ae6c07eb5129129c..82171252a1fc5a6c4f04c52a1d92680beb47198a 100644 (file)
@@ -905,6 +905,11 @@ void hvmloader_acpi_build_tables(struct acpi_config *config,
         config->dsdt_anycpu_len = dsdt_anycpu_len;
         config->dsdt_15cpu = dsdt_15cpu;
         config->dsdt_15cpu_len = dsdt_15cpu_len;
+        config->pm1a_evt = ACPI_PM1A_EVT_BLK_ADDRESS_V0;
+        config->pm1a_cnt = ACPI_PM1A_CNT_BLK_ADDRESS_V0;
+        config->pm_tmr = ACPI_PM_TMR_BLK_ADDRESS_V0;
+        config->gpe0 = ACPI_GPE0_BLK_ADDRESS_V0;
+        config->gpe0_len = ACPI_GPE0_BLK_LEN_V0;
 
         hvm_param_set(HVM_PARAM_ACPI_IOPORTS_LOCATION, 0);
     }
@@ -914,6 +919,11 @@ void hvmloader_acpi_build_tables(struct acpi_config *config,
         config->dsdt_anycpu_len = dsdt_anycpu_qemu_xen_len;
         config->dsdt_15cpu = NULL;
         config->dsdt_15cpu_len = 0;
+        config->pm1a_evt = ACPI_PM1A_EVT_BLK_ADDRESS_V1;
+        config->pm1a_cnt = ACPI_PM1A_CNT_BLK_ADDRESS_V1;
+        config->pm_tmr = ACPI_PM_TMR_BLK_ADDRESS_V1;
+        config->gpe0 = ACPI_GPE0_BLK_ADDRESS_V1;
+        config->gpe0_len = ACPI_GPE0_BLK_LEN_V1;
 
         hvm_param_set(HVM_PARAM_ACPI_IOPORTS_LOCATION, 1);
     }
index f9881c96047ffa1a7f1ffd5eb65e424d5b5baca3..50242f34c598ba607106179d9b88b84853d74380 100644 (file)
@@ -536,6 +536,15 @@ int acpi_build_tables(struct acpi_ctxt *ctxt, struct acpi_config *config)
         acpi_info->pci_hi_len = config->pci_hi_len;
     }
 
+    /*
+     * Set location of the control/event registers.
+     */
+    Fadt.pm1a_evt_blk = config->pm1a_evt;
+    Fadt.pm1a_cnt_blk = config->pm1a_cnt;
+    Fadt.pm_tmr_blk = config->pm_tmr;
+    Fadt.gpe0_blk = config->gpe0;
+    Fadt.gpe0_blk_len = config->gpe0_len;
+
     /*
      * Fill in high-memory data structures, starting at @buf.
      */
index 2ed1ecfc8e3a88fe3ad362486ba5a44829a3bc8c..2c56fb764603210f53d8c18d46176b913db7aa50 100644 (file)
@@ -96,6 +96,13 @@ struct acpi_config {
     uint32_t ioapic_base_address;
     uint16_t pci_isa_irq_mask;
     uint8_t ioapic_id;
+
+    /* Location of the control/event registers */
+    uint32_t pm1a_evt;
+    uint32_t pm1a_cnt;
+    uint32_t pm_tmr;
+    uint32_t gpe0;
+    uint8_t gpe0_len;
 };
 
 int acpi_build_tables(struct acpi_ctxt *ctxt, struct acpi_config *config);