All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v3 00/19] ACPI reorganization for hardware-reduced support
@ 2018-10-29 17:01 Samuel Ortiz
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 01/19] hw: i386: Decouple the ACPI build from the PC machine type Samuel Ortiz
                   ` (19 more replies)
  0 siblings, 20 replies; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-29 17:01 UTC (permalink / raw)
  To: qemu-devel

This patch set provides an ACPI code reorganization in preparation for
adding hardware-reduced support to QEMU.

The changes are coming from the NEMU [1] project where we're defining
a new x86 machine type: i386/virt. This is an EFI only, ACPI
hardware-reduced platform and as such we had to implement support
for the latter.

As a preliminary for adding hardware-reduced support to QEMU, we did
some ACPI code reorganization with the following goals:

* Share as much as possible of the current ACPI build APIs between
  legacy and hardware-reduced ACPI.
* Share the ACPI build code across machine types and architectures and
  remove the typical PC machine type dependency.
  Eventually we hope to see arm/virt also re-use much of that code.

The patches are also available in their own git branch [2].

[1] https://github.com/intel/nemu
[2] https://github.com/intel/nemu/tree/topic/upstream/acpi

v1 -> v2:
   * Drop the hardware-reduced implementation for now. Our next patch set
     will add hardware-reduced and convert arm/virt to it.
   * Implement the ACPI build methods as a QOM Interface Class and convert
     the PC machine type to it.
   * acpi_conf_pc_init() uses a PCMachineState pointer and not a
     MachineState one as its argument.

v2 -> v3:
   * Cc all relevant maintainers, no functional changes.

Samuel Ortiz (10):
  hw: i386: Decouple the ACPI build from the PC machine type
  hw: acpi: Export ACPI build alignment API
  hw: acpi: Export the RSDP build API
  hw: acpi: Implement XSDT support for RSDP
  hw: arm: Switch to the AML build RSDP building routine
  hw: acpi: Do not create hotplug method when handler is not defined
  hw: i386: Make the hotpluggable memory size property more generic
  hw: acpi: Define ACPI tables builder interface
  hw: i386: Export the MADT build method
  hw: i386: Implement the ACPI builder interface for PC

Sebastien Boeuf (2):
  hw: acpi: Export the PCI hotplug API
  hw: acpi: Retrieve the PCI bus from AcpiPciHpState

Yang Zhong (7):
  hw: acpi: Generalize AML build routines
  hw: acpi: Factorize _OSC AML across architectures
  hw: i386: Refactor PCI host getter
  hw: acpi: Export and generalize the PCI host AML API
  hw: acpi: Export the MCFG getter
  hw: acpi: Export the SRAT AML build API
  hw: acpi: Fix memory hotplug AML generation error

 hw/acpi/Makefile.objs          |    1 +
 hw/acpi/aml-build.c            | 1129 ++++++++++++++++++++++++++++++
 hw/acpi/builder.c              |   97 +++
 hw/acpi/cpu.c                  |    8 +-
 hw/acpi/cpu_hotplug.c          |    9 +-
 hw/acpi/memory_hotplug.c       |   21 +-
 hw/acpi/pcihp.c                |   10 +-
 hw/arm/virt-acpi-build.c       |   98 +--
 hw/i386/acpi-build.c           | 1174 ++------------------------------
 hw/i386/acpi-build.h           |    4 +-
 hw/i386/pc.c                   |  197 ++++--
 hw/i386/pc_piix.c              |   21 +-
 hw/i386/pc_q35.c               |   21 +-
 hw/i386/xen/xen-hvm.c          |   19 +-
 hw/pci-host/piix.c             |    8 -
 include/hw/acpi/acpi-defs.h    |   14 +
 include/hw/acpi/acpi.h         |   43 ++
 include/hw/acpi/aml-build.h    |   50 ++
 include/hw/acpi/builder.h      |   97 +++
 include/hw/i386/acpi.h         |   27 +
 include/hw/i386/pc.h           |   21 +-
 include/hw/mem/memory-device.h |    2 +
 stubs/Makefile.objs            |    1 -
 stubs/pci-host-piix.c          |    6 -
 24 files changed, 1734 insertions(+), 1344 deletions(-)
 create mode 100644 hw/acpi/builder.c
 create mode 100644 include/hw/acpi/builder.h
 create mode 100644 include/hw/i386/acpi.h
 delete mode 100644 stubs/pci-host-piix.c

-- 
2.17.2

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH v3 01/19] hw: i386: Decouple the ACPI build from the PC machine type
  2018-10-29 17:01 [Qemu-devel] [PATCH v3 00/19] ACPI reorganization for hardware-reduced support Samuel Ortiz
@ 2018-10-29 17:01 ` Samuel Ortiz
  2018-10-29 19:50     ` Philippe Mathieu-Daudé
  2018-10-29 17:01 ` Samuel Ortiz
                   ` (18 subsequent siblings)
  19 siblings, 1 reply; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-29 17:01 UTC (permalink / raw)
  To: qemu-devel
  Cc: Michael S. Tsirkin, Igor Mammedov, Shannon Zhao, Peter Maydell,
	Marcel Apfelbaum, Paolo Bonzini, Richard Henderson,
	Eduardo Habkost, Stefano Stabellini, Anthony Perard,
	open list:ARM ACPI Subsystem, open list:X86

ACPI tables are platform and machine type and even architecture
agnostic, and as such we want to provide an internal ACPI API that
only depends on platform agnostic information.

For the x86 architecture, in order to build ACPI tables independently
from the PC or Q35 machine types, we are moving a few MachineState
structure fields into a machine type agnostic structure called
AcpiConfiguration. The structure fields we move are:

   HotplugHandler *acpi_dev
   AcpiNVDIMMState acpi_nvdimm_state;
   FWCfgState *fw_cfg
   ram_addr_t below_4g_mem_size, above_4g_mem_size
   bool apic_xrupt_override
   unsigned apic_id_limit
   uint64_t numa_nodes
   uint64_t numa_mem

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 hw/acpi/cpu_hotplug.c    |   9 +-
 hw/arm/virt-acpi-build.c |  10 ---
 hw/i386/acpi-build.c     | 135 ++++++++++++++----------------
 hw/i386/acpi-build.h     |   4 +-
 hw/i386/pc.c             | 175 ++++++++++++++++++++++++---------------
 hw/i386/pc_piix.c        |  21 ++---
 hw/i386/pc_q35.c         |  21 ++---
 hw/i386/xen/xen-hvm.c    |  19 +++--
 include/hw/acpi/acpi.h   |  43 ++++++++++
 include/hw/i386/pc.h     |  19 ++---
 10 files changed, 254 insertions(+), 202 deletions(-)

diff --git a/hw/acpi/cpu_hotplug.c b/hw/acpi/cpu_hotplug.c
index 5243918125..634dc3b846 100644
--- a/hw/acpi/cpu_hotplug.c
+++ b/hw/acpi/cpu_hotplug.c
@@ -237,9 +237,9 @@ void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *machine,
     /* The current AML generator can cover the APIC ID range [0..255],
      * inclusive, for VCPU hotplug. */
     QEMU_BUILD_BUG_ON(ACPI_CPU_HOTPLUG_ID_LIMIT > 256);
-    if (pcms->apic_id_limit > ACPI_CPU_HOTPLUG_ID_LIMIT) {
+    if (pcms->acpi_configuration.apic_id_limit > ACPI_CPU_HOTPLUG_ID_LIMIT) {
         error_report("max_cpus is too large. APIC ID of last CPU is %u",
-                     pcms->apic_id_limit - 1);
+                     pcms->acpi_configuration.apic_id_limit - 1);
         exit(1);
     }
 
@@ -316,8 +316,9 @@ void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *machine,
      * ith up to 255 elements. Windows guests up to win2k8 fail when
      * VarPackageOp is used.
      */
-    pkg = pcms->apic_id_limit <= 255 ? aml_package(pcms->apic_id_limit) :
-                                       aml_varpackage(pcms->apic_id_limit);
+    pkg = pcms->acpi_configuration.apic_id_limit <= 255 ?
+        aml_package(pcms->acpi_configuration.apic_id_limit) :
+        aml_varpackage(pcms->acpi_configuration.apic_id_limit);
 
     for (i = 0, apic_idx = 0; i < apic_ids->len; i++) {
         int apic_id = apic_ids->cpus[i].arch_id;
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 5785fb697c..f28a2faa53 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -790,16 +790,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
     free_aml_allocator();
 }
 
-typedef
-struct AcpiBuildState {
-    /* Copy of table in RAM (for patching). */
-    MemoryRegion *table_mr;
-    MemoryRegion *rsdp_mr;
-    MemoryRegion *linker_mr;
-    /* Is table patched? */
-    bool patched;
-} AcpiBuildState;
-
 static
 void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
 {
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 1599caa7c5..c8545238c4 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -338,13 +338,14 @@ void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
 }
 
 static void
-build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms)
+build_madt(GArray *table_data, BIOSLinker *linker,
+           MachineState *ms, AcpiConfiguration *conf)
 {
-    MachineClass *mc = MACHINE_GET_CLASS(pcms);
-    const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(pcms));
+    MachineClass *mc = MACHINE_GET_CLASS(ms);
+    const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(ms);
     int madt_start = table_data->len;
-    AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(pcms->acpi_dev);
-    AcpiDeviceIf *adev = ACPI_DEVICE_IF(pcms->acpi_dev);
+    AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(conf->acpi_dev);
+    AcpiDeviceIf *adev = ACPI_DEVICE_IF(conf->acpi_dev);
     bool x2apic_mode = false;
 
     AcpiMultipleApicTable *madt;
@@ -370,7 +371,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms)
     io_apic->address = cpu_to_le32(IO_APIC_DEFAULT_ADDRESS);
     io_apic->interrupt = cpu_to_le32(0);
 
-    if (pcms->apic_xrupt_override) {
+    if (conf->apic_xrupt_override) {
         intsrcovr = acpi_data_push(table_data, sizeof *intsrcovr);
         intsrcovr->type   = ACPI_APIC_XRUPT_OVERRIDE;
         intsrcovr->length = sizeof(*intsrcovr);
@@ -1786,13 +1787,12 @@ static Aml *build_q35_osc_method(void)
 static void
 build_dsdt(GArray *table_data, BIOSLinker *linker,
            AcpiPmInfo *pm, AcpiMiscInfo *misc,
-           Range *pci_hole, Range *pci_hole64, MachineState *machine)
+           Range *pci_hole, Range *pci_hole64,
+           MachineState *machine, AcpiConfiguration *conf)
 {
     CrsRangeEntry *entry;
     Aml *dsdt, *sb_scope, *scope, *dev, *method, *field, *pkg, *crs;
     CrsRangeSet crs_range_set;
-    PCMachineState *pcms = PC_MACHINE(machine);
-    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(machine);
     uint32_t nr_mem = machine->ram_slots;
     int root_bus_limit = 0xFF;
     PCIBus *bus = NULL;
@@ -1836,7 +1836,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
         build_q35_pci0_int(dsdt);
     }
 
-    if (pcmc->legacy_cpu_hotplug) {
+    if (conf->legacy_cpu_hotplug) {
         build_legacy_cpu_hotplug_aml(dsdt, machine, pm->cpu_hp_io_base);
     } else {
         CPUHotplugFeatures opts = {
@@ -1860,7 +1860,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
             aml_append(scope, method);
         }
 
-        if (pcms->acpi_nvdimm_state.is_enabled) {
+        if (conf->acpi_nvdimm_state.is_enabled) {
             method = aml_method("_E04", 0, AML_NOTSERIALIZED);
             aml_append(method, aml_notify(aml_name("\\_SB.NVDR"),
                                           aml_int(0x80)));
@@ -2041,7 +2041,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
          * with half of the 16-bit control register. Hence, the total size
          * of the i/o region used is FW_CFG_CTL_SIZE; when using DMA, the
          * DMA control register is located at FW_CFG_DMA_IO_BASE + 4 */
-        uint8_t io_size = object_property_get_bool(OBJECT(pcms->fw_cfg),
+        uint8_t io_size = object_property_get_bool(OBJECT(conf->fw_cfg),
                                                    "dma_enabled", NULL) ?
                           ROUND_UP(FW_CFG_CTL_SIZE, 4) + sizeof(dma_addr_t) :
                           FW_CFG_CTL_SIZE;
@@ -2252,7 +2252,8 @@ build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog)
 #define HOLE_640K_END   (1 * MiB)
 
 static void
-build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
+build_srat(GArray *table_data, BIOSLinker *linker,
+           MachineState *machine, AcpiConfiguration *conf)
 {
     AcpiSystemResourceAffinityTable *srat;
     AcpiSratMemoryAffinity *numamem;
@@ -2262,9 +2263,8 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
     uint64_t mem_len, mem_base, next_base;
     MachineClass *mc = MACHINE_GET_CLASS(machine);
     const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(machine);
-    PCMachineState *pcms = PC_MACHINE(machine);
     ram_addr_t hotplugabble_address_space_size =
-        object_property_get_int(OBJECT(pcms), PC_MACHINE_DEVMEM_REGION_SIZE,
+        object_property_get_int(OBJECT(machine), PC_MACHINE_DEVMEM_REGION_SIZE,
                                 NULL);
 
     srat_start = table_data->len;
@@ -2306,9 +2306,9 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
     next_base = 0;
     numa_start = table_data->len;
 
-    for (i = 1; i < pcms->numa_nodes + 1; ++i) {
+    for (i = 1; i < conf->numa_nodes + 1; ++i) {
         mem_base = next_base;
-        mem_len = pcms->node_mem[i - 1];
+        mem_len = conf->node_mem[i - 1];
         next_base = mem_base + mem_len;
 
         /* Cut out the 640K hole */
@@ -2331,16 +2331,16 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
         }
 
         /* Cut out the ACPI_PCI hole */
-        if (mem_base <= pcms->below_4g_mem_size &&
-            next_base > pcms->below_4g_mem_size) {
-            mem_len -= next_base - pcms->below_4g_mem_size;
+        if (mem_base <= conf->below_4g_mem_size &&
+            next_base > conf->below_4g_mem_size) {
+            mem_len -= next_base - conf->below_4g_mem_size;
             if (mem_len > 0) {
                 numamem = acpi_data_push(table_data, sizeof *numamem);
                 build_srat_memory(numamem, mem_base, mem_len, i - 1,
                                   MEM_AFFINITY_ENABLED);
             }
             mem_base = 1ULL << 32;
-            mem_len = next_base - pcms->below_4g_mem_size;
+            mem_len = next_base - conf->below_4g_mem_size;
             next_base = mem_base + mem_len;
         }
 
@@ -2351,7 +2351,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
         }
     }
     slots = (table_data->len - numa_start) / sizeof *numamem;
-    for (; slots < pcms->numa_nodes + 2; slots++) {
+    for (; slots < conf->numa_nodes + 2; slots++) {
         numamem = acpi_data_push(table_data, sizeof *numamem);
         build_srat_memory(numamem, 0, 0, 0, MEM_AFFINITY_NOFLAGS);
     }
@@ -2367,7 +2367,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
     if (hotplugabble_address_space_size) {
         numamem = acpi_data_push(table_data, sizeof *numamem);
         build_srat_memory(numamem, machine->device_memory->base,
-                          hotplugabble_address_space_size, pcms->numa_nodes - 1,
+                          hotplugabble_address_space_size, conf->numa_nodes - 1,
                           MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
     }
 
@@ -2546,17 +2546,6 @@ build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset)
     return rsdp_table;
 }
 
-typedef
-struct AcpiBuildState {
-    /* Copy of table in RAM (for patching). */
-    MemoryRegion *table_mr;
-    /* Is table patched? */
-    uint8_t patched;
-    void *rsdp;
-    MemoryRegion *rsdp_mr;
-    MemoryRegion *linker_mr;
-} AcpiBuildState;
-
 static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
 {
     Object *pci_host;
@@ -2580,10 +2569,9 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
 }
 
 static
-void acpi_build(AcpiBuildTables *tables, MachineState *machine)
+void acpi_build(AcpiBuildTables *tables,
+                MachineState *machine, AcpiConfiguration *conf)
 {
-    PCMachineState *pcms = PC_MACHINE(machine);
-    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
     GArray *table_offsets;
     unsigned facs, dsdt, rsdt, fadt;
     AcpiPmInfo pm;
@@ -2621,7 +2609,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
     /* DSDT is pointed to by FADT */
     dsdt = tables_blob->len;
     build_dsdt(tables_blob, tables->linker, &pm, &misc,
-               &pci_hole, &pci_hole64, machine);
+               &pci_hole, &pci_hole64, machine, conf);
 
     /* Count the size of the DSDT and SSDT, we will need it for legacy
      * sizing of ACPI tables.
@@ -2639,7 +2627,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
     aml_len += tables_blob->len - fadt;
 
     acpi_add_table(table_offsets, tables_blob);
-    build_madt(tables_blob, tables->linker, pcms);
+    build_madt(tables_blob, tables->linker, machine, conf);
 
     vmgenid_dev = find_vmgenid_dev();
     if (vmgenid_dev) {
@@ -2661,9 +2649,9 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
             build_tpm2(tables_blob, tables->linker, tables->tcpalog);
         }
     }
-    if (pcms->numa_nodes) {
+    if (conf->numa_nodes) {
         acpi_add_table(table_offsets, tables_blob);
-        build_srat(tables_blob, tables->linker, machine);
+        build_srat(tables_blob, tables->linker, machine, conf);
         if (have_numa_distance) {
             acpi_add_table(table_offsets, tables_blob);
             build_slit(tables_blob, tables->linker);
@@ -2683,9 +2671,9 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
             build_dmar_q35(tables_blob, tables->linker);
         }
     }
-    if (pcms->acpi_nvdimm_state.is_enabled) {
+    if (conf->acpi_nvdimm_state.is_enabled) {
         nvdimm_build_acpi(table_offsets, tables_blob, tables->linker,
-                          &pcms->acpi_nvdimm_state, machine->ram_slots);
+                          &conf->acpi_nvdimm_state, machine->ram_slots);
     }
 
     /* Add tables supplied by user (if any) */
@@ -2721,13 +2709,13 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
      *
      * All this is for PIIX4, since QEMU 2.0 didn't support Q35 migration.
      */
-    if (pcmc->legacy_acpi_table_size) {
+    if (conf->legacy_acpi_table_size) {
         /* Subtracting aml_len gives the size of fixed tables.  Then add the
          * size of the PIIX4 DSDT/SSDT in QEMU 2.0.
          */
         int legacy_aml_len =
-            pcmc->legacy_acpi_table_size +
-            ACPI_BUILD_LEGACY_CPU_AML_SIZE * pcms->apic_id_limit;
+            conf->legacy_acpi_table_size +
+            ACPI_BUILD_LEGACY_CPU_AML_SIZE * conf->apic_id_limit;
         int legacy_table_size =
             ROUND_UP(tables_blob->len - aml_len + legacy_aml_len,
                      ACPI_BUILD_ALIGN_SIZE);
@@ -2772,9 +2760,17 @@ static void acpi_ram_update(MemoryRegion *mr, GArray *data)
 
 static void acpi_build_update(void *build_opaque)
 {
-    AcpiBuildState *build_state = build_opaque;
+    AcpiConfiguration *conf = build_opaque;
+    AcpiBuildState *build_state;
     AcpiBuildTables tables;
 
+    /* No ACPI configuration? Nothing to do. */
+    if (!conf) {
+        return;
+    }
+
+    build_state = conf->build_state;
+
     /* No state to update or already patched? Nothing to do. */
     if (!build_state || build_state->patched) {
         return;
@@ -2783,7 +2779,7 @@ static void acpi_build_update(void *build_opaque)
 
     acpi_build_tables_init(&tables);
 
-    acpi_build(&tables, MACHINE(qdev_get_machine()));
+    acpi_build(&tables, MACHINE(qdev_get_machine()), conf);
 
     acpi_ram_update(build_state->table_mr, tables.table_data);
 
@@ -2803,12 +2799,12 @@ static void acpi_build_reset(void *build_opaque)
     build_state->patched = 0;
 }
 
-static MemoryRegion *acpi_add_rom_blob(AcpiBuildState *build_state,
+static MemoryRegion *acpi_add_rom_blob(AcpiConfiguration *conf,
                                        GArray *blob, const char *name,
                                        uint64_t max_size)
 {
     return rom_add_blob(name, blob->data, acpi_data_len(blob), max_size, -1,
-                        name, acpi_build_update, build_state, NULL, true);
+                        name, acpi_build_update, conf, NULL, true);
 }
 
 static const VMStateDescription vmstate_acpi_build = {
@@ -2816,59 +2812,48 @@ static const VMStateDescription vmstate_acpi_build = {
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT8(patched, AcpiBuildState),
+        VMSTATE_BOOL(patched, AcpiBuildState),
         VMSTATE_END_OF_LIST()
     },
 };
 
-void acpi_setup(void)
+void acpi_setup(MachineState *machine, AcpiConfiguration *conf)
 {
-    PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
-    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
     AcpiBuildTables tables;
     AcpiBuildState *build_state;
     Object *vmgenid_dev;
 
-    if (!pcms->fw_cfg) {
-        ACPI_BUILD_DPRINTF("No fw cfg. Bailing out.\n");
-        return;
-    }
-
-    if (!pcms->acpi_build_enabled) {
-        ACPI_BUILD_DPRINTF("ACPI build disabled. Bailing out.\n");
-        return;
-    }
-
-    if (!acpi_enabled) {
-        ACPI_BUILD_DPRINTF("ACPI disabled. Bailing out.\n");
+    if (!conf) {
+        ACPI_BUILD_DPRINTF("No ACPI config. Bailing out.\n");
         return;
     }
 
     build_state = g_malloc0(sizeof *build_state);
+    conf->build_state = build_state;
 
     acpi_build_tables_init(&tables);
-    acpi_build(&tables, MACHINE(pcms));
+    acpi_build(&tables, machine, conf);
 
     /* Now expose it all to Guest */
-    build_state->table_mr = acpi_add_rom_blob(build_state, tables.table_data,
+    build_state->table_mr = acpi_add_rom_blob(conf, tables.table_data,
                                                ACPI_BUILD_TABLE_FILE,
                                                ACPI_BUILD_TABLE_MAX_SIZE);
     assert(build_state->table_mr != NULL);
 
     build_state->linker_mr =
-        acpi_add_rom_blob(build_state, tables.linker->cmd_blob,
+        acpi_add_rom_blob(conf, tables.linker->cmd_blob,
                           "etc/table-loader", 0);
 
-    fw_cfg_add_file(pcms->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
+    fw_cfg_add_file(conf->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
                     tables.tcpalog->data, acpi_data_len(tables.tcpalog));
 
     vmgenid_dev = find_vmgenid_dev();
     if (vmgenid_dev) {
-        vmgenid_add_fw_cfg(VMGENID(vmgenid_dev), pcms->fw_cfg,
+        vmgenid_add_fw_cfg(VMGENID(vmgenid_dev), conf->fw_cfg,
                            tables.vmgenid);
     }
 
-    if (!pcmc->rsdp_in_ram) {
+    if (!conf->rsdp_in_ram) {
         /*
          * Keep for compatibility with old machine types.
          * Though RSDP is small, its contents isn't immutable, so
@@ -2877,13 +2862,13 @@ void acpi_setup(void)
         uint32_t rsdp_size = acpi_data_len(tables.rsdp);
 
         build_state->rsdp = g_memdup(tables.rsdp->data, rsdp_size);
-        fw_cfg_add_file_callback(pcms->fw_cfg, ACPI_BUILD_RSDP_FILE,
-                                 acpi_build_update, NULL, build_state,
+        fw_cfg_add_file_callback(conf->fw_cfg, ACPI_BUILD_RSDP_FILE,
+                                 acpi_build_update, NULL, conf,
                                  build_state->rsdp, rsdp_size, true);
         build_state->rsdp_mr = NULL;
     } else {
         build_state->rsdp = NULL;
-        build_state->rsdp_mr = acpi_add_rom_blob(build_state, tables.rsdp,
+        build_state->rsdp_mr = acpi_add_rom_blob(conf, tables.rsdp,
                                                   ACPI_BUILD_RSDP_FILE, 0);
     }
 
diff --git a/hw/i386/acpi-build.h b/hw/i386/acpi-build.h
index 007332e51c..1e6b5a7c2e 100644
--- a/hw/i386/acpi-build.h
+++ b/hw/i386/acpi-build.h
@@ -2,6 +2,8 @@
 #ifndef HW_I386_ACPI_BUILD_H
 #define HW_I386_ACPI_BUILD_H
 
-void acpi_setup(void);
+#include "hw/acpi/acpi.h"
+
+void acpi_setup(MachineState *machine, AcpiConfiguration *conf);
 
 #endif
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index f095725dba..bd4a77b856 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -444,17 +444,18 @@ void pc_cmos_init(PCMachineState *pcms,
 {
     int val;
     static pc_cmos_init_late_arg arg;
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
 
     /* various important CMOS locations needed by PC/Bochs bios */
 
     /* memory size */
     /* base memory (first MiB) */
-    val = MIN(pcms->below_4g_mem_size / KiB, 640);
+    val = MIN(conf->below_4g_mem_size / KiB, 640);
     rtc_set_memory(s, 0x15, val);
     rtc_set_memory(s, 0x16, val >> 8);
     /* extended memory (next 64MiB) */
-    if (pcms->below_4g_mem_size > 1 * MiB) {
-        val = (pcms->below_4g_mem_size - 1 * MiB) / KiB;
+    if (conf->below_4g_mem_size > 1 * MiB) {
+        val = (conf->below_4g_mem_size - 1 * MiB) / KiB;
     } else {
         val = 0;
     }
@@ -465,8 +466,8 @@ void pc_cmos_init(PCMachineState *pcms,
     rtc_set_memory(s, 0x30, val);
     rtc_set_memory(s, 0x31, val >> 8);
     /* memory between 16MiB and 4GiB */
-    if (pcms->below_4g_mem_size > 16 * MiB) {
-        val = (pcms->below_4g_mem_size - 16 * MiB) / (64 * KiB);
+    if (conf->below_4g_mem_size > 16 * MiB) {
+        val = (conf->below_4g_mem_size - 16 * MiB) / (64 * KiB);
     } else {
         val = 0;
     }
@@ -475,7 +476,7 @@ void pc_cmos_init(PCMachineState *pcms,
     rtc_set_memory(s, 0x34, val);
     rtc_set_memory(s, 0x35, val >> 8);
     /* memory above 4GiB */
-    val = pcms->above_4g_mem_size / 65536;
+    val = conf->above_4g_mem_size / 65536;
     rtc_set_memory(s, 0x5b, val);
     rtc_set_memory(s, 0x5c, val >> 8);
     rtc_set_memory(s, 0x5d, val >> 16);
@@ -714,13 +715,14 @@ static void pc_build_smbios(PCMachineState *pcms)
     unsigned i, array_count;
     MachineState *ms = MACHINE(pcms);
     X86CPU *cpu = X86_CPU(ms->possible_cpus->cpus[0].cpu);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
 
     /* tell smbios about cpuid version and features */
     smbios_set_cpuid(cpu->env.cpuid_version, cpu->env.features[FEAT_1_EDX]);
 
     smbios_tables = smbios_get_table_legacy(&smbios_tables_len);
     if (smbios_tables) {
-        fw_cfg_add_bytes(pcms->fw_cfg, FW_CFG_SMBIOS_ENTRIES,
+        fw_cfg_add_bytes(conf->fw_cfg, FW_CFG_SMBIOS_ENTRIES,
                          smbios_tables, smbios_tables_len);
     }
 
@@ -741,9 +743,9 @@ static void pc_build_smbios(PCMachineState *pcms)
     g_free(mem_array);
 
     if (smbios_anchor) {
-        fw_cfg_add_file(pcms->fw_cfg, "etc/smbios/smbios-tables",
+        fw_cfg_add_file(conf->fw_cfg, "etc/smbios/smbios-tables",
                         smbios_tables, smbios_tables_len);
-        fw_cfg_add_file(pcms->fw_cfg, "etc/smbios/smbios-anchor",
+        fw_cfg_add_file(conf->fw_cfg, "etc/smbios/smbios-anchor",
                         smbios_anchor, smbios_anchor_len);
     }
 }
@@ -755,6 +757,7 @@ static FWCfgState *bochs_bios_init(AddressSpace *as, PCMachineState *pcms)
     int i;
     const CPUArchIdList *cpus;
     MachineClass *mc = MACHINE_GET_CLASS(pcms);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
 
     fw_cfg = fw_cfg_init_io_dma(FW_CFG_IO_BASE, FW_CFG_IO_BASE + 4, as);
     fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
@@ -771,7 +774,7 @@ static FWCfgState *bochs_bios_init(AddressSpace *as, PCMachineState *pcms)
      * So for compatibility reasons with old BIOSes we are stuck with
      * "etc/max-cpus" actually being apic_id_limit
      */
-    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)pcms->apic_id_limit);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)conf->apic_id_limit);
     fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
     fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES,
                      acpi_tables, acpi_tables_len);
@@ -787,20 +790,20 @@ static FWCfgState *bochs_bios_init(AddressSpace *as, PCMachineState *pcms)
      * of nodes, one word for each VCPU->node and one word for each node to
      * hold the amount of memory.
      */
-    numa_fw_cfg = g_new0(uint64_t, 1 + pcms->apic_id_limit + nb_numa_nodes);
+    numa_fw_cfg = g_new0(uint64_t, 1 + conf->apic_id_limit + nb_numa_nodes);
     numa_fw_cfg[0] = cpu_to_le64(nb_numa_nodes);
     cpus = mc->possible_cpu_arch_ids(MACHINE(pcms));
     for (i = 0; i < cpus->len; i++) {
         unsigned int apic_id = cpus->cpus[i].arch_id;
-        assert(apic_id < pcms->apic_id_limit);
+        assert(apic_id < conf->apic_id_limit);
         numa_fw_cfg[apic_id + 1] = cpu_to_le64(cpus->cpus[i].props.node_id);
     }
     for (i = 0; i < nb_numa_nodes; i++) {
-        numa_fw_cfg[pcms->apic_id_limit + 1 + i] =
+        numa_fw_cfg[conf->apic_id_limit + 1 + i] =
             cpu_to_le64(numa_info[i].node_mem);
     }
     fw_cfg_add_bytes(fw_cfg, FW_CFG_NUMA, numa_fw_cfg,
-                     (1 + pcms->apic_id_limit + nb_numa_nodes) *
+                     (1 + conf->apic_id_limit + nb_numa_nodes) *
                      sizeof(*numa_fw_cfg));
 
     return fw_cfg;
@@ -848,6 +851,7 @@ static void load_linux(PCMachineState *pcms,
     char *vmode;
     MachineState *machine = MACHINE(pcms);
     PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
     struct setup_data *setup_data;
     const char *kernel_filename = machine->kernel_filename;
     const char *initrd_filename = machine->initrd_filename;
@@ -917,8 +921,8 @@ static void load_linux(PCMachineState *pcms,
         initrd_max = 0x37ffffff;
     }
 
-    if (initrd_max >= pcms->below_4g_mem_size - pcmc->acpi_data_size) {
-        initrd_max = pcms->below_4g_mem_size - pcmc->acpi_data_size - 1;
+    if (initrd_max >= conf->below_4g_mem_size - pcmc->acpi_data_size) {
+        initrd_max = conf->below_4g_mem_size - pcmc->acpi_data_size - 1;
     }
 
     fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_ADDR, cmdline_addr);
@@ -1154,7 +1158,8 @@ void pc_cpus_init(PCMachineState *pcms)
      *
      * This is used for FW_CFG_MAX_CPUS. See comments on bochs_bios_init().
      */
-    pcms->apic_id_limit = x86_cpu_apic_id_from_index(max_cpus - 1) + 1;
+    pcms->acpi_configuration.apic_id_limit =
+        x86_cpu_apic_id_from_index(max_cpus - 1) + 1;
     possible_cpus = mc->possible_cpu_arch_ids(ms);
     for (i = 0; i < smp_cpus; i++) {
         pc_new_cpu(possible_cpus->cpus[i].type, possible_cpus->cpus[i].arch_id,
@@ -1188,7 +1193,8 @@ static void pc_build_feature_control_file(PCMachineState *pcms)
 
     val = g_malloc(sizeof(*val));
     *val = cpu_to_le64(feature_control_bits | FEATURE_CONTROL_LOCKED);
-    fw_cfg_add_file(pcms->fw_cfg, "etc/msr_feature_control", val, sizeof(*val));
+    fw_cfg_add_file(pcms->acpi_configuration.fw_cfg,
+                    "etc/msr_feature_control", val, sizeof(*val));
 }
 
 static void rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count)
@@ -1204,11 +1210,26 @@ static void rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count)
     }
 }
 
+static void acpi_conf_pc_init(PCMachineState *pcms)
+{
+    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
+
+    /* Machine class settings */
+    conf->legacy_acpi_table_size = pcmc->legacy_acpi_table_size;
+    conf->legacy_cpu_hotplug = pcmc->legacy_cpu_hotplug;
+    conf->rsdp_in_ram = pcmc->rsdp_in_ram;
+
+    /* ACPI build state */
+    conf->build_state = NULL;
+}
+
 static
 void pc_machine_done(Notifier *notifier, void *data)
 {
     PCMachineState *pcms = container_of(notifier,
                                         PCMachineState, machine_done);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
     PCIBus *bus = pcms->bus;
 
     /* set the number of CPUs */
@@ -1223,23 +1244,27 @@ void pc_machine_done(Notifier *notifier, void *data)
                 extra_hosts++;
             }
         }
-        if (extra_hosts && pcms->fw_cfg) {
+        if (extra_hosts && conf->fw_cfg) {
             uint64_t *val = g_malloc(sizeof(*val));
             *val = cpu_to_le64(extra_hosts);
-            fw_cfg_add_file(pcms->fw_cfg,
+            fw_cfg_add_file(conf->fw_cfg,
                     "etc/extra-pci-roots", val, sizeof(*val));
         }
     }
 
-    acpi_setup();
-    if (pcms->fw_cfg) {
+    if (pcms->acpi_build_enabled) {
+        acpi_conf_pc_init(pcms);
+        acpi_setup(MACHINE(pcms), conf);
+    }
+
+    if (conf->fw_cfg) {
         pc_build_smbios(pcms);
         pc_build_feature_control_file(pcms);
         /* update FW_CFG_NB_CPUS to account for -device added CPUs */
-        fw_cfg_modify_i16(pcms->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
+        fw_cfg_modify_i16(conf->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
     }
 
-    if (pcms->apic_id_limit > 255 && !xen_enabled()) {
+    if (conf->apic_id_limit > 255 && !xen_enabled()) {
         IntelIOMMUState *iommu = INTEL_IOMMU_DEVICE(x86_iommu_get_default());
 
         if (!iommu || !iommu->x86_iommu.intr_supported ||
@@ -1256,13 +1281,14 @@ void pc_machine_done(Notifier *notifier, void *data)
 void pc_guest_info_init(PCMachineState *pcms)
 {
     int i;
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
 
-    pcms->apic_xrupt_override = kvm_allows_irq0_override();
-    pcms->numa_nodes = nb_numa_nodes;
-    pcms->node_mem = g_malloc0(pcms->numa_nodes *
-                                    sizeof *pcms->node_mem);
+    conf->apic_xrupt_override = kvm_allows_irq0_override();
+    conf->numa_nodes = nb_numa_nodes;
+    conf->node_mem = g_malloc0(conf->numa_nodes *
+                                    sizeof *conf->node_mem);
     for (i = 0; i < nb_numa_nodes; i++) {
-        pcms->node_mem[i] = numa_info[i].node_mem;
+        conf->node_mem[i] = numa_info[i].node_mem;
     }
 
     pcms->machine_done.notify = pc_machine_done;
@@ -1323,7 +1349,7 @@ void xen_load_linux(PCMachineState *pcms)
                !strcmp(option_rom[i].name, "multiboot.bin"));
         rom_add_option(option_rom[i].name, option_rom[i].bootindex);
     }
-    pcms->fw_cfg = fw_cfg;
+    pcms->acpi_configuration.fw_cfg = fw_cfg;
 }
 
 void pc_memory_init(PCMachineState *pcms,
@@ -1337,9 +1363,10 @@ void pc_memory_init(PCMachineState *pcms,
     FWCfgState *fw_cfg;
     MachineState *machine = MACHINE(pcms);
     PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
 
-    assert(machine->ram_size == pcms->below_4g_mem_size +
-                                pcms->above_4g_mem_size);
+    assert(machine->ram_size == conf->below_4g_mem_size +
+                                conf->above_4g_mem_size);
 
     linux_boot = (machine->kernel_filename != NULL);
 
@@ -1353,17 +1380,17 @@ void pc_memory_init(PCMachineState *pcms,
     *ram_memory = ram;
     ram_below_4g = g_malloc(sizeof(*ram_below_4g));
     memory_region_init_alias(ram_below_4g, NULL, "ram-below-4g", ram,
-                             0, pcms->below_4g_mem_size);
+                             0, conf->below_4g_mem_size);
     memory_region_add_subregion(system_memory, 0, ram_below_4g);
-    e820_add_entry(0, pcms->below_4g_mem_size, E820_RAM);
-    if (pcms->above_4g_mem_size > 0) {
+    e820_add_entry(0, conf->below_4g_mem_size, E820_RAM);
+    if (conf->above_4g_mem_size > 0) {
         ram_above_4g = g_malloc(sizeof(*ram_above_4g));
         memory_region_init_alias(ram_above_4g, NULL, "ram-above-4g", ram,
-                                 pcms->below_4g_mem_size,
-                                 pcms->above_4g_mem_size);
+                                 conf->below_4g_mem_size,
+                                 conf->above_4g_mem_size);
         memory_region_add_subregion(system_memory, 0x100000000ULL,
                                     ram_above_4g);
-        e820_add_entry(0x100000000ULL, pcms->above_4g_mem_size, E820_RAM);
+        e820_add_entry(0x100000000ULL, conf->above_4g_mem_size, E820_RAM);
     }
 
     if (!pcmc->has_reserved_memory &&
@@ -1398,7 +1425,7 @@ void pc_memory_init(PCMachineState *pcms,
         }
 
         machine->device_memory->base =
-            ROUND_UP(0x100000000ULL + pcms->above_4g_mem_size, 1 * GiB);
+            ROUND_UP(0x100000000ULL + conf->above_4g_mem_size, 1 * GiB);
 
         if (pcmc->enforce_aligned_dimm) {
             /* size device region assuming 1G page max alignment per slot */
@@ -1455,7 +1482,7 @@ void pc_memory_init(PCMachineState *pcms,
     for (i = 0; i < nb_option_roms; i++) {
         rom_add_option(option_rom[i].name, option_rom[i].bootindex);
     }
-    pcms->fw_cfg = fw_cfg;
+    conf->fw_cfg = fw_cfg;
 
     /* Init default IOAPIC address space */
     pcms->ioapic_as = &address_space_memory;
@@ -1478,7 +1505,8 @@ uint64_t pc_pci_hole64_start(void)
             hole64_start += memory_region_size(&ms->device_memory->mr);
         }
     } else {
-        hole64_start = 0x100000000ULL + pcms->above_4g_mem_size;
+        hole64_start =
+            0x100000000ULL + pcms->acpi_configuration.above_4g_mem_size;
     }
 
     return ROUND_UP(hole64_start, 1 * GiB);
@@ -1685,21 +1713,22 @@ static void pc_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
 {
     const PCMachineState *pcms = PC_MACHINE(hotplug_dev);
     const PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
+    const AcpiConfiguration *conf = &pcms->acpi_configuration;
     const bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
     const uint64_t legacy_align = TARGET_PAGE_SIZE;
 
     /*
      * When -no-acpi is used with Q35 machine type, no ACPI is built,
-     * but pcms->acpi_dev is still created. Check !acpi_enabled in
+     * but acpi_dev is still created. Check !acpi_enabled in
      * addition to cover this case.
      */
-    if (!pcms->acpi_dev || !acpi_enabled) {
+    if (!conf->acpi_dev || !acpi_enabled) {
         error_setg(errp,
                    "memory hotplug is not enabled: missing acpi device or acpi disabled");
         return;
     }
 
-    if (is_nvdimm && !pcms->acpi_nvdimm_state.is_enabled) {
+    if (is_nvdimm && !conf->acpi_nvdimm_state.is_enabled) {
         error_setg(errp, "nvdimm is not enabled: missing 'nvdimm' in '-M'");
         return;
     }
@@ -1715,6 +1744,7 @@ static void pc_memory_plug(HotplugHandler *hotplug_dev,
     Error *local_err = NULL;
     PCMachineState *pcms = PC_MACHINE(hotplug_dev);
     bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
 
     pc_dimm_plug(PC_DIMM(dev), MACHINE(pcms), &local_err);
     if (local_err) {
@@ -1722,11 +1752,11 @@ static void pc_memory_plug(HotplugHandler *hotplug_dev,
     }
 
     if (is_nvdimm) {
-        nvdimm_plug(&pcms->acpi_nvdimm_state);
+        nvdimm_plug(&conf->acpi_nvdimm_state);
     }
 
-    hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
-    hhc->plug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &error_abort);
+    hhc = HOTPLUG_HANDLER_GET_CLASS(conf->acpi_dev);
+    hhc->plug(HOTPLUG_HANDLER(conf->acpi_dev), dev, &error_abort);
 out:
     error_propagate(errp, local_err);
 }
@@ -1737,13 +1767,14 @@ static void pc_memory_unplug_request(HotplugHandler *hotplug_dev,
     HotplugHandlerClass *hhc;
     Error *local_err = NULL;
     PCMachineState *pcms = PC_MACHINE(hotplug_dev);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
 
     /*
      * When -no-acpi is used with Q35 machine type, no ACPI is built,
-     * but pcms->acpi_dev is still created. Check !acpi_enabled in
+     * but acpi_dev is still created. Check !acpi_enabled in
      * addition to cover this case.
      */
-    if (!pcms->acpi_dev || !acpi_enabled) {
+    if (!conf->acpi_dev || !acpi_enabled) {
         error_setg(&local_err,
                    "memory hotplug is not enabled: missing acpi device or acpi disabled");
         goto out;
@@ -1755,8 +1786,8 @@ static void pc_memory_unplug_request(HotplugHandler *hotplug_dev,
         goto out;
     }
 
-    hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
-    hhc->unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
+    hhc = HOTPLUG_HANDLER_GET_CLASS(conf->acpi_dev);
+    hhc->unplug_request(HOTPLUG_HANDLER(conf->acpi_dev), dev, &local_err);
 
 out:
     error_propagate(errp, local_err);
@@ -1766,11 +1797,12 @@ static void pc_memory_unplug(HotplugHandler *hotplug_dev,
                              DeviceState *dev, Error **errp)
 {
     PCMachineState *pcms = PC_MACHINE(hotplug_dev);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
     HotplugHandlerClass *hhc;
     Error *local_err = NULL;
 
-    hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
-    hhc->unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
+    hhc = HOTPLUG_HANDLER_GET_CLASS(conf->acpi_dev);
+    hhc->unplug(HOTPLUG_HANDLER(conf->acpi_dev), dev, &local_err);
 
     if (local_err) {
         goto out;
@@ -1817,10 +1849,11 @@ static void pc_cpu_plug(HotplugHandler *hotplug_dev,
     Error *local_err = NULL;
     X86CPU *cpu = X86_CPU(dev);
     PCMachineState *pcms = PC_MACHINE(hotplug_dev);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
 
-    if (pcms->acpi_dev) {
-        hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
-        hhc->plug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
+    if (conf->acpi_dev) {
+        hhc = HOTPLUG_HANDLER_GET_CLASS(conf->acpi_dev);
+        hhc->plug(HOTPLUG_HANDLER(conf->acpi_dev), dev, &local_err);
         if (local_err) {
             goto out;
         }
@@ -1831,8 +1864,8 @@ static void pc_cpu_plug(HotplugHandler *hotplug_dev,
     if (pcms->rtc) {
         rtc_set_cpus_count(pcms->rtc, pcms->boot_cpus);
     }
-    if (pcms->fw_cfg) {
-        fw_cfg_modify_i16(pcms->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
+    if (conf->fw_cfg) {
+        fw_cfg_modify_i16(conf->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
     }
 
     found_cpu = pc_find_cpu_slot(MACHINE(pcms), cpu->apic_id, NULL);
@@ -1848,8 +1881,9 @@ static void pc_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
     Error *local_err = NULL;
     X86CPU *cpu = X86_CPU(dev);
     PCMachineState *pcms = PC_MACHINE(hotplug_dev);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
 
-    if (!pcms->acpi_dev) {
+    if (!conf->acpi_dev) {
         error_setg(&local_err, "CPU hot unplug not supported without ACPI");
         goto out;
     }
@@ -1861,8 +1895,8 @@ static void pc_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
         goto out;
     }
 
-    hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
-    hhc->unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
+    hhc = HOTPLUG_HANDLER_GET_CLASS(conf->acpi_dev);
+    hhc->unplug_request(HOTPLUG_HANDLER(conf->acpi_dev), dev, &local_err);
 
     if (local_err) {
         goto out;
@@ -1881,9 +1915,10 @@ static void pc_cpu_unplug_cb(HotplugHandler *hotplug_dev,
     Error *local_err = NULL;
     X86CPU *cpu = X86_CPU(dev);
     PCMachineState *pcms = PC_MACHINE(hotplug_dev);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
 
-    hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
-    hhc->unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
+    hhc = HOTPLUG_HANDLER_GET_CLASS(conf->acpi_dev);
+    hhc->unplug(HOTPLUG_HANDLER(conf->acpi_dev), dev, &local_err);
 
     if (local_err) {
         goto out;
@@ -1897,7 +1932,7 @@ static void pc_cpu_unplug_cb(HotplugHandler *hotplug_dev,
     pcms->boot_cpus--;
     /* Update the number of CPUs in CMOS */
     rtc_set_cpus_count(pcms->rtc, pcms->boot_cpus);
-    fw_cfg_modify_i16(pcms->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
+    fw_cfg_modify_i16(conf->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
  out:
     error_propagate(errp, local_err);
 }
@@ -2181,28 +2216,30 @@ static bool pc_machine_get_nvdimm(Object *obj, Error **errp)
 {
     PCMachineState *pcms = PC_MACHINE(obj);
 
-    return pcms->acpi_nvdimm_state.is_enabled;
+    return pcms->acpi_configuration.acpi_nvdimm_state.is_enabled;
 }
 
 static void pc_machine_set_nvdimm(Object *obj, bool value, Error **errp)
 {
     PCMachineState *pcms = PC_MACHINE(obj);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
 
-    pcms->acpi_nvdimm_state.is_enabled = value;
+    conf->acpi_nvdimm_state.is_enabled = value;
 }
 
 static char *pc_machine_get_nvdimm_persistence(Object *obj, Error **errp)
 {
     PCMachineState *pcms = PC_MACHINE(obj);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
 
-    return g_strdup(pcms->acpi_nvdimm_state.persistence_string);
+    return g_strdup(conf->acpi_nvdimm_state.persistence_string);
 }
 
 static void pc_machine_set_nvdimm_persistence(Object *obj, const char *value,
                                                Error **errp)
 {
     PCMachineState *pcms = PC_MACHINE(obj);
-    AcpiNVDIMMState *nvdimm_state = &pcms->acpi_nvdimm_state;
+    AcpiNVDIMMState *nvdimm_state = &pcms->acpi_configuration.acpi_nvdimm_state;
 
     if (strcmp(value, "cpu") == 0)
         nvdimm_state->persistence = 3;
@@ -2268,7 +2305,7 @@ static void pc_machine_initfn(Object *obj)
     pcms->smm = ON_OFF_AUTO_AUTO;
     pcms->vmport = ON_OFF_AUTO_AUTO;
     /* nvdimm is disabled on default. */
-    pcms->acpi_nvdimm_state.is_enabled = false;
+    pcms->acpi_configuration.acpi_nvdimm_state.is_enabled = false;
     /* acpi build is enabled by default if machine supports it */
     pcms->acpi_build_enabled = PC_MACHINE_GET_CLASS(pcms)->has_acpi_build;
     pcms->smbus = true;
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index dc09466b3e..1d10374dfa 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -71,6 +71,7 @@ static void pc_init1(MachineState *machine,
 {
     PCMachineState *pcms = PC_MACHINE(machine);
     PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
     MemoryRegion *system_memory = get_system_memory();
     MemoryRegion *system_io = get_system_io();
     int i;
@@ -142,11 +143,11 @@ static void pc_init1(MachineState *machine,
         }
 
         if (machine->ram_size >= lowmem) {
-            pcms->above_4g_mem_size = machine->ram_size - lowmem;
-            pcms->below_4g_mem_size = lowmem;
+            conf->above_4g_mem_size = machine->ram_size - lowmem;
+            conf->below_4g_mem_size = lowmem;
         } else {
-            pcms->above_4g_mem_size = 0;
-            pcms->below_4g_mem_size = machine->ram_size;
+            conf->above_4g_mem_size = 0;
+            conf->below_4g_mem_size = machine->ram_size;
         }
     }
 
@@ -199,8 +200,8 @@ static void pc_init1(MachineState *machine,
                               pci_type,
                               &i440fx_state, &piix3_devfn, &isa_bus, pcms->gsi,
                               system_memory, system_io, machine->ram_size,
-                              pcms->below_4g_mem_size,
-                              pcms->above_4g_mem_size,
+                              conf->below_4g_mem_size,
+                              conf->above_4g_mem_size,
                               pci_memory, ram_memory);
         pcms->bus = pci_bus;
     } else {
@@ -289,16 +290,16 @@ static void pc_init1(MachineState *machine,
 
         object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP,
                                  TYPE_HOTPLUG_HANDLER,
-                                 (Object **)&pcms->acpi_dev,
+                                 (Object **)&conf->acpi_dev,
                                  object_property_allow_set_link,
                                  OBJ_PROP_LINK_STRONG, &error_abort);
         object_property_set_link(OBJECT(machine), OBJECT(piix4_pm),
                                  PC_MACHINE_ACPI_DEVICE_PROP, &error_abort);
     }
 
-    if (pcms->acpi_nvdimm_state.is_enabled) {
-        nvdimm_init_acpi_state(&pcms->acpi_nvdimm_state, system_io,
-                               pcms->fw_cfg, OBJECT(pcms));
+    if (conf->acpi_nvdimm_state.is_enabled) {
+        nvdimm_init_acpi_state(&conf->acpi_nvdimm_state, system_io,
+                               conf->fw_cfg, OBJECT(pcms));
     }
 }
 
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 532241e3f8..fb5c89bf7c 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -63,6 +63,7 @@ static void pc_q35_init(MachineState *machine)
 {
     PCMachineState *pcms = PC_MACHINE(machine);
     PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
     Q35PCIHost *q35_host;
     PCIHostState *phb;
     PCIBus *host_bus;
@@ -116,11 +117,11 @@ static void pc_q35_init(MachineState *machine)
     }
 
     if (machine->ram_size >= lowmem) {
-        pcms->above_4g_mem_size = machine->ram_size - lowmem;
-        pcms->below_4g_mem_size = lowmem;
+        conf->above_4g_mem_size = machine->ram_size - lowmem;
+        conf->below_4g_mem_size = lowmem;
     } else {
-        pcms->above_4g_mem_size = 0;
-        pcms->below_4g_mem_size = machine->ram_size;
+        conf->above_4g_mem_size = 0;
+        conf->below_4g_mem_size = machine->ram_size;
     }
 
     if (xen_enabled()) {
@@ -179,9 +180,9 @@ static void pc_q35_init(MachineState *machine)
                              MCH_HOST_PROP_SYSTEM_MEM, NULL);
     object_property_set_link(OBJECT(q35_host), OBJECT(system_io),
                              MCH_HOST_PROP_IO_MEM, NULL);
-    object_property_set_int(OBJECT(q35_host), pcms->below_4g_mem_size,
+    object_property_set_int(OBJECT(q35_host), conf->below_4g_mem_size,
                             PCI_HOST_BELOW_4G_MEM_SIZE, NULL);
-    object_property_set_int(OBJECT(q35_host), pcms->above_4g_mem_size,
+    object_property_set_int(OBJECT(q35_host), conf->above_4g_mem_size,
                             PCI_HOST_ABOVE_4G_MEM_SIZE, NULL);
     /* pci */
     qdev_init_nofail(DEVICE(q35_host));
@@ -194,7 +195,7 @@ static void pc_q35_init(MachineState *machine)
 
     object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP,
                              TYPE_HOTPLUG_HANDLER,
-                             (Object **)&pcms->acpi_dev,
+                             (Object **)&conf->acpi_dev,
                              object_property_allow_set_link,
                              OBJ_PROP_LINK_STRONG, &error_abort);
     object_property_set_link(OBJECT(machine), OBJECT(lpc),
@@ -276,9 +277,9 @@ static void pc_q35_init(MachineState *machine)
     pc_vga_init(isa_bus, host_bus);
     pc_nic_init(pcmc, isa_bus, host_bus);
 
-    if (pcms->acpi_nvdimm_state.is_enabled) {
-        nvdimm_init_acpi_state(&pcms->acpi_nvdimm_state, system_io,
-                               pcms->fw_cfg, OBJECT(pcms));
+    if (conf->acpi_nvdimm_state.is_enabled) {
+        nvdimm_init_acpi_state(&conf->acpi_nvdimm_state, system_io,
+                               conf->fw_cfg, OBJECT(pcms));
     }
 }
 
diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
index 935a3676c8..4ad5b10d64 100644
--- a/hw/i386/xen/xen-hvm.c
+++ b/hw/i386/xen/xen-hvm.c
@@ -190,6 +190,7 @@ qemu_irq *xen_interrupt_controller_init(void)
 static void xen_ram_init(PCMachineState *pcms,
                          ram_addr_t ram_size, MemoryRegion **ram_memory_p)
 {
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
     MemoryRegion *sysmem = get_system_memory();
     ram_addr_t block_len;
     uint64_t user_lowmem = object_property_get_uint(qdev_get_machine(),
@@ -207,20 +208,20 @@ static void xen_ram_init(PCMachineState *pcms,
     }
 
     if (ram_size >= user_lowmem) {
-        pcms->above_4g_mem_size = ram_size - user_lowmem;
-        pcms->below_4g_mem_size = user_lowmem;
+        conf->above_4g_mem_size = ram_size - user_lowmem;
+        conf->below_4g_mem_size = user_lowmem;
     } else {
-        pcms->above_4g_mem_size = 0;
-        pcms->below_4g_mem_size = ram_size;
+        conf->above_4g_mem_size = 0;
+        conf->below_4g_mem_size = ram_size;
     }
-    if (!pcms->above_4g_mem_size) {
+    if (!conf->above_4g_mem_size) {
         block_len = ram_size;
     } else {
         /*
          * Xen does not allocate the memory continuously, it keeps a
          * hole of the size computed above or passed in.
          */
-        block_len = (1ULL << 32) + pcms->above_4g_mem_size;
+        block_len = (1ULL << 32) + conf->above_4g_mem_size;
     }
     memory_region_init_ram(&ram_memory, NULL, "xen.ram", block_len,
                            &error_fatal);
@@ -237,12 +238,12 @@ static void xen_ram_init(PCMachineState *pcms,
      */
     memory_region_init_alias(&ram_lo, NULL, "xen.ram.lo",
                              &ram_memory, 0xc0000,
-                             pcms->below_4g_mem_size - 0xc0000);
+                             conf->below_4g_mem_size - 0xc0000);
     memory_region_add_subregion(sysmem, 0xc0000, &ram_lo);
-    if (pcms->above_4g_mem_size > 0) {
+    if (conf->above_4g_mem_size > 0) {
         memory_region_init_alias(&ram_hi, NULL, "xen.ram.hi",
                                  &ram_memory, 0x100000000ULL,
-                                 pcms->above_4g_mem_size);
+                                 conf->above_4g_mem_size);
         memory_region_add_subregion(sysmem, 0x100000000ULL, &ram_hi);
     }
 }
diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h
index c20ace0d0b..6a94452928 100644
--- a/include/hw/acpi/acpi.h
+++ b/include/hw/acpi/acpi.h
@@ -24,6 +24,8 @@
 #include "exec/memory.h"
 #include "hw/irq.h"
 #include "hw/acpi/acpi_dev_interface.h"
+#include "hw/hotplug.h"
+#include "hw/mem/nvdimm.h"
 
 /*
  * current device naming scheme supports up to 256 memory devices
@@ -186,6 +188,47 @@ extern int acpi_enabled;
 extern char unsigned *acpi_tables;
 extern size_t acpi_tables_len;
 
+typedef
+struct AcpiBuildState {
+    /* Copy of table in RAM (for patching). */
+    MemoryRegion *table_mr;
+    /* Is table patched? */
+    bool patched;
+    void *rsdp;
+    MemoryRegion *rsdp_mr;
+    MemoryRegion *linker_mr;
+} AcpiBuildState;
+
+typedef
+struct AcpiConfiguration {
+    /* Machine class ACPI settings */
+    int legacy_acpi_table_size;
+    bool rsdp_in_ram;
+    unsigned acpi_data_size;
+
+    /* Machine state ACPI settings */
+    HotplugHandler *acpi_dev;
+    AcpiNVDIMMState acpi_nvdimm_state;
+
+    /*
+     * The fields below are machine settings that
+     * are not ACPI specific. However they are needed
+     * for building ACPI tables and as such should be
+     * carried through the ACPI configuration structure.
+     */
+    bool legacy_cpu_hotplug;
+    bool linuxboot_dma_enabled;
+    FWCfgState *fw_cfg;
+    ram_addr_t below_4g_mem_size, above_4g_mem_size;;
+    uint64_t numa_nodes;
+    uint64_t *node_mem;
+    bool apic_xrupt_override;
+    unsigned apic_id_limit;
+
+    /* Build state */
+    AcpiBuildState *build_state;
+} AcpiConfiguration;
+
 uint8_t *acpi_table_first(void);
 uint8_t *acpi_table_next(uint8_t *current);
 unsigned acpi_table_len(void *current);
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index dfe6746692..da0bd39741 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -12,6 +12,7 @@
 #include "qemu/range.h"
 #include "qemu/bitmap.h"
 #include "sysemu/sysemu.h"
+#include "hw/acpi/acpi.h"
 #include "hw/pci/pci.h"
 #include "hw/compat.h"
 #include "hw/mem/pc-dimm.h"
@@ -35,10 +36,8 @@ struct PCMachineState {
     Notifier machine_done;
 
     /* Pointers to devices and objects: */
-    HotplugHandler *acpi_dev;
     ISADevice *rtc;
     PCIBus *bus;
-    FWCfgState *fw_cfg;
     qemu_irq *gsi;
 
     /* Configuration options: */
@@ -46,28 +45,20 @@ struct PCMachineState {
     OnOffAuto vmport;
     OnOffAuto smm;
 
-    AcpiNVDIMMState acpi_nvdimm_state;
-
     bool acpi_build_enabled;
     bool smbus;
     bool sata;
     bool pit;
 
-    /* RAM information (sizes, addresses, configuration): */
-    ram_addr_t below_4g_mem_size, above_4g_mem_size;
-
-    /* CPU and apic information: */
-    bool apic_xrupt_override;
-    unsigned apic_id_limit;
+    /* CPU information */
     uint16_t boot_cpus;
 
-    /* NUMA information: */
-    uint64_t numa_nodes;
-    uint64_t *node_mem;
-
     /* Address space used by IOAPIC device. All IOAPIC interrupts
      * will be translated to MSI messages in the address space. */
     AddressSpace *ioapic_as;
+
+    /* ACPI configuration */
+    AcpiConfiguration acpi_configuration;
 };
 
 #define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device"
-- 
2.17.2

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH v3 01/19] hw: i386: Decouple the ACPI build from the PC machine type
  2018-10-29 17:01 [Qemu-devel] [PATCH v3 00/19] ACPI reorganization for hardware-reduced support Samuel Ortiz
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 01/19] hw: i386: Decouple the ACPI build from the PC machine type Samuel Ortiz
@ 2018-10-29 17:01 ` Samuel Ortiz
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 02/19] hw: acpi: Export ACPI build alignment API Samuel Ortiz
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-29 17:01 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Stefano Stabellini, Eduardo Habkost,
	Michael S. Tsirkin, open list:X86, Paolo Bonzini,
	Marcel Apfelbaum, Shannon Zhao, Anthony Perard, Igor Mammedov,
	open list:ARM ACPI Subsystem, Richard Henderson

ACPI tables are platform and machine type and even architecture
agnostic, and as such we want to provide an internal ACPI API that
only depends on platform agnostic information.

For the x86 architecture, in order to build ACPI tables independently
from the PC or Q35 machine types, we are moving a few MachineState
structure fields into a machine type agnostic structure called
AcpiConfiguration. The structure fields we move are:

   HotplugHandler *acpi_dev
   AcpiNVDIMMState acpi_nvdimm_state;
   FWCfgState *fw_cfg
   ram_addr_t below_4g_mem_size, above_4g_mem_size
   bool apic_xrupt_override
   unsigned apic_id_limit
   uint64_t numa_nodes
   uint64_t numa_mem

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 hw/acpi/cpu_hotplug.c    |   9 +-
 hw/arm/virt-acpi-build.c |  10 ---
 hw/i386/acpi-build.c     | 135 ++++++++++++++----------------
 hw/i386/acpi-build.h     |   4 +-
 hw/i386/pc.c             | 175 ++++++++++++++++++++++++---------------
 hw/i386/pc_piix.c        |  21 ++---
 hw/i386/pc_q35.c         |  21 ++---
 hw/i386/xen/xen-hvm.c    |  19 +++--
 include/hw/acpi/acpi.h   |  43 ++++++++++
 include/hw/i386/pc.h     |  19 ++---
 10 files changed, 254 insertions(+), 202 deletions(-)

diff --git a/hw/acpi/cpu_hotplug.c b/hw/acpi/cpu_hotplug.c
index 5243918125..634dc3b846 100644
--- a/hw/acpi/cpu_hotplug.c
+++ b/hw/acpi/cpu_hotplug.c
@@ -237,9 +237,9 @@ void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *machine,
     /* The current AML generator can cover the APIC ID range [0..255],
      * inclusive, for VCPU hotplug. */
     QEMU_BUILD_BUG_ON(ACPI_CPU_HOTPLUG_ID_LIMIT > 256);
-    if (pcms->apic_id_limit > ACPI_CPU_HOTPLUG_ID_LIMIT) {
+    if (pcms->acpi_configuration.apic_id_limit > ACPI_CPU_HOTPLUG_ID_LIMIT) {
         error_report("max_cpus is too large. APIC ID of last CPU is %u",
-                     pcms->apic_id_limit - 1);
+                     pcms->acpi_configuration.apic_id_limit - 1);
         exit(1);
     }
 
@@ -316,8 +316,9 @@ void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *machine,
      * ith up to 255 elements. Windows guests up to win2k8 fail when
      * VarPackageOp is used.
      */
-    pkg = pcms->apic_id_limit <= 255 ? aml_package(pcms->apic_id_limit) :
-                                       aml_varpackage(pcms->apic_id_limit);
+    pkg = pcms->acpi_configuration.apic_id_limit <= 255 ?
+        aml_package(pcms->acpi_configuration.apic_id_limit) :
+        aml_varpackage(pcms->acpi_configuration.apic_id_limit);
 
     for (i = 0, apic_idx = 0; i < apic_ids->len; i++) {
         int apic_id = apic_ids->cpus[i].arch_id;
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 5785fb697c..f28a2faa53 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -790,16 +790,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
     free_aml_allocator();
 }
 
-typedef
-struct AcpiBuildState {
-    /* Copy of table in RAM (for patching). */
-    MemoryRegion *table_mr;
-    MemoryRegion *rsdp_mr;
-    MemoryRegion *linker_mr;
-    /* Is table patched? */
-    bool patched;
-} AcpiBuildState;
-
 static
 void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
 {
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 1599caa7c5..c8545238c4 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -338,13 +338,14 @@ void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
 }
 
 static void
-build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms)
+build_madt(GArray *table_data, BIOSLinker *linker,
+           MachineState *ms, AcpiConfiguration *conf)
 {
-    MachineClass *mc = MACHINE_GET_CLASS(pcms);
-    const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(pcms));
+    MachineClass *mc = MACHINE_GET_CLASS(ms);
+    const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(ms);
     int madt_start = table_data->len;
-    AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(pcms->acpi_dev);
-    AcpiDeviceIf *adev = ACPI_DEVICE_IF(pcms->acpi_dev);
+    AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(conf->acpi_dev);
+    AcpiDeviceIf *adev = ACPI_DEVICE_IF(conf->acpi_dev);
     bool x2apic_mode = false;
 
     AcpiMultipleApicTable *madt;
@@ -370,7 +371,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms)
     io_apic->address = cpu_to_le32(IO_APIC_DEFAULT_ADDRESS);
     io_apic->interrupt = cpu_to_le32(0);
 
-    if (pcms->apic_xrupt_override) {
+    if (conf->apic_xrupt_override) {
         intsrcovr = acpi_data_push(table_data, sizeof *intsrcovr);
         intsrcovr->type   = ACPI_APIC_XRUPT_OVERRIDE;
         intsrcovr->length = sizeof(*intsrcovr);
@@ -1786,13 +1787,12 @@ static Aml *build_q35_osc_method(void)
 static void
 build_dsdt(GArray *table_data, BIOSLinker *linker,
            AcpiPmInfo *pm, AcpiMiscInfo *misc,
-           Range *pci_hole, Range *pci_hole64, MachineState *machine)
+           Range *pci_hole, Range *pci_hole64,
+           MachineState *machine, AcpiConfiguration *conf)
 {
     CrsRangeEntry *entry;
     Aml *dsdt, *sb_scope, *scope, *dev, *method, *field, *pkg, *crs;
     CrsRangeSet crs_range_set;
-    PCMachineState *pcms = PC_MACHINE(machine);
-    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(machine);
     uint32_t nr_mem = machine->ram_slots;
     int root_bus_limit = 0xFF;
     PCIBus *bus = NULL;
@@ -1836,7 +1836,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
         build_q35_pci0_int(dsdt);
     }
 
-    if (pcmc->legacy_cpu_hotplug) {
+    if (conf->legacy_cpu_hotplug) {
         build_legacy_cpu_hotplug_aml(dsdt, machine, pm->cpu_hp_io_base);
     } else {
         CPUHotplugFeatures opts = {
@@ -1860,7 +1860,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
             aml_append(scope, method);
         }
 
-        if (pcms->acpi_nvdimm_state.is_enabled) {
+        if (conf->acpi_nvdimm_state.is_enabled) {
             method = aml_method("_E04", 0, AML_NOTSERIALIZED);
             aml_append(method, aml_notify(aml_name("\\_SB.NVDR"),
                                           aml_int(0x80)));
@@ -2041,7 +2041,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
          * with half of the 16-bit control register. Hence, the total size
          * of the i/o region used is FW_CFG_CTL_SIZE; when using DMA, the
          * DMA control register is located at FW_CFG_DMA_IO_BASE + 4 */
-        uint8_t io_size = object_property_get_bool(OBJECT(pcms->fw_cfg),
+        uint8_t io_size = object_property_get_bool(OBJECT(conf->fw_cfg),
                                                    "dma_enabled", NULL) ?
                           ROUND_UP(FW_CFG_CTL_SIZE, 4) + sizeof(dma_addr_t) :
                           FW_CFG_CTL_SIZE;
@@ -2252,7 +2252,8 @@ build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog)
 #define HOLE_640K_END   (1 * MiB)
 
 static void
-build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
+build_srat(GArray *table_data, BIOSLinker *linker,
+           MachineState *machine, AcpiConfiguration *conf)
 {
     AcpiSystemResourceAffinityTable *srat;
     AcpiSratMemoryAffinity *numamem;
@@ -2262,9 +2263,8 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
     uint64_t mem_len, mem_base, next_base;
     MachineClass *mc = MACHINE_GET_CLASS(machine);
     const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(machine);
-    PCMachineState *pcms = PC_MACHINE(machine);
     ram_addr_t hotplugabble_address_space_size =
-        object_property_get_int(OBJECT(pcms), PC_MACHINE_DEVMEM_REGION_SIZE,
+        object_property_get_int(OBJECT(machine), PC_MACHINE_DEVMEM_REGION_SIZE,
                                 NULL);
 
     srat_start = table_data->len;
@@ -2306,9 +2306,9 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
     next_base = 0;
     numa_start = table_data->len;
 
-    for (i = 1; i < pcms->numa_nodes + 1; ++i) {
+    for (i = 1; i < conf->numa_nodes + 1; ++i) {
         mem_base = next_base;
-        mem_len = pcms->node_mem[i - 1];
+        mem_len = conf->node_mem[i - 1];
         next_base = mem_base + mem_len;
 
         /* Cut out the 640K hole */
@@ -2331,16 +2331,16 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
         }
 
         /* Cut out the ACPI_PCI hole */
-        if (mem_base <= pcms->below_4g_mem_size &&
-            next_base > pcms->below_4g_mem_size) {
-            mem_len -= next_base - pcms->below_4g_mem_size;
+        if (mem_base <= conf->below_4g_mem_size &&
+            next_base > conf->below_4g_mem_size) {
+            mem_len -= next_base - conf->below_4g_mem_size;
             if (mem_len > 0) {
                 numamem = acpi_data_push(table_data, sizeof *numamem);
                 build_srat_memory(numamem, mem_base, mem_len, i - 1,
                                   MEM_AFFINITY_ENABLED);
             }
             mem_base = 1ULL << 32;
-            mem_len = next_base - pcms->below_4g_mem_size;
+            mem_len = next_base - conf->below_4g_mem_size;
             next_base = mem_base + mem_len;
         }
 
@@ -2351,7 +2351,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
         }
     }
     slots = (table_data->len - numa_start) / sizeof *numamem;
-    for (; slots < pcms->numa_nodes + 2; slots++) {
+    for (; slots < conf->numa_nodes + 2; slots++) {
         numamem = acpi_data_push(table_data, sizeof *numamem);
         build_srat_memory(numamem, 0, 0, 0, MEM_AFFINITY_NOFLAGS);
     }
@@ -2367,7 +2367,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
     if (hotplugabble_address_space_size) {
         numamem = acpi_data_push(table_data, sizeof *numamem);
         build_srat_memory(numamem, machine->device_memory->base,
-                          hotplugabble_address_space_size, pcms->numa_nodes - 1,
+                          hotplugabble_address_space_size, conf->numa_nodes - 1,
                           MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
     }
 
@@ -2546,17 +2546,6 @@ build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset)
     return rsdp_table;
 }
 
-typedef
-struct AcpiBuildState {
-    /* Copy of table in RAM (for patching). */
-    MemoryRegion *table_mr;
-    /* Is table patched? */
-    uint8_t patched;
-    void *rsdp;
-    MemoryRegion *rsdp_mr;
-    MemoryRegion *linker_mr;
-} AcpiBuildState;
-
 static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
 {
     Object *pci_host;
@@ -2580,10 +2569,9 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
 }
 
 static
-void acpi_build(AcpiBuildTables *tables, MachineState *machine)
+void acpi_build(AcpiBuildTables *tables,
+                MachineState *machine, AcpiConfiguration *conf)
 {
-    PCMachineState *pcms = PC_MACHINE(machine);
-    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
     GArray *table_offsets;
     unsigned facs, dsdt, rsdt, fadt;
     AcpiPmInfo pm;
@@ -2621,7 +2609,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
     /* DSDT is pointed to by FADT */
     dsdt = tables_blob->len;
     build_dsdt(tables_blob, tables->linker, &pm, &misc,
-               &pci_hole, &pci_hole64, machine);
+               &pci_hole, &pci_hole64, machine, conf);
 
     /* Count the size of the DSDT and SSDT, we will need it for legacy
      * sizing of ACPI tables.
@@ -2639,7 +2627,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
     aml_len += tables_blob->len - fadt;
 
     acpi_add_table(table_offsets, tables_blob);
-    build_madt(tables_blob, tables->linker, pcms);
+    build_madt(tables_blob, tables->linker, machine, conf);
 
     vmgenid_dev = find_vmgenid_dev();
     if (vmgenid_dev) {
@@ -2661,9 +2649,9 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
             build_tpm2(tables_blob, tables->linker, tables->tcpalog);
         }
     }
-    if (pcms->numa_nodes) {
+    if (conf->numa_nodes) {
         acpi_add_table(table_offsets, tables_blob);
-        build_srat(tables_blob, tables->linker, machine);
+        build_srat(tables_blob, tables->linker, machine, conf);
         if (have_numa_distance) {
             acpi_add_table(table_offsets, tables_blob);
             build_slit(tables_blob, tables->linker);
@@ -2683,9 +2671,9 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
             build_dmar_q35(tables_blob, tables->linker);
         }
     }
-    if (pcms->acpi_nvdimm_state.is_enabled) {
+    if (conf->acpi_nvdimm_state.is_enabled) {
         nvdimm_build_acpi(table_offsets, tables_blob, tables->linker,
-                          &pcms->acpi_nvdimm_state, machine->ram_slots);
+                          &conf->acpi_nvdimm_state, machine->ram_slots);
     }
 
     /* Add tables supplied by user (if any) */
@@ -2721,13 +2709,13 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
      *
      * All this is for PIIX4, since QEMU 2.0 didn't support Q35 migration.
      */
-    if (pcmc->legacy_acpi_table_size) {
+    if (conf->legacy_acpi_table_size) {
         /* Subtracting aml_len gives the size of fixed tables.  Then add the
          * size of the PIIX4 DSDT/SSDT in QEMU 2.0.
          */
         int legacy_aml_len =
-            pcmc->legacy_acpi_table_size +
-            ACPI_BUILD_LEGACY_CPU_AML_SIZE * pcms->apic_id_limit;
+            conf->legacy_acpi_table_size +
+            ACPI_BUILD_LEGACY_CPU_AML_SIZE * conf->apic_id_limit;
         int legacy_table_size =
             ROUND_UP(tables_blob->len - aml_len + legacy_aml_len,
                      ACPI_BUILD_ALIGN_SIZE);
@@ -2772,9 +2760,17 @@ static void acpi_ram_update(MemoryRegion *mr, GArray *data)
 
 static void acpi_build_update(void *build_opaque)
 {
-    AcpiBuildState *build_state = build_opaque;
+    AcpiConfiguration *conf = build_opaque;
+    AcpiBuildState *build_state;
     AcpiBuildTables tables;
 
+    /* No ACPI configuration? Nothing to do. */
+    if (!conf) {
+        return;
+    }
+
+    build_state = conf->build_state;
+
     /* No state to update or already patched? Nothing to do. */
     if (!build_state || build_state->patched) {
         return;
@@ -2783,7 +2779,7 @@ static void acpi_build_update(void *build_opaque)
 
     acpi_build_tables_init(&tables);
 
-    acpi_build(&tables, MACHINE(qdev_get_machine()));
+    acpi_build(&tables, MACHINE(qdev_get_machine()), conf);
 
     acpi_ram_update(build_state->table_mr, tables.table_data);
 
@@ -2803,12 +2799,12 @@ static void acpi_build_reset(void *build_opaque)
     build_state->patched = 0;
 }
 
-static MemoryRegion *acpi_add_rom_blob(AcpiBuildState *build_state,
+static MemoryRegion *acpi_add_rom_blob(AcpiConfiguration *conf,
                                        GArray *blob, const char *name,
                                        uint64_t max_size)
 {
     return rom_add_blob(name, blob->data, acpi_data_len(blob), max_size, -1,
-                        name, acpi_build_update, build_state, NULL, true);
+                        name, acpi_build_update, conf, NULL, true);
 }
 
 static const VMStateDescription vmstate_acpi_build = {
@@ -2816,59 +2812,48 @@ static const VMStateDescription vmstate_acpi_build = {
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT8(patched, AcpiBuildState),
+        VMSTATE_BOOL(patched, AcpiBuildState),
         VMSTATE_END_OF_LIST()
     },
 };
 
-void acpi_setup(void)
+void acpi_setup(MachineState *machine, AcpiConfiguration *conf)
 {
-    PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
-    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
     AcpiBuildTables tables;
     AcpiBuildState *build_state;
     Object *vmgenid_dev;
 
-    if (!pcms->fw_cfg) {
-        ACPI_BUILD_DPRINTF("No fw cfg. Bailing out.\n");
-        return;
-    }
-
-    if (!pcms->acpi_build_enabled) {
-        ACPI_BUILD_DPRINTF("ACPI build disabled. Bailing out.\n");
-        return;
-    }
-
-    if (!acpi_enabled) {
-        ACPI_BUILD_DPRINTF("ACPI disabled. Bailing out.\n");
+    if (!conf) {
+        ACPI_BUILD_DPRINTF("No ACPI config. Bailing out.\n");
         return;
     }
 
     build_state = g_malloc0(sizeof *build_state);
+    conf->build_state = build_state;
 
     acpi_build_tables_init(&tables);
-    acpi_build(&tables, MACHINE(pcms));
+    acpi_build(&tables, machine, conf);
 
     /* Now expose it all to Guest */
-    build_state->table_mr = acpi_add_rom_blob(build_state, tables.table_data,
+    build_state->table_mr = acpi_add_rom_blob(conf, tables.table_data,
                                                ACPI_BUILD_TABLE_FILE,
                                                ACPI_BUILD_TABLE_MAX_SIZE);
     assert(build_state->table_mr != NULL);
 
     build_state->linker_mr =
-        acpi_add_rom_blob(build_state, tables.linker->cmd_blob,
+        acpi_add_rom_blob(conf, tables.linker->cmd_blob,
                           "etc/table-loader", 0);
 
-    fw_cfg_add_file(pcms->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
+    fw_cfg_add_file(conf->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
                     tables.tcpalog->data, acpi_data_len(tables.tcpalog));
 
     vmgenid_dev = find_vmgenid_dev();
     if (vmgenid_dev) {
-        vmgenid_add_fw_cfg(VMGENID(vmgenid_dev), pcms->fw_cfg,
+        vmgenid_add_fw_cfg(VMGENID(vmgenid_dev), conf->fw_cfg,
                            tables.vmgenid);
     }
 
-    if (!pcmc->rsdp_in_ram) {
+    if (!conf->rsdp_in_ram) {
         /*
          * Keep for compatibility with old machine types.
          * Though RSDP is small, its contents isn't immutable, so
@@ -2877,13 +2862,13 @@ void acpi_setup(void)
         uint32_t rsdp_size = acpi_data_len(tables.rsdp);
 
         build_state->rsdp = g_memdup(tables.rsdp->data, rsdp_size);
-        fw_cfg_add_file_callback(pcms->fw_cfg, ACPI_BUILD_RSDP_FILE,
-                                 acpi_build_update, NULL, build_state,
+        fw_cfg_add_file_callback(conf->fw_cfg, ACPI_BUILD_RSDP_FILE,
+                                 acpi_build_update, NULL, conf,
                                  build_state->rsdp, rsdp_size, true);
         build_state->rsdp_mr = NULL;
     } else {
         build_state->rsdp = NULL;
-        build_state->rsdp_mr = acpi_add_rom_blob(build_state, tables.rsdp,
+        build_state->rsdp_mr = acpi_add_rom_blob(conf, tables.rsdp,
                                                   ACPI_BUILD_RSDP_FILE, 0);
     }
 
diff --git a/hw/i386/acpi-build.h b/hw/i386/acpi-build.h
index 007332e51c..1e6b5a7c2e 100644
--- a/hw/i386/acpi-build.h
+++ b/hw/i386/acpi-build.h
@@ -2,6 +2,8 @@
 #ifndef HW_I386_ACPI_BUILD_H
 #define HW_I386_ACPI_BUILD_H
 
-void acpi_setup(void);
+#include "hw/acpi/acpi.h"
+
+void acpi_setup(MachineState *machine, AcpiConfiguration *conf);
 
 #endif
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index f095725dba..bd4a77b856 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -444,17 +444,18 @@ void pc_cmos_init(PCMachineState *pcms,
 {
     int val;
     static pc_cmos_init_late_arg arg;
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
 
     /* various important CMOS locations needed by PC/Bochs bios */
 
     /* memory size */
     /* base memory (first MiB) */
-    val = MIN(pcms->below_4g_mem_size / KiB, 640);
+    val = MIN(conf->below_4g_mem_size / KiB, 640);
     rtc_set_memory(s, 0x15, val);
     rtc_set_memory(s, 0x16, val >> 8);
     /* extended memory (next 64MiB) */
-    if (pcms->below_4g_mem_size > 1 * MiB) {
-        val = (pcms->below_4g_mem_size - 1 * MiB) / KiB;
+    if (conf->below_4g_mem_size > 1 * MiB) {
+        val = (conf->below_4g_mem_size - 1 * MiB) / KiB;
     } else {
         val = 0;
     }
@@ -465,8 +466,8 @@ void pc_cmos_init(PCMachineState *pcms,
     rtc_set_memory(s, 0x30, val);
     rtc_set_memory(s, 0x31, val >> 8);
     /* memory between 16MiB and 4GiB */
-    if (pcms->below_4g_mem_size > 16 * MiB) {
-        val = (pcms->below_4g_mem_size - 16 * MiB) / (64 * KiB);
+    if (conf->below_4g_mem_size > 16 * MiB) {
+        val = (conf->below_4g_mem_size - 16 * MiB) / (64 * KiB);
     } else {
         val = 0;
     }
@@ -475,7 +476,7 @@ void pc_cmos_init(PCMachineState *pcms,
     rtc_set_memory(s, 0x34, val);
     rtc_set_memory(s, 0x35, val >> 8);
     /* memory above 4GiB */
-    val = pcms->above_4g_mem_size / 65536;
+    val = conf->above_4g_mem_size / 65536;
     rtc_set_memory(s, 0x5b, val);
     rtc_set_memory(s, 0x5c, val >> 8);
     rtc_set_memory(s, 0x5d, val >> 16);
@@ -714,13 +715,14 @@ static void pc_build_smbios(PCMachineState *pcms)
     unsigned i, array_count;
     MachineState *ms = MACHINE(pcms);
     X86CPU *cpu = X86_CPU(ms->possible_cpus->cpus[0].cpu);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
 
     /* tell smbios about cpuid version and features */
     smbios_set_cpuid(cpu->env.cpuid_version, cpu->env.features[FEAT_1_EDX]);
 
     smbios_tables = smbios_get_table_legacy(&smbios_tables_len);
     if (smbios_tables) {
-        fw_cfg_add_bytes(pcms->fw_cfg, FW_CFG_SMBIOS_ENTRIES,
+        fw_cfg_add_bytes(conf->fw_cfg, FW_CFG_SMBIOS_ENTRIES,
                          smbios_tables, smbios_tables_len);
     }
 
@@ -741,9 +743,9 @@ static void pc_build_smbios(PCMachineState *pcms)
     g_free(mem_array);
 
     if (smbios_anchor) {
-        fw_cfg_add_file(pcms->fw_cfg, "etc/smbios/smbios-tables",
+        fw_cfg_add_file(conf->fw_cfg, "etc/smbios/smbios-tables",
                         smbios_tables, smbios_tables_len);
-        fw_cfg_add_file(pcms->fw_cfg, "etc/smbios/smbios-anchor",
+        fw_cfg_add_file(conf->fw_cfg, "etc/smbios/smbios-anchor",
                         smbios_anchor, smbios_anchor_len);
     }
 }
@@ -755,6 +757,7 @@ static FWCfgState *bochs_bios_init(AddressSpace *as, PCMachineState *pcms)
     int i;
     const CPUArchIdList *cpus;
     MachineClass *mc = MACHINE_GET_CLASS(pcms);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
 
     fw_cfg = fw_cfg_init_io_dma(FW_CFG_IO_BASE, FW_CFG_IO_BASE + 4, as);
     fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
@@ -771,7 +774,7 @@ static FWCfgState *bochs_bios_init(AddressSpace *as, PCMachineState *pcms)
      * So for compatibility reasons with old BIOSes we are stuck with
      * "etc/max-cpus" actually being apic_id_limit
      */
-    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)pcms->apic_id_limit);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)conf->apic_id_limit);
     fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
     fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES,
                      acpi_tables, acpi_tables_len);
@@ -787,20 +790,20 @@ static FWCfgState *bochs_bios_init(AddressSpace *as, PCMachineState *pcms)
      * of nodes, one word for each VCPU->node and one word for each node to
      * hold the amount of memory.
      */
-    numa_fw_cfg = g_new0(uint64_t, 1 + pcms->apic_id_limit + nb_numa_nodes);
+    numa_fw_cfg = g_new0(uint64_t, 1 + conf->apic_id_limit + nb_numa_nodes);
     numa_fw_cfg[0] = cpu_to_le64(nb_numa_nodes);
     cpus = mc->possible_cpu_arch_ids(MACHINE(pcms));
     for (i = 0; i < cpus->len; i++) {
         unsigned int apic_id = cpus->cpus[i].arch_id;
-        assert(apic_id < pcms->apic_id_limit);
+        assert(apic_id < conf->apic_id_limit);
         numa_fw_cfg[apic_id + 1] = cpu_to_le64(cpus->cpus[i].props.node_id);
     }
     for (i = 0; i < nb_numa_nodes; i++) {
-        numa_fw_cfg[pcms->apic_id_limit + 1 + i] =
+        numa_fw_cfg[conf->apic_id_limit + 1 + i] =
             cpu_to_le64(numa_info[i].node_mem);
     }
     fw_cfg_add_bytes(fw_cfg, FW_CFG_NUMA, numa_fw_cfg,
-                     (1 + pcms->apic_id_limit + nb_numa_nodes) *
+                     (1 + conf->apic_id_limit + nb_numa_nodes) *
                      sizeof(*numa_fw_cfg));
 
     return fw_cfg;
@@ -848,6 +851,7 @@ static void load_linux(PCMachineState *pcms,
     char *vmode;
     MachineState *machine = MACHINE(pcms);
     PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
     struct setup_data *setup_data;
     const char *kernel_filename = machine->kernel_filename;
     const char *initrd_filename = machine->initrd_filename;
@@ -917,8 +921,8 @@ static void load_linux(PCMachineState *pcms,
         initrd_max = 0x37ffffff;
     }
 
-    if (initrd_max >= pcms->below_4g_mem_size - pcmc->acpi_data_size) {
-        initrd_max = pcms->below_4g_mem_size - pcmc->acpi_data_size - 1;
+    if (initrd_max >= conf->below_4g_mem_size - pcmc->acpi_data_size) {
+        initrd_max = conf->below_4g_mem_size - pcmc->acpi_data_size - 1;
     }
 
     fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_ADDR, cmdline_addr);
@@ -1154,7 +1158,8 @@ void pc_cpus_init(PCMachineState *pcms)
      *
      * This is used for FW_CFG_MAX_CPUS. See comments on bochs_bios_init().
      */
-    pcms->apic_id_limit = x86_cpu_apic_id_from_index(max_cpus - 1) + 1;
+    pcms->acpi_configuration.apic_id_limit =
+        x86_cpu_apic_id_from_index(max_cpus - 1) + 1;
     possible_cpus = mc->possible_cpu_arch_ids(ms);
     for (i = 0; i < smp_cpus; i++) {
         pc_new_cpu(possible_cpus->cpus[i].type, possible_cpus->cpus[i].arch_id,
@@ -1188,7 +1193,8 @@ static void pc_build_feature_control_file(PCMachineState *pcms)
 
     val = g_malloc(sizeof(*val));
     *val = cpu_to_le64(feature_control_bits | FEATURE_CONTROL_LOCKED);
-    fw_cfg_add_file(pcms->fw_cfg, "etc/msr_feature_control", val, sizeof(*val));
+    fw_cfg_add_file(pcms->acpi_configuration.fw_cfg,
+                    "etc/msr_feature_control", val, sizeof(*val));
 }
 
 static void rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count)
@@ -1204,11 +1210,26 @@ static void rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count)
     }
 }
 
+static void acpi_conf_pc_init(PCMachineState *pcms)
+{
+    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
+
+    /* Machine class settings */
+    conf->legacy_acpi_table_size = pcmc->legacy_acpi_table_size;
+    conf->legacy_cpu_hotplug = pcmc->legacy_cpu_hotplug;
+    conf->rsdp_in_ram = pcmc->rsdp_in_ram;
+
+    /* ACPI build state */
+    conf->build_state = NULL;
+}
+
 static
 void pc_machine_done(Notifier *notifier, void *data)
 {
     PCMachineState *pcms = container_of(notifier,
                                         PCMachineState, machine_done);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
     PCIBus *bus = pcms->bus;
 
     /* set the number of CPUs */
@@ -1223,23 +1244,27 @@ void pc_machine_done(Notifier *notifier, void *data)
                 extra_hosts++;
             }
         }
-        if (extra_hosts && pcms->fw_cfg) {
+        if (extra_hosts && conf->fw_cfg) {
             uint64_t *val = g_malloc(sizeof(*val));
             *val = cpu_to_le64(extra_hosts);
-            fw_cfg_add_file(pcms->fw_cfg,
+            fw_cfg_add_file(conf->fw_cfg,
                     "etc/extra-pci-roots", val, sizeof(*val));
         }
     }
 
-    acpi_setup();
-    if (pcms->fw_cfg) {
+    if (pcms->acpi_build_enabled) {
+        acpi_conf_pc_init(pcms);
+        acpi_setup(MACHINE(pcms), conf);
+    }
+
+    if (conf->fw_cfg) {
         pc_build_smbios(pcms);
         pc_build_feature_control_file(pcms);
         /* update FW_CFG_NB_CPUS to account for -device added CPUs */
-        fw_cfg_modify_i16(pcms->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
+        fw_cfg_modify_i16(conf->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
     }
 
-    if (pcms->apic_id_limit > 255 && !xen_enabled()) {
+    if (conf->apic_id_limit > 255 && !xen_enabled()) {
         IntelIOMMUState *iommu = INTEL_IOMMU_DEVICE(x86_iommu_get_default());
 
         if (!iommu || !iommu->x86_iommu.intr_supported ||
@@ -1256,13 +1281,14 @@ void pc_machine_done(Notifier *notifier, void *data)
 void pc_guest_info_init(PCMachineState *pcms)
 {
     int i;
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
 
-    pcms->apic_xrupt_override = kvm_allows_irq0_override();
-    pcms->numa_nodes = nb_numa_nodes;
-    pcms->node_mem = g_malloc0(pcms->numa_nodes *
-                                    sizeof *pcms->node_mem);
+    conf->apic_xrupt_override = kvm_allows_irq0_override();
+    conf->numa_nodes = nb_numa_nodes;
+    conf->node_mem = g_malloc0(conf->numa_nodes *
+                                    sizeof *conf->node_mem);
     for (i = 0; i < nb_numa_nodes; i++) {
-        pcms->node_mem[i] = numa_info[i].node_mem;
+        conf->node_mem[i] = numa_info[i].node_mem;
     }
 
     pcms->machine_done.notify = pc_machine_done;
@@ -1323,7 +1349,7 @@ void xen_load_linux(PCMachineState *pcms)
                !strcmp(option_rom[i].name, "multiboot.bin"));
         rom_add_option(option_rom[i].name, option_rom[i].bootindex);
     }
-    pcms->fw_cfg = fw_cfg;
+    pcms->acpi_configuration.fw_cfg = fw_cfg;
 }
 
 void pc_memory_init(PCMachineState *pcms,
@@ -1337,9 +1363,10 @@ void pc_memory_init(PCMachineState *pcms,
     FWCfgState *fw_cfg;
     MachineState *machine = MACHINE(pcms);
     PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
 
-    assert(machine->ram_size == pcms->below_4g_mem_size +
-                                pcms->above_4g_mem_size);
+    assert(machine->ram_size == conf->below_4g_mem_size +
+                                conf->above_4g_mem_size);
 
     linux_boot = (machine->kernel_filename != NULL);
 
@@ -1353,17 +1380,17 @@ void pc_memory_init(PCMachineState *pcms,
     *ram_memory = ram;
     ram_below_4g = g_malloc(sizeof(*ram_below_4g));
     memory_region_init_alias(ram_below_4g, NULL, "ram-below-4g", ram,
-                             0, pcms->below_4g_mem_size);
+                             0, conf->below_4g_mem_size);
     memory_region_add_subregion(system_memory, 0, ram_below_4g);
-    e820_add_entry(0, pcms->below_4g_mem_size, E820_RAM);
-    if (pcms->above_4g_mem_size > 0) {
+    e820_add_entry(0, conf->below_4g_mem_size, E820_RAM);
+    if (conf->above_4g_mem_size > 0) {
         ram_above_4g = g_malloc(sizeof(*ram_above_4g));
         memory_region_init_alias(ram_above_4g, NULL, "ram-above-4g", ram,
-                                 pcms->below_4g_mem_size,
-                                 pcms->above_4g_mem_size);
+                                 conf->below_4g_mem_size,
+                                 conf->above_4g_mem_size);
         memory_region_add_subregion(system_memory, 0x100000000ULL,
                                     ram_above_4g);
-        e820_add_entry(0x100000000ULL, pcms->above_4g_mem_size, E820_RAM);
+        e820_add_entry(0x100000000ULL, conf->above_4g_mem_size, E820_RAM);
     }
 
     if (!pcmc->has_reserved_memory &&
@@ -1398,7 +1425,7 @@ void pc_memory_init(PCMachineState *pcms,
         }
 
         machine->device_memory->base =
-            ROUND_UP(0x100000000ULL + pcms->above_4g_mem_size, 1 * GiB);
+            ROUND_UP(0x100000000ULL + conf->above_4g_mem_size, 1 * GiB);
 
         if (pcmc->enforce_aligned_dimm) {
             /* size device region assuming 1G page max alignment per slot */
@@ -1455,7 +1482,7 @@ void pc_memory_init(PCMachineState *pcms,
     for (i = 0; i < nb_option_roms; i++) {
         rom_add_option(option_rom[i].name, option_rom[i].bootindex);
     }
-    pcms->fw_cfg = fw_cfg;
+    conf->fw_cfg = fw_cfg;
 
     /* Init default IOAPIC address space */
     pcms->ioapic_as = &address_space_memory;
@@ -1478,7 +1505,8 @@ uint64_t pc_pci_hole64_start(void)
             hole64_start += memory_region_size(&ms->device_memory->mr);
         }
     } else {
-        hole64_start = 0x100000000ULL + pcms->above_4g_mem_size;
+        hole64_start =
+            0x100000000ULL + pcms->acpi_configuration.above_4g_mem_size;
     }
 
     return ROUND_UP(hole64_start, 1 * GiB);
@@ -1685,21 +1713,22 @@ static void pc_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
 {
     const PCMachineState *pcms = PC_MACHINE(hotplug_dev);
     const PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
+    const AcpiConfiguration *conf = &pcms->acpi_configuration;
     const bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
     const uint64_t legacy_align = TARGET_PAGE_SIZE;
 
     /*
      * When -no-acpi is used with Q35 machine type, no ACPI is built,
-     * but pcms->acpi_dev is still created. Check !acpi_enabled in
+     * but acpi_dev is still created. Check !acpi_enabled in
      * addition to cover this case.
      */
-    if (!pcms->acpi_dev || !acpi_enabled) {
+    if (!conf->acpi_dev || !acpi_enabled) {
         error_setg(errp,
                    "memory hotplug is not enabled: missing acpi device or acpi disabled");
         return;
     }
 
-    if (is_nvdimm && !pcms->acpi_nvdimm_state.is_enabled) {
+    if (is_nvdimm && !conf->acpi_nvdimm_state.is_enabled) {
         error_setg(errp, "nvdimm is not enabled: missing 'nvdimm' in '-M'");
         return;
     }
@@ -1715,6 +1744,7 @@ static void pc_memory_plug(HotplugHandler *hotplug_dev,
     Error *local_err = NULL;
     PCMachineState *pcms = PC_MACHINE(hotplug_dev);
     bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
 
     pc_dimm_plug(PC_DIMM(dev), MACHINE(pcms), &local_err);
     if (local_err) {
@@ -1722,11 +1752,11 @@ static void pc_memory_plug(HotplugHandler *hotplug_dev,
     }
 
     if (is_nvdimm) {
-        nvdimm_plug(&pcms->acpi_nvdimm_state);
+        nvdimm_plug(&conf->acpi_nvdimm_state);
     }
 
-    hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
-    hhc->plug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &error_abort);
+    hhc = HOTPLUG_HANDLER_GET_CLASS(conf->acpi_dev);
+    hhc->plug(HOTPLUG_HANDLER(conf->acpi_dev), dev, &error_abort);
 out:
     error_propagate(errp, local_err);
 }
@@ -1737,13 +1767,14 @@ static void pc_memory_unplug_request(HotplugHandler *hotplug_dev,
     HotplugHandlerClass *hhc;
     Error *local_err = NULL;
     PCMachineState *pcms = PC_MACHINE(hotplug_dev);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
 
     /*
      * When -no-acpi is used with Q35 machine type, no ACPI is built,
-     * but pcms->acpi_dev is still created. Check !acpi_enabled in
+     * but acpi_dev is still created. Check !acpi_enabled in
      * addition to cover this case.
      */
-    if (!pcms->acpi_dev || !acpi_enabled) {
+    if (!conf->acpi_dev || !acpi_enabled) {
         error_setg(&local_err,
                    "memory hotplug is not enabled: missing acpi device or acpi disabled");
         goto out;
@@ -1755,8 +1786,8 @@ static void pc_memory_unplug_request(HotplugHandler *hotplug_dev,
         goto out;
     }
 
-    hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
-    hhc->unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
+    hhc = HOTPLUG_HANDLER_GET_CLASS(conf->acpi_dev);
+    hhc->unplug_request(HOTPLUG_HANDLER(conf->acpi_dev), dev, &local_err);
 
 out:
     error_propagate(errp, local_err);
@@ -1766,11 +1797,12 @@ static void pc_memory_unplug(HotplugHandler *hotplug_dev,
                              DeviceState *dev, Error **errp)
 {
     PCMachineState *pcms = PC_MACHINE(hotplug_dev);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
     HotplugHandlerClass *hhc;
     Error *local_err = NULL;
 
-    hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
-    hhc->unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
+    hhc = HOTPLUG_HANDLER_GET_CLASS(conf->acpi_dev);
+    hhc->unplug(HOTPLUG_HANDLER(conf->acpi_dev), dev, &local_err);
 
     if (local_err) {
         goto out;
@@ -1817,10 +1849,11 @@ static void pc_cpu_plug(HotplugHandler *hotplug_dev,
     Error *local_err = NULL;
     X86CPU *cpu = X86_CPU(dev);
     PCMachineState *pcms = PC_MACHINE(hotplug_dev);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
 
-    if (pcms->acpi_dev) {
-        hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
-        hhc->plug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
+    if (conf->acpi_dev) {
+        hhc = HOTPLUG_HANDLER_GET_CLASS(conf->acpi_dev);
+        hhc->plug(HOTPLUG_HANDLER(conf->acpi_dev), dev, &local_err);
         if (local_err) {
             goto out;
         }
@@ -1831,8 +1864,8 @@ static void pc_cpu_plug(HotplugHandler *hotplug_dev,
     if (pcms->rtc) {
         rtc_set_cpus_count(pcms->rtc, pcms->boot_cpus);
     }
-    if (pcms->fw_cfg) {
-        fw_cfg_modify_i16(pcms->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
+    if (conf->fw_cfg) {
+        fw_cfg_modify_i16(conf->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
     }
 
     found_cpu = pc_find_cpu_slot(MACHINE(pcms), cpu->apic_id, NULL);
@@ -1848,8 +1881,9 @@ static void pc_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
     Error *local_err = NULL;
     X86CPU *cpu = X86_CPU(dev);
     PCMachineState *pcms = PC_MACHINE(hotplug_dev);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
 
-    if (!pcms->acpi_dev) {
+    if (!conf->acpi_dev) {
         error_setg(&local_err, "CPU hot unplug not supported without ACPI");
         goto out;
     }
@@ -1861,8 +1895,8 @@ static void pc_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
         goto out;
     }
 
-    hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
-    hhc->unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
+    hhc = HOTPLUG_HANDLER_GET_CLASS(conf->acpi_dev);
+    hhc->unplug_request(HOTPLUG_HANDLER(conf->acpi_dev), dev, &local_err);
 
     if (local_err) {
         goto out;
@@ -1881,9 +1915,10 @@ static void pc_cpu_unplug_cb(HotplugHandler *hotplug_dev,
     Error *local_err = NULL;
     X86CPU *cpu = X86_CPU(dev);
     PCMachineState *pcms = PC_MACHINE(hotplug_dev);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
 
-    hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
-    hhc->unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
+    hhc = HOTPLUG_HANDLER_GET_CLASS(conf->acpi_dev);
+    hhc->unplug(HOTPLUG_HANDLER(conf->acpi_dev), dev, &local_err);
 
     if (local_err) {
         goto out;
@@ -1897,7 +1932,7 @@ static void pc_cpu_unplug_cb(HotplugHandler *hotplug_dev,
     pcms->boot_cpus--;
     /* Update the number of CPUs in CMOS */
     rtc_set_cpus_count(pcms->rtc, pcms->boot_cpus);
-    fw_cfg_modify_i16(pcms->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
+    fw_cfg_modify_i16(conf->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
  out:
     error_propagate(errp, local_err);
 }
@@ -2181,28 +2216,30 @@ static bool pc_machine_get_nvdimm(Object *obj, Error **errp)
 {
     PCMachineState *pcms = PC_MACHINE(obj);
 
-    return pcms->acpi_nvdimm_state.is_enabled;
+    return pcms->acpi_configuration.acpi_nvdimm_state.is_enabled;
 }
 
 static void pc_machine_set_nvdimm(Object *obj, bool value, Error **errp)
 {
     PCMachineState *pcms = PC_MACHINE(obj);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
 
-    pcms->acpi_nvdimm_state.is_enabled = value;
+    conf->acpi_nvdimm_state.is_enabled = value;
 }
 
 static char *pc_machine_get_nvdimm_persistence(Object *obj, Error **errp)
 {
     PCMachineState *pcms = PC_MACHINE(obj);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
 
-    return g_strdup(pcms->acpi_nvdimm_state.persistence_string);
+    return g_strdup(conf->acpi_nvdimm_state.persistence_string);
 }
 
 static void pc_machine_set_nvdimm_persistence(Object *obj, const char *value,
                                                Error **errp)
 {
     PCMachineState *pcms = PC_MACHINE(obj);
-    AcpiNVDIMMState *nvdimm_state = &pcms->acpi_nvdimm_state;
+    AcpiNVDIMMState *nvdimm_state = &pcms->acpi_configuration.acpi_nvdimm_state;
 
     if (strcmp(value, "cpu") == 0)
         nvdimm_state->persistence = 3;
@@ -2268,7 +2305,7 @@ static void pc_machine_initfn(Object *obj)
     pcms->smm = ON_OFF_AUTO_AUTO;
     pcms->vmport = ON_OFF_AUTO_AUTO;
     /* nvdimm is disabled on default. */
-    pcms->acpi_nvdimm_state.is_enabled = false;
+    pcms->acpi_configuration.acpi_nvdimm_state.is_enabled = false;
     /* acpi build is enabled by default if machine supports it */
     pcms->acpi_build_enabled = PC_MACHINE_GET_CLASS(pcms)->has_acpi_build;
     pcms->smbus = true;
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index dc09466b3e..1d10374dfa 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -71,6 +71,7 @@ static void pc_init1(MachineState *machine,
 {
     PCMachineState *pcms = PC_MACHINE(machine);
     PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
     MemoryRegion *system_memory = get_system_memory();
     MemoryRegion *system_io = get_system_io();
     int i;
@@ -142,11 +143,11 @@ static void pc_init1(MachineState *machine,
         }
 
         if (machine->ram_size >= lowmem) {
-            pcms->above_4g_mem_size = machine->ram_size - lowmem;
-            pcms->below_4g_mem_size = lowmem;
+            conf->above_4g_mem_size = machine->ram_size - lowmem;
+            conf->below_4g_mem_size = lowmem;
         } else {
-            pcms->above_4g_mem_size = 0;
-            pcms->below_4g_mem_size = machine->ram_size;
+            conf->above_4g_mem_size = 0;
+            conf->below_4g_mem_size = machine->ram_size;
         }
     }
 
@@ -199,8 +200,8 @@ static void pc_init1(MachineState *machine,
                               pci_type,
                               &i440fx_state, &piix3_devfn, &isa_bus, pcms->gsi,
                               system_memory, system_io, machine->ram_size,
-                              pcms->below_4g_mem_size,
-                              pcms->above_4g_mem_size,
+                              conf->below_4g_mem_size,
+                              conf->above_4g_mem_size,
                               pci_memory, ram_memory);
         pcms->bus = pci_bus;
     } else {
@@ -289,16 +290,16 @@ static void pc_init1(MachineState *machine,
 
         object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP,
                                  TYPE_HOTPLUG_HANDLER,
-                                 (Object **)&pcms->acpi_dev,
+                                 (Object **)&conf->acpi_dev,
                                  object_property_allow_set_link,
                                  OBJ_PROP_LINK_STRONG, &error_abort);
         object_property_set_link(OBJECT(machine), OBJECT(piix4_pm),
                                  PC_MACHINE_ACPI_DEVICE_PROP, &error_abort);
     }
 
-    if (pcms->acpi_nvdimm_state.is_enabled) {
-        nvdimm_init_acpi_state(&pcms->acpi_nvdimm_state, system_io,
-                               pcms->fw_cfg, OBJECT(pcms));
+    if (conf->acpi_nvdimm_state.is_enabled) {
+        nvdimm_init_acpi_state(&conf->acpi_nvdimm_state, system_io,
+                               conf->fw_cfg, OBJECT(pcms));
     }
 }
 
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 532241e3f8..fb5c89bf7c 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -63,6 +63,7 @@ static void pc_q35_init(MachineState *machine)
 {
     PCMachineState *pcms = PC_MACHINE(machine);
     PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
     Q35PCIHost *q35_host;
     PCIHostState *phb;
     PCIBus *host_bus;
@@ -116,11 +117,11 @@ static void pc_q35_init(MachineState *machine)
     }
 
     if (machine->ram_size >= lowmem) {
-        pcms->above_4g_mem_size = machine->ram_size - lowmem;
-        pcms->below_4g_mem_size = lowmem;
+        conf->above_4g_mem_size = machine->ram_size - lowmem;
+        conf->below_4g_mem_size = lowmem;
     } else {
-        pcms->above_4g_mem_size = 0;
-        pcms->below_4g_mem_size = machine->ram_size;
+        conf->above_4g_mem_size = 0;
+        conf->below_4g_mem_size = machine->ram_size;
     }
 
     if (xen_enabled()) {
@@ -179,9 +180,9 @@ static void pc_q35_init(MachineState *machine)
                              MCH_HOST_PROP_SYSTEM_MEM, NULL);
     object_property_set_link(OBJECT(q35_host), OBJECT(system_io),
                              MCH_HOST_PROP_IO_MEM, NULL);
-    object_property_set_int(OBJECT(q35_host), pcms->below_4g_mem_size,
+    object_property_set_int(OBJECT(q35_host), conf->below_4g_mem_size,
                             PCI_HOST_BELOW_4G_MEM_SIZE, NULL);
-    object_property_set_int(OBJECT(q35_host), pcms->above_4g_mem_size,
+    object_property_set_int(OBJECT(q35_host), conf->above_4g_mem_size,
                             PCI_HOST_ABOVE_4G_MEM_SIZE, NULL);
     /* pci */
     qdev_init_nofail(DEVICE(q35_host));
@@ -194,7 +195,7 @@ static void pc_q35_init(MachineState *machine)
 
     object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP,
                              TYPE_HOTPLUG_HANDLER,
-                             (Object **)&pcms->acpi_dev,
+                             (Object **)&conf->acpi_dev,
                              object_property_allow_set_link,
                              OBJ_PROP_LINK_STRONG, &error_abort);
     object_property_set_link(OBJECT(machine), OBJECT(lpc),
@@ -276,9 +277,9 @@ static void pc_q35_init(MachineState *machine)
     pc_vga_init(isa_bus, host_bus);
     pc_nic_init(pcmc, isa_bus, host_bus);
 
-    if (pcms->acpi_nvdimm_state.is_enabled) {
-        nvdimm_init_acpi_state(&pcms->acpi_nvdimm_state, system_io,
-                               pcms->fw_cfg, OBJECT(pcms));
+    if (conf->acpi_nvdimm_state.is_enabled) {
+        nvdimm_init_acpi_state(&conf->acpi_nvdimm_state, system_io,
+                               conf->fw_cfg, OBJECT(pcms));
     }
 }
 
diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
index 935a3676c8..4ad5b10d64 100644
--- a/hw/i386/xen/xen-hvm.c
+++ b/hw/i386/xen/xen-hvm.c
@@ -190,6 +190,7 @@ qemu_irq *xen_interrupt_controller_init(void)
 static void xen_ram_init(PCMachineState *pcms,
                          ram_addr_t ram_size, MemoryRegion **ram_memory_p)
 {
+    AcpiConfiguration *conf = &pcms->acpi_configuration;
     MemoryRegion *sysmem = get_system_memory();
     ram_addr_t block_len;
     uint64_t user_lowmem = object_property_get_uint(qdev_get_machine(),
@@ -207,20 +208,20 @@ static void xen_ram_init(PCMachineState *pcms,
     }
 
     if (ram_size >= user_lowmem) {
-        pcms->above_4g_mem_size = ram_size - user_lowmem;
-        pcms->below_4g_mem_size = user_lowmem;
+        conf->above_4g_mem_size = ram_size - user_lowmem;
+        conf->below_4g_mem_size = user_lowmem;
     } else {
-        pcms->above_4g_mem_size = 0;
-        pcms->below_4g_mem_size = ram_size;
+        conf->above_4g_mem_size = 0;
+        conf->below_4g_mem_size = ram_size;
     }
-    if (!pcms->above_4g_mem_size) {
+    if (!conf->above_4g_mem_size) {
         block_len = ram_size;
     } else {
         /*
          * Xen does not allocate the memory continuously, it keeps a
          * hole of the size computed above or passed in.
          */
-        block_len = (1ULL << 32) + pcms->above_4g_mem_size;
+        block_len = (1ULL << 32) + conf->above_4g_mem_size;
     }
     memory_region_init_ram(&ram_memory, NULL, "xen.ram", block_len,
                            &error_fatal);
@@ -237,12 +238,12 @@ static void xen_ram_init(PCMachineState *pcms,
      */
     memory_region_init_alias(&ram_lo, NULL, "xen.ram.lo",
                              &ram_memory, 0xc0000,
-                             pcms->below_4g_mem_size - 0xc0000);
+                             conf->below_4g_mem_size - 0xc0000);
     memory_region_add_subregion(sysmem, 0xc0000, &ram_lo);
-    if (pcms->above_4g_mem_size > 0) {
+    if (conf->above_4g_mem_size > 0) {
         memory_region_init_alias(&ram_hi, NULL, "xen.ram.hi",
                                  &ram_memory, 0x100000000ULL,
-                                 pcms->above_4g_mem_size);
+                                 conf->above_4g_mem_size);
         memory_region_add_subregion(sysmem, 0x100000000ULL, &ram_hi);
     }
 }
diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h
index c20ace0d0b..6a94452928 100644
--- a/include/hw/acpi/acpi.h
+++ b/include/hw/acpi/acpi.h
@@ -24,6 +24,8 @@
 #include "exec/memory.h"
 #include "hw/irq.h"
 #include "hw/acpi/acpi_dev_interface.h"
+#include "hw/hotplug.h"
+#include "hw/mem/nvdimm.h"
 
 /*
  * current device naming scheme supports up to 256 memory devices
@@ -186,6 +188,47 @@ extern int acpi_enabled;
 extern char unsigned *acpi_tables;
 extern size_t acpi_tables_len;
 
+typedef
+struct AcpiBuildState {
+    /* Copy of table in RAM (for patching). */
+    MemoryRegion *table_mr;
+    /* Is table patched? */
+    bool patched;
+    void *rsdp;
+    MemoryRegion *rsdp_mr;
+    MemoryRegion *linker_mr;
+} AcpiBuildState;
+
+typedef
+struct AcpiConfiguration {
+    /* Machine class ACPI settings */
+    int legacy_acpi_table_size;
+    bool rsdp_in_ram;
+    unsigned acpi_data_size;
+
+    /* Machine state ACPI settings */
+    HotplugHandler *acpi_dev;
+    AcpiNVDIMMState acpi_nvdimm_state;
+
+    /*
+     * The fields below are machine settings that
+     * are not ACPI specific. However they are needed
+     * for building ACPI tables and as such should be
+     * carried through the ACPI configuration structure.
+     */
+    bool legacy_cpu_hotplug;
+    bool linuxboot_dma_enabled;
+    FWCfgState *fw_cfg;
+    ram_addr_t below_4g_mem_size, above_4g_mem_size;;
+    uint64_t numa_nodes;
+    uint64_t *node_mem;
+    bool apic_xrupt_override;
+    unsigned apic_id_limit;
+
+    /* Build state */
+    AcpiBuildState *build_state;
+} AcpiConfiguration;
+
 uint8_t *acpi_table_first(void);
 uint8_t *acpi_table_next(uint8_t *current);
 unsigned acpi_table_len(void *current);
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index dfe6746692..da0bd39741 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -12,6 +12,7 @@
 #include "qemu/range.h"
 #include "qemu/bitmap.h"
 #include "sysemu/sysemu.h"
+#include "hw/acpi/acpi.h"
 #include "hw/pci/pci.h"
 #include "hw/compat.h"
 #include "hw/mem/pc-dimm.h"
@@ -35,10 +36,8 @@ struct PCMachineState {
     Notifier machine_done;
 
     /* Pointers to devices and objects: */
-    HotplugHandler *acpi_dev;
     ISADevice *rtc;
     PCIBus *bus;
-    FWCfgState *fw_cfg;
     qemu_irq *gsi;
 
     /* Configuration options: */
@@ -46,28 +45,20 @@ struct PCMachineState {
     OnOffAuto vmport;
     OnOffAuto smm;
 
-    AcpiNVDIMMState acpi_nvdimm_state;
-
     bool acpi_build_enabled;
     bool smbus;
     bool sata;
     bool pit;
 
-    /* RAM information (sizes, addresses, configuration): */
-    ram_addr_t below_4g_mem_size, above_4g_mem_size;
-
-    /* CPU and apic information: */
-    bool apic_xrupt_override;
-    unsigned apic_id_limit;
+    /* CPU information */
     uint16_t boot_cpus;
 
-    /* NUMA information: */
-    uint64_t numa_nodes;
-    uint64_t *node_mem;
-
     /* Address space used by IOAPIC device. All IOAPIC interrupts
      * will be translated to MSI messages in the address space. */
     AddressSpace *ioapic_as;
+
+    /* ACPI configuration */
+    AcpiConfiguration acpi_configuration;
 };
 
 #define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device"
-- 
2.17.2


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH v3 02/19] hw: acpi: Export ACPI build alignment API
  2018-10-29 17:01 [Qemu-devel] [PATCH v3 00/19] ACPI reorganization for hardware-reduced support Samuel Ortiz
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 01/19] hw: i386: Decouple the ACPI build from the PC machine type Samuel Ortiz
  2018-10-29 17:01 ` Samuel Ortiz
@ 2018-10-29 17:01 ` Samuel Ortiz
  2018-10-29 19:01   ` Philippe Mathieu-Daudé
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 03/19] hw: acpi: Export the RSDP build API Samuel Ortiz
                   ` (16 subsequent siblings)
  19 siblings, 1 reply; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-29 17:01 UTC (permalink / raw)
  To: qemu-devel
  Cc: Michael S. Tsirkin, Igor Mammedov, Marcel Apfelbaum,
	Paolo Bonzini, Richard Henderson, Eduardo Habkost

This is going to be needed by the Hardware-reduced ACPI routines.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 hw/acpi/aml-build.c         | 8 ++++++++
 hw/i386/acpi-build.c        | 8 --------
 include/hw/acpi/aml-build.h | 2 ++
 3 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 1e43cd736d..51b608432f 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1565,6 +1565,14 @@ unsigned acpi_data_len(GArray *table)
     return table->len;
 }
 
+void acpi_align_size(GArray *blob, unsigned align)
+{
+    /* Align size to multiple of given size. This reduces the chance
+     * we need to change size in the future (breaking cross version migration).
+     */
+    g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align));
+}
+
 void acpi_add_table(GArray *table_offsets, GArray *table_data)
 {
     uint32_t offset = table_data->len;
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index c8545238c4..1bf02b6a93 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -282,14 +282,6 @@ static void acpi_get_pci_holes(Range *hole, Range *hole64)
                                                NULL));
 }
 
-static void acpi_align_size(GArray *blob, unsigned align)
-{
-    /* Align size to multiple of given size. This reduces the chance
-     * we need to change size in the future (breaking cross version migration).
-     */
-    g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align));
-}
-
 /* FACS */
 static void
 build_facs(GArray *table_data, BIOSLinker *linker)
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 6c36903c0a..813f51317c 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -6,6 +6,7 @@
 
 /* Reserve RAM space for tables: add another order of magnitude. */
 #define ACPI_BUILD_TABLE_MAX_SIZE         0x200000
+#define ACPI_BUILD_ALIGN_SIZE             0x1000
 
 #define ACPI_BUILD_APPNAME6 "BOCHS "
 #define ACPI_BUILD_APPNAME4 "BXPC"
@@ -384,6 +385,7 @@ build_header(BIOSLinker *linker, GArray *table_data,
              const char *oem_id, const char *oem_table_id);
 void *acpi_data_push(GArray *table_data, unsigned size);
 unsigned acpi_data_len(GArray *table);
+void acpi_align_size(GArray *blob, unsigned align);
 void acpi_add_table(GArray *table_offsets, GArray *table_data);
 void acpi_build_tables_init(AcpiBuildTables *tables);
 void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre);
-- 
2.17.2

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH v3 03/19] hw: acpi: Export the RSDP build API
  2018-10-29 17:01 [Qemu-devel] [PATCH v3 00/19] ACPI reorganization for hardware-reduced support Samuel Ortiz
                   ` (2 preceding siblings ...)
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 02/19] hw: acpi: Export ACPI build alignment API Samuel Ortiz
@ 2018-10-29 17:01 ` Samuel Ortiz
  2018-10-29 18:58   ` Philippe Mathieu-Daudé
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 04/19] hw: acpi: Implement XSDT support for RSDP Samuel Ortiz
                   ` (15 subsequent siblings)
  19 siblings, 1 reply; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-29 17:01 UTC (permalink / raw)
  To: qemu-devel
  Cc: Michael S. Tsirkin, Igor Mammedov, Paolo Bonzini,
	Richard Henderson, Eduardo Habkost, Marcel Apfelbaum

The hardware-reduced API will need to build RSDP as well, so we should
export this routine. While doing so, we also slightly change the
function prototype. Since no caller needs it, and to make it more
consistent with the rest of the AML build API, the function no longer
returns its RSDP table.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 hw/acpi/aml-build.c         | 24 ++++++++++++++++++++++++
 hw/i386/acpi-build.c        | 26 --------------------------
 include/hw/acpi/aml-build.h |  3 +++
 3 files changed, 27 insertions(+), 26 deletions(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 51b608432f..2d6f538f9d 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1651,6 +1651,30 @@ build_xsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
                  (void *)xsdt, "XSDT", xsdt_len, 1, oem_id, oem_table_id);
 }
 
+void
+build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset)
+{
+    AcpiRsdpDescriptor *rsdp = acpi_data_push(rsdp_table, sizeof *rsdp);
+    unsigned rsdt_pa_size = sizeof(rsdp->rsdt_physical_address);
+    unsigned rsdt_pa_offset =
+        (char *)&rsdp->rsdt_physical_address - rsdp_table->data;
+
+    bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, rsdp_table, 16,
+                             true /* fseg memory */);
+
+    memcpy(&rsdp->signature, "RSD PTR ", 8);
+    memcpy(rsdp->oem_id, ACPI_BUILD_APPNAME6, 6);
+    /* Address to be filled by Guest linker */
+    bios_linker_loader_add_pointer(linker,
+        ACPI_BUILD_RSDP_FILE, rsdt_pa_offset, rsdt_pa_size,
+        ACPI_BUILD_TABLE_FILE, rsdt_tbl_offset);
+
+    /* Checksum to be filled by Guest linker */
+    bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE,
+        (char *)rsdp - rsdp_table->data, sizeof *rsdp,
+        (char *)&rsdp->checksum - rsdp_table->data);
+}
+
 void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base,
                        uint64_t len, int node, MemoryAffinityFlags flags)
 {
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 1bf02b6a93..9f1c9f4cf5 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -2512,32 +2512,6 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker)
                  "IVRS", table_data->len - iommu_start, 1, NULL, NULL);
 }
 
-static GArray *
-build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset)
-{
-    AcpiRsdpDescriptor *rsdp = acpi_data_push(rsdp_table, sizeof *rsdp);
-    unsigned rsdt_pa_size = sizeof(rsdp->rsdt_physical_address);
-    unsigned rsdt_pa_offset =
-        (char *)&rsdp->rsdt_physical_address - rsdp_table->data;
-
-    bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, rsdp_table, 16,
-                             true /* fseg memory */);
-
-    memcpy(&rsdp->signature, "RSD PTR ", 8);
-    memcpy(rsdp->oem_id, ACPI_BUILD_APPNAME6, 6);
-    /* Address to be filled by Guest linker */
-    bios_linker_loader_add_pointer(linker,
-        ACPI_BUILD_RSDP_FILE, rsdt_pa_offset, rsdt_pa_size,
-        ACPI_BUILD_TABLE_FILE, rsdt_tbl_offset);
-
-    /* Checksum to be filled by Guest linker */
-    bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE,
-        (char *)rsdp - rsdp_table->data, sizeof *rsdp,
-        (char *)&rsdp->checksum - rsdp_table->data);
-
-    return rsdp_table;
-}
-
 static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
 {
     Object *pci_host;
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 813f51317c..865f5d23f5 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -390,6 +390,9 @@ void acpi_add_table(GArray *table_offsets, GArray *table_data);
 void acpi_build_tables_init(AcpiBuildTables *tables);
 void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre);
 void
+build_rsdp(GArray *table_data,
+           BIOSLinker *linker, unsigned rsdt_tbl_offset);
+void
 build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
            const char *oem_id, const char *oem_table_id);
 void
-- 
2.17.2

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH v3 04/19] hw: acpi: Implement XSDT support for RSDP
  2018-10-29 17:01 [Qemu-devel] [PATCH v3 00/19] ACPI reorganization for hardware-reduced support Samuel Ortiz
                   ` (3 preceding siblings ...)
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 03/19] hw: acpi: Export the RSDP build API Samuel Ortiz
@ 2018-10-29 17:01 ` Samuel Ortiz
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 05/19] hw: arm: Switch to the AML build RSDP building routine Samuel Ortiz
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-29 17:01 UTC (permalink / raw)
  To: qemu-devel
  Cc: Michael S. Tsirkin, Igor Mammedov, Marcel Apfelbaum,
	Paolo Bonzini, Richard Henderson, Eduardo Habkost

XSDT is the 64-bit version of the legacy ACPI RSDT (Root System
Description Table). RSDT only allow for 32-bit addressses and have thus
been deprecated. Since ACPI version 2.0, RSDPs should point at XSDTs and
no longer RSDTs, although RSDTs are still supported for backward
compatibility.

Since version 2.0, RSDPs should add an extended checksum, a complete table
length and a version field to the table.

Here we provide a legacy API (RSDP points at RSDTs) for backward
compatibility purpose and a default, XSDT pointing API.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 hw/acpi/aml-build.c         | 41 ++++++++++++++++++++++++++++++++++++-
 hw/i386/acpi-build.c        |  2 +-
 include/hw/acpi/aml-build.h |  5 ++++-
 3 files changed, 45 insertions(+), 3 deletions(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 2d6f538f9d..77eb17b113 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1651,8 +1651,10 @@ build_xsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
                  (void *)xsdt, "XSDT", xsdt_len, 1, oem_id, oem_table_id);
 }
 
+/* Legacy RSDP pointing at an RSDT. This is deprecated */
 void
-build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset)
+build_rsdp_rsdt(GArray *rsdp_table,
+                BIOSLinker *linker, unsigned rsdt_tbl_offset)
 {
     AcpiRsdpDescriptor *rsdp = acpi_data_push(rsdp_table, sizeof *rsdp);
     unsigned rsdt_pa_size = sizeof(rsdp->rsdt_physical_address);
@@ -1675,6 +1677,43 @@ build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset)
         (char *)&rsdp->checksum - rsdp_table->data);
 }
 
+/* RSDP pointing at an XSDT */
+void
+build_rsdp(GArray *rsdp_table,
+           BIOSLinker *linker, unsigned xsdt_tbl_offset)
+{
+    AcpiRsdpDescriptor *rsdp = acpi_data_push(rsdp_table, sizeof *rsdp);
+    unsigned xsdt_pa_size = sizeof(rsdp->xsdt_physical_address);
+    unsigned xsdt_pa_offset =
+        (char *)&rsdp->xsdt_physical_address - rsdp_table->data;
+    unsigned xsdt_offset =
+        (char *)&rsdp->length - rsdp_table->data;
+
+    bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, rsdp_table, 16,
+                             true /* fseg memory */);
+
+    memcpy(&rsdp->signature, "RSD PTR ", 8);
+    memcpy(rsdp->oem_id, ACPI_BUILD_APPNAME6, 6);
+    rsdp->length = cpu_to_le32(sizeof(*rsdp));
+    /* version 2, we will use the XSDT pointer */
+    rsdp->revision = 0x02;
+
+    /* Address to be filled by Guest linker */
+    bios_linker_loader_add_pointer(linker,
+        ACPI_BUILD_RSDP_FILE, xsdt_pa_offset, xsdt_pa_size,
+        ACPI_BUILD_TABLE_FILE, xsdt_tbl_offset);
+
+    /* Legacy checksum to be filled by Guest linker */
+    bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE,
+        (char *)rsdp - rsdp_table->data, xsdt_offset,
+        (char *)&rsdp->checksum - rsdp_table->data);
+
+    /* Extended checksum to be filled by Guest linker */
+    bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE,
+        (char *)rsdp - rsdp_table->data, sizeof *rsdp,
+        (char *)&rsdp->extended_checksum - rsdp_table->data);
+}
+
 void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base,
                        uint64_t len, int node, MemoryAffinityFlags flags)
 {
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 9f1c9f4cf5..eee2eb3ed2 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -2656,7 +2656,7 @@ void acpi_build(AcpiBuildTables *tables,
                slic_oem.id, slic_oem.table_id);
 
     /* RSDP is in FSEG memory, so allocate it separately */
-    build_rsdp(tables->rsdp, tables->linker, rsdt);
+    build_rsdp_rsdt(tables->rsdp, tables->linker, rsdt);
 
     /* We'll expose it all to Guest so we want to reduce
      * chance of size changes.
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 865f5d23f5..8d1063a40b 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -390,8 +390,11 @@ void acpi_add_table(GArray *table_offsets, GArray *table_data);
 void acpi_build_tables_init(AcpiBuildTables *tables);
 void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre);
 void
+build_rsdp_rsdt(GArray *table_data,
+                BIOSLinker *linker, unsigned rsdt_tbl_offset);
+void
 build_rsdp(GArray *table_data,
-           BIOSLinker *linker, unsigned rsdt_tbl_offset);
+           BIOSLinker *linker, unsigned xsdt_tbl_offset);
 void
 build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
            const char *oem_id, const char *oem_table_id);
-- 
2.17.2

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH v3 05/19] hw: arm: Switch to the AML build RSDP building routine
  2018-10-29 17:01 [Qemu-devel] [PATCH v3 00/19] ACPI reorganization for hardware-reduced support Samuel Ortiz
                   ` (4 preceding siblings ...)
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 04/19] hw: acpi: Implement XSDT support for RSDP Samuel Ortiz
@ 2018-10-29 17:01 ` Samuel Ortiz
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 06/19] hw: acpi: Generalize AML build routines Samuel Ortiz
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-29 17:01 UTC (permalink / raw)
  To: qemu-devel
  Cc: Michael S. Tsirkin, Igor Mammedov, Shannon Zhao, Peter Maydell,
	open list:ARM ACPI Subsystem

We make the ARM virt ACPI code use the now shared build_rsdp() API from
aml-build.c. By doing so we fix a bug where the ARM implementation was
missing adding both the legacy and extended checksums, which was
building an invalid RSDP table.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 hw/arm/virt-acpi-build.c | 31 +------------------------------
 1 file changed, 1 insertion(+), 30 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index f28a2faa53..0a6a88380a 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -35,6 +35,7 @@
 #include "target/arm/cpu.h"
 #include "hw/acpi/acpi-defs.h"
 #include "hw/acpi/acpi.h"
+#include "hw/acpi/aml-build.h"
 #include "hw/nvram/fw_cfg.h"
 #include "hw/acpi/bios-linker-loader.h"
 #include "hw/loader.h"
@@ -366,36 +367,6 @@ static void acpi_dsdt_add_power_button(Aml *scope)
     aml_append(scope, dev);
 }
 
-/* RSDP */
-static GArray *
-build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned xsdt_tbl_offset)
-{
-    AcpiRsdpDescriptor *rsdp = acpi_data_push(rsdp_table, sizeof *rsdp);
-    unsigned xsdt_pa_size = sizeof(rsdp->xsdt_physical_address);
-    unsigned xsdt_pa_offset =
-        (char *)&rsdp->xsdt_physical_address - rsdp_table->data;
-
-    bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, rsdp_table, 16,
-                             true /* fseg memory */);
-
-    memcpy(&rsdp->signature, "RSD PTR ", sizeof(rsdp->signature));
-    memcpy(rsdp->oem_id, ACPI_BUILD_APPNAME6, sizeof(rsdp->oem_id));
-    rsdp->length = cpu_to_le32(sizeof(*rsdp));
-    rsdp->revision = 0x02;
-
-    /* Address to be filled by Guest linker */
-    bios_linker_loader_add_pointer(linker,
-        ACPI_BUILD_RSDP_FILE, xsdt_pa_offset, xsdt_pa_size,
-        ACPI_BUILD_TABLE_FILE, xsdt_tbl_offset);
-
-    /* Checksum to be filled by Guest linker */
-    bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE,
-        (char *)rsdp - rsdp_table->data, sizeof *rsdp,
-        (char *)&rsdp->checksum - rsdp_table->data);
-
-    return rsdp_table;
-}
-
 static void
 build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 {
-- 
2.17.2

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH v3 06/19] hw: acpi: Generalize AML build routines
  2018-10-29 17:01 [Qemu-devel] [PATCH v3 00/19] ACPI reorganization for hardware-reduced support Samuel Ortiz
                   ` (5 preceding siblings ...)
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 05/19] hw: arm: Switch to the AML build RSDP building routine Samuel Ortiz
@ 2018-10-29 17:01 ` Samuel Ortiz
  2018-10-29 19:09   ` Philippe Mathieu-Daudé
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 07/19] hw: acpi: Factorize _OSC AML across architectures Samuel Ortiz
                   ` (12 subsequent siblings)
  19 siblings, 1 reply; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-29 17:01 UTC (permalink / raw)
  To: qemu-devel
  Cc: Yang Zhong, Michael S. Tsirkin, Igor Mammedov, Shannon Zhao,
	Peter Maydell, Paolo Bonzini, Richard Henderson, Eduardo Habkost,
	Marcel Apfelbaum, open list:ARM ACPI Subsystem

From: Yang Zhong <yang.zhong@intel.com>

Most of the AML build routines under acpi-build are not even
architecture specific. They can be moved to the more generic hw/acpi
folder where they could be shared across machine types and
architectures.

Signed-off-by: Yang Zhong <yang.zhong@intel.com>
---
 hw/acpi/aml-build.c         | 498 ++++++++++++++++++++++++++++++++++
 hw/arm/virt-acpi-build.c    |   4 +-
 hw/i386/acpi-build.c        | 516 +-----------------------------------
 include/hw/acpi/aml-build.h |  25 ++
 4 files changed, 528 insertions(+), 515 deletions(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 77eb17b113..43aec8dacd 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -25,6 +25,10 @@
 #include "qemu/bswap.h"
 #include "qemu/bitops.h"
 #include "sysemu/numa.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
+#include "qemu/range.h"
+#include "hw/pci/pci_bridge.h"
 
 static GArray *build_alloc_array(void)
 {
@@ -1597,6 +1601,500 @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
     g_array_free(tables->vmgenid, mfre);
 }
 
+static void crs_range_insert(GPtrArray *ranges, uint64_t base, uint64_t limit)
+{
+    CrsRangeEntry *entry;
+
+    entry = g_malloc(sizeof(*entry));
+    entry->base = base;
+    entry->limit = limit;
+
+    g_ptr_array_add(ranges, entry);
+}
+
+static void crs_range_free(gpointer data)
+{
+    CrsRangeEntry *entry = (CrsRangeEntry *)data;
+    g_free(entry);
+}
+
+void crs_range_set_init(CrsRangeSet *range_set)
+{
+    range_set->io_ranges = g_ptr_array_new_with_free_func(crs_range_free);
+    range_set->mem_ranges = g_ptr_array_new_with_free_func(crs_range_free);
+    range_set->mem_64bit_ranges =
+            g_ptr_array_new_with_free_func(crs_range_free);
+}
+
+void crs_range_set_free(CrsRangeSet *range_set)
+{
+    g_ptr_array_free(range_set->io_ranges, true);
+    g_ptr_array_free(range_set->mem_ranges, true);
+    g_ptr_array_free(range_set->mem_64bit_ranges, true);
+}
+
+static gint crs_range_compare(gconstpointer a, gconstpointer b)
+{
+     CrsRangeEntry *entry_a = *(CrsRangeEntry **)a;
+     CrsRangeEntry *entry_b = *(CrsRangeEntry **)b;
+
+     return (int64_t)entry_a->base - (int64_t)entry_b->base;
+}
+
+/*
+ * crs_replace_with_free_ranges - given the 'used' ranges within [start - end]
+ * interval, computes the 'free' ranges from the same interval.
+ * Example: If the input array is { [a1 - a2],[b1 - b2] }, the function
+ * will return { [base - a1], [a2 - b1], [b2 - limit] }.
+ */
+void crs_replace_with_free_ranges(GPtrArray *ranges,
+                                         uint64_t start, uint64_t end)
+{
+    GPtrArray *free_ranges = g_ptr_array_new();
+    uint64_t free_base = start;
+    int i;
+
+    g_ptr_array_sort(ranges, crs_range_compare);
+    for (i = 0; i < ranges->len; i++) {
+        CrsRangeEntry *used = g_ptr_array_index(ranges, i);
+
+        if (free_base < used->base) {
+            crs_range_insert(free_ranges, free_base, used->base - 1);
+        }
+
+        free_base = used->limit + 1;
+    }
+
+    if (free_base < end) {
+        crs_range_insert(free_ranges, free_base, end);
+    }
+
+    g_ptr_array_set_size(ranges, 0);
+    for (i = 0; i < free_ranges->len; i++) {
+        g_ptr_array_add(ranges, g_ptr_array_index(free_ranges, i));
+    }
+
+    g_ptr_array_free(free_ranges, true);
+}
+
+/*
+ * crs_range_merge - merges adjacent ranges in the given array.
+ * Array elements are deleted and replaced with the merged ranges.
+ */
+static void crs_range_merge(GPtrArray *range)
+{
+    GPtrArray *tmp =  g_ptr_array_new_with_free_func(crs_range_free);
+    CrsRangeEntry *entry;
+    uint64_t range_base, range_limit;
+    int i;
+
+    if (!range->len) {
+        return;
+    }
+
+    g_ptr_array_sort(range, crs_range_compare);
+
+    entry = g_ptr_array_index(range, 0);
+    range_base = entry->base;
+    range_limit = entry->limit;
+    for (i = 1; i < range->len; i++) {
+        entry = g_ptr_array_index(range, i);
+        if (entry->base - 1 == range_limit) {
+            range_limit = entry->limit;
+        } else {
+            crs_range_insert(tmp, range_base, range_limit);
+            range_base = entry->base;
+            range_limit = entry->limit;
+        }
+    }
+    crs_range_insert(tmp, range_base, range_limit);
+
+    g_ptr_array_set_size(range, 0);
+    for (i = 0; i < tmp->len; i++) {
+        entry = g_ptr_array_index(tmp, i);
+        crs_range_insert(range, entry->base, entry->limit);
+    }
+    g_ptr_array_free(tmp, true);
+}
+
+Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set)
+{
+    Aml *crs = aml_resource_template();
+    CrsRangeSet temp_range_set;
+    CrsRangeEntry *entry;
+    uint8_t max_bus = pci_bus_num(host->bus);
+    uint8_t type;
+    int devfn;
+    int i;
+
+    crs_range_set_init(&temp_range_set);
+    for (devfn = 0; devfn < ARRAY_SIZE(host->bus->devices); devfn++) {
+        uint64_t range_base, range_limit;
+        PCIDevice *dev = host->bus->devices[devfn];
+
+        if (!dev) {
+            continue;
+        }
+
+        for (i = 0; i < PCI_NUM_REGIONS; i++) {
+            PCIIORegion *r = &dev->io_regions[i];
+
+            range_base = r->addr;
+            range_limit = r->addr + r->size - 1;
+
+            /*
+             * Work-around for old bioses
+             * that do not support multiple root buses
+             */
+            if (!range_base || range_base > range_limit) {
+                continue;
+            }
+
+            if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
+                crs_range_insert(temp_range_set.io_ranges,
+                                 range_base, range_limit);
+            } else { /* "memory" */
+                crs_range_insert(temp_range_set.mem_ranges,
+                                 range_base, range_limit);
+            }
+        }
+
+        type = dev->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION;
+        if (type == PCI_HEADER_TYPE_BRIDGE) {
+            uint8_t subordinate = dev->config[PCI_SUBORDINATE_BUS];
+            if (subordinate > max_bus) {
+                max_bus = subordinate;
+            }
+
+            range_base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_IO);
+            range_limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_IO);
+
+            /*
+             * Work-around for old bioses
+             * that do not support multiple root buses
+             */
+            if (range_base && range_base <= range_limit) {
+                crs_range_insert(temp_range_set.io_ranges,
+                                 range_base, range_limit);
+            }
+
+            range_base =
+                pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_MEMORY);
+            range_limit =
+                pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_MEMORY);
+
+            /*
+             * Work-around for old bioses
+             * that do not support multiple root buses
+             */
+            if (range_base && range_base <= range_limit) {
+                uint64_t length = range_limit - range_base + 1;
+                if (range_limit <= UINT32_MAX && length <= UINT32_MAX)  {
+                    crs_range_insert(temp_range_set.mem_ranges,
+                                     range_base, range_limit);
+                } else {
+                    crs_range_insert(temp_range_set.mem_64bit_ranges,
+                                     range_base, range_limit);
+                }
+            }
+
+            range_base =
+                pci_bridge_get_base(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
+            range_limit =
+                pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
+
+            /*
+             * Work-around for old bioses
+             * that do not support multiple root buses
+             */
+            if (range_base && range_base <= range_limit) {
+                uint64_t length = range_limit - range_base + 1;
+                if (range_limit <= UINT32_MAX && length <= UINT32_MAX) {
+                    crs_range_insert(temp_range_set.mem_ranges,
+                                     range_base, range_limit);
+                } else {
+                    crs_range_insert(temp_range_set.mem_64bit_ranges,
+                                     range_base, range_limit);
+                }
+            }
+        }
+    }
+
+    crs_range_merge(temp_range_set.io_ranges);
+    for (i = 0; i < temp_range_set.io_ranges->len; i++) {
+        entry = g_ptr_array_index(temp_range_set.io_ranges, i);
+        aml_append(crs,
+                   aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,
+                               AML_POS_DECODE, AML_ENTIRE_RANGE,
+                               0, entry->base, entry->limit, 0,
+                               entry->limit - entry->base + 1));
+        crs_range_insert(range_set->io_ranges, entry->base, entry->limit);
+    }
+
+    crs_range_merge(temp_range_set.mem_ranges);
+    for (i = 0; i < temp_range_set.mem_ranges->len; i++) {
+        entry = g_ptr_array_index(temp_range_set.mem_ranges, i);
+        aml_append(crs,
+                   aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED,
+                                    AML_MAX_FIXED, AML_NON_CACHEABLE,
+                                    AML_READ_WRITE,
+                                    0, entry->base, entry->limit, 0,
+                                    entry->limit - entry->base + 1));
+        crs_range_insert(range_set->mem_ranges, entry->base, entry->limit);
+    }
+
+    crs_range_merge(temp_range_set.mem_64bit_ranges);
+    for (i = 0; i < temp_range_set.mem_64bit_ranges->len; i++) {
+        entry = g_ptr_array_index(temp_range_set.mem_64bit_ranges, i);
+        aml_append(crs,
+                   aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED,
+                                    AML_MAX_FIXED, AML_NON_CACHEABLE,
+                                    AML_READ_WRITE,
+                                    0, entry->base, entry->limit, 0,
+                                    entry->limit - entry->base + 1));
+        crs_range_insert(range_set->mem_64bit_ranges,
+                         entry->base, entry->limit);
+    }
+
+    crs_range_set_free(&temp_range_set);
+
+    aml_append(crs,
+        aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
+                            0,
+                            pci_bus_num(host->bus),
+                            max_bus,
+                            0,
+                            max_bus - pci_bus_num(host->bus) + 1));
+
+    return crs;
+}
+
+Aml *build_osc_method(void)
+{
+    Aml *if_ctx;
+    Aml *if_ctx2;
+    Aml *else_ctx;
+    Aml *method;
+    Aml *a_cwd1 = aml_name("CDW1");
+    Aml *a_ctrl = aml_local(0);
+
+    method = aml_method("_OSC", 4, AML_NOTSERIALIZED);
+    aml_append(method, aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1"));
+
+    if_ctx = aml_if(aml_equal(
+        aml_arg(0), aml_touuid("33DB4D5B-1FF7-401C-9657-7441C03DD766")));
+    aml_append(if_ctx, aml_create_dword_field(aml_arg(3), aml_int(4), "CDW2"));
+    aml_append(if_ctx, aml_create_dword_field(aml_arg(3), aml_int(8), "CDW3"));
+
+    aml_append(if_ctx, aml_store(aml_name("CDW3"), a_ctrl));
+
+    /*
+     * Always allow native PME, AER (no dependencies)
+     * Allow SHPC (PCI bridges can have SHPC controller)
+     */
+    aml_append(if_ctx, aml_and(a_ctrl, aml_int(0x1F), a_ctrl));
+
+    if_ctx2 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(1))));
+    /* Unknown revision */
+    aml_append(if_ctx2, aml_or(a_cwd1, aml_int(0x08), a_cwd1));
+    aml_append(if_ctx, if_ctx2);
+
+    if_ctx2 = aml_if(aml_lnot(aml_equal(aml_name("CDW3"), a_ctrl)));
+    /* Capabilities bits were masked */
+    aml_append(if_ctx2, aml_or(a_cwd1, aml_int(0x10), a_cwd1));
+    aml_append(if_ctx, if_ctx2);
+
+    /* Update DWORD3 in the buffer */
+    aml_append(if_ctx, aml_store(a_ctrl, aml_name("CDW3")));
+    aml_append(method, if_ctx);
+
+    else_ctx = aml_else();
+    /* Unrecognized UUID */
+    aml_append(else_ctx, aml_or(a_cwd1, aml_int(4), a_cwd1));
+    aml_append(method, else_ctx);
+
+    aml_append(method, aml_return(aml_arg(3)));
+    return method;
+}
+
+void
+build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info)
+{
+    AcpiTableMcfg *mcfg;
+    const char *sig;
+    int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]);
+
+    mcfg = acpi_data_push(table_data, len);
+    mcfg->allocation[0].address = cpu_to_le64(info->mcfg_base);
+    /* Only a single allocation so no need to play with segments */
+    mcfg->allocation[0].pci_segment = cpu_to_le16(0);
+    mcfg->allocation[0].start_bus_number = 0;
+    mcfg->allocation[0].end_bus_number = PCIE_MMCFG_BUS(info->mcfg_size - 1);
+
+    /* MCFG is used for ECAM which can be enabled or disabled by guest.
+     * To avoid table size changes (which create migration issues),
+     * always create the table even if there are no allocations,
+     * but set the signature to a reserved value in this case.
+     * ACPI spec requires OSPMs to ignore such tables.
+     */
+    if (info->mcfg_base == PCIE_BASE_ADDR_UNMAPPED) {
+        /* Reserved signature: ignored by OSPM */
+        sig = "QEMU";
+    } else {
+        sig = "MCFG";
+    }
+    build_header(linker, table_data, (void *)mcfg, sig, len, 1, NULL, NULL);
+}
+
+Aml *build_gsi_link_dev(const char *name, uint8_t uid, uint8_t gsi)
+{
+    Aml *dev;
+    Aml *crs;
+    Aml *method;
+    uint32_t irqs;
+
+    dev = aml_device("%s", name);
+    aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C0F")));
+    aml_append(dev, aml_name_decl("_UID", aml_int(uid)));
+
+    crs = aml_resource_template();
+    irqs = gsi;
+    aml_append(crs, aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
+                                  AML_SHARED, &irqs, 1));
+    aml_append(dev, aml_name_decl("_PRS", crs));
+
+    aml_append(dev, aml_name_decl("_CRS", crs));
+
+    /*
+     * _DIS can be no-op because the interrupt cannot be disabled.
+     */
+    method = aml_method("_DIS", 0, AML_NOTSERIALIZED);
+    aml_append(dev, method);
+
+    method = aml_method("_SRS", 1, AML_NOTSERIALIZED);
+    aml_append(dev, method);
+
+    return dev;
+}
+
+/**
+ * build_prt_entry:
+ * @link_name: link name for PCI route entry
+ *
+ * build AML package containing a PCI route entry for @link_name
+ */
+static Aml *build_prt_entry(const char *link_name)
+{
+    Aml *a_zero = aml_int(0);
+    Aml *pkg = aml_package(4);
+    aml_append(pkg, a_zero);
+    aml_append(pkg, a_zero);
+    aml_append(pkg, aml_name("%s", link_name));
+    aml_append(pkg, a_zero);
+    return pkg;
+}
+
+/*
+ * initialize_route - Initialize the interrupt routing rule
+ * through a specific LINK:
+ *  if (lnk_idx == idx)
+ *      route using link 'link_name'
+ */
+static Aml *initialize_route(Aml *route, const char *link_name,
+                             Aml *lnk_idx, int idx)
+{
+    Aml *if_ctx = aml_if(aml_equal(lnk_idx, aml_int(idx)));
+    Aml *pkg = build_prt_entry(link_name);
+
+    aml_append(if_ctx, aml_store(pkg, route));
+
+    return if_ctx;
+}
+
+/*
+ * build_prt - Define interrupt rounting rules
+ *
+ * Returns an array of 128 routes, one for each device,
+ * based on device location.
+ * The main goal is to equaly distribute the interrupts
+ * over the 4 existing ACPI links (works only for i440fx).
+ * The hash function is  (slot + pin) & 3 -> "LNK[D|A|B|C]".
+ *
+ */
+Aml *build_prt(bool is_pci0_prt)
+{
+    Aml *method, *while_ctx, *pin, *res;
+
+    method = aml_method("_PRT", 0, AML_NOTSERIALIZED);
+    res = aml_local(0);
+    pin = aml_local(1);
+    aml_append(method, aml_store(aml_package(128), res));
+    aml_append(method, aml_store(aml_int(0), pin));
+
+    /* while (pin < 128) */
+    while_ctx = aml_while(aml_lless(pin, aml_int(128)));
+    {
+        Aml *slot = aml_local(2);
+        Aml *lnk_idx = aml_local(3);
+        Aml *route = aml_local(4);
+
+        /* slot = pin >> 2 */
+        aml_append(while_ctx,
+                   aml_store(aml_shiftright(pin, aml_int(2), NULL), slot));
+        /* lnk_idx = (slot + pin) & 3 */
+        aml_append(while_ctx,
+            aml_store(aml_and(aml_add(pin, slot, NULL), aml_int(3), NULL),
+                      lnk_idx));
+
+        /* route[2] = "LNK[D|A|B|C]", selection based on pin % 3  */
+        aml_append(while_ctx, initialize_route(route, "LNKD", lnk_idx, 0));
+        if (is_pci0_prt) {
+            Aml *if_device_1, *if_pin_4, *else_pin_4;
+
+            /* device 1 is the power-management device, needs SCI */
+            if_device_1 = aml_if(aml_equal(lnk_idx, aml_int(1)));
+            {
+                if_pin_4 = aml_if(aml_equal(pin, aml_int(4)));
+                {
+                    aml_append(if_pin_4,
+                        aml_store(build_prt_entry("LNKS"), route));
+                }
+                aml_append(if_device_1, if_pin_4);
+                else_pin_4 = aml_else();
+                {
+                    aml_append(else_pin_4,
+                        aml_store(build_prt_entry("LNKA"), route));
+                }
+                aml_append(if_device_1, else_pin_4);
+            }
+            aml_append(while_ctx, if_device_1);
+        } else {
+            aml_append(while_ctx, initialize_route(route, "LNKA", lnk_idx, 1));
+        }
+        aml_append(while_ctx, initialize_route(route, "LNKB", lnk_idx, 2));
+        aml_append(while_ctx, initialize_route(route, "LNKC", lnk_idx, 3));
+
+        /* route[0] = 0x[slot]FFFF */
+        aml_append(while_ctx,
+            aml_store(aml_or(aml_shiftleft(slot, aml_int(16)), aml_int(0xFFFF),
+                             NULL),
+                      aml_index(route, aml_int(0))));
+        /* route[1] = pin & 3 */
+        aml_append(while_ctx,
+            aml_store(aml_and(pin, aml_int(3), NULL),
+                      aml_index(route, aml_int(1))));
+        /* res[pin] = route */
+        aml_append(while_ctx, aml_store(route, aml_index(res, pin)));
+        /* pin++ */
+        aml_append(while_ctx, aml_increment(pin));
+    }
+    aml_append(method, while_ctx);
+    /* return res*/
+    aml_append(method, aml_return(res));
+
+    return method;
+}
+
 /* Build rsdt table */
 void
 build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 0a6a88380a..6822ee4eaa 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -546,7 +546,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 }
 
 static void
-build_mcfg(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
+virt_build_mcfg(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 {
     AcpiTableMcfg *mcfg;
     const MemMapEntry *memmap = vms->memmap;
@@ -791,7 +791,7 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
     build_gtdt(tables_blob, tables->linker, vms);
 
     acpi_add_table(table_offsets, tables_blob);
-    build_mcfg(tables_blob, tables->linker, vms);
+    virt_build_mcfg(tables_blob, tables->linker, vms);
 
     acpi_add_table(table_offsets, tables_blob);
     build_spcr(tables_blob, tables->linker, vms);
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index eee2eb3ed2..3ab68fd24d 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -86,11 +86,6 @@
 /* Default IOAPIC ID */
 #define ACPI_BUILD_IOAPIC_ID 0x0
 
-typedef struct AcpiMcfgInfo {
-    uint64_t mcfg_base;
-    uint32_t mcfg_size;
-} AcpiMcfgInfo;
-
 typedef struct AcpiPmInfo {
     bool s3_disabled;
     bool s4_disabled;
@@ -567,403 +562,6 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
     qobject_unref(bsel);
 }
 
-/**
- * build_prt_entry:
- * @link_name: link name for PCI route entry
- *
- * build AML package containing a PCI route entry for @link_name
- */
-static Aml *build_prt_entry(const char *link_name)
-{
-    Aml *a_zero = aml_int(0);
-    Aml *pkg = aml_package(4);
-    aml_append(pkg, a_zero);
-    aml_append(pkg, a_zero);
-    aml_append(pkg, aml_name("%s", link_name));
-    aml_append(pkg, a_zero);
-    return pkg;
-}
-
-/*
- * initialize_route - Initialize the interrupt routing rule
- * through a specific LINK:
- *  if (lnk_idx == idx)
- *      route using link 'link_name'
- */
-static Aml *initialize_route(Aml *route, const char *link_name,
-                             Aml *lnk_idx, int idx)
-{
-    Aml *if_ctx = aml_if(aml_equal(lnk_idx, aml_int(idx)));
-    Aml *pkg = build_prt_entry(link_name);
-
-    aml_append(if_ctx, aml_store(pkg, route));
-
-    return if_ctx;
-}
-
-/*
- * build_prt - Define interrupt rounting rules
- *
- * Returns an array of 128 routes, one for each device,
- * based on device location.
- * The main goal is to equaly distribute the interrupts
- * over the 4 existing ACPI links (works only for i440fx).
- * The hash function is  (slot + pin) & 3 -> "LNK[D|A|B|C]".
- *
- */
-static Aml *build_prt(bool is_pci0_prt)
-{
-    Aml *method, *while_ctx, *pin, *res;
-
-    method = aml_method("_PRT", 0, AML_NOTSERIALIZED);
-    res = aml_local(0);
-    pin = aml_local(1);
-    aml_append(method, aml_store(aml_package(128), res));
-    aml_append(method, aml_store(aml_int(0), pin));
-
-    /* while (pin < 128) */
-    while_ctx = aml_while(aml_lless(pin, aml_int(128)));
-    {
-        Aml *slot = aml_local(2);
-        Aml *lnk_idx = aml_local(3);
-        Aml *route = aml_local(4);
-
-        /* slot = pin >> 2 */
-        aml_append(while_ctx,
-                   aml_store(aml_shiftright(pin, aml_int(2), NULL), slot));
-        /* lnk_idx = (slot + pin) & 3 */
-        aml_append(while_ctx,
-            aml_store(aml_and(aml_add(pin, slot, NULL), aml_int(3), NULL),
-                      lnk_idx));
-
-        /* route[2] = "LNK[D|A|B|C]", selection based on pin % 3  */
-        aml_append(while_ctx, initialize_route(route, "LNKD", lnk_idx, 0));
-        if (is_pci0_prt) {
-            Aml *if_device_1, *if_pin_4, *else_pin_4;
-
-            /* device 1 is the power-management device, needs SCI */
-            if_device_1 = aml_if(aml_equal(lnk_idx, aml_int(1)));
-            {
-                if_pin_4 = aml_if(aml_equal(pin, aml_int(4)));
-                {
-                    aml_append(if_pin_4,
-                        aml_store(build_prt_entry("LNKS"), route));
-                }
-                aml_append(if_device_1, if_pin_4);
-                else_pin_4 = aml_else();
-                {
-                    aml_append(else_pin_4,
-                        aml_store(build_prt_entry("LNKA"), route));
-                }
-                aml_append(if_device_1, else_pin_4);
-            }
-            aml_append(while_ctx, if_device_1);
-        } else {
-            aml_append(while_ctx, initialize_route(route, "LNKA", lnk_idx, 1));
-        }
-        aml_append(while_ctx, initialize_route(route, "LNKB", lnk_idx, 2));
-        aml_append(while_ctx, initialize_route(route, "LNKC", lnk_idx, 3));
-
-        /* route[0] = 0x[slot]FFFF */
-        aml_append(while_ctx,
-            aml_store(aml_or(aml_shiftleft(slot, aml_int(16)), aml_int(0xFFFF),
-                             NULL),
-                      aml_index(route, aml_int(0))));
-        /* route[1] = pin & 3 */
-        aml_append(while_ctx,
-            aml_store(aml_and(pin, aml_int(3), NULL),
-                      aml_index(route, aml_int(1))));
-        /* res[pin] = route */
-        aml_append(while_ctx, aml_store(route, aml_index(res, pin)));
-        /* pin++ */
-        aml_append(while_ctx, aml_increment(pin));
-    }
-    aml_append(method, while_ctx);
-    /* return res*/
-    aml_append(method, aml_return(res));
-
-    return method;
-}
-
-typedef struct CrsRangeEntry {
-    uint64_t base;
-    uint64_t limit;
-} CrsRangeEntry;
-
-static void crs_range_insert(GPtrArray *ranges, uint64_t base, uint64_t limit)
-{
-    CrsRangeEntry *entry;
-
-    entry = g_malloc(sizeof(*entry));
-    entry->base = base;
-    entry->limit = limit;
-
-    g_ptr_array_add(ranges, entry);
-}
-
-static void crs_range_free(gpointer data)
-{
-    CrsRangeEntry *entry = (CrsRangeEntry *)data;
-    g_free(entry);
-}
-
-typedef struct CrsRangeSet {
-    GPtrArray *io_ranges;
-    GPtrArray *mem_ranges;
-    GPtrArray *mem_64bit_ranges;
- } CrsRangeSet;
-
-static void crs_range_set_init(CrsRangeSet *range_set)
-{
-    range_set->io_ranges = g_ptr_array_new_with_free_func(crs_range_free);
-    range_set->mem_ranges = g_ptr_array_new_with_free_func(crs_range_free);
-    range_set->mem_64bit_ranges =
-            g_ptr_array_new_with_free_func(crs_range_free);
-}
-
-static void crs_range_set_free(CrsRangeSet *range_set)
-{
-    g_ptr_array_free(range_set->io_ranges, true);
-    g_ptr_array_free(range_set->mem_ranges, true);
-    g_ptr_array_free(range_set->mem_64bit_ranges, true);
-}
-
-static gint crs_range_compare(gconstpointer a, gconstpointer b)
-{
-     CrsRangeEntry *entry_a = *(CrsRangeEntry **)a;
-     CrsRangeEntry *entry_b = *(CrsRangeEntry **)b;
-
-     return (int64_t)entry_a->base - (int64_t)entry_b->base;
-}
-
-/*
- * crs_replace_with_free_ranges - given the 'used' ranges within [start - end]
- * interval, computes the 'free' ranges from the same interval.
- * Example: If the input array is { [a1 - a2],[b1 - b2] }, the function
- * will return { [base - a1], [a2 - b1], [b2 - limit] }.
- */
-static void crs_replace_with_free_ranges(GPtrArray *ranges,
-                                         uint64_t start, uint64_t end)
-{
-    GPtrArray *free_ranges = g_ptr_array_new();
-    uint64_t free_base = start;
-    int i;
-
-    g_ptr_array_sort(ranges, crs_range_compare);
-    for (i = 0; i < ranges->len; i++) {
-        CrsRangeEntry *used = g_ptr_array_index(ranges, i);
-
-        if (free_base < used->base) {
-            crs_range_insert(free_ranges, free_base, used->base - 1);
-        }
-
-        free_base = used->limit + 1;
-    }
-
-    if (free_base < end) {
-        crs_range_insert(free_ranges, free_base, end);
-    }
-
-    g_ptr_array_set_size(ranges, 0);
-    for (i = 0; i < free_ranges->len; i++) {
-        g_ptr_array_add(ranges, g_ptr_array_index(free_ranges, i));
-    }
-
-    g_ptr_array_free(free_ranges, true);
-}
-
-/*
- * crs_range_merge - merges adjacent ranges in the given array.
- * Array elements are deleted and replaced with the merged ranges.
- */
-static void crs_range_merge(GPtrArray *range)
-{
-    GPtrArray *tmp =  g_ptr_array_new_with_free_func(crs_range_free);
-    CrsRangeEntry *entry;
-    uint64_t range_base, range_limit;
-    int i;
-
-    if (!range->len) {
-        return;
-    }
-
-    g_ptr_array_sort(range, crs_range_compare);
-
-    entry = g_ptr_array_index(range, 0);
-    range_base = entry->base;
-    range_limit = entry->limit;
-    for (i = 1; i < range->len; i++) {
-        entry = g_ptr_array_index(range, i);
-        if (entry->base - 1 == range_limit) {
-            range_limit = entry->limit;
-        } else {
-            crs_range_insert(tmp, range_base, range_limit);
-            range_base = entry->base;
-            range_limit = entry->limit;
-        }
-    }
-    crs_range_insert(tmp, range_base, range_limit);
-
-    g_ptr_array_set_size(range, 0);
-    for (i = 0; i < tmp->len; i++) {
-        entry = g_ptr_array_index(tmp, i);
-        crs_range_insert(range, entry->base, entry->limit);
-    }
-    g_ptr_array_free(tmp, true);
-}
-
-static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set)
-{
-    Aml *crs = aml_resource_template();
-    CrsRangeSet temp_range_set;
-    CrsRangeEntry *entry;
-    uint8_t max_bus = pci_bus_num(host->bus);
-    uint8_t type;
-    int devfn;
-    int i;
-
-    crs_range_set_init(&temp_range_set);
-    for (devfn = 0; devfn < ARRAY_SIZE(host->bus->devices); devfn++) {
-        uint64_t range_base, range_limit;
-        PCIDevice *dev = host->bus->devices[devfn];
-
-        if (!dev) {
-            continue;
-        }
-
-        for (i = 0; i < PCI_NUM_REGIONS; i++) {
-            PCIIORegion *r = &dev->io_regions[i];
-
-            range_base = r->addr;
-            range_limit = r->addr + r->size - 1;
-
-            /*
-             * Work-around for old bioses
-             * that do not support multiple root buses
-             */
-            if (!range_base || range_base > range_limit) {
-                continue;
-            }
-
-            if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
-                crs_range_insert(temp_range_set.io_ranges,
-                                 range_base, range_limit);
-            } else { /* "memory" */
-                crs_range_insert(temp_range_set.mem_ranges,
-                                 range_base, range_limit);
-            }
-        }
-
-        type = dev->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION;
-        if (type == PCI_HEADER_TYPE_BRIDGE) {
-            uint8_t subordinate = dev->config[PCI_SUBORDINATE_BUS];
-            if (subordinate > max_bus) {
-                max_bus = subordinate;
-            }
-
-            range_base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_IO);
-            range_limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_IO);
-
-            /*
-             * Work-around for old bioses
-             * that do not support multiple root buses
-             */
-            if (range_base && range_base <= range_limit) {
-                crs_range_insert(temp_range_set.io_ranges,
-                                 range_base, range_limit);
-            }
-
-            range_base =
-                pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_MEMORY);
-            range_limit =
-                pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_MEMORY);
-
-            /*
-             * Work-around for old bioses
-             * that do not support multiple root buses
-             */
-            if (range_base && range_base <= range_limit) {
-                uint64_t length = range_limit - range_base + 1;
-                if (range_limit <= UINT32_MAX && length <= UINT32_MAX) {
-                    crs_range_insert(temp_range_set.mem_ranges,
-                                     range_base, range_limit);
-                } else {
-                    crs_range_insert(temp_range_set.mem_64bit_ranges,
-                                     range_base, range_limit);
-                }
-            }
-
-            range_base =
-                pci_bridge_get_base(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
-            range_limit =
-                pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
-
-            /*
-             * Work-around for old bioses
-             * that do not support multiple root buses
-             */
-            if (range_base && range_base <= range_limit) {
-                uint64_t length = range_limit - range_base + 1;
-                if (range_limit <= UINT32_MAX && length <= UINT32_MAX) {
-                    crs_range_insert(temp_range_set.mem_ranges,
-                                     range_base, range_limit);
-                } else {
-                    crs_range_insert(temp_range_set.mem_64bit_ranges,
-                                     range_base, range_limit);
-                }
-            }
-        }
-    }
-
-    crs_range_merge(temp_range_set.io_ranges);
-    for (i = 0; i < temp_range_set.io_ranges->len; i++) {
-        entry = g_ptr_array_index(temp_range_set.io_ranges, i);
-        aml_append(crs,
-                   aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,
-                               AML_POS_DECODE, AML_ENTIRE_RANGE,
-                               0, entry->base, entry->limit, 0,
-                               entry->limit - entry->base + 1));
-        crs_range_insert(range_set->io_ranges, entry->base, entry->limit);
-    }
-
-    crs_range_merge(temp_range_set.mem_ranges);
-    for (i = 0; i < temp_range_set.mem_ranges->len; i++) {
-        entry = g_ptr_array_index(temp_range_set.mem_ranges, i);
-        aml_append(crs,
-                   aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED,
-                                    AML_MAX_FIXED, AML_NON_CACHEABLE,
-                                    AML_READ_WRITE,
-                                    0, entry->base, entry->limit, 0,
-                                    entry->limit - entry->base + 1));
-        crs_range_insert(range_set->mem_ranges, entry->base, entry->limit);
-    }
-
-    crs_range_merge(temp_range_set.mem_64bit_ranges);
-    for (i = 0; i < temp_range_set.mem_64bit_ranges->len; i++) {
-        entry = g_ptr_array_index(temp_range_set.mem_64bit_ranges, i);
-        aml_append(crs,
-                   aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED,
-                                    AML_MAX_FIXED, AML_NON_CACHEABLE,
-                                    AML_READ_WRITE,
-                                    0, entry->base, entry->limit, 0,
-                                    entry->limit - entry->base + 1));
-        crs_range_insert(range_set->mem_64bit_ranges,
-                         entry->base, entry->limit);
-    }
-
-    crs_range_set_free(&temp_range_set);
-
-    aml_append(crs,
-        aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
-                            0,
-                            pci_bus_num(host->bus),
-                            max_bus,
-                            0,
-                            max_bus - pci_bus_num(host->bus) + 1));
-
-    return crs;
-}
-
 static void build_hpet_aml(Aml *table)
 {
     Aml *crs;
@@ -1334,37 +932,6 @@ static Aml *build_link_dev(const char *name, uint8_t uid, Aml *reg)
     return dev;
  }
 
-static Aml *build_gsi_link_dev(const char *name, uint8_t uid, uint8_t gsi)
-{
-    Aml *dev;
-    Aml *crs;
-    Aml *method;
-    uint32_t irqs;
-
-    dev = aml_device("%s", name);
-    aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C0F")));
-    aml_append(dev, aml_name_decl("_UID", aml_int(uid)));
-
-    crs = aml_resource_template();
-    irqs = gsi;
-    aml_append(crs, aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
-                                  AML_SHARED, &irqs, 1));
-    aml_append(dev, aml_name_decl("_PRS", crs));
-
-    aml_append(dev, aml_name_decl("_CRS", crs));
-
-    /*
-     * _DIS can be no-op because the interrupt cannot be disabled.
-     */
-    method = aml_method("_DIS", 0, AML_NOTSERIALIZED);
-    aml_append(dev, method);
-
-    method = aml_method("_SRS", 1, AML_NOTSERIALIZED);
-    aml_append(dev, method);
-
-    return dev;
-}
-
 /* _CRS method - get current settings */
 static Aml *build_iqcr_method(bool is_piix4)
 {
@@ -1728,54 +1295,6 @@ static void build_piix4_pci_hotplug(Aml *table)
     aml_append(table, scope);
 }
 
-static Aml *build_q35_osc_method(void)
-{
-    Aml *if_ctx;
-    Aml *if_ctx2;
-    Aml *else_ctx;
-    Aml *method;
-    Aml *a_cwd1 = aml_name("CDW1");
-    Aml *a_ctrl = aml_local(0);
-
-    method = aml_method("_OSC", 4, AML_NOTSERIALIZED);
-    aml_append(method, aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1"));
-
-    if_ctx = aml_if(aml_equal(
-        aml_arg(0), aml_touuid("33DB4D5B-1FF7-401C-9657-7441C03DD766")));
-    aml_append(if_ctx, aml_create_dword_field(aml_arg(3), aml_int(4), "CDW2"));
-    aml_append(if_ctx, aml_create_dword_field(aml_arg(3), aml_int(8), "CDW3"));
-
-    aml_append(if_ctx, aml_store(aml_name("CDW3"), a_ctrl));
-
-    /*
-     * Always allow native PME, AER (no dependencies)
-     * Allow SHPC (PCI bridges can have SHPC controller)
-     */
-    aml_append(if_ctx, aml_and(a_ctrl, aml_int(0x1F), a_ctrl));
-
-    if_ctx2 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(1))));
-    /* Unknown revision */
-    aml_append(if_ctx2, aml_or(a_cwd1, aml_int(0x08), a_cwd1));
-    aml_append(if_ctx, if_ctx2);
-
-    if_ctx2 = aml_if(aml_lnot(aml_equal(aml_name("CDW3"), a_ctrl)));
-    /* Capabilities bits were masked */
-    aml_append(if_ctx2, aml_or(a_cwd1, aml_int(0x10), a_cwd1));
-    aml_append(if_ctx, if_ctx2);
-
-    /* Update DWORD3 in the buffer */
-    aml_append(if_ctx, aml_store(a_ctrl, aml_name("CDW3")));
-    aml_append(method, if_ctx);
-
-    else_ctx = aml_else();
-    /* Unrecognized UUID */
-    aml_append(else_ctx, aml_or(a_cwd1, aml_int(4), a_cwd1));
-    aml_append(method, else_ctx);
-
-    aml_append(method, aml_return(aml_arg(3)));
-    return method;
-}
-
 static void
 build_dsdt(GArray *table_data, BIOSLinker *linker,
            AcpiPmInfo *pm, AcpiMiscInfo *misc,
@@ -1818,7 +1337,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
         aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03")));
         aml_append(dev, aml_name_decl("_ADR", aml_int(0)));
         aml_append(dev, aml_name_decl("_UID", aml_int(1)));
-        aml_append(dev, build_q35_osc_method());
+        aml_append(dev, build_osc_method());
         aml_append(sb_scope, dev);
         aml_append(dsdt, sb_scope);
 
@@ -1883,7 +1402,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
             aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03")));
             aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
             if (pci_bus_is_express(bus)) {
-                aml_append(dev, build_q35_osc_method());
+                aml_append(dev, build_osc_method());
             }
 
             if (numa_node != NUMA_NODE_UNASSIGNED) {
@@ -2369,35 +1888,6 @@ build_srat(GArray *table_data, BIOSLinker *linker,
                  table_data->len - srat_start, 1, NULL, NULL);
 }
 
-static void
-build_mcfg_q35(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info)
-{
-    AcpiTableMcfg *mcfg;
-    const char *sig;
-    int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]);
-
-    mcfg = acpi_data_push(table_data, len);
-    mcfg->allocation[0].address = cpu_to_le64(info->mcfg_base);
-    /* Only a single allocation so no need to play with segments */
-    mcfg->allocation[0].pci_segment = cpu_to_le16(0);
-    mcfg->allocation[0].start_bus_number = 0;
-    mcfg->allocation[0].end_bus_number = PCIE_MMCFG_BUS(info->mcfg_size - 1);
-
-    /* MCFG is used for ECAM which can be enabled or disabled by guest.
-     * To avoid table size changes (which create migration issues),
-     * always create the table even if there are no allocations,
-     * but set the signature to a reserved value in this case.
-     * ACPI spec requires OSPMs to ignore such tables.
-     */
-    if (info->mcfg_base == PCIE_BASE_ADDR_UNMAPPED) {
-        /* Reserved signature: ignored by OSPM */
-        sig = "QEMU";
-    } else {
-        sig = "MCFG";
-    }
-    build_header(linker, table_data, (void *)mcfg, sig, len, 1, NULL, NULL);
-}
-
 /*
  * VT-d spec 8.1 DMA Remapping Reporting Structure
  * (version Oct. 2014 or later)
@@ -2625,7 +2115,7 @@ void acpi_build(AcpiBuildTables *tables,
     }
     if (acpi_get_mcfg(&mcfg)) {
         acpi_add_table(table_offsets, tables_blob);
-        build_mcfg_q35(tables_blob, tables->linker, &mcfg);
+        build_mcfg(tables_blob, tables->linker, &mcfg);
     }
     if (x86_iommu_get_default()) {
         IommuType IOMMUType = x86_iommu_get_type();
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 8d1063a40b..cd744e9472 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -3,6 +3,7 @@
 
 #include "hw/acpi/acpi-defs.h"
 #include "hw/acpi/bios-linker-loader.h"
+#include "hw/pci/pcie_host.h"
 
 /* Reserve RAM space for tables: add another order of magnitude. */
 #define ACPI_BUILD_TABLE_MAX_SIZE         0x200000
@@ -224,6 +225,21 @@ struct AcpiBuildTables {
     BIOSLinker *linker;
 } AcpiBuildTables;
 
+typedef struct AcpiMcfgInfo {
+    uint64_t mcfg_base;
+    uint32_t mcfg_size;
+} AcpiMcfgInfo;
+
+typedef struct CrsRangeEntry {
+    uint64_t base;
+    uint64_t limit;
+} CrsRangeEntry;
+
+typedef struct CrsRangeSet {
+    GPtrArray *io_ranges;
+    GPtrArray *mem_ranges;
+    GPtrArray *mem_64bit_ranges;
+} CrsRangeSet;
 /**
  * init_aml_allocator:
  *
@@ -389,6 +405,15 @@ void acpi_align_size(GArray *blob, unsigned align);
 void acpi_add_table(GArray *table_offsets, GArray *table_data);
 void acpi_build_tables_init(AcpiBuildTables *tables);
 void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre);
+Aml *build_osc_method(void);
+void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info);
+Aml *build_gsi_link_dev(const char *name, uint8_t uid, uint8_t gsi);
+Aml *build_prt(bool is_pci0_prt);
+void crs_range_set_init(CrsRangeSet *range_set);
+Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set);
+void crs_replace_with_free_ranges(GPtrArray *ranges,
+                                  uint64_t start, uint64_t end);
+void crs_range_set_free(CrsRangeSet *range_set);
 void
 build_rsdp_rsdt(GArray *table_data,
                 BIOSLinker *linker, unsigned rsdt_tbl_offset);
-- 
2.17.2

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH v3 07/19] hw: acpi: Factorize _OSC AML across architectures
  2018-10-29 17:01 [Qemu-devel] [PATCH v3 00/19] ACPI reorganization for hardware-reduced support Samuel Ortiz
                   ` (6 preceding siblings ...)
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 06/19] hw: acpi: Generalize AML build routines Samuel Ortiz
@ 2018-10-29 17:01 ` Samuel Ortiz
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 08/19] hw: i386: Refactor PCI host getter Samuel Ortiz
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-29 17:01 UTC (permalink / raw)
  To: qemu-devel
  Cc: Yang Zhong, Michael S. Tsirkin, Igor Mammedov, Shannon Zhao,
	Peter Maydell, Marcel Apfelbaum, Paolo Bonzini,
	Richard Henderson, Eduardo Habkost, open list:ARM ACPI Subsystem

From: Yang Zhong <yang.zhong@intel.com>

The _OSC AML table is almost identical between the i386 Q35 and arm virt
machine types. We can make it slightly more generic and share it across
all PCIe architectures.

Signed-off-by: Yang Zhong <yang.zhong@intel.com>
---
 hw/acpi/aml-build.c         | 84 +++++++++++++++++++------------------
 hw/arm/virt-acpi-build.c    | 45 ++------------------
 hw/i386/acpi-build.c        |  6 ++-
 include/hw/acpi/acpi-defs.h | 14 +++++++
 include/hw/acpi/aml-build.h |  2 +-
 5 files changed, 66 insertions(+), 85 deletions(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 43aec8dacd..52ac39acdb 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1869,51 +1869,55 @@ Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set)
     return crs;
 }
 
-Aml *build_osc_method(void)
+/*
+ * ctrl_mask is the _OSC capabilities buffer control field mask.
+ */
+Aml *build_osc_method(uint32_t ctrl_mask)
 {
-    Aml *if_ctx;
-    Aml *if_ctx2;
-    Aml *else_ctx;
-    Aml *method;
-    Aml *a_cwd1 = aml_name("CDW1");
-    Aml *a_ctrl = aml_local(0);
+    Aml *ifctx, *ifctx1, *elsectx, *method, *UUID;
 
     method = aml_method("_OSC", 4, AML_NOTSERIALIZED);
-    aml_append(method, aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1"));
-
-    if_ctx = aml_if(aml_equal(
-        aml_arg(0), aml_touuid("33DB4D5B-1FF7-401C-9657-7441C03DD766")));
-    aml_append(if_ctx, aml_create_dword_field(aml_arg(3), aml_int(4), "CDW2"));
-    aml_append(if_ctx, aml_create_dword_field(aml_arg(3), aml_int(8), "CDW3"));
-
-    aml_append(if_ctx, aml_store(aml_name("CDW3"), a_ctrl));
-
-    /*
-     * Always allow native PME, AER (no dependencies)
-     * Allow SHPC (PCI bridges can have SHPC controller)
+    aml_append(method,
+        aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1"));
+
+    /* PCI Firmware Specification 3.0
+     * 4.5.1. _OSC Interface for PCI Host Bridge Devices
+     * The _OSC interface for a PCI/PCI-X/PCI Express hierarchy is
+     * identified by the Universal Unique IDentifier (UUID)
+     * 33DB4D5B-1FF7-401C-9657-7441C03DD766
      */
-    aml_append(if_ctx, aml_and(a_ctrl, aml_int(0x1F), a_ctrl));
-
-    if_ctx2 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(1))));
-    /* Unknown revision */
-    aml_append(if_ctx2, aml_or(a_cwd1, aml_int(0x08), a_cwd1));
-    aml_append(if_ctx, if_ctx2);
-
-    if_ctx2 = aml_if(aml_lnot(aml_equal(aml_name("CDW3"), a_ctrl)));
-    /* Capabilities bits were masked */
-    aml_append(if_ctx2, aml_or(a_cwd1, aml_int(0x10), a_cwd1));
-    aml_append(if_ctx, if_ctx2);
-
-    /* Update DWORD3 in the buffer */
-    aml_append(if_ctx, aml_store(a_ctrl, aml_name("CDW3")));
-    aml_append(method, if_ctx);
-
-    else_ctx = aml_else();
-    /* Unrecognized UUID */
-    aml_append(else_ctx, aml_or(a_cwd1, aml_int(4), a_cwd1));
-    aml_append(method, else_ctx);
+    UUID = aml_touuid("33DB4D5B-1FF7-401C-9657-7441C03DD766");
+    ifctx = aml_if(aml_equal(aml_arg(0), UUID));
+    aml_append(ifctx,
+        aml_create_dword_field(aml_arg(3), aml_int(4), "CDW2"));
+    aml_append(ifctx,
+        aml_create_dword_field(aml_arg(3), aml_int(8), "CDW3"));
+    aml_append(ifctx, aml_store(aml_name("CDW2"), aml_name("SUPP")));
+    aml_append(ifctx, aml_store(aml_name("CDW3"), aml_name("CTRL")));
+    aml_append(ifctx, aml_store(aml_and(aml_name("CTRL"),
+                                        aml_int(ctrl_mask), NULL),
+                                aml_name("CTRL")));
+
+    ifctx1 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(0x1))));
+    aml_append(ifctx1, aml_store(aml_or(aml_name("CDW1"), aml_int(0x08), NULL),
+                                 aml_name("CDW1")));
+    aml_append(ifctx, ifctx1);
+
+    ifctx1 = aml_if(aml_lnot(aml_equal(aml_name("CDW3"), aml_name("CTRL"))));
+    aml_append(ifctx1, aml_store(aml_or(aml_name("CDW1"), aml_int(0x10), NULL),
+                                 aml_name("CDW1")));
+    aml_append(ifctx, ifctx1);
+
+    aml_append(ifctx, aml_store(aml_name("CTRL"), aml_name("CDW3")));
+    aml_append(ifctx, aml_return(aml_arg(3)));
+    aml_append(method, ifctx);
+
+    elsectx = aml_else();
+    aml_append(elsectx, aml_store(aml_or(aml_name("CDW1"), aml_int(4), NULL),
+                                  aml_name("CDW1")));
+    aml_append(elsectx, aml_return(aml_arg(3)));
+    aml_append(method, elsectx);
 
-    aml_append(method, aml_return(aml_arg(3)));
     return method;
 }
 
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 6822ee4eaa..f9a60907f1 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -154,7 +154,7 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
                               uint32_t irq, bool use_highmem, bool highmem_ecam)
 {
     int ecam_id = VIRT_ECAM_ID(highmem_ecam);
-    Aml *method, *crs, *ifctx, *UUID, *ifctx1, *elsectx, *buf;
+    Aml *method, *crs, *ifctx, *UUID, *ifctx1, *buf;
     int i, bus_no;
     hwaddr base_mmio = memmap[VIRT_PCIE_MMIO].base;
     hwaddr size_mmio = memmap[VIRT_PCIE_MMIO].size;
@@ -248,47 +248,8 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
     /* Declare an _OSC (OS Control Handoff) method */
     aml_append(dev, aml_name_decl("SUPP", aml_int(0)));
     aml_append(dev, aml_name_decl("CTRL", aml_int(0)));
-    method = aml_method("_OSC", 4, AML_NOTSERIALIZED);
-    aml_append(method,
-        aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1"));
-
-    /* PCI Firmware Specification 3.0
-     * 4.5.1. _OSC Interface for PCI Host Bridge Devices
-     * The _OSC interface for a PCI/PCI-X/PCI Express hierarchy is
-     * identified by the Universal Unique IDentifier (UUID)
-     * 33DB4D5B-1FF7-401C-9657-7441C03DD766
-     */
-    UUID = aml_touuid("33DB4D5B-1FF7-401C-9657-7441C03DD766");
-    ifctx = aml_if(aml_equal(aml_arg(0), UUID));
-    aml_append(ifctx,
-        aml_create_dword_field(aml_arg(3), aml_int(4), "CDW2"));
-    aml_append(ifctx,
-        aml_create_dword_field(aml_arg(3), aml_int(8), "CDW3"));
-    aml_append(ifctx, aml_store(aml_name("CDW2"), aml_name("SUPP")));
-    aml_append(ifctx, aml_store(aml_name("CDW3"), aml_name("CTRL")));
-    aml_append(ifctx, aml_store(aml_and(aml_name("CTRL"), aml_int(0x1D), NULL),
-                                aml_name("CTRL")));
-
-    ifctx1 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(0x1))));
-    aml_append(ifctx1, aml_store(aml_or(aml_name("CDW1"), aml_int(0x08), NULL),
-                                 aml_name("CDW1")));
-    aml_append(ifctx, ifctx1);
-
-    ifctx1 = aml_if(aml_lnot(aml_equal(aml_name("CDW3"), aml_name("CTRL"))));
-    aml_append(ifctx1, aml_store(aml_or(aml_name("CDW1"), aml_int(0x10), NULL),
-                                 aml_name("CDW1")));
-    aml_append(ifctx, ifctx1);
-
-    aml_append(ifctx, aml_store(aml_name("CTRL"), aml_name("CDW3")));
-    aml_append(ifctx, aml_return(aml_arg(3)));
-    aml_append(method, ifctx);
-
-    elsectx = aml_else();
-    aml_append(elsectx, aml_store(aml_or(aml_name("CDW1"), aml_int(4), NULL),
-                                  aml_name("CDW1")));
-    aml_append(elsectx, aml_return(aml_arg(3)));
-    aml_append(method, elsectx);
-    aml_append(dev, method);
+    aml_append(dev, build_osc_method(ACPI_OSC_CTRL_PCI_ALL &
+                                     ~ACPI_OSC_CTRL_SHPC_NATIVE_HP));
 
     method = aml_method("_DSM", 4, AML_NOTSERIALIZED);
 
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 3ab68fd24d..fdfd6f4ba2 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1337,7 +1337,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
         aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03")));
         aml_append(dev, aml_name_decl("_ADR", aml_int(0)));
         aml_append(dev, aml_name_decl("_UID", aml_int(1)));
-        aml_append(dev, build_osc_method());
+        aml_append(dev, aml_name_decl("SUPP", aml_int(0)));
+        aml_append(dev, aml_name_decl("CTRL", aml_int(0)));
+        aml_append(dev, build_osc_method(ACPI_OSC_CTRL_PCI_ALL));
         aml_append(sb_scope, dev);
         aml_append(dsdt, sb_scope);
 
@@ -1402,7 +1404,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
             aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03")));
             aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
             if (pci_bus_is_express(bus)) {
-                aml_append(dev, build_osc_method());
+                aml_append(dev, build_osc_method(ACPI_OSC_CTRL_PCI_ALL));
             }
 
             if (numa_node != NUMA_NODE_UNASSIGNED) {
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index af8e023968..6e1726e0a2 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -652,4 +652,18 @@ struct AcpiIortRC {
 } QEMU_PACKED;
 typedef struct AcpiIortRC AcpiIortRC;
 
+/* _OSC */
+
+#define ACPI_OSC_CTRL_PCIE_NATIVE_HP (1 << 0)
+#define ACPI_OSC_CTRL_SHPC_NATIVE_HP (1 << 1)
+#define ACPI_OSC_CTRL_PCIE_PM_EVT    (1 << 2)
+#define ACPI_OSC_CTRL_PCIE_AER       (1 << 3)
+#define ACPI_OSC_CTRL_PCIE_CAP_CTRL  (1 << 4)
+#define ACPI_OSC_CTRL_PCI_ALL \
+    (ACPI_OSC_CTRL_PCIE_NATIVE_HP |             \
+     ACPI_OSC_CTRL_SHPC_NATIVE_HP |             \
+     ACPI_OSC_CTRL_PCIE_PM_EVT |                \
+     ACPI_OSC_CTRL_PCIE_AER |                   \
+     ACPI_OSC_CTRL_PCIE_CAP_CTRL)
+
 #endif
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index cd744e9472..40b307c97d 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -405,7 +405,7 @@ void acpi_align_size(GArray *blob, unsigned align);
 void acpi_add_table(GArray *table_offsets, GArray *table_data);
 void acpi_build_tables_init(AcpiBuildTables *tables);
 void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre);
-Aml *build_osc_method(void);
+Aml *build_osc_method(uint32_t value);
 void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info);
 Aml *build_gsi_link_dev(const char *name, uint8_t uid, uint8_t gsi);
 Aml *build_prt(bool is_pci0_prt);
-- 
2.17.2

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH v3 08/19] hw: i386: Refactor PCI host getter
  2018-10-29 17:01 [Qemu-devel] [PATCH v3 00/19] ACPI reorganization for hardware-reduced support Samuel Ortiz
                   ` (7 preceding siblings ...)
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 07/19] hw: acpi: Factorize _OSC AML across architectures Samuel Ortiz
@ 2018-10-29 17:01 ` Samuel Ortiz
  2018-10-29 19:18   ` Philippe Mathieu-Daudé
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 09/19] hw: acpi: Export and generalize the PCI host AML API Samuel Ortiz
                   ` (10 subsequent siblings)
  19 siblings, 1 reply; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-29 17:01 UTC (permalink / raw)
  To: qemu-devel
  Cc: Yang Zhong, Michael S. Tsirkin, Igor Mammedov, Paolo Bonzini,
	Richard Henderson, Eduardo Habkost, Marcel Apfelbaum

From: Yang Zhong <yang.zhong@intel.com>

Make it more flexible by having it parsing a PCI host paths array
instead of open coding those paths deep down into the code logic itself.
This will be needed for PCI machine types that are neither emulatiing the
ich9 nor the i440fx chipsets.

Signed-off-by: Yang Zhong <yang.zhong@intel.com>
---
 hw/i386/acpi-build.c | 29 +++++++++++++++++++----------
 1 file changed, 19 insertions(+), 10 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index fdfd6f4ba2..35f95baca7 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -114,6 +114,12 @@ typedef struct AcpiBuildPciBusHotplugState {
     bool pcihp_bridge_en;
 } AcpiBuildPciBusHotplugState;
 
+static const char *pci_hosts[] = {
+   "/machine/i440fx",
+   "/machine/q35",
+   NULL,
+};
+
 static void init_common_fadt_data(Object *o, AcpiFadtData *data)
 {
     uint32_t io = object_property_get_uint(o, ACPI_PM_PROP_PM_IO_BASE, NULL);
@@ -238,27 +244,30 @@ static void acpi_get_misc_info(AcpiMiscInfo *info)
  * Because of the PXB hosts we cannot simply query TYPE_PCI_HOST_BRIDGE.
  * On i386 arch we only have two pci hosts, so we can look only for them.
  */
-static Object *acpi_get_i386_pci_host(void)
+static Object *acpi_get_pci_host(void)
 {
     PCIHostState *host;
+    int i = 0;
 
-    host = OBJECT_CHECK(PCIHostState,
-                        object_resolve_path("/machine/i440fx", NULL),
-                        TYPE_PCI_HOST_BRIDGE);
-    if (!host) {
+    while (pci_hosts[i]) {
         host = OBJECT_CHECK(PCIHostState,
-                            object_resolve_path("/machine/q35", NULL),
+                            object_resolve_path(pci_hosts[i], NULL),
                             TYPE_PCI_HOST_BRIDGE);
+        if (host) {
+            return OBJECT(host);
+        }
+
+        i++;
     }
 
-    return OBJECT(host);
+    return NULL;
 }
 
 static void acpi_get_pci_holes(Range *hole, Range *hole64)
 {
     Object *pci_host;
 
-    pci_host = acpi_get_i386_pci_host();
+    pci_host = acpi_get_pci_host();
     g_assert(pci_host);
 
     range_set_bounds1(hole,
@@ -1636,7 +1645,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
         Object *pci_host;
         PCIBus *bus = NULL;
 
-        pci_host = acpi_get_i386_pci_host();
+        pci_host = acpi_get_pci_host();
         if (pci_host) {
             bus = PCI_HOST_BRIDGE(pci_host)->bus;
         }
@@ -2009,7 +2018,7 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
     Object *pci_host;
     QObject *o;
 
-    pci_host = acpi_get_i386_pci_host();
+    pci_host = acpi_get_pci_host();
     g_assert(pci_host);
 
     o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_BASE, NULL);
-- 
2.17.2

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH v3 09/19] hw: acpi: Export and generalize the PCI host AML API
  2018-10-29 17:01 [Qemu-devel] [PATCH v3 00/19] ACPI reorganization for hardware-reduced support Samuel Ortiz
                   ` (8 preceding siblings ...)
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 08/19] hw: i386: Refactor PCI host getter Samuel Ortiz
@ 2018-10-29 17:01 ` Samuel Ortiz
  2018-10-29 19:23   ` Philippe Mathieu-Daudé
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 10/19] hw: acpi: Export the MCFG getter Samuel Ortiz
                   ` (9 subsequent siblings)
  19 siblings, 1 reply; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-29 17:01 UTC (permalink / raw)
  To: qemu-devel
  Cc: Yang Zhong, Rob Bradford, Michael S. Tsirkin, Igor Mammedov,
	Marcel Apfelbaum, Paolo Bonzini, Richard Henderson,
	Eduardo Habkost

From: Yang Zhong <yang.zhong@intel.com>

The AML build routines for the PCI host bridge and the corresponding
DSDT addition are neither x86 nor PC machine type specific.
We can move them to the architecture agnostic hw/acpi folder, and by
carrying all the needed information through a new AcpiPciBus structure,
we can make them PC machine type independent.

Signed-off-by: Yang Zhong <yang.zhong@intel.com>
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
---
 hw/acpi/aml-build.c         | 208 ++++++++++++++++++++++++++++++++++++
 hw/i386/acpi-build.c        | 167 ++---------------------------
 include/hw/acpi/aml-build.h |  10 ++
 3 files changed, 226 insertions(+), 159 deletions(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 52ac39acdb..aa72b5459c 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -29,6 +29,25 @@
 #include "hw/pci/pci_bus.h"
 #include "qemu/range.h"
 #include "hw/pci/pci_bridge.h"
+#include "hw/i386/pc.h"
+#include "sysemu/tpm.h"
+#include "hw/acpi/tpm.h"
+
+#define PCI_HOST_BRIDGE_CONFIG_ADDR        0xcf8
+#define PCI_HOST_BRIDGE_IO_0_MIN_ADDR      0x0000
+#define PCI_HOST_BRIDGE_IO_0_MAX_ADDR      0x0cf7
+#define PCI_HOST_BRIDGE_IO_1_MIN_ADDR      0x0d00
+#define PCI_HOST_BRIDGE_IO_1_MAX_ADDR      0xffff
+#define PCI_VGA_MEM_BASE_ADDR              0x000a0000
+#define PCI_VGA_MEM_MAX_ADDR               0x000bffff
+#define IO_0_LEN                           0xcf8
+#define VGA_MEM_LEN                        0x20000
+
+static const char *pci_hosts[] = {
+   "/machine/i440fx",
+   "/machine/q35",
+   NULL,
+};
 
 static GArray *build_alloc_array(void)
 {
@@ -1601,6 +1620,51 @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
     g_array_free(tables->vmgenid, mfre);
 }
 
+/*
+ * Because of the PXB hosts we cannot simply query TYPE_PCI_HOST_BRIDGE.
+ */
+Object *acpi_get_pci_host(void)
+{
+    PCIHostState *host;
+    int i = 0;
+
+    while (pci_hosts[i]) {
+        host = OBJECT_CHECK(PCIHostState,
+                            object_resolve_path(pci_hosts[i], NULL),
+                            TYPE_PCI_HOST_BRIDGE);
+        if (host) {
+            return OBJECT(host);
+        }
+
+        i++;
+    }
+
+    return NULL;
+}
+
+void acpi_get_pci_holes(Range *hole, Range *hole64)
+{
+    Object *pci_host;
+
+    pci_host = acpi_get_pci_host();
+    g_assert(pci_host);
+
+    range_set_bounds1(hole,
+                      object_property_get_uint(pci_host,
+                                               PCI_HOST_PROP_PCI_HOLE_START,
+                                               NULL),
+                      object_property_get_uint(pci_host,
+                                               PCI_HOST_PROP_PCI_HOLE_END,
+                                               NULL));
+    range_set_bounds1(hole64,
+                      object_property_get_uint(pci_host,
+                                               PCI_HOST_PROP_PCI_HOLE64_START,
+                                               NULL),
+                      object_property_get_uint(pci_host,
+                                               PCI_HOST_PROP_PCI_HOLE64_END,
+                                               NULL));
+}
+
 static void crs_range_insert(GPtrArray *ranges, uint64_t base, uint64_t limit)
 {
     CrsRangeEntry *entry;
@@ -2099,6 +2163,150 @@ Aml *build_prt(bool is_pci0_prt)
     return method;
 }
 
+Aml *build_pci_host_bridge(Aml *table, AcpiPciBus *pci_host)
+{
+    CrsRangeEntry *entry;
+    Aml *scope, *dev, *crs;
+    CrsRangeSet crs_range_set;
+    Range *pci_hole = NULL;
+    Range *pci_hole64 = NULL;
+    PCIBus *bus = NULL;
+    int root_bus_limit = 0xFF;
+    int i;
+
+    bus = pci_host->pci_bus;
+    assert(bus);
+    pci_hole = pci_host->pci_hole;
+    pci_hole64 = pci_host->pci_hole64;
+
+    crs_range_set_init(&crs_range_set);
+    QLIST_FOREACH(bus, &bus->child, sibling) {
+        uint8_t bus_num = pci_bus_num(bus);
+        uint8_t numa_node = pci_bus_numa_node(bus);
+
+        /* look only for expander root buses */
+        if (!pci_bus_is_root(bus)) {
+            continue;
+        }
+
+        if (bus_num < root_bus_limit) {
+            root_bus_limit = bus_num - 1;
+        }
+
+        scope = aml_scope("\\_SB");
+        dev = aml_device("PC%.02X", bus_num);
+        aml_append(dev, aml_name_decl("_UID", aml_int(bus_num)));
+        aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03")));
+        aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
+        if (pci_bus_is_express(bus)) {
+            aml_append(dev, aml_name_decl("SUPP", aml_int(0)));
+            aml_append(dev, aml_name_decl("CTRL", aml_int(0)));
+            aml_append(dev, build_osc_method(0x1F));
+        }
+        if (numa_node != NUMA_NODE_UNASSIGNED) {
+            aml_append(dev, aml_name_decl("_PXM", aml_int(numa_node)));
+        }
+
+        aml_append(dev, build_prt(false));
+        crs = build_crs(PCI_HOST_BRIDGE(BUS(bus)->parent), &crs_range_set);
+        aml_append(dev, aml_name_decl("_CRS", crs));
+        aml_append(scope, dev);
+        aml_append(table, scope);
+    }
+    scope = aml_scope("\\_SB.PCI0");
+    /* build PCI0._CRS */
+    crs = aml_resource_template();
+    /* set the pcie bus num */
+    aml_append(crs,
+        aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
+                            0x0000, 0x0, root_bus_limit,
+                            0x0000, root_bus_limit + 1));
+    aml_append(crs, aml_io(AML_DECODE16, PCI_HOST_BRIDGE_CONFIG_ADDR,
+                           PCI_HOST_BRIDGE_CONFIG_ADDR, 0x01, 0x08));
+    /* set the io region 0 in pci host bridge */
+    aml_append(crs,
+        aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,
+                    AML_POS_DECODE, AML_ENTIRE_RANGE,
+                    0x0000, PCI_HOST_BRIDGE_IO_0_MIN_ADDR,
+                    PCI_HOST_BRIDGE_IO_0_MAX_ADDR, 0x0000, IO_0_LEN));
+
+    /* set the io region 1 in pci host bridge */
+    crs_replace_with_free_ranges(crs_range_set.io_ranges,
+                                 PCI_HOST_BRIDGE_IO_1_MIN_ADDR,
+                                 PCI_HOST_BRIDGE_IO_1_MAX_ADDR);
+    for (i = 0; i < crs_range_set.io_ranges->len; i++) {
+        entry = g_ptr_array_index(crs_range_set.io_ranges, i);
+        aml_append(crs,
+            aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,
+                        AML_POS_DECODE, AML_ENTIRE_RANGE,
+                        0x0000, entry->base, entry->limit,
+                        0x0000, entry->limit - entry->base + 1));
+    }
+
+    /* set the vga mem region(0) in pci host bridge */
+    aml_append(crs,
+        aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
+                         AML_CACHEABLE, AML_READ_WRITE,
+                         0, PCI_VGA_MEM_BASE_ADDR, PCI_VGA_MEM_MAX_ADDR,
+                         0, VGA_MEM_LEN));
+
+    /* set the mem region 1 in pci host bridge */
+    crs_replace_with_free_ranges(crs_range_set.mem_ranges,
+                                 range_lob(pci_hole),
+                                 range_upb(pci_hole));
+    for (i = 0; i < crs_range_set.mem_ranges->len; i++) {
+        entry = g_ptr_array_index(crs_range_set.mem_ranges, i);
+        aml_append(crs,
+            aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
+                             AML_NON_CACHEABLE, AML_READ_WRITE,
+                             0, entry->base, entry->limit,
+                             0, entry->limit - entry->base + 1));
+    }
+
+    /* set the mem region 2 in pci host bridge */
+    if (!range_is_empty(pci_hole64)) {
+        crs_replace_with_free_ranges(crs_range_set.mem_64bit_ranges,
+                                     range_lob(pci_hole64),
+                                     range_upb(pci_hole64));
+        for (i = 0; i < crs_range_set.mem_64bit_ranges->len; i++) {
+            entry = g_ptr_array_index(crs_range_set.mem_64bit_ranges, i);
+            aml_append(crs,
+                       aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED,
+                                        AML_MAX_FIXED,
+                                        AML_CACHEABLE, AML_READ_WRITE,
+                                        0, entry->base, entry->limit,
+                                        0, entry->limit - entry->base + 1));
+        }
+    }
+
+    if (TPM_IS_TIS(tpm_find())) {
+        aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE,
+                   TPM_TIS_ADDR_SIZE, AML_READ_WRITE));
+    }
+
+    aml_append(scope, aml_name_decl("_CRS", crs));
+    crs_range_set_free(&crs_range_set);
+    return scope;
+}
+
+void acpi_dsdt_add_pci_bus(Aml *dsdt, AcpiPciBus *pci_host)
+{
+    Aml *dev, *pci_scope;
+
+    dev = aml_device("\\_SB.PCI0");
+    aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08")));
+    aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03")));
+    aml_append(dev, aml_name_decl("_ADR", aml_int(0)));
+    aml_append(dev, aml_name_decl("_UID", aml_int(1)));
+    aml_append(dev, aml_name_decl("SUPP", aml_int(0)));
+    aml_append(dev, aml_name_decl("CTRL", aml_int(0)));
+    aml_append(dev, build_osc_method(0x1F));
+    aml_append(dsdt, dev);
+
+    pci_scope = build_pci_host_bridge(dsdt, pci_host);
+    aml_append(dsdt, pci_scope);
+}
+
 /* Build rsdt table */
 void
 build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 35f95baca7..12a8d8210a 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -114,12 +114,6 @@ typedef struct AcpiBuildPciBusHotplugState {
     bool pcihp_bridge_en;
 } AcpiBuildPciBusHotplugState;
 
-static const char *pci_hosts[] = {
-   "/machine/i440fx",
-   "/machine/q35",
-   NULL,
-};
-
 static void init_common_fadt_data(Object *o, AcpiFadtData *data)
 {
     uint32_t io = object_property_get_uint(o, ACPI_PM_PROP_PM_IO_BASE, NULL);
@@ -240,52 +234,6 @@ static void acpi_get_misc_info(AcpiMiscInfo *info)
     info->applesmc_io_base = applesmc_port();
 }
 
-/*
- * Because of the PXB hosts we cannot simply query TYPE_PCI_HOST_BRIDGE.
- * On i386 arch we only have two pci hosts, so we can look only for them.
- */
-static Object *acpi_get_pci_host(void)
-{
-    PCIHostState *host;
-    int i = 0;
-
-    while (pci_hosts[i]) {
-        host = OBJECT_CHECK(PCIHostState,
-                            object_resolve_path(pci_hosts[i], NULL),
-                            TYPE_PCI_HOST_BRIDGE);
-        if (host) {
-            return OBJECT(host);
-        }
-
-        i++;
-    }
-
-    return NULL;
-}
-
-static void acpi_get_pci_holes(Range *hole, Range *hole64)
-{
-    Object *pci_host;
-
-    pci_host = acpi_get_pci_host();
-    g_assert(pci_host);
-
-    range_set_bounds1(hole,
-                      object_property_get_uint(pci_host,
-                                               PCI_HOST_PROP_PCI_HOLE_START,
-                                               NULL),
-                      object_property_get_uint(pci_host,
-                                               PCI_HOST_PROP_PCI_HOLE_END,
-                                               NULL));
-    range_set_bounds1(hole64,
-                      object_property_get_uint(pci_host,
-                                               PCI_HOST_PROP_PCI_HOLE64_START,
-                                               NULL),
-                      object_property_get_uint(pci_host,
-                                               PCI_HOST_PROP_PCI_HOLE64_END,
-                                               NULL));
-}
-
 /* FACS */
 static void
 build_facs(GArray *table_data, BIOSLinker *linker)
@@ -1307,16 +1255,11 @@ static void build_piix4_pci_hotplug(Aml *table)
 static void
 build_dsdt(GArray *table_data, BIOSLinker *linker,
            AcpiPmInfo *pm, AcpiMiscInfo *misc,
-           Range *pci_hole, Range *pci_hole64,
+           AcpiPciBus *pci_host,
            MachineState *machine, AcpiConfiguration *conf)
 {
-    CrsRangeEntry *entry;
     Aml *dsdt, *sb_scope, *scope, *dev, *method, *field, *pkg, *crs;
-    CrsRangeSet crs_range_set;
     uint32_t nr_mem = machine->ram_slots;
-    int root_bus_limit = 0xFF;
-    PCIBus *bus = NULL;
-    int i;
 
     dsdt = init_aml_allocator();
 
@@ -1391,104 +1334,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
     }
     aml_append(dsdt, scope);
 
-    crs_range_set_init(&crs_range_set);
-    bus = PC_MACHINE(machine)->bus;
-    if (bus) {
-        QLIST_FOREACH(bus, &bus->child, sibling) {
-            uint8_t bus_num = pci_bus_num(bus);
-            uint8_t numa_node = pci_bus_numa_node(bus);
-
-            /* look only for expander root buses */
-            if (!pci_bus_is_root(bus)) {
-                continue;
-            }
-
-            if (bus_num < root_bus_limit) {
-                root_bus_limit = bus_num - 1;
-            }
-
-            scope = aml_scope("\\_SB");
-            dev = aml_device("PC%.02X", bus_num);
-            aml_append(dev, aml_name_decl("_UID", aml_int(bus_num)));
-            aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03")));
-            aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
-            if (pci_bus_is_express(bus)) {
-                aml_append(dev, build_osc_method(ACPI_OSC_CTRL_PCI_ALL));
-            }
-
-            if (numa_node != NUMA_NODE_UNASSIGNED) {
-                aml_append(dev, aml_name_decl("_PXM", aml_int(numa_node)));
-            }
-
-            aml_append(dev, build_prt(false));
-            crs = build_crs(PCI_HOST_BRIDGE(BUS(bus)->parent), &crs_range_set);
-            aml_append(dev, aml_name_decl("_CRS", crs));
-            aml_append(scope, dev);
-            aml_append(dsdt, scope);
-        }
-    }
-
-    scope = aml_scope("\\_SB.PCI0");
-    /* build PCI0._CRS */
-    crs = aml_resource_template();
-    aml_append(crs,
-        aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
-                            0x0000, 0x0, root_bus_limit,
-                            0x0000, root_bus_limit + 1));
-    aml_append(crs, aml_io(AML_DECODE16, 0x0CF8, 0x0CF8, 0x01, 0x08));
-
-    aml_append(crs,
-        aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,
-                    AML_POS_DECODE, AML_ENTIRE_RANGE,
-                    0x0000, 0x0000, 0x0CF7, 0x0000, 0x0CF8));
-
-    crs_replace_with_free_ranges(crs_range_set.io_ranges, 0x0D00, 0xFFFF);
-    for (i = 0; i < crs_range_set.io_ranges->len; i++) {
-        entry = g_ptr_array_index(crs_range_set.io_ranges, i);
-        aml_append(crs,
-            aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,
-                        AML_POS_DECODE, AML_ENTIRE_RANGE,
-                        0x0000, entry->base, entry->limit,
-                        0x0000, entry->limit - entry->base + 1));
-    }
-
-    aml_append(crs,
-        aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
-                         AML_CACHEABLE, AML_READ_WRITE,
-                         0, 0x000A0000, 0x000BFFFF, 0, 0x00020000));
-
-    crs_replace_with_free_ranges(crs_range_set.mem_ranges,
-                                 range_lob(pci_hole),
-                                 range_upb(pci_hole));
-    for (i = 0; i < crs_range_set.mem_ranges->len; i++) {
-        entry = g_ptr_array_index(crs_range_set.mem_ranges, i);
-        aml_append(crs,
-            aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
-                             AML_NON_CACHEABLE, AML_READ_WRITE,
-                             0, entry->base, entry->limit,
-                             0, entry->limit - entry->base + 1));
-    }
-
-    if (!range_is_empty(pci_hole64)) {
-        crs_replace_with_free_ranges(crs_range_set.mem_64bit_ranges,
-                                     range_lob(pci_hole64),
-                                     range_upb(pci_hole64));
-        for (i = 0; i < crs_range_set.mem_64bit_ranges->len; i++) {
-            entry = g_ptr_array_index(crs_range_set.mem_64bit_ranges, i);
-            aml_append(crs,
-                       aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED,
-                                        AML_MAX_FIXED,
-                                        AML_CACHEABLE, AML_READ_WRITE,
-                                        0, entry->base, entry->limit,
-                                        0, entry->limit - entry->base + 1));
-        }
-    }
-
-    if (TPM_IS_TIS(tpm_find())) {
-        aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE,
-                   TPM_TIS_ADDR_SIZE, AML_READ_WRITE));
-    }
-    aml_append(scope, aml_name_decl("_CRS", crs));
+    scope = build_pci_host_bridge(dsdt, pci_host);
 
     /* reserve GPE0 block resources */
     dev = aml_device("GPE0");
@@ -1508,8 +1354,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
     aml_append(dev, aml_name_decl("_CRS", crs));
     aml_append(scope, dev);
 
-    crs_range_set_free(&crs_range_set);
-
     /* reserve PCIHP resources */
     if (pm->pcihp_io_len) {
         dev = aml_device("PHPR");
@@ -2065,6 +1909,11 @@ void acpi_build(AcpiBuildTables *tables,
                              64 /* Ensure FACS is aligned */,
                              false /* high memory */);
 
+    AcpiPciBus pci_host = {
+        .pci_bus    = PC_MACHINE(machine)->bus,
+        .pci_hole   = &pci_hole,
+        .pci_hole64 = &pci_hole64,
+    };
     /*
      * FACS is pointed to by FADT.
      * We place it first since it's the only table that has alignment
@@ -2076,7 +1925,7 @@ void acpi_build(AcpiBuildTables *tables,
     /* DSDT is pointed to by FADT */
     dsdt = tables_blob->len;
     build_dsdt(tables_blob, tables->linker, &pm, &misc,
-               &pci_hole, &pci_hole64, machine, conf);
+               &pci_host, machine, conf);
 
     /* Count the size of the DSDT and SSDT, we will need it for legacy
      * sizing of ACPI tables.
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 40b307c97d..cdd290dd70 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -230,6 +230,12 @@ typedef struct AcpiMcfgInfo {
     uint32_t mcfg_size;
 } AcpiMcfgInfo;
 
+typedef struct AcpiPciBus {
+    PCIBus *pci_bus;
+    Range *pci_hole;
+    Range *pci_hole64;
+} AcpiPciBus;
+
 typedef struct CrsRangeEntry {
     uint64_t base;
     uint64_t limit;
@@ -401,6 +407,8 @@ build_header(BIOSLinker *linker, GArray *table_data,
              const char *oem_id, const char *oem_table_id);
 void *acpi_data_push(GArray *table_data, unsigned size);
 unsigned acpi_data_len(GArray *table);
+Object *acpi_get_pci_host(void);
+void acpi_get_pci_holes(Range *hole, Range *hole64);
 void acpi_align_size(GArray *blob, unsigned align);
 void acpi_add_table(GArray *table_offsets, GArray *table_data);
 void acpi_build_tables_init(AcpiBuildTables *tables);
@@ -409,6 +417,8 @@ Aml *build_osc_method(uint32_t value);
 void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info);
 Aml *build_gsi_link_dev(const char *name, uint8_t uid, uint8_t gsi);
 Aml *build_prt(bool is_pci0_prt);
+void acpi_dsdt_add_pci_bus(Aml *dsdt, AcpiPciBus *pci_host);
+Aml *build_pci_host_bridge(Aml *table, AcpiPciBus *pci_host);
 void crs_range_set_init(CrsRangeSet *range_set);
 Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set);
 void crs_replace_with_free_ranges(GPtrArray *ranges,
-- 
2.17.2

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH v3 10/19] hw: acpi: Export the MCFG getter
  2018-10-29 17:01 [Qemu-devel] [PATCH v3 00/19] ACPI reorganization for hardware-reduced support Samuel Ortiz
                   ` (9 preceding siblings ...)
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 09/19] hw: acpi: Export and generalize the PCI host AML API Samuel Ortiz
@ 2018-10-29 17:01 ` Samuel Ortiz
  2018-10-29 19:31   ` Philippe Mathieu-Daudé
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 11/19] hw: acpi: Do not create hotplug method when handler is not defined Samuel Ortiz
                   ` (8 subsequent siblings)
  19 siblings, 1 reply; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-29 17:01 UTC (permalink / raw)
  To: qemu-devel
  Cc: Yang Zhong, Michael S. Tsirkin, Igor Mammedov, Marcel Apfelbaum,
	Paolo Bonzini, Richard Henderson, Eduardo Habkost

From: Yang Zhong <yang.zhong@intel.com>

The ACPI MCFG getter is not x86 specific and could be called from
anywhere within generic ACPI API, so let's export it.

Signed-off-by: Yang Zhong <yang.zhong@intel.com>
---
 hw/acpi/aml-build.c         | 24 ++++++++++++++++++++++++
 hw/i386/acpi-build.c        | 22 ----------------------
 include/hw/acpi/aml-build.h |  1 +
 3 files changed, 25 insertions(+), 22 deletions(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index aa72b5459c..2110e18799 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -32,6 +32,8 @@
 #include "hw/i386/pc.h"
 #include "sysemu/tpm.h"
 #include "hw/acpi/tpm.h"
+#include "qom/qom-qobject.h"
+#include "qapi/qmp/qnum.h"
 
 #define PCI_HOST_BRIDGE_CONFIG_ADDR        0xcf8
 #define PCI_HOST_BRIDGE_IO_0_MIN_ADDR      0x0000
@@ -1665,6 +1667,28 @@ void acpi_get_pci_holes(Range *hole, Range *hole64)
                                                NULL));
 }
 
+bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
+{
+    Object *pci_host;
+    QObject *o;
+
+    pci_host = acpi_get_pci_host();
+    g_assert(pci_host);
+
+    o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_BASE, NULL);
+    if (!o) {
+        return false;
+    }
+    mcfg->mcfg_base = qnum_get_uint(qobject_to(QNum, o));
+    qobject_unref(o);
+
+    o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_SIZE, NULL);
+    assert(o);
+    mcfg->mcfg_size = qnum_get_uint(qobject_to(QNum, o));
+    qobject_unref(o);
+    return true;
+}
+
 static void crs_range_insert(GPtrArray *ranges, uint64_t base, uint64_t limit)
 {
     CrsRangeEntry *entry;
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 12a8d8210a..414a6c4c4e 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1857,28 +1857,6 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker)
                  "IVRS", table_data->len - iommu_start, 1, NULL, NULL);
 }
 
-static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
-{
-    Object *pci_host;
-    QObject *o;
-
-    pci_host = acpi_get_pci_host();
-    g_assert(pci_host);
-
-    o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_BASE, NULL);
-    if (!o) {
-        return false;
-    }
-    mcfg->mcfg_base = qnum_get_uint(qobject_to(QNum, o));
-    qobject_unref(o);
-
-    o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_SIZE, NULL);
-    assert(o);
-    mcfg->mcfg_size = qnum_get_uint(qobject_to(QNum, o));
-    qobject_unref(o);
-    return true;
-}
-
 static
 void acpi_build(AcpiBuildTables *tables,
                 MachineState *machine, AcpiConfiguration *conf)
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index cdd290dd70..1fabf58df2 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -409,6 +409,7 @@ void *acpi_data_push(GArray *table_data, unsigned size);
 unsigned acpi_data_len(GArray *table);
 Object *acpi_get_pci_host(void);
 void acpi_get_pci_holes(Range *hole, Range *hole64);
+bool acpi_get_mcfg(AcpiMcfgInfo *mcfg);
 void acpi_align_size(GArray *blob, unsigned align);
 void acpi_add_table(GArray *table_offsets, GArray *table_data);
 void acpi_build_tables_init(AcpiBuildTables *tables);
-- 
2.17.2

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH v3 11/19] hw: acpi: Do not create hotplug method when handler is not defined
  2018-10-29 17:01 [Qemu-devel] [PATCH v3 00/19] ACPI reorganization for hardware-reduced support Samuel Ortiz
                   ` (10 preceding siblings ...)
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 10/19] hw: acpi: Export the MCFG getter Samuel Ortiz
@ 2018-10-29 17:01 ` Samuel Ortiz
  2018-10-29 19:33   ` Philippe Mathieu-Daudé
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 12/19] hw: i386: Make the hotpluggable memory size property more generic Samuel Ortiz
                   ` (7 subsequent siblings)
  19 siblings, 1 reply; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-29 17:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael S. Tsirkin, Igor Mammedov

CPU and memory ACPI hotplug are not necessarily handled through SCI
events. For example, with Hardware-reduced ACPI, the GED device will
manage ACPI hotplug entirely.
As a consequence, we make the CPU and memory specific events AML
generation optional. The code will only be added when the method name is
not NULL.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 hw/acpi/cpu.c            |  8 +++++---
 hw/acpi/memory_hotplug.c | 11 +++++++----
 2 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
index f10b190019..cd41377b5a 100644
--- a/hw/acpi/cpu.c
+++ b/hw/acpi/cpu.c
@@ -569,9 +569,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
     aml_append(sb_scope, cpus_dev);
     aml_append(table, sb_scope);
 
-    method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED);
-    aml_append(method, aml_call0("\\_SB.CPUS." CPU_SCAN_METHOD));
-    aml_append(table, method);
+    if (event_handler_method) {
+        method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED);
+        aml_append(method, aml_call0("\\_SB.CPUS." CPU_SCAN_METHOD));
+        aml_append(table, method);
+    }
 
     g_free(cphp_res_path);
 }
diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c
index 8c7c1013f3..db2c4df961 100644
--- a/hw/acpi/memory_hotplug.c
+++ b/hw/acpi/memory_hotplug.c
@@ -715,10 +715,13 @@ void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem,
     }
     aml_append(table, dev_container);
 
-    method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED);
-    aml_append(method,
-        aml_call0(MEMORY_DEVICES_CONTAINER "." MEMORY_SLOT_SCAN_METHOD));
-    aml_append(table, method);
+    if (event_handler_method) {
+        method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED);
+        aml_append(method,
+                   aml_call0(MEMORY_DEVICES_CONTAINER "."
+                             MEMORY_SLOT_SCAN_METHOD));
+        aml_append(table, method);
+    }
 
     g_free(mhp_res_path);
 }
-- 
2.17.2

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH v3 12/19] hw: i386: Make the hotpluggable memory size property more generic
  2018-10-29 17:01 [Qemu-devel] [PATCH v3 00/19] ACPI reorganization for hardware-reduced support Samuel Ortiz
                   ` (11 preceding siblings ...)
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 11/19] hw: acpi: Do not create hotplug method when handler is not defined Samuel Ortiz
@ 2018-10-29 17:01 ` Samuel Ortiz
  2018-10-29 19:38   ` Philippe Mathieu-Daudé
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 13/19] hw: acpi: Export the SRAT AML build API Samuel Ortiz
                   ` (6 subsequent siblings)
  19 siblings, 1 reply; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-29 17:01 UTC (permalink / raw)
  To: qemu-devel
  Cc: Michael S. Tsirkin, Igor Mammedov, Marcel Apfelbaum,
	Paolo Bonzini, Richard Henderson, Eduardo Habkost

This property is currently defined under i386/pc while it only describes
a region size that's eventually fetched from the AML ACPI code.

We can make it more generic and shareable across machine types by moving
it to memory-device.h instead.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 hw/i386/acpi-build.c           | 2 +-
 hw/i386/pc.c                   | 3 ++-
 include/hw/i386/pc.h           | 1 -
 include/hw/mem/memory-device.h | 2 ++
 4 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 414a6c4c4e..dfc02a8a85 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1630,7 +1630,7 @@ build_srat(GArray *table_data, BIOSLinker *linker,
     MachineClass *mc = MACHINE_GET_CLASS(machine);
     const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(machine);
     ram_addr_t hotplugabble_address_space_size =
-        object_property_get_int(OBJECT(machine), PC_MACHINE_DEVMEM_REGION_SIZE,
+        object_property_get_int(OBJECT(machine), MEMORY_DEVICE_REGION_SIZE,
                                 NULL);
 
     srat_start = table_data->len;
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index bd4a77b856..1dcbbd5139 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -67,6 +67,7 @@
 #include "hw/boards.h"
 #include "acpi-build.h"
 #include "hw/mem/pc-dimm.h"
+#include "hw/mem/memory-device.h"
 #include "qapi/error.h"
 #include "qapi/qapi-visit-common.h"
 #include "qapi/visitor.h"
@@ -2442,7 +2443,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
     nc->nmi_monitor_handler = x86_nmi;
     mc->default_cpu_type = TARGET_DEFAULT_CPU_TYPE;
 
-    object_class_property_add(oc, PC_MACHINE_DEVMEM_REGION_SIZE, "int",
+    object_class_property_add(oc, MEMORY_DEVICE_REGION_SIZE, "int",
         pc_machine_get_device_memory_region_size, NULL,
         NULL, NULL, &error_abort);
 
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index da0bd39741..7d177cd207 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -62,7 +62,6 @@ struct PCMachineState {
 };
 
 #define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device"
-#define PC_MACHINE_DEVMEM_REGION_SIZE "device-memory-region-size"
 #define PC_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g"
 #define PC_MACHINE_VMPORT           "vmport"
 #define PC_MACHINE_SMM              "smm"
diff --git a/include/hw/mem/memory-device.h b/include/hw/mem/memory-device.h
index e904e194d5..d9a4fc7c3e 100644
--- a/include/hw/mem/memory-device.h
+++ b/include/hw/mem/memory-device.h
@@ -97,6 +97,8 @@ typedef struct MemoryDeviceClass {
                              MemoryDeviceInfo *info);
 } MemoryDeviceClass;
 
+#define MEMORY_DEVICE_REGION_SIZE "memory-device-region-size"
+
 MemoryDeviceInfoList *qmp_memory_device_list(void);
 uint64_t get_plugged_memory_size(void);
 void memory_device_pre_plug(MemoryDeviceState *md, MachineState *ms,
-- 
2.17.2

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH v3 13/19] hw: acpi: Export the SRAT AML build API
  2018-10-29 17:01 [Qemu-devel] [PATCH v3 00/19] ACPI reorganization for hardware-reduced support Samuel Ortiz
                   ` (12 preceding siblings ...)
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 12/19] hw: i386: Make the hotpluggable memory size property more generic Samuel Ortiz
@ 2018-10-29 17:01 ` Samuel Ortiz
  2018-10-29 19:40   ` Philippe Mathieu-Daudé
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 14/19] hw: acpi: Fix memory hotplug AML generation error Samuel Ortiz
                   ` (5 subsequent siblings)
  19 siblings, 1 reply; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-29 17:01 UTC (permalink / raw)
  To: qemu-devel
  Cc: Yang Zhong, Michael S. Tsirkin, Igor Mammedov, Shannon Zhao,
	Peter Maydell, Paolo Bonzini, Richard Henderson, Eduardo Habkost,
	Marcel Apfelbaum, open list:ARM ACPI Subsystem

From: Yang Zhong <yang.zhong@intel.com>

The SRAT ACPI table is not x86 specific and will be needed for the
Hardware-reduced ACPI implementation. So we should export it through the
architecture independent hw/acpi folder.

Also, now that the generic build_srat() API is exported, we have to
rename the ARM static one in order to avoid build time conflicts.

Signed-off-by: Yang Zhong <yang.zhong@intel.com>
---
 hw/acpi/aml-build.c         | 130 ++++++++++++++++++++++++++++++++++++
 hw/arm/virt-acpi-build.c    |   4 +-
 hw/i386/acpi-build.c        | 129 -----------------------------------
 include/hw/acpi/aml-build.h |   3 +
 4 files changed, 135 insertions(+), 131 deletions(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 2110e18799..c3f652a68f 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -22,6 +22,7 @@
 #include "qemu/osdep.h"
 #include <glib/gprintf.h>
 #include "hw/acpi/aml-build.h"
+#include "hw/mem/memory-device.h"
 #include "qemu/bswap.h"
 #include "qemu/bitops.h"
 #include "sysemu/numa.h"
@@ -2459,6 +2460,135 @@ void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base,
     numamem->range_length = cpu_to_le64(len);
 }
 
+#define HOLE_640K_START  (640 * KiB)
+#define HOLE_640K_END   (1 * MiB)
+
+void
+build_srat(GArray *table_data, BIOSLinker *linker,
+           MachineState *machine, AcpiConfiguration *conf)
+{
+    AcpiSystemResourceAffinityTable *srat;
+    AcpiSratMemoryAffinity *numamem;
+
+    int i;
+    int srat_start, numa_start, slots;
+    uint64_t mem_len, mem_base, next_base;
+    MachineClass *mc = MACHINE_GET_CLASS(machine);
+    const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(machine);
+    ram_addr_t hotplugabble_address_space_size =
+        object_property_get_int(OBJECT(machine), MEMORY_DEVICE_REGION_SIZE,
+                                NULL);
+
+    srat_start = table_data->len;
+
+    srat = acpi_data_push(table_data, sizeof *srat);
+    srat->reserved1 = cpu_to_le32(1);
+
+    for (i = 0; i < apic_ids->len; i++) {
+        int node_id = apic_ids->cpus[i].props.node_id;
+        uint32_t apic_id = apic_ids->cpus[i].arch_id;
+
+        if (apic_id < 255) {
+            AcpiSratProcessorAffinity *core;
+
+            core = acpi_data_push(table_data, sizeof *core);
+            core->type = ACPI_SRAT_PROCESSOR_APIC;
+            core->length = sizeof(*core);
+            core->local_apic_id = apic_id;
+            core->proximity_lo = node_id;
+            memset(core->proximity_hi, 0, 3);
+            core->local_sapic_eid = 0;
+            core->flags = cpu_to_le32(1);
+        } else {
+            AcpiSratProcessorX2ApicAffinity *core;
+
+            core = acpi_data_push(table_data, sizeof *core);
+            core->type = ACPI_SRAT_PROCESSOR_x2APIC;
+            core->length = sizeof(*core);
+            core->x2apic_id = cpu_to_le32(apic_id);
+            core->proximity_domain = cpu_to_le32(node_id);
+            core->flags = cpu_to_le32(1);
+        }
+    }
+
+
+    /* the memory map is a bit tricky, it contains at least one hole
+     * from 640k-1M and possibly another one from 3.5G-4G.
+     */
+    next_base = 0;
+    numa_start = table_data->len;
+
+    for (i = 1; i < conf->numa_nodes + 1; ++i) {
+        mem_base = next_base;
+        mem_len = conf->node_mem[i - 1];
+        next_base = mem_base + mem_len;
+
+        /* Cut out the 640K hole */
+        if (mem_base <= HOLE_640K_START &&
+            next_base > HOLE_640K_START) {
+            mem_len -= next_base - HOLE_640K_START;
+            if (mem_len > 0) {
+                numamem = acpi_data_push(table_data, sizeof *numamem);
+                build_srat_memory(numamem, mem_base, mem_len, i - 1,
+                                  MEM_AFFINITY_ENABLED);
+            }
+
+            /* Check for the rare case: 640K < RAM < 1M */
+            if (next_base <= HOLE_640K_END) {
+                next_base = HOLE_640K_END;
+                continue;
+            }
+            mem_base = HOLE_640K_END;
+            mem_len = next_base - HOLE_640K_END;
+        }
+
+        /* Cut out the ACPI_PCI hole */
+        if (mem_base <= conf->below_4g_mem_size &&
+            next_base > conf->below_4g_mem_size) {
+            mem_len -= next_base - conf->below_4g_mem_size;
+            if (mem_len > 0) {
+                numamem = acpi_data_push(table_data, sizeof *numamem);
+                build_srat_memory(numamem, mem_base, mem_len, i - 1,
+                                  MEM_AFFINITY_ENABLED);
+            }
+            mem_base = 1ULL << 32;
+            mem_len = next_base - conf->below_4g_mem_size;
+            next_base = mem_base + mem_len;
+        }
+
+        if (mem_len > 0) {
+            numamem = acpi_data_push(table_data, sizeof *numamem);
+            build_srat_memory(numamem, mem_base, mem_len, i - 1,
+                              MEM_AFFINITY_ENABLED);
+        }
+    }
+    slots = (table_data->len - numa_start) / sizeof *numamem;
+    for (; slots < conf->numa_nodes + 2; slots++) {
+        numamem = acpi_data_push(table_data, sizeof *numamem);
+        build_srat_memory(numamem, 0, 0, 0, MEM_AFFINITY_NOFLAGS);
+    }
+
+    /*
+     * Entry is required for Windows to enable memory hotplug in OS
+     * and for Linux to enable SWIOTLB when booted with less than
+     * 4G of RAM. Windows works better if the entry sets proximity
+     * to the highest NUMA node in the machine.
+     * Memory devices may override proximity set by this entry,
+     * providing _PXM method if necessary.
+     */
+    if (hotplugabble_address_space_size) {
+        numamem = acpi_data_push(table_data, sizeof *numamem);
+        build_srat_memory(numamem, machine->device_memory->base,
+                          hotplugabble_address_space_size, conf->numa_nodes - 1,
+                          MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
+    }
+
+    build_header(linker, table_data,
+                 (void *)(table_data->data + srat_start),
+                 "SRAT",
+                 table_data->len - srat_start, 1, NULL, NULL);
+}
+
 /*
  * ACPI spec 5.2.17 System Locality Distance Information Table
  * (Revision 2.0 or later)
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index f9a60907f1..353aa55357 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -469,7 +469,7 @@ build_spcr(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 }
 
 static void
-build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
+virt_build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 {
     AcpiSystemResourceAffinityTable *srat;
     AcpiSratProcessorGiccAffinity *core;
@@ -759,7 +759,7 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
 
     if (nb_numa_nodes > 0) {
         acpi_add_table(table_offsets, tables_blob);
-        build_srat(tables_blob, tables->linker, vms);
+        virt_build_srat(tables_blob, tables->linker, vms);
         if (have_numa_distance) {
             acpi_add_table(table_offsets, tables_blob);
             build_slit(tables_blob, tables->linker);
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index dfc02a8a85..5932dbe825 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1614,135 +1614,6 @@ build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog)
                  (void *)tpm2_ptr, "TPM2", sizeof(*tpm2_ptr), 4, NULL, NULL);
 }
 
-#define HOLE_640K_START  (640 * KiB)
-#define HOLE_640K_END   (1 * MiB)
-
-static void
-build_srat(GArray *table_data, BIOSLinker *linker,
-           MachineState *machine, AcpiConfiguration *conf)
-{
-    AcpiSystemResourceAffinityTable *srat;
-    AcpiSratMemoryAffinity *numamem;
-
-    int i;
-    int srat_start, numa_start, slots;
-    uint64_t mem_len, mem_base, next_base;
-    MachineClass *mc = MACHINE_GET_CLASS(machine);
-    const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(machine);
-    ram_addr_t hotplugabble_address_space_size =
-        object_property_get_int(OBJECT(machine), MEMORY_DEVICE_REGION_SIZE,
-                                NULL);
-
-    srat_start = table_data->len;
-
-    srat = acpi_data_push(table_data, sizeof *srat);
-    srat->reserved1 = cpu_to_le32(1);
-
-    for (i = 0; i < apic_ids->len; i++) {
-        int node_id = apic_ids->cpus[i].props.node_id;
-        uint32_t apic_id = apic_ids->cpus[i].arch_id;
-
-        if (apic_id < 255) {
-            AcpiSratProcessorAffinity *core;
-
-            core = acpi_data_push(table_data, sizeof *core);
-            core->type = ACPI_SRAT_PROCESSOR_APIC;
-            core->length = sizeof(*core);
-            core->local_apic_id = apic_id;
-            core->proximity_lo = node_id;
-            memset(core->proximity_hi, 0, 3);
-            core->local_sapic_eid = 0;
-            core->flags = cpu_to_le32(1);
-        } else {
-            AcpiSratProcessorX2ApicAffinity *core;
-
-            core = acpi_data_push(table_data, sizeof *core);
-            core->type = ACPI_SRAT_PROCESSOR_x2APIC;
-            core->length = sizeof(*core);
-            core->x2apic_id = cpu_to_le32(apic_id);
-            core->proximity_domain = cpu_to_le32(node_id);
-            core->flags = cpu_to_le32(1);
-        }
-    }
-
-
-    /* the memory map is a bit tricky, it contains at least one hole
-     * from 640k-1M and possibly another one from 3.5G-4G.
-     */
-    next_base = 0;
-    numa_start = table_data->len;
-
-    for (i = 1; i < conf->numa_nodes + 1; ++i) {
-        mem_base = next_base;
-        mem_len = conf->node_mem[i - 1];
-        next_base = mem_base + mem_len;
-
-        /* Cut out the 640K hole */
-        if (mem_base <= HOLE_640K_START &&
-            next_base > HOLE_640K_START) {
-            mem_len -= next_base - HOLE_640K_START;
-            if (mem_len > 0) {
-                numamem = acpi_data_push(table_data, sizeof *numamem);
-                build_srat_memory(numamem, mem_base, mem_len, i - 1,
-                                  MEM_AFFINITY_ENABLED);
-            }
-
-            /* Check for the rare case: 640K < RAM < 1M */
-            if (next_base <= HOLE_640K_END) {
-                next_base = HOLE_640K_END;
-                continue;
-            }
-            mem_base = HOLE_640K_END;
-            mem_len = next_base - HOLE_640K_END;
-        }
-
-        /* Cut out the ACPI_PCI hole */
-        if (mem_base <= conf->below_4g_mem_size &&
-            next_base > conf->below_4g_mem_size) {
-            mem_len -= next_base - conf->below_4g_mem_size;
-            if (mem_len > 0) {
-                numamem = acpi_data_push(table_data, sizeof *numamem);
-                build_srat_memory(numamem, mem_base, mem_len, i - 1,
-                                  MEM_AFFINITY_ENABLED);
-            }
-            mem_base = 1ULL << 32;
-            mem_len = next_base - conf->below_4g_mem_size;
-            next_base = mem_base + mem_len;
-        }
-
-        if (mem_len > 0) {
-            numamem = acpi_data_push(table_data, sizeof *numamem);
-            build_srat_memory(numamem, mem_base, mem_len, i - 1,
-                              MEM_AFFINITY_ENABLED);
-        }
-    }
-    slots = (table_data->len - numa_start) / sizeof *numamem;
-    for (; slots < conf->numa_nodes + 2; slots++) {
-        numamem = acpi_data_push(table_data, sizeof *numamem);
-        build_srat_memory(numamem, 0, 0, 0, MEM_AFFINITY_NOFLAGS);
-    }
-
-    /*
-     * Entry is required for Windows to enable memory hotplug in OS
-     * and for Linux to enable SWIOTLB when booted with less than
-     * 4G of RAM. Windows works better if the entry sets proximity
-     * to the highest NUMA node in the machine.
-     * Memory devices may override proximity set by this entry,
-     * providing _PXM method if necessary.
-     */
-    if (hotplugabble_address_space_size) {
-        numamem = acpi_data_push(table_data, sizeof *numamem);
-        build_srat_memory(numamem, machine->device_memory->base,
-                          hotplugabble_address_space_size, conf->numa_nodes - 1,
-                          MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
-    }
-
-    build_header(linker, table_data,
-                 (void *)(table_data->data + srat_start),
-                 "SRAT",
-                 table_data->len - srat_start, 1, NULL, NULL);
-}
-
 /*
  * VT-d spec 8.1 DMA Remapping Reporting Structure
  * (version Oct. 2014 or later)
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 1fabf58df2..654ce2ec26 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -1,6 +1,7 @@
 #ifndef HW_ACPI_AML_BUILD_H
 #define HW_ACPI_AML_BUILD_H
 
+#include "hw/acpi/acpi.h"
 #include "hw/acpi/acpi-defs.h"
 #include "hw/acpi/bios-linker-loader.h"
 #include "hw/pci/pcie_host.h"
@@ -438,6 +439,8 @@ void
 build_xsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
            const char *oem_id, const char *oem_table_id);
 
+void build_srat(GArray *table_data, BIOSLinker *linker,
+                MachineState *machine, AcpiConfiguration *conf);
 int
 build_append_named_dword(GArray *array, const char *name_format, ...)
 GCC_FMT_ATTR(2, 3);
-- 
2.17.2

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH v3 14/19] hw: acpi: Fix memory hotplug AML generation error
  2018-10-29 17:01 [Qemu-devel] [PATCH v3 00/19] ACPI reorganization for hardware-reduced support Samuel Ortiz
                   ` (13 preceding siblings ...)
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 13/19] hw: acpi: Export the SRAT AML build API Samuel Ortiz
@ 2018-10-29 17:01 ` Samuel Ortiz
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 15/19] hw: acpi: Export the PCI hotplug API Samuel Ortiz
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-29 17:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: Yang Zhong, Michael S. Tsirkin, Igor Mammedov

From: Yang Zhong <yang.zhong@intel.com>

When using the generated memory hotplug AML, the iasl
compiler would give the following error:

dsdt.dsl 266: Return (MOST (_UID, Arg0, Arg1, Arg2))
Error 6080 - Called method returns no value ^

Signed-off-by: Yang Zhong <yang.zhong@intel.com>
---
 hw/acpi/memory_hotplug.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c
index db2c4df961..893fc2bd27 100644
--- a/hw/acpi/memory_hotplug.c
+++ b/hw/acpi/memory_hotplug.c
@@ -686,15 +686,15 @@ void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem,
 
             method = aml_method("_OST", 3, AML_NOTSERIALIZED);
             s = MEMORY_SLOT_OST_METHOD;
-            aml_append(method, aml_return(aml_call4(
-                s, aml_name("_UID"), aml_arg(0), aml_arg(1), aml_arg(2)
-            )));
+            aml_append(method,
+                       aml_call4(s, aml_name("_UID"), aml_arg(0),
+                                 aml_arg(1), aml_arg(2)));
             aml_append(dev, method);
 
             method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
             s = MEMORY_SLOT_EJECT_METHOD;
-            aml_append(method, aml_return(aml_call2(
-                       s, aml_name("_UID"), aml_arg(0))));
+            aml_append(method,
+                       aml_call2(s, aml_name("_UID"), aml_arg(0)));
             aml_append(dev, method);
 
             aml_append(dev_container, dev);
-- 
2.17.2

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH v3 15/19] hw: acpi: Export the PCI hotplug API
  2018-10-29 17:01 [Qemu-devel] [PATCH v3 00/19] ACPI reorganization for hardware-reduced support Samuel Ortiz
                   ` (14 preceding siblings ...)
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 14/19] hw: acpi: Fix memory hotplug AML generation error Samuel Ortiz
@ 2018-10-29 17:01 ` Samuel Ortiz
  2018-10-29 19:46   ` Philippe Mathieu-Daudé
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 16/19] hw: acpi: Retrieve the PCI bus from AcpiPciHpState Samuel Ortiz
                   ` (3 subsequent siblings)
  19 siblings, 1 reply; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-29 17:01 UTC (permalink / raw)
  To: qemu-devel
  Cc: Sebastien Boeuf, Jing Liu, Michael S. Tsirkin, Igor Mammedov,
	Marcel Apfelbaum, Paolo Bonzini, Richard Henderson,
	Eduardo Habkost

From: Sebastien Boeuf <sebastien.boeuf@intel.com>

The ACPI hotplug support for PCI devices APIs are not x86 or even
machine type specific. In order for future machine types to be able to
re-use that code, we export it through the architecture agnostic
hw/acpi folder.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
Signed-off-by: Jing Liu <jing2.liu@linux.intel.com>
---
 hw/acpi/aml-build.c         | 194 ++++++++++++++++++++++++++++++++++++
 hw/i386/acpi-build.c        | 192 +----------------------------------
 include/hw/acpi/aml-build.h |   3 +
 3 files changed, 199 insertions(+), 190 deletions(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index c3f652a68f..1b057d1191 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -35,6 +35,7 @@
 #include "hw/acpi/tpm.h"
 #include "qom/qom-qobject.h"
 #include "qapi/qmp/qnum.h"
+#include "hw/acpi/pcihp.h"
 
 #define PCI_HOST_BRIDGE_CONFIG_ADDR        0xcf8
 #define PCI_HOST_BRIDGE_IO_0_MIN_ADDR      0x0000
@@ -2314,6 +2315,199 @@ Aml *build_pci_host_bridge(Aml *table, AcpiPciBus *pci_host)
     return scope;
 }
 
+void build_acpi_pci_hotplug(Aml *scope)
+{
+    Aml *field;
+    Aml *method;
+
+    aml_append(scope,
+        aml_operation_region("PCST", AML_SYSTEM_IO, aml_int(0xae00), 0x08));
+    field = aml_field("PCST", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
+    aml_append(field, aml_named_field("PCIU", 32));
+    aml_append(field, aml_named_field("PCID", 32));
+    aml_append(scope, field);
+
+    aml_append(scope,
+        aml_operation_region("SEJ", AML_SYSTEM_IO, aml_int(0xae08), 0x04));
+    field = aml_field("SEJ", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
+    aml_append(field, aml_named_field("B0EJ", 32));
+    aml_append(scope, field);
+
+    aml_append(scope,
+        aml_operation_region("BNMR", AML_SYSTEM_IO, aml_int(0xae10), 0x04));
+    field = aml_field("BNMR", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
+    aml_append(field, aml_named_field("BNUM", 32));
+    aml_append(scope, field);
+
+    aml_append(scope, aml_mutex("BLCK", 0));
+
+    method = aml_method("PCEJ", 2, AML_NOTSERIALIZED);
+    aml_append(method, aml_acquire(aml_name("BLCK"), 0xFFFF));
+    aml_append(method, aml_store(aml_arg(0), aml_name("BNUM")));
+    aml_append(method,
+        aml_store(aml_shiftleft(aml_int(1), aml_arg(1)), aml_name("B0EJ")));
+    aml_append(method, aml_release(aml_name("BLCK")));
+    aml_append(method, aml_return(aml_int(0)));
+    aml_append(scope, method);
+}
+
+static void build_append_pcihp_notify_entry(Aml *method, int slot)
+{
+    Aml *if_ctx;
+    int32_t devfn = PCI_DEVFN(slot, 0);
+
+    if_ctx = aml_if(aml_and(aml_arg(0), aml_int(0x1U << slot), NULL));
+    aml_append(if_ctx, aml_notify(aml_name("S%.02X", devfn), aml_arg(1)));
+    aml_append(method, if_ctx);
+}
+
+void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
+                                  bool pcihp_bridge_en)
+{
+    Aml *dev, *notify_method = NULL, *method;
+    QObject *bsel;
+    PCIBus *sec;
+    int i;
+
+    bsel = object_property_get_qobject(OBJECT(bus), ACPI_PCIHP_PROP_BSEL, NULL);
+    if (bsel) {
+        uint64_t bsel_val = qnum_get_uint(qobject_to(QNum, bsel));
+
+        aml_append(parent_scope, aml_name_decl("BSEL", aml_int(bsel_val)));
+        notify_method = aml_method("DVNT", 2, AML_NOTSERIALIZED);
+    }
+
+    for (i = 0; i < ARRAY_SIZE(bus->devices); i += PCI_FUNC_MAX) {
+        DeviceClass *dc;
+        PCIDeviceClass *pc;
+        PCIDevice *pdev = bus->devices[i];
+        int slot = PCI_SLOT(i);
+        bool hotplug_enabled_dev;
+        bool bridge_in_acpi;
+
+        if (!pdev) {
+            if (bsel) { /* add hotplug slots for non present devices */
+                dev = aml_device("S%.02X", PCI_DEVFN(slot, 0));
+                aml_append(dev, aml_name_decl("_SUN", aml_int(slot)));
+                aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16)));
+                method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
+                aml_append(method,
+                    aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN"))
+                );
+                aml_append(dev, method);
+                aml_append(parent_scope, dev);
+
+                build_append_pcihp_notify_entry(notify_method, slot);
+            }
+            continue;
+        }
+
+        pc = PCI_DEVICE_GET_CLASS(pdev);
+        dc = DEVICE_GET_CLASS(pdev);
+
+        /* When hotplug for bridges is enabled, bridges are
+         * described in ACPI separately (see build_pci_bus_end).
+         * In this case they aren't themselves hot-pluggable.
+         * Hotplugged bridges *are* hot-pluggable.
+         */
+        bridge_in_acpi = pc->is_bridge && pcihp_bridge_en &&
+            !DEVICE(pdev)->hotplugged;
+
+        hotplug_enabled_dev = bsel && dc->hotpluggable && !bridge_in_acpi;
+
+        if (pc->class_id == PCI_CLASS_BRIDGE_ISA) {
+            continue;
+        }
+
+        /* start to compose PCI slot descriptor */
+        dev = aml_device("S%.02X", PCI_DEVFN(slot, 0));
+        aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16)));
+
+        if (pc->class_id == PCI_CLASS_DISPLAY_VGA) {
+            /* add VGA specific AML methods */
+            int s3d;
+
+            if (object_dynamic_cast(OBJECT(pdev), "qxl-vga")) {
+                s3d = 3;
+            } else {
+                s3d = 0;
+            }
+
+            method = aml_method("_S1D", 0, AML_NOTSERIALIZED);
+            aml_append(method, aml_return(aml_int(0)));
+            aml_append(dev, method);
+
+            method = aml_method("_S2D", 0, AML_NOTSERIALIZED);
+            aml_append(method, aml_return(aml_int(0)));
+            aml_append(dev, method);
+
+            method = aml_method("_S3D", 0, AML_NOTSERIALIZED);
+            aml_append(method, aml_return(aml_int(s3d)));
+            aml_append(dev, method);
+        } else if (hotplug_enabled_dev) {
+            /* add _SUN/_EJ0 to make slot hotpluggable  */
+            aml_append(dev, aml_name_decl("_SUN", aml_int(slot)));
+
+            method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
+            aml_append(method,
+                aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN"))
+            );
+            aml_append(dev, method);
+
+            if (bsel) {
+                build_append_pcihp_notify_entry(notify_method, slot);
+            }
+        } else if (bridge_in_acpi) {
+            /*
+             * device is coldplugged bridge,
+             * add child device descriptions into its scope
+             */
+            PCIBus *sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(pdev));
+
+            build_append_pci_bus_devices(dev, sec_bus, pcihp_bridge_en);
+        }
+        /* slot descriptor has been composed, add it into parent context */
+        aml_append(parent_scope, dev);
+    }
+
+    if (bsel) {
+        aml_append(parent_scope, notify_method);
+    }
+
+    /* Append PCNT method to notify about events on local and child buses.
+     * Add unconditionally for root since DSDT expects it.
+     */
+    method = aml_method("PCNT", 0, AML_NOTSERIALIZED);
+
+    /* If bus supports hotplug select it and notify about local events */
+    if (bsel) {
+        uint64_t bsel_val = qnum_get_uint(qobject_to(QNum, bsel));
+
+        aml_append(method, aml_store(aml_int(bsel_val), aml_name("BNUM")));
+        aml_append(method,
+            aml_call2("DVNT", aml_name("PCIU"), aml_int(1) /* Device Check */)
+        );
+        aml_append(method,
+            aml_call2("DVNT", aml_name("PCID"), aml_int(3)/* Eject Request */)
+        );
+    }
+
+    /* Notify about child bus events in any case */
+    if (pcihp_bridge_en) {
+        QLIST_FOREACH(sec, &bus->child, sibling) {
+            int32_t devfn = sec->parent_dev->devfn;
+
+            if (pci_bus_is_root(sec) || pci_bus_is_express(sec)) {
+                continue;
+            }
+
+            aml_append(method, aml_name("^S%.02X.PCNT", devfn));
+        }
+    }
+    aml_append(parent_scope, method);
+    qobject_unref(bsel);
+}
+
 void acpi_dsdt_add_pci_bus(Aml *dsdt, AcpiPciBus *pci_host)
 {
     Aml *dev, *pci_scope;
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 5932dbe825..9cb739bf5c 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -362,163 +362,6 @@ build_madt(GArray *table_data, BIOSLinker *linker,
                  table_data->len - madt_start, 1, NULL, NULL);
 }
 
-static void build_append_pcihp_notify_entry(Aml *method, int slot)
-{
-    Aml *if_ctx;
-    int32_t devfn = PCI_DEVFN(slot, 0);
-
-    if_ctx = aml_if(aml_and(aml_arg(0), aml_int(0x1U << slot), NULL));
-    aml_append(if_ctx, aml_notify(aml_name("S%.02X", devfn), aml_arg(1)));
-    aml_append(method, if_ctx);
-}
-
-static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
-                                         bool pcihp_bridge_en)
-{
-    Aml *dev, *notify_method = NULL, *method;
-    QObject *bsel;
-    PCIBus *sec;
-    int i;
-
-    bsel = object_property_get_qobject(OBJECT(bus), ACPI_PCIHP_PROP_BSEL, NULL);
-    if (bsel) {
-        uint64_t bsel_val = qnum_get_uint(qobject_to(QNum, bsel));
-
-        aml_append(parent_scope, aml_name_decl("BSEL", aml_int(bsel_val)));
-        notify_method = aml_method("DVNT", 2, AML_NOTSERIALIZED);
-    }
-
-    for (i = 0; i < ARRAY_SIZE(bus->devices); i += PCI_FUNC_MAX) {
-        DeviceClass *dc;
-        PCIDeviceClass *pc;
-        PCIDevice *pdev = bus->devices[i];
-        int slot = PCI_SLOT(i);
-        bool hotplug_enabled_dev;
-        bool bridge_in_acpi;
-
-        if (!pdev) {
-            if (bsel) { /* add hotplug slots for non present devices */
-                dev = aml_device("S%.02X", PCI_DEVFN(slot, 0));
-                aml_append(dev, aml_name_decl("_SUN", aml_int(slot)));
-                aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16)));
-                method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
-                aml_append(method,
-                    aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN"))
-                );
-                aml_append(dev, method);
-                aml_append(parent_scope, dev);
-
-                build_append_pcihp_notify_entry(notify_method, slot);
-            }
-            continue;
-        }
-
-        pc = PCI_DEVICE_GET_CLASS(pdev);
-        dc = DEVICE_GET_CLASS(pdev);
-
-        /* When hotplug for bridges is enabled, bridges are
-         * described in ACPI separately (see build_pci_bus_end).
-         * In this case they aren't themselves hot-pluggable.
-         * Hotplugged bridges *are* hot-pluggable.
-         */
-        bridge_in_acpi = pc->is_bridge && pcihp_bridge_en &&
-            !DEVICE(pdev)->hotplugged;
-
-        hotplug_enabled_dev = bsel && dc->hotpluggable && !bridge_in_acpi;
-
-        if (pc->class_id == PCI_CLASS_BRIDGE_ISA) {
-            continue;
-        }
-
-        /* start to compose PCI slot descriptor */
-        dev = aml_device("S%.02X", PCI_DEVFN(slot, 0));
-        aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16)));
-
-        if (pc->class_id == PCI_CLASS_DISPLAY_VGA) {
-            /* add VGA specific AML methods */
-            int s3d;
-
-            if (object_dynamic_cast(OBJECT(pdev), "qxl-vga")) {
-                s3d = 3;
-            } else {
-                s3d = 0;
-            }
-
-            method = aml_method("_S1D", 0, AML_NOTSERIALIZED);
-            aml_append(method, aml_return(aml_int(0)));
-            aml_append(dev, method);
-
-            method = aml_method("_S2D", 0, AML_NOTSERIALIZED);
-            aml_append(method, aml_return(aml_int(0)));
-            aml_append(dev, method);
-
-            method = aml_method("_S3D", 0, AML_NOTSERIALIZED);
-            aml_append(method, aml_return(aml_int(s3d)));
-            aml_append(dev, method);
-        } else if (hotplug_enabled_dev) {
-            /* add _SUN/_EJ0 to make slot hotpluggable  */
-            aml_append(dev, aml_name_decl("_SUN", aml_int(slot)));
-
-            method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
-            aml_append(method,
-                aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN"))
-            );
-            aml_append(dev, method);
-
-            if (bsel) {
-                build_append_pcihp_notify_entry(notify_method, slot);
-            }
-        } else if (bridge_in_acpi) {
-            /*
-             * device is coldplugged bridge,
-             * add child device descriptions into its scope
-             */
-            PCIBus *sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(pdev));
-
-            build_append_pci_bus_devices(dev, sec_bus, pcihp_bridge_en);
-        }
-        /* slot descriptor has been composed, add it into parent context */
-        aml_append(parent_scope, dev);
-    }
-
-    if (bsel) {
-        aml_append(parent_scope, notify_method);
-    }
-
-    /* Append PCNT method to notify about events on local and child buses.
-     * Add unconditionally for root since DSDT expects it.
-     */
-    method = aml_method("PCNT", 0, AML_NOTSERIALIZED);
-
-    /* If bus supports hotplug select it and notify about local events */
-    if (bsel) {
-        uint64_t bsel_val = qnum_get_uint(qobject_to(QNum, bsel));
-
-        aml_append(method, aml_store(aml_int(bsel_val), aml_name("BNUM")));
-        aml_append(method,
-            aml_call2("DVNT", aml_name("PCIU"), aml_int(1) /* Device Check */)
-        );
-        aml_append(method,
-            aml_call2("DVNT", aml_name("PCID"), aml_int(3)/* Eject Request */)
-        );
-    }
-
-    /* Notify about child bus events in any case */
-    if (pcihp_bridge_en) {
-        QLIST_FOREACH(sec, &bus->child, sibling) {
-            int32_t devfn = sec->parent_dev->devfn;
-
-            if (pci_bus_is_root(sec) || pci_bus_is_express(sec)) {
-                continue;
-            }
-
-            aml_append(method, aml_name("^S%.02X.PCNT", devfn));
-        }
-    }
-    aml_append(parent_scope, method);
-    qobject_unref(bsel);
-}
-
 static void build_hpet_aml(Aml *table)
 {
     Aml *crs;
@@ -1214,41 +1057,10 @@ static void build_piix4_isa_bridge(Aml *table)
 static void build_piix4_pci_hotplug(Aml *table)
 {
     Aml *scope;
-    Aml *field;
-    Aml *method;
-
-    scope =  aml_scope("_SB.PCI0");
-
-    aml_append(scope,
-        aml_operation_region("PCST", AML_SYSTEM_IO, aml_int(0xae00), 0x08));
-    field = aml_field("PCST", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
-    aml_append(field, aml_named_field("PCIU", 32));
-    aml_append(field, aml_named_field("PCID", 32));
-    aml_append(scope, field);
 
-    aml_append(scope,
-        aml_operation_region("SEJ", AML_SYSTEM_IO, aml_int(0xae08), 0x04));
-    field = aml_field("SEJ", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
-    aml_append(field, aml_named_field("B0EJ", 32));
-    aml_append(scope, field);
-
-    aml_append(scope,
-        aml_operation_region("BNMR", AML_SYSTEM_IO, aml_int(0xae10), 0x04));
-    field = aml_field("BNMR", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
-    aml_append(field, aml_named_field("BNUM", 32));
-    aml_append(scope, field);
-
-    aml_append(scope, aml_mutex("BLCK", 0));
-
-    method = aml_method("PCEJ", 2, AML_NOTSERIALIZED);
-    aml_append(method, aml_acquire(aml_name("BLCK"), 0xFFFF));
-    aml_append(method, aml_store(aml_arg(0), aml_name("BNUM")));
-    aml_append(method,
-        aml_store(aml_shiftleft(aml_int(1), aml_arg(1)), aml_name("B0EJ")));
-    aml_append(method, aml_release(aml_name("BLCK")));
-    aml_append(method, aml_return(aml_int(0)));
-    aml_append(scope, method);
+    scope = aml_scope("_SB.PCI0");
 
+    build_acpi_pci_hotplug(scope);
     aml_append(table, scope);
 }
 
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 654ce2ec26..3ea2df5f83 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -419,6 +419,9 @@ Aml *build_osc_method(uint32_t value);
 void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info);
 Aml *build_gsi_link_dev(const char *name, uint8_t uid, uint8_t gsi);
 Aml *build_prt(bool is_pci0_prt);
+void build_acpi_pci_hotplug(Aml *scope);
+void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
+                                  bool pcihp_bridge_en);
 void acpi_dsdt_add_pci_bus(Aml *dsdt, AcpiPciBus *pci_host);
 Aml *build_pci_host_bridge(Aml *table, AcpiPciBus *pci_host);
 void crs_range_set_init(CrsRangeSet *range_set);
-- 
2.17.2

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH v3 16/19] hw: acpi: Retrieve the PCI bus from AcpiPciHpState
  2018-10-29 17:01 [Qemu-devel] [PATCH v3 00/19] ACPI reorganization for hardware-reduced support Samuel Ortiz
                   ` (15 preceding siblings ...)
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 15/19] hw: acpi: Export the PCI hotplug API Samuel Ortiz
@ 2018-10-29 17:01 ` Samuel Ortiz
  2018-10-29 21:02   ` Philippe Mathieu-Daudé
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 17/19] hw: acpi: Define ACPI tables builder interface Samuel Ortiz
                   ` (2 subsequent siblings)
  19 siblings, 1 reply; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-29 17:01 UTC (permalink / raw)
  To: qemu-devel
  Cc: Sebastien Boeuf, Jing Liu, Michael S. Tsirkin, Igor Mammedov,
	Marcel Apfelbaum, Paolo Bonzini

From: Sebastien Boeuf <sebastien.boeuf@intel.com>

Instead of using the machine type specific method find_i440fx() to
retrieve the PCI bus, this commit aims to rely on the fact that the
PCI bus is known by the structure AcpiPciHpState.

When the structure is initialized through acpi_pcihp_init() call,
it saves the PCI bus, which means there is no need to invoke a
special function later on.

Based on the fact that find_i440fx() was only used there, this
patch also removes the function find_i440fx() itself from the
entire codebase.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
Signed-off-by: Jing Liu <jing2.liu@linux.intel.com>
---
 hw/acpi/pcihp.c       | 10 ++++------
 hw/pci-host/piix.c    |  8 --------
 include/hw/i386/pc.h  |  1 -
 stubs/Makefile.objs   |  1 -
 stubs/pci-host-piix.c |  6 ------
 5 files changed, 4 insertions(+), 22 deletions(-)
 delete mode 100644 stubs/pci-host-piix.c

diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
index 80d42e12ff..254b2e50ab 100644
--- a/hw/acpi/pcihp.c
+++ b/hw/acpi/pcihp.c
@@ -93,10 +93,9 @@ static void *acpi_set_bsel(PCIBus *bus, void *opaque)
     return bsel_alloc;
 }
 
-static void acpi_set_pci_info(void)
+static void acpi_set_pci_info(AcpiPciHpState *s)
 {
     static bool bsel_is_set;
-    PCIBus *bus;
     unsigned bsel_alloc = ACPI_PCIHP_BSEL_DEFAULT;
 
     if (bsel_is_set) {
@@ -104,10 +103,9 @@ static void acpi_set_pci_info(void)
     }
     bsel_is_set = true;
 
-    bus = find_i440fx(); /* TODO: Q35 support */
-    if (bus) {
+    if (s->root) {
         /* Scan all PCI buses. Set property to enable acpi based hotplug. */
-        pci_for_each_bus_depth_first(bus, acpi_set_bsel, NULL, &bsel_alloc);
+        pci_for_each_bus_depth_first(s->root, acpi_set_bsel, NULL, &bsel_alloc);
     }
 }
 
@@ -213,7 +211,7 @@ static void acpi_pcihp_update(AcpiPciHpState *s)
 
 void acpi_pcihp_reset(AcpiPciHpState *s)
 {
-    acpi_set_pci_info();
+    acpi_set_pci_info(s);
     acpi_pcihp_update(s);
 }
 
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index da73743fa2..4940f59c9b 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -445,14 +445,6 @@ PCIBus *i440fx_init(const char *host_type, const char *pci_type,
     return b;
 }
 
-PCIBus *find_i440fx(void)
-{
-    PCIHostState *s = OBJECT_CHECK(PCIHostState,
-                                   object_resolve_path("/machine/i440fx", NULL),
-                                   TYPE_PCI_HOST_BRIDGE);
-    return s ? s->bus : NULL;
-}
-
 /* PIIX3 PCI to ISA bridge */
 static void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq)
 {
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 7d177cd207..f6b2649cf8 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -260,7 +260,6 @@ PCIBus *i440fx_init(const char *host_type, const char *pci_type,
                     MemoryRegion *pci_memory,
                     MemoryRegion *ram_memory);
 
-PCIBus *find_i440fx(void);
 /* piix4.c */
 extern PCIDevice *piix4_dev;
 int piix4_init(PCIBus *bus, ISABus **isa_bus, int devfn);
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index 5dd0aeeec6..725f78bedc 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -41,6 +41,5 @@ stub-obj-y += pc_madt_cpu_entry.o
 stub-obj-y += vmgenid.o
 stub-obj-y += xen-common.o
 stub-obj-y += xen-hvm.o
-stub-obj-y += pci-host-piix.o
 stub-obj-y += ram-block.o
 stub-obj-y += ramfb.o
diff --git a/stubs/pci-host-piix.c b/stubs/pci-host-piix.c
deleted file mode 100644
index 6ed81b1f21..0000000000
--- a/stubs/pci-host-piix.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include "qemu/osdep.h"
-#include "hw/i386/pc.h"
-PCIBus *find_i440fx(void)
-{
-    return NULL;
-}
-- 
2.17.2

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH v3 17/19] hw: acpi: Define ACPI tables builder interface
  2018-10-29 17:01 [Qemu-devel] [PATCH v3 00/19] ACPI reorganization for hardware-reduced support Samuel Ortiz
                   ` (16 preceding siblings ...)
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 16/19] hw: acpi: Retrieve the PCI bus from AcpiPciHpState Samuel Ortiz
@ 2018-10-29 17:01 ` Samuel Ortiz
  2018-10-29 21:06   ` Philippe Mathieu-Daudé
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 18/19] hw: i386: Export the MADT build method Samuel Ortiz
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 19/19] hw: i386: Implement the ACPI builder interface for PC Samuel Ortiz
  19 siblings, 1 reply; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-29 17:01 UTC (permalink / raw)
  To: qemu-devel
  Cc: Eduardo Habkost, Marcel Apfelbaum, Michael S. Tsirkin, Igor Mammedov

In order to decouple ACPI APIs from specific machine types, we are
creating an ACPI builder interface that each ACPI platform can choose to
implement.
This way, a new machine type can re-use the high level ACPI APIs and
define some custom table build methods, without having to duplicate most
of the existing implementation only to add small variations to it.

Cc: Eduardo Habkost <ehabkost@redhat.com>
Cc: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 hw/acpi/Makefile.objs     |  1 +
 hw/acpi/builder.c         | 97 +++++++++++++++++++++++++++++++++++++++
 include/hw/acpi/builder.h | 97 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 195 insertions(+)
 create mode 100644 hw/acpi/builder.c
 create mode 100644 include/hw/acpi/builder.h

diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
index 11c35bcb44..2f383adc6f 100644
--- a/hw/acpi/Makefile.objs
+++ b/hw/acpi/Makefile.objs
@@ -11,6 +11,7 @@ common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o
 common-obj-y += acpi_interface.o
 common-obj-y += bios-linker-loader.o
 common-obj-y += aml-build.o
+common-obj-y += builder.o
 
 common-obj-$(CONFIG_IPMI) += ipmi.o
 common-obj-$(call lnot,$(CONFIG_IPMI)) += ipmi-stub.o
diff --git a/hw/acpi/builder.c b/hw/acpi/builder.c
new file mode 100644
index 0000000000..c29a614793
--- /dev/null
+++ b/hw/acpi/builder.c
@@ -0,0 +1,97 @@
+/*
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/module.h"
+#include "qom/object.h"
+#include "hw/acpi/builder.h"
+
+void acpi_builder_rsdp(AcpiBuilder *builder,
+                       GArray *table_data, BIOSLinker *linker,
+                       unsigned rsdt_tbl_offset)
+{
+    AcpiBuilderMethods *abm = ACPI_BUILDER_GET_METHODS(builder);
+
+    if (abm && abm->rsdp) {
+        abm->rsdp(table_data, linker, rsdt_tbl_offset);
+    }
+}
+
+void acpi_builder_madt(AcpiBuilder *builder,
+                       GArray *table_data, BIOSLinker *linker,
+                       MachineState *ms, AcpiConfiguration *conf)
+{
+    AcpiBuilderMethods *abm = ACPI_BUILDER_GET_METHODS(builder);
+
+    if (abm && abm->madt) {
+        abm->madt(table_data, linker, ms, conf);
+    }
+}
+
+void acpi_builder_mcfg(AcpiBuilder *builder,
+                       GArray *table_data, BIOSLinker *linker,
+                       AcpiMcfgInfo *info)
+{
+    AcpiBuilderMethods *abm = ACPI_BUILDER_GET_METHODS(builder);
+
+    if (abm && abm->mcfg) {
+        abm->mcfg(table_data, linker, info);
+    }
+}
+
+void acpi_builder_srat(AcpiBuilder *builder,
+                       GArray *table_data, BIOSLinker *linker,
+                       MachineState *machine, AcpiConfiguration *conf)
+{
+    AcpiBuilderMethods *abm = ACPI_BUILDER_GET_METHODS(builder);
+
+    if (abm && abm->srat) {
+        abm->srat(table_data, linker, machine, conf);
+    }
+}
+
+void acpi_builder_slit(AcpiBuilder *builder,
+                       GArray *table_data, BIOSLinker *linker)
+{
+    AcpiBuilderMethods *abm = ACPI_BUILDER_GET_METHODS(builder);
+
+    if (abm && abm->slit) {
+        abm->slit(table_data, linker);
+    }
+}
+
+AcpiConfiguration *acpi_builder_configuration(AcpiBuilder *builder)
+{
+    AcpiBuilderMethods *abm = ACPI_BUILDER_GET_METHODS(builder);
+    if (abm && abm->configuration) {
+        return abm->configuration(builder);
+    }
+    return NULL;
+}
+
+static const TypeInfo acpi_builder_info = {
+    .name          = TYPE_ACPI_BUILDER,
+    .parent        = TYPE_INTERFACE,
+    .class_size    = sizeof(AcpiBuilderMethods),
+};
+
+static void acpi_builder_register_type(void)
+{
+    type_register_static(&acpi_builder_info);
+}
+
+type_init(acpi_builder_register_type)
diff --git a/include/hw/acpi/builder.h b/include/hw/acpi/builder.h
new file mode 100644
index 0000000000..639b554de3
--- /dev/null
+++ b/include/hw/acpi/builder.h
@@ -0,0 +1,97 @@
+/*
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ACPI_BUILDER_H
+#define ACPI_BUILDER_H
+
+#include "qemu/osdep.h"
+#include "hw/acpi/bios-linker-loader.h"
+#include "qom/object.h"
+
+#define TYPE_ACPI_BUILDER "acpi-builder"
+
+#define ACPI_BUILDER_METHODS(klass) \
+     OBJECT_CLASS_CHECK(AcpiBuilderMethods, (klass), TYPE_ACPI_BUILDER)
+#define ACPI_BUILDER_GET_METHODS(obj) \
+     OBJECT_GET_CLASS(AcpiBuilderMethods, (obj), TYPE_ACPI_BUILDER)
+#define ACPI_BUILDER(obj)                                       \
+     INTERFACE_CHECK(AcpiBuilder, (obj), TYPE_ACPI_BUILDER)
+
+typedef struct AcpiConfiguration AcpiConfiguration;
+typedef struct AcpiBuildState AcpiBuildState;
+typedef struct AcpiMcfgInfo AcpiMcfgInfo;
+
+typedef struct AcpiBuilder {
+    /* <private> */
+    Object Parent;
+} AcpiBuilder;
+
+/**
+ * AcpiBuildMethods:
+ *
+ * Interface to be implemented by a machine type that needs to provide
+ * custom ACPI tables build method.
+ *
+ * @parent: Opaque parent interface.
+ *
+ * @rsdp:
+ * @madt:
+ * @mcfg:
+ * @srat:
+ * @slit:
+ * @setup:
+ */
+typedef struct AcpiBuilderMethods {
+    /* <private> */
+    InterfaceClass parent;
+
+    /* <public> */
+    void (*rsdp)(GArray *table_data, BIOSLinker *linker,
+                 unsigned rsdt_tbl_offset);
+    void (*madt)(GArray *table_data, BIOSLinker *linker,
+                 MachineState *ms, AcpiConfiguration *conf);
+    void (*mcfg)(GArray *table_data, BIOSLinker *linker,
+                 AcpiMcfgInfo *info);
+    void (*srat)(GArray *table_data, BIOSLinker *linker,
+                 MachineState *machine, AcpiConfiguration *conf);
+    void (*slit)(GArray *table_data, BIOSLinker *linker);
+
+    AcpiConfiguration *(*configuration)(AcpiBuilder *builder);
+} AcpiBuilderMethods;
+
+void acpi_builder_rsdp(AcpiBuilder *builder,
+                       GArray *table_data, BIOSLinker *linker,
+                       unsigned rsdt_tbl_offset);
+
+void acpi_builder_madt(AcpiBuilder *builder,
+                       GArray *table_data, BIOSLinker *linker,
+                       MachineState *ms, AcpiConfiguration *conf);
+
+void acpi_builder_mcfg(AcpiBuilder *builder,
+                       GArray *table_data, BIOSLinker *linker,
+                       AcpiMcfgInfo *info);
+
+void acpi_builder_srat(AcpiBuilder *builder,
+                       GArray *table_data, BIOSLinker *linker,
+                       MachineState *machine, AcpiConfiguration *conf);
+
+void acpi_builder_slit(AcpiBuilder *builder,
+                       GArray *table_data, BIOSLinker *linker);
+
+AcpiConfiguration *acpi_builder_configuration(AcpiBuilder *builder);
+
+#endif
-- 
2.17.2

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH v3 18/19] hw: i386: Export the MADT build method
  2018-10-29 17:01 [Qemu-devel] [PATCH v3 00/19] ACPI reorganization for hardware-reduced support Samuel Ortiz
                   ` (17 preceding siblings ...)
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 17/19] hw: acpi: Define ACPI tables builder interface Samuel Ortiz
@ 2018-10-29 17:01 ` Samuel Ortiz
  2018-10-29 21:18   ` Philippe Mathieu-Daudé
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 19/19] hw: i386: Implement the ACPI builder interface for PC Samuel Ortiz
  19 siblings, 1 reply; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-29 17:01 UTC (permalink / raw)
  To: qemu-devel
  Cc: Michael S. Tsirkin, Igor Mammedov, Shannon Zhao, Peter Maydell,
	Marcel Apfelbaum, Paolo Bonzini, Richard Henderson,
	Eduardo Habkost, open list:ARM ACPI Subsystem

It is going to be used by the PC machine type as the MADT table builder
method and thus needs to be exported outside of acpi-build.c

Also, now that the generic build_madt() API is exported, we have to
rename the ARM static one in order to avoid build time conflicts.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 hw/arm/virt-acpi-build.c |  4 ++--
 hw/i386/acpi-build.c     |  3 ++-
 include/hw/i386/acpi.h   | 27 +++++++++++++++++++++++++++
 3 files changed, 31 insertions(+), 3 deletions(-)
 create mode 100644 include/hw/i386/acpi.h

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 353aa55357..0c349e1c60 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -565,7 +565,7 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 
 /* MADT */
 static void
-build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
+virt_build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 {
     VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
     int madt_start = table_data->len;
@@ -746,7 +746,7 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
     build_fadt_rev5(tables_blob, tables->linker, vms, dsdt);
 
     acpi_add_table(table_offsets, tables_blob);
-    build_madt(tables_blob, tables->linker, vms);
+    virt_build_madt(tables_blob, tables->linker, vms);
 
     acpi_add_table(table_offsets, tables_blob);
     build_gtdt(tables_blob, tables->linker, vms);
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 9cb739bf5c..5035dac556 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -62,6 +62,7 @@
 #include "qom/qom-qobject.h"
 #include "hw/i386/amd_iommu.h"
 #include "hw/i386/intel_iommu.h"
+#include "hw/i386/acpi.h"
 
 #include "hw/acpi/ipmi.h"
 
@@ -281,7 +282,7 @@ void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
     }
 }
 
-static void
+void
 build_madt(GArray *table_data, BIOSLinker *linker,
            MachineState *ms, AcpiConfiguration *conf)
 {
diff --git a/include/hw/i386/acpi.h b/include/hw/i386/acpi.h
new file mode 100644
index 0000000000..53bf94c3ca
--- /dev/null
+++ b/include/hw/i386/acpi.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * Copyright (c) 2018 Intel Corportation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef QEMU_I386_ACPI_H
+#define QEMU_I386_ACPI_H
+
+#include "hw/acpi/acpi.h"
+
+/* Build methods */
+void build_madt(GArray *table_data, BIOSLinker *linker,
+                MachineState *ms, AcpiConfiguration *conf);
+
+#endif
-- 
2.17.2

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH v3 19/19] hw: i386: Implement the ACPI builder interface for PC
  2018-10-29 17:01 [Qemu-devel] [PATCH v3 00/19] ACPI reorganization for hardware-reduced support Samuel Ortiz
                   ` (18 preceding siblings ...)
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 18/19] hw: i386: Export the MADT build method Samuel Ortiz
@ 2018-10-29 17:01 ` Samuel Ortiz
  2018-10-29 17:28   ` Paolo Bonzini
  2018-10-29 21:23   ` Philippe Mathieu-Daudé
  19 siblings, 2 replies; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-29 17:01 UTC (permalink / raw)
  To: qemu-devel
  Cc: Michael S. Tsirkin, Igor Mammedov, Paolo Bonzini,
	Richard Henderson, Eduardo Habkost, Marcel Apfelbaum

All PC machine type derivatives will use the same ACPI table build
methods. But with that change in place, any new x86 machine type will be
able to re-use the acpi-build API and customize part of it by defining
its own ACPI table build methods.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 hw/i386/acpi-build.c | 15 ++++++++++-----
 hw/i386/pc.c         | 19 +++++++++++++++++++
 2 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 5035dac556..d40599e6d1 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -35,6 +35,7 @@
 #include "hw/acpi/acpi-defs.h"
 #include "hw/acpi/acpi.h"
 #include "hw/acpi/cpu.h"
+#include "hw/acpi/builder.h"
 #include "hw/nvram/fw_cfg.h"
 #include "hw/acpi/bios-linker-loader.h"
 #include "hw/loader.h"
@@ -1556,6 +1557,7 @@ void acpi_build(AcpiBuildTables *tables,
     GArray *tables_blob = tables->table_data;
     AcpiSlicOem slic_oem = { .id = NULL, .table_id = NULL };
     Object *vmgenid_dev;
+    AcpiBuilder *ab = ACPI_BUILDER(machine);
 
     acpi_get_pm_info(&pm);
     acpi_get_misc_info(&misc);
@@ -1605,7 +1607,8 @@ void acpi_build(AcpiBuildTables *tables,
     aml_len += tables_blob->len - fadt;
 
     acpi_add_table(table_offsets, tables_blob);
-    build_madt(tables_blob, tables->linker, machine, conf);
+    acpi_builder_madt(ab, tables_blob, tables->linker,
+                      machine, conf);
 
     vmgenid_dev = find_vmgenid_dev();
     if (vmgenid_dev) {
@@ -1629,15 +1632,17 @@ void acpi_build(AcpiBuildTables *tables,
     }
     if (conf->numa_nodes) {
         acpi_add_table(table_offsets, tables_blob);
-        build_srat(tables_blob, tables->linker, machine, conf);
+
+        acpi_builder_srat(ab, tables_blob, tables->linker,
+                          machine, conf);
         if (have_numa_distance) {
             acpi_add_table(table_offsets, tables_blob);
-            build_slit(tables_blob, tables->linker);
+            acpi_builder_slit(ab, tables_blob, tables->linker);
         }
     }
     if (acpi_get_mcfg(&mcfg)) {
         acpi_add_table(table_offsets, tables_blob);
-        build_mcfg(tables_blob, tables->linker, &mcfg);
+        acpi_builder_mcfg(ab, tables_blob, tables->linker, &mcfg);
     }
     if (x86_iommu_get_default()) {
         IommuType IOMMUType = x86_iommu_get_type();
@@ -1668,7 +1673,7 @@ void acpi_build(AcpiBuildTables *tables,
                slic_oem.id, slic_oem.table_id);
 
     /* RSDP is in FSEG memory, so allocate it separately */
-    build_rsdp_rsdt(tables->rsdp, tables->linker, rsdt);
+    acpi_builder_rsdp(ab, tables->rsdp, tables->linker, rsdt);
 
     /* We'll expose it all to Guest so we want to reduce
      * chance of size changes.
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 1dcbbd5139..986ed0eabd 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -64,6 +64,7 @@
 #include "qemu/option.h"
 #include "hw/acpi/acpi.h"
 #include "hw/acpi/cpu_hotplug.h"
+#include "hw/acpi/builder.h"
 #include "hw/boards.h"
 #include "acpi-build.h"
 #include "hw/mem/pc-dimm.h"
@@ -75,6 +76,7 @@
 #include "hw/nmi.h"
 #include "hw/i386/intel_iommu.h"
 #include "hw/net/ne2000-isa.h"
+#include "hw/i386/acpi.h"
 
 /* debug PC/ISA interrupts */
 //#define DEBUG_IRQ
@@ -2403,12 +2405,20 @@ static void x86_nmi(NMIState *n, int cpu_index, Error **errp)
     }
 }
 
+static AcpiConfiguration *pc_acpi_configuration(AcpiBuilder *builder)
+{
+    PCMachineState *pcms = PC_MACHINE(builder);
+
+    return &pcms->acpi_configuration;
+}
+
 static void pc_machine_class_init(ObjectClass *oc, void *data)
 {
     MachineClass *mc = MACHINE_CLASS(oc);
     PCMachineClass *pcmc = PC_MACHINE_CLASS(oc);
     HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
     NMIClass *nc = NMI_CLASS(oc);
+    AcpiBuilderMethods *abm = ACPI_BUILDER_METHODS(oc);
 
     pcmc->pci_enabled = true;
     pcmc->has_acpi_build = true;
@@ -2443,6 +2453,14 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
     nc->nmi_monitor_handler = x86_nmi;
     mc->default_cpu_type = TARGET_DEFAULT_CPU_TYPE;
 
+    /* ACPI building methods */
+    abm->madt = build_madt;
+    abm->rsdp = build_rsdp_rsdt;
+    abm->mcfg = build_mcfg;
+    abm->srat = build_srat;
+    abm->slit = build_slit;
+    abm->configuration = pc_acpi_configuration;
+
     object_class_property_add(oc, MEMORY_DEVICE_REGION_SIZE, "int",
         pc_machine_get_device_memory_region_size, NULL,
         NULL, NULL, &error_abort);
@@ -2494,6 +2512,7 @@ static const TypeInfo pc_machine_info = {
     .interfaces = (InterfaceInfo[]) {
          { TYPE_HOTPLUG_HANDLER },
          { TYPE_NMI },
+         { TYPE_ACPI_BUILDER },
          { }
     },
 };
-- 
2.17.2

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 19/19] hw: i386: Implement the ACPI builder interface for PC
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 19/19] hw: i386: Implement the ACPI builder interface for PC Samuel Ortiz
@ 2018-10-29 17:28   ` Paolo Bonzini
  2018-10-30 14:13     ` Samuel Ortiz
  2018-10-29 21:23   ` Philippe Mathieu-Daudé
  1 sibling, 1 reply; 47+ messages in thread
From: Paolo Bonzini @ 2018-10-29 17:28 UTC (permalink / raw)
  To: Samuel Ortiz, qemu-devel
  Cc: Eduardo Habkost, Michael S. Tsirkin, Igor Mammedov, Richard Henderson

On 29/10/2018 18:01, Samuel Ortiz wrote:
> @@ -1556,6 +1557,7 @@ void acpi_build(AcpiBuildTables *tables,
>      GArray *tables_blob = tables->table_data;
>      AcpiSlicOem slic_oem = { .id = NULL, .table_id = NULL };
>      Object *vmgenid_dev;
> +    AcpiBuilder *ab = ACPI_BUILDER(machine);
>  
>      acpi_get_pm_info(&pm);
>      acpi_get_misc_info(&misc);
> @@ -1605,7 +1607,8 @@ void acpi_build(AcpiBuildTables *tables,
>      aml_len += tables_blob->len - fadt;
>  
>      acpi_add_table(table_offsets, tables_blob);
> -    build_madt(tables_blob, tables->linker, machine, conf);
> +    acpi_builder_madt(ab, tables_blob, tables->linker,
> +                      machine, conf);
>  
>      vmgenid_dev = find_vmgenid_dev();
>      if (vmgenid_dev) {

Just a quick question before I go and actually apply the patches to look
at the resulting code: is there any reason why you didn't add the
MachineState and/or AcpiBuilder to AcpiBuildState, similar to how it was
in v1?

Thanks,

Paolo

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 03/19] hw: acpi: Export the RSDP build API
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 03/19] hw: acpi: Export the RSDP build API Samuel Ortiz
@ 2018-10-29 18:58   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 47+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-10-29 18:58 UTC (permalink / raw)
  To: Samuel Ortiz, qemu-devel
  Cc: Eduardo Habkost, Michael S. Tsirkin, Paolo Bonzini,
	Igor Mammedov, Richard Henderson

Hi Samuel,

On 29/10/18 18:01, Samuel Ortiz wrote:
> The hardware-reduced API will need to build RSDP as well, so we should
> export this routine. While doing so, we also slightly change the
> function prototype. Since no caller needs it, and to make it more
> consistent with the rest of the AML build API, the function no longer
> returns its RSDP table.
> 
> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
> ---
>   hw/acpi/aml-build.c         | 24 ++++++++++++++++++++++++
>   hw/i386/acpi-build.c        | 26 --------------------------
>   include/hw/acpi/aml-build.h |  3 +++
>   3 files changed, 27 insertions(+), 26 deletions(-)
> 
> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> index 51b608432f..2d6f538f9d 100644
> --- a/hw/acpi/aml-build.c
> +++ b/hw/acpi/aml-build.c
> @@ -1651,6 +1651,30 @@ build_xsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
>                    (void *)xsdt, "XSDT", xsdt_len, 1, oem_id, oem_table_id);
>   }
>   
> +void
> +build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset)
> +{
> +    AcpiRsdpDescriptor *rsdp = acpi_data_push(rsdp_table, sizeof *rsdp);
> +    unsigned rsdt_pa_size = sizeof(rsdp->rsdt_physical_address);
> +    unsigned rsdt_pa_offset =
> +        (char *)&rsdp->rsdt_physical_address - rsdp_table->data;
> +
> +    bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, rsdp_table, 16,
> +                             true /* fseg memory */);
> +
> +    memcpy(&rsdp->signature, "RSD PTR ", 8);
> +    memcpy(rsdp->oem_id, ACPI_BUILD_APPNAME6, 6);
> +    /* Address to be filled by Guest linker */
> +    bios_linker_loader_add_pointer(linker,
> +        ACPI_BUILD_RSDP_FILE, rsdt_pa_offset, rsdt_pa_size,
> +        ACPI_BUILD_TABLE_FILE, rsdt_tbl_offset);
> +
> +    /* Checksum to be filled by Guest linker */
> +    bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE,
> +        (char *)rsdp - rsdp_table->data, sizeof *rsdp,
> +        (char *)&rsdp->checksum - rsdp_table->data);
> +}
> +
>   void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base,
>                          uint64_t len, int node, MemoryAffinityFlags flags)
>   {
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 1bf02b6a93..9f1c9f4cf5 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -2512,32 +2512,6 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker)
>                    "IVRS", table_data->len - iommu_start, 1, NULL, NULL);
>   }
>   
> -static GArray *
> -build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset)
> -{
> -    AcpiRsdpDescriptor *rsdp = acpi_data_push(rsdp_table, sizeof *rsdp);
> -    unsigned rsdt_pa_size = sizeof(rsdp->rsdt_physical_address);
> -    unsigned rsdt_pa_offset =
> -        (char *)&rsdp->rsdt_physical_address - rsdp_table->data;
> -
> -    bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, rsdp_table, 16,
> -                             true /* fseg memory */);
> -
> -    memcpy(&rsdp->signature, "RSD PTR ", 8);
> -    memcpy(rsdp->oem_id, ACPI_BUILD_APPNAME6, 6);
> -    /* Address to be filled by Guest linker */
> -    bios_linker_loader_add_pointer(linker,
> -        ACPI_BUILD_RSDP_FILE, rsdt_pa_offset, rsdt_pa_size,
> -        ACPI_BUILD_TABLE_FILE, rsdt_tbl_offset);
> -
> -    /* Checksum to be filled by Guest linker */
> -    bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE,
> -        (char *)rsdp - rsdp_table->data, sizeof *rsdp,
> -        (char *)&rsdp->checksum - rsdp_table->data);
> -
> -    return rsdp_table;
> -}
> -
>   static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
>   {
>       Object *pci_host;
> diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
> index 813f51317c..865f5d23f5 100644
> --- a/include/hw/acpi/aml-build.h
> +++ b/include/hw/acpi/aml-build.h
> @@ -390,6 +390,9 @@ void acpi_add_table(GArray *table_offsets, GArray *table_data);
>   void acpi_build_tables_init(AcpiBuildTables *tables);
>   void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre);
>   void
> +build_rsdp(GArray *table_data,
> +           BIOSLinker *linker, unsigned rsdt_tbl_offset);

You now need to update the prototype of build_rsdp() in 
hw/arm/virt-acpi-build.c to have this patch bisectable, even if you 
remove this function in your patch #5.

Maybe it is easier to first export it (removing bug in ARM),
then change the prototype.

> +void
>   build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
>              const char *oem_id, const char *oem_table_id);
>   void
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 02/19] hw: acpi: Export ACPI build alignment API
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 02/19] hw: acpi: Export ACPI build alignment API Samuel Ortiz
@ 2018-10-29 19:01   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 47+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-10-29 19:01 UTC (permalink / raw)
  To: Samuel Ortiz, qemu-devel
  Cc: Eduardo Habkost, Michael S. Tsirkin, Paolo Bonzini,
	Igor Mammedov, Richard Henderson

On 29/10/18 18:01, Samuel Ortiz wrote:
> This is going to be needed by the Hardware-reduced ACPI routines.
> 
> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
> ---
>   hw/acpi/aml-build.c         | 8 ++++++++
>   hw/i386/acpi-build.c        | 8 --------
>   include/hw/acpi/aml-build.h | 2 ++
>   3 files changed, 10 insertions(+), 8 deletions(-)
> 
> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> index 1e43cd736d..51b608432f 100644
> --- a/hw/acpi/aml-build.c
> +++ b/hw/acpi/aml-build.c
> @@ -1565,6 +1565,14 @@ unsigned acpi_data_len(GArray *table)
>       return table->len;
>   }
>   
> +void acpi_align_size(GArray *blob, unsigned align)
> +{
> +    /* Align size to multiple of given size. This reduces the chance
> +     * we need to change size in the future (breaking cross version migration).
> +     */
> +    g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align));
> +}
> +
>   void acpi_add_table(GArray *table_offsets, GArray *table_data)
>   {
>       uint32_t offset = table_data->len;
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index c8545238c4..1bf02b6a93 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -282,14 +282,6 @@ static void acpi_get_pci_holes(Range *hole, Range *hole64)
>                                                  NULL));
>   }
>   
> -static void acpi_align_size(GArray *blob, unsigned align)
> -{
> -    /* Align size to multiple of given size. This reduces the chance
> -     * we need to change size in the future (breaking cross version migration).
> -     */
> -    g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align));
> -}
> -
>   /* FACS */
>   static void
>   build_facs(GArray *table_data, BIOSLinker *linker)
> diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
> index 6c36903c0a..813f51317c 100644
> --- a/include/hw/acpi/aml-build.h
> +++ b/include/hw/acpi/aml-build.h
> @@ -6,6 +6,7 @@
>   
>   /* Reserve RAM space for tables: add another order of magnitude. */
>   #define ACPI_BUILD_TABLE_MAX_SIZE         0x200000
> +#define ACPI_BUILD_ALIGN_SIZE             0x1000

This definition doesn't seem used in this series.

>   
>   #define ACPI_BUILD_APPNAME6 "BOCHS "
>   #define ACPI_BUILD_APPNAME4 "BXPC"
> @@ -384,6 +385,7 @@ build_header(BIOSLinker *linker, GArray *table_data,
>                const char *oem_id, const char *oem_table_id);
>   void *acpi_data_push(GArray *table_data, unsigned size);
>   unsigned acpi_data_len(GArray *table);

With a 1 line documentation comment here:
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>

> +void acpi_align_size(GArray *blob, unsigned align);
>   void acpi_add_table(GArray *table_offsets, GArray *table_data);
>   void acpi_build_tables_init(AcpiBuildTables *tables);
>   void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre);
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 06/19] hw: acpi: Generalize AML build routines
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 06/19] hw: acpi: Generalize AML build routines Samuel Ortiz
@ 2018-10-29 19:09   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 47+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-10-29 19:09 UTC (permalink / raw)
  To: Samuel Ortiz, qemu-devel
  Cc: Yang Zhong, Peter Maydell, Eduardo Habkost, Michael S. Tsirkin,
	Paolo Bonzini, Shannon Zhao, Igor Mammedov,
	open list:ARM ACPI Subsystem, Richard Henderson

On 29/10/18 18:01, Samuel Ortiz wrote:
> From: Yang Zhong <yang.zhong@intel.com>
> 
> Most of the AML build routines under acpi-build are not even
> architecture specific. They can be moved to the more generic hw/acpi
> folder where they could be shared across machine types and
> architectures.
> 
> Signed-off-by: Yang Zhong <yang.zhong@intel.com>
> ---
>   hw/acpi/aml-build.c         | 498 ++++++++++++++++++++++++++++++++++
>   hw/arm/virt-acpi-build.c    |   4 +-
>   hw/i386/acpi-build.c        | 516 +-----------------------------------
>   include/hw/acpi/aml-build.h |  25 ++
>   4 files changed, 528 insertions(+), 515 deletions(-)
> 
> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> index 77eb17b113..43aec8dacd 100644
> --- a/hw/acpi/aml-build.c
> +++ b/hw/acpi/aml-build.c
> @@ -25,6 +25,10 @@
>   #include "qemu/bswap.h"
>   #include "qemu/bitops.h"
>   #include "sysemu/numa.h"
> +#include "hw/pci/pci.h"
> +#include "hw/pci/pci_bus.h"
> +#include "qemu/range.h"
> +#include "hw/pci/pci_bridge.h"
>   
>   static GArray *build_alloc_array(void)
>   {
> @@ -1597,6 +1601,500 @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
>       g_array_free(tables->vmgenid, mfre);
>   }
>   
> +static void crs_range_insert(GPtrArray *ranges, uint64_t base, uint64_t limit)
> +{
> +    CrsRangeEntry *entry;
> +
> +    entry = g_malloc(sizeof(*entry));
> +    entry->base = base;
> +    entry->limit = limit;
> +
> +    g_ptr_array_add(ranges, entry);
> +}
> +
> +static void crs_range_free(gpointer data)
> +{
> +    CrsRangeEntry *entry = (CrsRangeEntry *)data;
> +    g_free(entry);
> +}
> +
> +void crs_range_set_init(CrsRangeSet *range_set)
> +{
> +    range_set->io_ranges = g_ptr_array_new_with_free_func(crs_range_free);
> +    range_set->mem_ranges = g_ptr_array_new_with_free_func(crs_range_free);
> +    range_set->mem_64bit_ranges =
> +            g_ptr_array_new_with_free_func(crs_range_free);
> +}
> +
> +void crs_range_set_free(CrsRangeSet *range_set)
> +{
> +    g_ptr_array_free(range_set->io_ranges, true);
> +    g_ptr_array_free(range_set->mem_ranges, true);
> +    g_ptr_array_free(range_set->mem_64bit_ranges, true);
> +}
> +
> +static gint crs_range_compare(gconstpointer a, gconstpointer b)
> +{
> +     CrsRangeEntry *entry_a = *(CrsRangeEntry **)a;
> +     CrsRangeEntry *entry_b = *(CrsRangeEntry **)b;
> +
> +     return (int64_t)entry_a->base - (int64_t)entry_b->base;
> +}
> +
> +/*
> + * crs_replace_with_free_ranges - given the 'used' ranges within [start - end]
> + * interval, computes the 'free' ranges from the same interval.
> + * Example: If the input array is { [a1 - a2],[b1 - b2] }, the function
> + * will return { [base - a1], [a2 - b1], [b2 - limit] }.
> + */
> +void crs_replace_with_free_ranges(GPtrArray *ranges,
> +                                         uint64_t start, uint64_t end)
> +{
> +    GPtrArray *free_ranges = g_ptr_array_new();
> +    uint64_t free_base = start;
> +    int i;
> +
> +    g_ptr_array_sort(ranges, crs_range_compare);
> +    for (i = 0; i < ranges->len; i++) {
> +        CrsRangeEntry *used = g_ptr_array_index(ranges, i);
> +
> +        if (free_base < used->base) {
> +            crs_range_insert(free_ranges, free_base, used->base - 1);
> +        }
> +
> +        free_base = used->limit + 1;
> +    }
> +
> +    if (free_base < end) {
> +        crs_range_insert(free_ranges, free_base, end);
> +    }
> +
> +    g_ptr_array_set_size(ranges, 0);
> +    for (i = 0; i < free_ranges->len; i++) {
> +        g_ptr_array_add(ranges, g_ptr_array_index(free_ranges, i));
> +    }
> +
> +    g_ptr_array_free(free_ranges, true);
> +}
> +
> +/*
> + * crs_range_merge - merges adjacent ranges in the given array.
> + * Array elements are deleted and replaced with the merged ranges.
> + */
> +static void crs_range_merge(GPtrArray *range)
> +{
> +    GPtrArray *tmp =  g_ptr_array_new_with_free_func(crs_range_free);
> +    CrsRangeEntry *entry;
> +    uint64_t range_base, range_limit;
> +    int i;
> +
> +    if (!range->len) {
> +        return;
> +    }
> +
> +    g_ptr_array_sort(range, crs_range_compare);
> +
> +    entry = g_ptr_array_index(range, 0);
> +    range_base = entry->base;
> +    range_limit = entry->limit;
> +    for (i = 1; i < range->len; i++) {
> +        entry = g_ptr_array_index(range, i);
> +        if (entry->base - 1 == range_limit) {
> +            range_limit = entry->limit;
> +        } else {
> +            crs_range_insert(tmp, range_base, range_limit);
> +            range_base = entry->base;
> +            range_limit = entry->limit;
> +        }
> +    }
> +    crs_range_insert(tmp, range_base, range_limit);
> +
> +    g_ptr_array_set_size(range, 0);
> +    for (i = 0; i < tmp->len; i++) {
> +        entry = g_ptr_array_index(tmp, i);
> +        crs_range_insert(range, entry->base, entry->limit);
> +    }
> +    g_ptr_array_free(tmp, true);
> +}
> +
> +Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set)
> +{
> +    Aml *crs = aml_resource_template();
> +    CrsRangeSet temp_range_set;
> +    CrsRangeEntry *entry;
> +    uint8_t max_bus = pci_bus_num(host->bus);
> +    uint8_t type;
> +    int devfn;
> +    int i;
> +
> +    crs_range_set_init(&temp_range_set);
> +    for (devfn = 0; devfn < ARRAY_SIZE(host->bus->devices); devfn++) {
> +        uint64_t range_base, range_limit;
> +        PCIDevice *dev = host->bus->devices[devfn];
> +
> +        if (!dev) {
> +            continue;
> +        }
> +
> +        for (i = 0; i < PCI_NUM_REGIONS; i++) {
> +            PCIIORegion *r = &dev->io_regions[i];
> +
> +            range_base = r->addr;
> +            range_limit = r->addr + r->size - 1;
> +
> +            /*
> +             * Work-around for old bioses
> +             * that do not support multiple root buses
> +             */
> +            if (!range_base || range_base > range_limit) {
> +                continue;
> +            }
> +
> +            if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
> +                crs_range_insert(temp_range_set.io_ranges,
> +                                 range_base, range_limit);
> +            } else { /* "memory" */
> +                crs_range_insert(temp_range_set.mem_ranges,
> +                                 range_base, range_limit);
> +            }
> +        }
> +
> +        type = dev->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION;
> +        if (type == PCI_HEADER_TYPE_BRIDGE) {
> +            uint8_t subordinate = dev->config[PCI_SUBORDINATE_BUS];
> +            if (subordinate > max_bus) {
> +                max_bus = subordinate;
> +            }
> +
> +            range_base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_IO);
> +            range_limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_IO);
> +
> +            /*
> +             * Work-around for old bioses
> +             * that do not support multiple root buses
> +             */
> +            if (range_base && range_base <= range_limit) {
> +                crs_range_insert(temp_range_set.io_ranges,
> +                                 range_base, range_limit);
> +            }
> +
> +            range_base =
> +                pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_MEMORY);
> +            range_limit =
> +                pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_MEMORY);
> +
> +            /*
> +             * Work-around for old bioses
> +             * that do not support multiple root buses
> +             */
> +            if (range_base && range_base <= range_limit) {
> +                uint64_t length = range_limit - range_base + 1;
> +                if (range_limit <= UINT32_MAX && length <= UINT32_MAX)  {
> +                    crs_range_insert(temp_range_set.mem_ranges,
> +                                     range_base, range_limit);
> +                } else {
> +                    crs_range_insert(temp_range_set.mem_64bit_ranges,
> +                                     range_base, range_limit);
> +                }
> +            }
> +
> +            range_base =
> +                pci_bridge_get_base(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
> +            range_limit =
> +                pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
> +
> +            /*
> +             * Work-around for old bioses
> +             * that do not support multiple root buses
> +             */
> +            if (range_base && range_base <= range_limit) {
> +                uint64_t length = range_limit - range_base + 1;
> +                if (range_limit <= UINT32_MAX && length <= UINT32_MAX) {
> +                    crs_range_insert(temp_range_set.mem_ranges,
> +                                     range_base, range_limit);
> +                } else {
> +                    crs_range_insert(temp_range_set.mem_64bit_ranges,
> +                                     range_base, range_limit);
> +                }
> +            }
> +        }
> +    }
> +
> +    crs_range_merge(temp_range_set.io_ranges);
> +    for (i = 0; i < temp_range_set.io_ranges->len; i++) {
> +        entry = g_ptr_array_index(temp_range_set.io_ranges, i);
> +        aml_append(crs,
> +                   aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,
> +                               AML_POS_DECODE, AML_ENTIRE_RANGE,
> +                               0, entry->base, entry->limit, 0,
> +                               entry->limit - entry->base + 1));
> +        crs_range_insert(range_set->io_ranges, entry->base, entry->limit);
> +    }
> +
> +    crs_range_merge(temp_range_set.mem_ranges);
> +    for (i = 0; i < temp_range_set.mem_ranges->len; i++) {
> +        entry = g_ptr_array_index(temp_range_set.mem_ranges, i);
> +        aml_append(crs,
> +                   aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED,
> +                                    AML_MAX_FIXED, AML_NON_CACHEABLE,
> +                                    AML_READ_WRITE,
> +                                    0, entry->base, entry->limit, 0,
> +                                    entry->limit - entry->base + 1));
> +        crs_range_insert(range_set->mem_ranges, entry->base, entry->limit);
> +    }
> +
> +    crs_range_merge(temp_range_set.mem_64bit_ranges);
> +    for (i = 0; i < temp_range_set.mem_64bit_ranges->len; i++) {
> +        entry = g_ptr_array_index(temp_range_set.mem_64bit_ranges, i);
> +        aml_append(crs,
> +                   aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED,
> +                                    AML_MAX_FIXED, AML_NON_CACHEABLE,
> +                                    AML_READ_WRITE,
> +                                    0, entry->base, entry->limit, 0,
> +                                    entry->limit - entry->base + 1));
> +        crs_range_insert(range_set->mem_64bit_ranges,
> +                         entry->base, entry->limit);
> +    }
> +
> +    crs_range_set_free(&temp_range_set);
> +
> +    aml_append(crs,
> +        aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
> +                            0,
> +                            pci_bus_num(host->bus),
> +                            max_bus,
> +                            0,
> +                            max_bus - pci_bus_num(host->bus) + 1));
> +
> +    return crs;
> +}
> +
> +Aml *build_osc_method(void)
> +{
> +    Aml *if_ctx;
> +    Aml *if_ctx2;
> +    Aml *else_ctx;
> +    Aml *method;
> +    Aml *a_cwd1 = aml_name("CDW1");
> +    Aml *a_ctrl = aml_local(0);
> +
> +    method = aml_method("_OSC", 4, AML_NOTSERIALIZED);
> +    aml_append(method, aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1"));
> +
> +    if_ctx = aml_if(aml_equal(
> +        aml_arg(0), aml_touuid("33DB4D5B-1FF7-401C-9657-7441C03DD766")));
> +    aml_append(if_ctx, aml_create_dword_field(aml_arg(3), aml_int(4), "CDW2"));
> +    aml_append(if_ctx, aml_create_dword_field(aml_arg(3), aml_int(8), "CDW3"));
> +
> +    aml_append(if_ctx, aml_store(aml_name("CDW3"), a_ctrl));
> +
> +    /*
> +     * Always allow native PME, AER (no dependencies)
> +     * Allow SHPC (PCI bridges can have SHPC controller)
> +     */
> +    aml_append(if_ctx, aml_and(a_ctrl, aml_int(0x1F), a_ctrl));
> +
> +    if_ctx2 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(1))));
> +    /* Unknown revision */
> +    aml_append(if_ctx2, aml_or(a_cwd1, aml_int(0x08), a_cwd1));
> +    aml_append(if_ctx, if_ctx2);
> +
> +    if_ctx2 = aml_if(aml_lnot(aml_equal(aml_name("CDW3"), a_ctrl)));
> +    /* Capabilities bits were masked */
> +    aml_append(if_ctx2, aml_or(a_cwd1, aml_int(0x10), a_cwd1));
> +    aml_append(if_ctx, if_ctx2);
> +
> +    /* Update DWORD3 in the buffer */
> +    aml_append(if_ctx, aml_store(a_ctrl, aml_name("CDW3")));
> +    aml_append(method, if_ctx);
> +
> +    else_ctx = aml_else();
> +    /* Unrecognized UUID */
> +    aml_append(else_ctx, aml_or(a_cwd1, aml_int(4), a_cwd1));
> +    aml_append(method, else_ctx);
> +
> +    aml_append(method, aml_return(aml_arg(3)));
> +    return method;
> +}
> +
> +void
> +build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info)
> +{
> +    AcpiTableMcfg *mcfg;
> +    const char *sig;
> +    int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]);
> +
> +    mcfg = acpi_data_push(table_data, len);
> +    mcfg->allocation[0].address = cpu_to_le64(info->mcfg_base);
> +    /* Only a single allocation so no need to play with segments */
> +    mcfg->allocation[0].pci_segment = cpu_to_le16(0);
> +    mcfg->allocation[0].start_bus_number = 0;
> +    mcfg->allocation[0].end_bus_number = PCIE_MMCFG_BUS(info->mcfg_size - 1);
> +
> +    /* MCFG is used for ECAM which can be enabled or disabled by guest.
> +     * To avoid table size changes (which create migration issues),
> +     * always create the table even if there are no allocations,
> +     * but set the signature to a reserved value in this case.
> +     * ACPI spec requires OSPMs to ignore such tables.
> +     */
> +    if (info->mcfg_base == PCIE_BASE_ADDR_UNMAPPED) {
> +        /* Reserved signature: ignored by OSPM */
> +        sig = "QEMU";
> +    } else {
> +        sig = "MCFG";
> +    }
> +    build_header(linker, table_data, (void *)mcfg, sig, len, 1, NULL, NULL);
> +}
> +
> +Aml *build_gsi_link_dev(const char *name, uint8_t uid, uint8_t gsi)
> +{
> +    Aml *dev;
> +    Aml *crs;
> +    Aml *method;
> +    uint32_t irqs;
> +
> +    dev = aml_device("%s", name);
> +    aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C0F")));
> +    aml_append(dev, aml_name_decl("_UID", aml_int(uid)));
> +
> +    crs = aml_resource_template();
> +    irqs = gsi;
> +    aml_append(crs, aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
> +                                  AML_SHARED, &irqs, 1));
> +    aml_append(dev, aml_name_decl("_PRS", crs));
> +
> +    aml_append(dev, aml_name_decl("_CRS", crs));
> +
> +    /*
> +     * _DIS can be no-op because the interrupt cannot be disabled.
> +     */
> +    method = aml_method("_DIS", 0, AML_NOTSERIALIZED);
> +    aml_append(dev, method);
> +
> +    method = aml_method("_SRS", 1, AML_NOTSERIALIZED);
> +    aml_append(dev, method);
> +
> +    return dev;
> +}
> +
> +/**
> + * build_prt_entry:
> + * @link_name: link name for PCI route entry
> + *
> + * build AML package containing a PCI route entry for @link_name
> + */
> +static Aml *build_prt_entry(const char *link_name)
> +{
> +    Aml *a_zero = aml_int(0);
> +    Aml *pkg = aml_package(4);
> +    aml_append(pkg, a_zero);
> +    aml_append(pkg, a_zero);
> +    aml_append(pkg, aml_name("%s", link_name));
> +    aml_append(pkg, a_zero);
> +    return pkg;
> +}
> +
> +/*
> + * initialize_route - Initialize the interrupt routing rule
> + * through a specific LINK:
> + *  if (lnk_idx == idx)
> + *      route using link 'link_name'
> + */
> +static Aml *initialize_route(Aml *route, const char *link_name,
> +                             Aml *lnk_idx, int idx)
> +{
> +    Aml *if_ctx = aml_if(aml_equal(lnk_idx, aml_int(idx)));
> +    Aml *pkg = build_prt_entry(link_name);
> +
> +    aml_append(if_ctx, aml_store(pkg, route));
> +
> +    return if_ctx;
> +}
> +
> +/*
> + * build_prt - Define interrupt rounting rules
> + *
> + * Returns an array of 128 routes, one for each device,
> + * based on device location.
> + * The main goal is to equaly distribute the interrupts
> + * over the 4 existing ACPI links (works only for i440fx).
> + * The hash function is  (slot + pin) & 3 -> "LNK[D|A|B|C]".
> + *
> + */
> +Aml *build_prt(bool is_pci0_prt)
> +{
> +    Aml *method, *while_ctx, *pin, *res;
> +
> +    method = aml_method("_PRT", 0, AML_NOTSERIALIZED);
> +    res = aml_local(0);
> +    pin = aml_local(1);
> +    aml_append(method, aml_store(aml_package(128), res));
> +    aml_append(method, aml_store(aml_int(0), pin));
> +
> +    /* while (pin < 128) */
> +    while_ctx = aml_while(aml_lless(pin, aml_int(128)));
> +    {
> +        Aml *slot = aml_local(2);
> +        Aml *lnk_idx = aml_local(3);
> +        Aml *route = aml_local(4);
> +
> +        /* slot = pin >> 2 */
> +        aml_append(while_ctx,
> +                   aml_store(aml_shiftright(pin, aml_int(2), NULL), slot));
> +        /* lnk_idx = (slot + pin) & 3 */
> +        aml_append(while_ctx,
> +            aml_store(aml_and(aml_add(pin, slot, NULL), aml_int(3), NULL),
> +                      lnk_idx));
> +
> +        /* route[2] = "LNK[D|A|B|C]", selection based on pin % 3  */
> +        aml_append(while_ctx, initialize_route(route, "LNKD", lnk_idx, 0));
> +        if (is_pci0_prt) {
> +            Aml *if_device_1, *if_pin_4, *else_pin_4;
> +
> +            /* device 1 is the power-management device, needs SCI */
> +            if_device_1 = aml_if(aml_equal(lnk_idx, aml_int(1)));
> +            {
> +                if_pin_4 = aml_if(aml_equal(pin, aml_int(4)));
> +                {
> +                    aml_append(if_pin_4,
> +                        aml_store(build_prt_entry("LNKS"), route));
> +                }
> +                aml_append(if_device_1, if_pin_4);
> +                else_pin_4 = aml_else();
> +                {
> +                    aml_append(else_pin_4,
> +                        aml_store(build_prt_entry("LNKA"), route));
> +                }
> +                aml_append(if_device_1, else_pin_4);
> +            }
> +            aml_append(while_ctx, if_device_1);
> +        } else {
> +            aml_append(while_ctx, initialize_route(route, "LNKA", lnk_idx, 1));
> +        }
> +        aml_append(while_ctx, initialize_route(route, "LNKB", lnk_idx, 2));
> +        aml_append(while_ctx, initialize_route(route, "LNKC", lnk_idx, 3));
> +
> +        /* route[0] = 0x[slot]FFFF */
> +        aml_append(while_ctx,
> +            aml_store(aml_or(aml_shiftleft(slot, aml_int(16)), aml_int(0xFFFF),
> +                             NULL),
> +                      aml_index(route, aml_int(0))));
> +        /* route[1] = pin & 3 */
> +        aml_append(while_ctx,
> +            aml_store(aml_and(pin, aml_int(3), NULL),
> +                      aml_index(route, aml_int(1))));
> +        /* res[pin] = route */
> +        aml_append(while_ctx, aml_store(route, aml_index(res, pin)));
> +        /* pin++ */
> +        aml_append(while_ctx, aml_increment(pin));
> +    }
> +    aml_append(method, while_ctx);
> +    /* return res*/
> +    aml_append(method, aml_return(res));
> +
> +    return method;
> +}
> +
>   /* Build rsdt table */
>   void
>   build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index 0a6a88380a..6822ee4eaa 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -546,7 +546,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>   }
>   
>   static void
> -build_mcfg(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> +virt_build_mcfg(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>   {
>       AcpiTableMcfg *mcfg;
>       const MemMapEntry *memmap = vms->memmap;
> @@ -791,7 +791,7 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
>       build_gtdt(tables_blob, tables->linker, vms);
>   
>       acpi_add_table(table_offsets, tables_blob);
> -    build_mcfg(tables_blob, tables->linker, vms);
> +    virt_build_mcfg(tables_blob, tables->linker, vms);
>   
>       acpi_add_table(table_offsets, tables_blob);
>       build_spcr(tables_blob, tables->linker, vms);
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index eee2eb3ed2..3ab68fd24d 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c

You can now remove these includes from this file :

   -#include "hw/pci/pci.h"
   -#include "hw/pci/pci_bus.h"

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>

> @@ -86,11 +86,6 @@
>   /* Default IOAPIC ID */
>   #define ACPI_BUILD_IOAPIC_ID 0x0
>   
> -typedef struct AcpiMcfgInfo {
> -    uint64_t mcfg_base;
> -    uint32_t mcfg_size;
> -} AcpiMcfgInfo;
> -
>   typedef struct AcpiPmInfo {
>       bool s3_disabled;
>       bool s4_disabled;
> @@ -567,403 +562,6 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
>       qobject_unref(bsel);
>   }
>   
> -/**
> - * build_prt_entry:
> - * @link_name: link name for PCI route entry
> - *
> - * build AML package containing a PCI route entry for @link_name
> - */
> -static Aml *build_prt_entry(const char *link_name)
> -{
> -    Aml *a_zero = aml_int(0);
> -    Aml *pkg = aml_package(4);
> -    aml_append(pkg, a_zero);
> -    aml_append(pkg, a_zero);
> -    aml_append(pkg, aml_name("%s", link_name));
> -    aml_append(pkg, a_zero);
> -    return pkg;
> -}
> -
> -/*
> - * initialize_route - Initialize the interrupt routing rule
> - * through a specific LINK:
> - *  if (lnk_idx == idx)
> - *      route using link 'link_name'
> - */
> -static Aml *initialize_route(Aml *route, const char *link_name,
> -                             Aml *lnk_idx, int idx)
> -{
> -    Aml *if_ctx = aml_if(aml_equal(lnk_idx, aml_int(idx)));
> -    Aml *pkg = build_prt_entry(link_name);
> -
> -    aml_append(if_ctx, aml_store(pkg, route));
> -
> -    return if_ctx;
> -}
> -
> -/*
> - * build_prt - Define interrupt rounting rules
> - *
> - * Returns an array of 128 routes, one for each device,
> - * based on device location.
> - * The main goal is to equaly distribute the interrupts
> - * over the 4 existing ACPI links (works only for i440fx).
> - * The hash function is  (slot + pin) & 3 -> "LNK[D|A|B|C]".
> - *
> - */
> -static Aml *build_prt(bool is_pci0_prt)
> -{
> -    Aml *method, *while_ctx, *pin, *res;
> -
> -    method = aml_method("_PRT", 0, AML_NOTSERIALIZED);
> -    res = aml_local(0);
> -    pin = aml_local(1);
> -    aml_append(method, aml_store(aml_package(128), res));
> -    aml_append(method, aml_store(aml_int(0), pin));
> -
> -    /* while (pin < 128) */
> -    while_ctx = aml_while(aml_lless(pin, aml_int(128)));
> -    {
> -        Aml *slot = aml_local(2);
> -        Aml *lnk_idx = aml_local(3);
> -        Aml *route = aml_local(4);
> -
> -        /* slot = pin >> 2 */
> -        aml_append(while_ctx,
> -                   aml_store(aml_shiftright(pin, aml_int(2), NULL), slot));
> -        /* lnk_idx = (slot + pin) & 3 */
> -        aml_append(while_ctx,
> -            aml_store(aml_and(aml_add(pin, slot, NULL), aml_int(3), NULL),
> -                      lnk_idx));
> -
> -        /* route[2] = "LNK[D|A|B|C]", selection based on pin % 3  */
> -        aml_append(while_ctx, initialize_route(route, "LNKD", lnk_idx, 0));
> -        if (is_pci0_prt) {
> -            Aml *if_device_1, *if_pin_4, *else_pin_4;
> -
> -            /* device 1 is the power-management device, needs SCI */
> -            if_device_1 = aml_if(aml_equal(lnk_idx, aml_int(1)));
> -            {
> -                if_pin_4 = aml_if(aml_equal(pin, aml_int(4)));
> -                {
> -                    aml_append(if_pin_4,
> -                        aml_store(build_prt_entry("LNKS"), route));
> -                }
> -                aml_append(if_device_1, if_pin_4);
> -                else_pin_4 = aml_else();
> -                {
> -                    aml_append(else_pin_4,
> -                        aml_store(build_prt_entry("LNKA"), route));
> -                }
> -                aml_append(if_device_1, else_pin_4);
> -            }
> -            aml_append(while_ctx, if_device_1);
> -        } else {
> -            aml_append(while_ctx, initialize_route(route, "LNKA", lnk_idx, 1));
> -        }
> -        aml_append(while_ctx, initialize_route(route, "LNKB", lnk_idx, 2));
> -        aml_append(while_ctx, initialize_route(route, "LNKC", lnk_idx, 3));
> -
> -        /* route[0] = 0x[slot]FFFF */
> -        aml_append(while_ctx,
> -            aml_store(aml_or(aml_shiftleft(slot, aml_int(16)), aml_int(0xFFFF),
> -                             NULL),
> -                      aml_index(route, aml_int(0))));
> -        /* route[1] = pin & 3 */
> -        aml_append(while_ctx,
> -            aml_store(aml_and(pin, aml_int(3), NULL),
> -                      aml_index(route, aml_int(1))));
> -        /* res[pin] = route */
> -        aml_append(while_ctx, aml_store(route, aml_index(res, pin)));
> -        /* pin++ */
> -        aml_append(while_ctx, aml_increment(pin));
> -    }
> -    aml_append(method, while_ctx);
> -    /* return res*/
> -    aml_append(method, aml_return(res));
> -
> -    return method;
> -}
> -
> -typedef struct CrsRangeEntry {
> -    uint64_t base;
> -    uint64_t limit;
> -} CrsRangeEntry;
> -
> -static void crs_range_insert(GPtrArray *ranges, uint64_t base, uint64_t limit)
> -{
> -    CrsRangeEntry *entry;
> -
> -    entry = g_malloc(sizeof(*entry));
> -    entry->base = base;
> -    entry->limit = limit;
> -
> -    g_ptr_array_add(ranges, entry);
> -}
> -
> -static void crs_range_free(gpointer data)
> -{
> -    CrsRangeEntry *entry = (CrsRangeEntry *)data;
> -    g_free(entry);
> -}
> -
> -typedef struct CrsRangeSet {
> -    GPtrArray *io_ranges;
> -    GPtrArray *mem_ranges;
> -    GPtrArray *mem_64bit_ranges;
> - } CrsRangeSet;
> -
> -static void crs_range_set_init(CrsRangeSet *range_set)
> -{
> -    range_set->io_ranges = g_ptr_array_new_with_free_func(crs_range_free);
> -    range_set->mem_ranges = g_ptr_array_new_with_free_func(crs_range_free);
> -    range_set->mem_64bit_ranges =
> -            g_ptr_array_new_with_free_func(crs_range_free);
> -}
> -
> -static void crs_range_set_free(CrsRangeSet *range_set)
> -{
> -    g_ptr_array_free(range_set->io_ranges, true);
> -    g_ptr_array_free(range_set->mem_ranges, true);
> -    g_ptr_array_free(range_set->mem_64bit_ranges, true);
> -}
> -
> -static gint crs_range_compare(gconstpointer a, gconstpointer b)
> -{
> -     CrsRangeEntry *entry_a = *(CrsRangeEntry **)a;
> -     CrsRangeEntry *entry_b = *(CrsRangeEntry **)b;
> -
> -     return (int64_t)entry_a->base - (int64_t)entry_b->base;
> -}
> -
> -/*
> - * crs_replace_with_free_ranges - given the 'used' ranges within [start - end]
> - * interval, computes the 'free' ranges from the same interval.
> - * Example: If the input array is { [a1 - a2],[b1 - b2] }, the function
> - * will return { [base - a1], [a2 - b1], [b2 - limit] }.
> - */
> -static void crs_replace_with_free_ranges(GPtrArray *ranges,
> -                                         uint64_t start, uint64_t end)
> -{
> -    GPtrArray *free_ranges = g_ptr_array_new();
> -    uint64_t free_base = start;
> -    int i;
> -
> -    g_ptr_array_sort(ranges, crs_range_compare);
> -    for (i = 0; i < ranges->len; i++) {
> -        CrsRangeEntry *used = g_ptr_array_index(ranges, i);
> -
> -        if (free_base < used->base) {
> -            crs_range_insert(free_ranges, free_base, used->base - 1);
> -        }
> -
> -        free_base = used->limit + 1;
> -    }
> -
> -    if (free_base < end) {
> -        crs_range_insert(free_ranges, free_base, end);
> -    }
> -
> -    g_ptr_array_set_size(ranges, 0);
> -    for (i = 0; i < free_ranges->len; i++) {
> -        g_ptr_array_add(ranges, g_ptr_array_index(free_ranges, i));
> -    }
> -
> -    g_ptr_array_free(free_ranges, true);
> -}
> -
> -/*
> - * crs_range_merge - merges adjacent ranges in the given array.
> - * Array elements are deleted and replaced with the merged ranges.
> - */
> -static void crs_range_merge(GPtrArray *range)
> -{
> -    GPtrArray *tmp =  g_ptr_array_new_with_free_func(crs_range_free);
> -    CrsRangeEntry *entry;
> -    uint64_t range_base, range_limit;
> -    int i;
> -
> -    if (!range->len) {
> -        return;
> -    }
> -
> -    g_ptr_array_sort(range, crs_range_compare);
> -
> -    entry = g_ptr_array_index(range, 0);
> -    range_base = entry->base;
> -    range_limit = entry->limit;
> -    for (i = 1; i < range->len; i++) {
> -        entry = g_ptr_array_index(range, i);
> -        if (entry->base - 1 == range_limit) {
> -            range_limit = entry->limit;
> -        } else {
> -            crs_range_insert(tmp, range_base, range_limit);
> -            range_base = entry->base;
> -            range_limit = entry->limit;
> -        }
> -    }
> -    crs_range_insert(tmp, range_base, range_limit);
> -
> -    g_ptr_array_set_size(range, 0);
> -    for (i = 0; i < tmp->len; i++) {
> -        entry = g_ptr_array_index(tmp, i);
> -        crs_range_insert(range, entry->base, entry->limit);
> -    }
> -    g_ptr_array_free(tmp, true);
> -}
> -
> -static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set)
> -{
> -    Aml *crs = aml_resource_template();
> -    CrsRangeSet temp_range_set;
> -    CrsRangeEntry *entry;
> -    uint8_t max_bus = pci_bus_num(host->bus);
> -    uint8_t type;
> -    int devfn;
> -    int i;
> -
> -    crs_range_set_init(&temp_range_set);
> -    for (devfn = 0; devfn < ARRAY_SIZE(host->bus->devices); devfn++) {
> -        uint64_t range_base, range_limit;
> -        PCIDevice *dev = host->bus->devices[devfn];
> -
> -        if (!dev) {
> -            continue;
> -        }
> -
> -        for (i = 0; i < PCI_NUM_REGIONS; i++) {
> -            PCIIORegion *r = &dev->io_regions[i];
> -
> -            range_base = r->addr;
> -            range_limit = r->addr + r->size - 1;
> -
> -            /*
> -             * Work-around for old bioses
> -             * that do not support multiple root buses
> -             */
> -            if (!range_base || range_base > range_limit) {
> -                continue;
> -            }
> -
> -            if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
> -                crs_range_insert(temp_range_set.io_ranges,
> -                                 range_base, range_limit);
> -            } else { /* "memory" */
> -                crs_range_insert(temp_range_set.mem_ranges,
> -                                 range_base, range_limit);
> -            }
> -        }
> -
> -        type = dev->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION;
> -        if (type == PCI_HEADER_TYPE_BRIDGE) {
> -            uint8_t subordinate = dev->config[PCI_SUBORDINATE_BUS];
> -            if (subordinate > max_bus) {
> -                max_bus = subordinate;
> -            }
> -
> -            range_base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_IO);
> -            range_limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_IO);
> -
> -            /*
> -             * Work-around for old bioses
> -             * that do not support multiple root buses
> -             */
> -            if (range_base && range_base <= range_limit) {
> -                crs_range_insert(temp_range_set.io_ranges,
> -                                 range_base, range_limit);
> -            }
> -
> -            range_base =
> -                pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_MEMORY);
> -            range_limit =
> -                pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_MEMORY);
> -
> -            /*
> -             * Work-around for old bioses
> -             * that do not support multiple root buses
> -             */
> -            if (range_base && range_base <= range_limit) {
> -                uint64_t length = range_limit - range_base + 1;
> -                if (range_limit <= UINT32_MAX && length <= UINT32_MAX) {
> -                    crs_range_insert(temp_range_set.mem_ranges,
> -                                     range_base, range_limit);
> -                } else {
> -                    crs_range_insert(temp_range_set.mem_64bit_ranges,
> -                                     range_base, range_limit);
> -                }
> -            }
> -
> -            range_base =
> -                pci_bridge_get_base(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
> -            range_limit =
> -                pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
> -
> -            /*
> -             * Work-around for old bioses
> -             * that do not support multiple root buses
> -             */
> -            if (range_base && range_base <= range_limit) {
> -                uint64_t length = range_limit - range_base + 1;
> -                if (range_limit <= UINT32_MAX && length <= UINT32_MAX) {
> -                    crs_range_insert(temp_range_set.mem_ranges,
> -                                     range_base, range_limit);
> -                } else {
> -                    crs_range_insert(temp_range_set.mem_64bit_ranges,
> -                                     range_base, range_limit);
> -                }
> -            }
> -        }
> -    }
> -
> -    crs_range_merge(temp_range_set.io_ranges);
> -    for (i = 0; i < temp_range_set.io_ranges->len; i++) {
> -        entry = g_ptr_array_index(temp_range_set.io_ranges, i);
> -        aml_append(crs,
> -                   aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,
> -                               AML_POS_DECODE, AML_ENTIRE_RANGE,
> -                               0, entry->base, entry->limit, 0,
> -                               entry->limit - entry->base + 1));
> -        crs_range_insert(range_set->io_ranges, entry->base, entry->limit);
> -    }
> -
> -    crs_range_merge(temp_range_set.mem_ranges);
> -    for (i = 0; i < temp_range_set.mem_ranges->len; i++) {
> -        entry = g_ptr_array_index(temp_range_set.mem_ranges, i);
> -        aml_append(crs,
> -                   aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED,
> -                                    AML_MAX_FIXED, AML_NON_CACHEABLE,
> -                                    AML_READ_WRITE,
> -                                    0, entry->base, entry->limit, 0,
> -                                    entry->limit - entry->base + 1));
> -        crs_range_insert(range_set->mem_ranges, entry->base, entry->limit);
> -    }
> -
> -    crs_range_merge(temp_range_set.mem_64bit_ranges);
> -    for (i = 0; i < temp_range_set.mem_64bit_ranges->len; i++) {
> -        entry = g_ptr_array_index(temp_range_set.mem_64bit_ranges, i);
> -        aml_append(crs,
> -                   aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED,
> -                                    AML_MAX_FIXED, AML_NON_CACHEABLE,
> -                                    AML_READ_WRITE,
> -                                    0, entry->base, entry->limit, 0,
> -                                    entry->limit - entry->base + 1));
> -        crs_range_insert(range_set->mem_64bit_ranges,
> -                         entry->base, entry->limit);
> -    }
> -
> -    crs_range_set_free(&temp_range_set);
> -
> -    aml_append(crs,
> -        aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
> -                            0,
> -                            pci_bus_num(host->bus),
> -                            max_bus,
> -                            0,
> -                            max_bus - pci_bus_num(host->bus) + 1));
> -
> -    return crs;
> -}
> -
>   static void build_hpet_aml(Aml *table)
>   {
>       Aml *crs;
> @@ -1334,37 +932,6 @@ static Aml *build_link_dev(const char *name, uint8_t uid, Aml *reg)
>       return dev;
>    }
>   
> -static Aml *build_gsi_link_dev(const char *name, uint8_t uid, uint8_t gsi)
> -{
> -    Aml *dev;
> -    Aml *crs;
> -    Aml *method;
> -    uint32_t irqs;
> -
> -    dev = aml_device("%s", name);
> -    aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C0F")));
> -    aml_append(dev, aml_name_decl("_UID", aml_int(uid)));
> -
> -    crs = aml_resource_template();
> -    irqs = gsi;
> -    aml_append(crs, aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
> -                                  AML_SHARED, &irqs, 1));
> -    aml_append(dev, aml_name_decl("_PRS", crs));
> -
> -    aml_append(dev, aml_name_decl("_CRS", crs));
> -
> -    /*
> -     * _DIS can be no-op because the interrupt cannot be disabled.
> -     */
> -    method = aml_method("_DIS", 0, AML_NOTSERIALIZED);
> -    aml_append(dev, method);
> -
> -    method = aml_method("_SRS", 1, AML_NOTSERIALIZED);
> -    aml_append(dev, method);
> -
> -    return dev;
> -}
> -
>   /* _CRS method - get current settings */
>   static Aml *build_iqcr_method(bool is_piix4)
>   {
> @@ -1728,54 +1295,6 @@ static void build_piix4_pci_hotplug(Aml *table)
>       aml_append(table, scope);
>   }
>   
> -static Aml *build_q35_osc_method(void)
> -{
> -    Aml *if_ctx;
> -    Aml *if_ctx2;
> -    Aml *else_ctx;
> -    Aml *method;
> -    Aml *a_cwd1 = aml_name("CDW1");
> -    Aml *a_ctrl = aml_local(0);
> -
> -    method = aml_method("_OSC", 4, AML_NOTSERIALIZED);
> -    aml_append(method, aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1"));
> -
> -    if_ctx = aml_if(aml_equal(
> -        aml_arg(0), aml_touuid("33DB4D5B-1FF7-401C-9657-7441C03DD766")));
> -    aml_append(if_ctx, aml_create_dword_field(aml_arg(3), aml_int(4), "CDW2"));
> -    aml_append(if_ctx, aml_create_dword_field(aml_arg(3), aml_int(8), "CDW3"));
> -
> -    aml_append(if_ctx, aml_store(aml_name("CDW3"), a_ctrl));
> -
> -    /*
> -     * Always allow native PME, AER (no dependencies)
> -     * Allow SHPC (PCI bridges can have SHPC controller)
> -     */
> -    aml_append(if_ctx, aml_and(a_ctrl, aml_int(0x1F), a_ctrl));
> -
> -    if_ctx2 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(1))));
> -    /* Unknown revision */
> -    aml_append(if_ctx2, aml_or(a_cwd1, aml_int(0x08), a_cwd1));
> -    aml_append(if_ctx, if_ctx2);
> -
> -    if_ctx2 = aml_if(aml_lnot(aml_equal(aml_name("CDW3"), a_ctrl)));
> -    /* Capabilities bits were masked */
> -    aml_append(if_ctx2, aml_or(a_cwd1, aml_int(0x10), a_cwd1));
> -    aml_append(if_ctx, if_ctx2);
> -
> -    /* Update DWORD3 in the buffer */
> -    aml_append(if_ctx, aml_store(a_ctrl, aml_name("CDW3")));
> -    aml_append(method, if_ctx);
> -
> -    else_ctx = aml_else();
> -    /* Unrecognized UUID */
> -    aml_append(else_ctx, aml_or(a_cwd1, aml_int(4), a_cwd1));
> -    aml_append(method, else_ctx);
> -
> -    aml_append(method, aml_return(aml_arg(3)));
> -    return method;
> -}
> -
>   static void
>   build_dsdt(GArray *table_data, BIOSLinker *linker,
>              AcpiPmInfo *pm, AcpiMiscInfo *misc,
> @@ -1818,7 +1337,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
>           aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03")));
>           aml_append(dev, aml_name_decl("_ADR", aml_int(0)));
>           aml_append(dev, aml_name_decl("_UID", aml_int(1)));
> -        aml_append(dev, build_q35_osc_method());
> +        aml_append(dev, build_osc_method());
>           aml_append(sb_scope, dev);
>           aml_append(dsdt, sb_scope);
>   
> @@ -1883,7 +1402,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
>               aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03")));
>               aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
>               if (pci_bus_is_express(bus)) {
> -                aml_append(dev, build_q35_osc_method());
> +                aml_append(dev, build_osc_method());
>               }
>   
>               if (numa_node != NUMA_NODE_UNASSIGNED) {
> @@ -2369,35 +1888,6 @@ build_srat(GArray *table_data, BIOSLinker *linker,
>                    table_data->len - srat_start, 1, NULL, NULL);
>   }
>   
> -static void
> -build_mcfg_q35(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info)
> -{
> -    AcpiTableMcfg *mcfg;
> -    const char *sig;
> -    int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]);
> -
> -    mcfg = acpi_data_push(table_data, len);
> -    mcfg->allocation[0].address = cpu_to_le64(info->mcfg_base);
> -    /* Only a single allocation so no need to play with segments */
> -    mcfg->allocation[0].pci_segment = cpu_to_le16(0);
> -    mcfg->allocation[0].start_bus_number = 0;
> -    mcfg->allocation[0].end_bus_number = PCIE_MMCFG_BUS(info->mcfg_size - 1);
> -
> -    /* MCFG is used for ECAM which can be enabled or disabled by guest.
> -     * To avoid table size changes (which create migration issues),
> -     * always create the table even if there are no allocations,
> -     * but set the signature to a reserved value in this case.
> -     * ACPI spec requires OSPMs to ignore such tables.
> -     */
> -    if (info->mcfg_base == PCIE_BASE_ADDR_UNMAPPED) {
> -        /* Reserved signature: ignored by OSPM */
> -        sig = "QEMU";
> -    } else {
> -        sig = "MCFG";
> -    }
> -    build_header(linker, table_data, (void *)mcfg, sig, len, 1, NULL, NULL);
> -}
> -
>   /*
>    * VT-d spec 8.1 DMA Remapping Reporting Structure
>    * (version Oct. 2014 or later)
> @@ -2625,7 +2115,7 @@ void acpi_build(AcpiBuildTables *tables,
>       }
>       if (acpi_get_mcfg(&mcfg)) {
>           acpi_add_table(table_offsets, tables_blob);
> -        build_mcfg_q35(tables_blob, tables->linker, &mcfg);
> +        build_mcfg(tables_blob, tables->linker, &mcfg);
>       }
>       if (x86_iommu_get_default()) {
>           IommuType IOMMUType = x86_iommu_get_type();
> diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
> index 8d1063a40b..cd744e9472 100644
> --- a/include/hw/acpi/aml-build.h
> +++ b/include/hw/acpi/aml-build.h
> @@ -3,6 +3,7 @@
>   
>   #include "hw/acpi/acpi-defs.h"
>   #include "hw/acpi/bios-linker-loader.h"
> +#include "hw/pci/pcie_host.h"
>   
>   /* Reserve RAM space for tables: add another order of magnitude. */
>   #define ACPI_BUILD_TABLE_MAX_SIZE         0x200000
> @@ -224,6 +225,21 @@ struct AcpiBuildTables {
>       BIOSLinker *linker;
>   } AcpiBuildTables;
>   
> +typedef struct AcpiMcfgInfo {
> +    uint64_t mcfg_base;
> +    uint32_t mcfg_size;
> +} AcpiMcfgInfo;
> +
> +typedef struct CrsRangeEntry {
> +    uint64_t base;
> +    uint64_t limit;
> +} CrsRangeEntry;
> +
> +typedef struct CrsRangeSet {
> +    GPtrArray *io_ranges;
> +    GPtrArray *mem_ranges;
> +    GPtrArray *mem_64bit_ranges;
> +} CrsRangeSet;
>   /**
>    * init_aml_allocator:
>    *
> @@ -389,6 +405,15 @@ void acpi_align_size(GArray *blob, unsigned align);
>   void acpi_add_table(GArray *table_offsets, GArray *table_data);
>   void acpi_build_tables_init(AcpiBuildTables *tables);
>   void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre);
> +Aml *build_osc_method(void);
> +void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info);
> +Aml *build_gsi_link_dev(const char *name, uint8_t uid, uint8_t gsi);
> +Aml *build_prt(bool is_pci0_prt);
> +void crs_range_set_init(CrsRangeSet *range_set);
> +Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set);
> +void crs_replace_with_free_ranges(GPtrArray *ranges,
> +                                  uint64_t start, uint64_t end);
> +void crs_range_set_free(CrsRangeSet *range_set);
>   void
>   build_rsdp_rsdt(GArray *table_data,
>                   BIOSLinker *linker, unsigned rsdt_tbl_offset);
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 08/19] hw: i386: Refactor PCI host getter
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 08/19] hw: i386: Refactor PCI host getter Samuel Ortiz
@ 2018-10-29 19:18   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 47+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-10-29 19:18 UTC (permalink / raw)
  To: Samuel Ortiz, qemu-devel
  Cc: Yang Zhong, Eduardo Habkost, Michael S. Tsirkin, Paolo Bonzini,
	Igor Mammedov, Richard Henderson

Hi Yang, Samuel.

On 29/10/18 18:01, Samuel Ortiz wrote:
> From: Yang Zhong <yang.zhong@intel.com>
> 
> Make it more flexible by having it parsing a PCI host paths array
> instead of open coding those paths deep down into the code logic itself.
> This will be needed for PCI machine types that are neither emulatiing the
> ich9 nor the i440fx chipsets.
> 
> Signed-off-by: Yang Zhong <yang.zhong@intel.com>
> ---
>   hw/i386/acpi-build.c | 29 +++++++++++++++++++----------
>   1 file changed, 19 insertions(+), 10 deletions(-)
> 
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index fdfd6f4ba2..35f95baca7 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -114,6 +114,12 @@ typedef struct AcpiBuildPciBusHotplugState {
>       bool pcihp_bridge_en;
>   } AcpiBuildPciBusHotplugState;
>   
> +static const char *pci_hosts[] = {
> +   "/machine/i440fx",
> +   "/machine/q35",
> +   NULL,
> +};
> +
>   static void init_common_fadt_data(Object *o, AcpiFadtData *data)
>   {
>       uint32_t io = object_property_get_uint(o, ACPI_PM_PROP_PM_IO_BASE, NULL);
> @@ -238,27 +244,30 @@ static void acpi_get_misc_info(AcpiMiscInfo *info)
>    * Because of the PXB hosts we cannot simply query TYPE_PCI_HOST_BRIDGE.
>    * On i386 arch we only have two pci hosts, so we can look only for them.
>    */
> -static Object *acpi_get_i386_pci_host(void)
> +static Object *acpi_get_pci_host(void)

I'd rather have the machine array passed as argument:

    static Object *acpi_get_pci_host(const char *machine_paths)

So in your next patch you keep the hw/acpi/aml-build.c namespace 
generic. You would also add this argument to acpi_get_pci_holes().

With this change:
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>

>   {
>       PCIHostState *host;
> +    int i = 0;
>   
> -    host = OBJECT_CHECK(PCIHostState,
> -                        object_resolve_path("/machine/i440fx", NULL),
> -                        TYPE_PCI_HOST_BRIDGE);
> -    if (!host) {
> +    while (pci_hosts[i]) {
>           host = OBJECT_CHECK(PCIHostState,
> -                            object_resolve_path("/machine/q35", NULL),
> +                            object_resolve_path(pci_hosts[i], NULL),
>                               TYPE_PCI_HOST_BRIDGE);
> +        if (host) {
> +            return OBJECT(host);
> +        }
> +
> +        i++;
>       }
>   
> -    return OBJECT(host);
> +    return NULL;
>   }
>   
>   static void acpi_get_pci_holes(Range *hole, Range *hole64)
>   {
>       Object *pci_host;
>   
> -    pci_host = acpi_get_i386_pci_host();
> +    pci_host = acpi_get_pci_host();
>       g_assert(pci_host);
>   
>       range_set_bounds1(hole,
> @@ -1636,7 +1645,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
>           Object *pci_host;
>           PCIBus *bus = NULL;
>   
> -        pci_host = acpi_get_i386_pci_host();
> +        pci_host = acpi_get_pci_host();
>           if (pci_host) {
>               bus = PCI_HOST_BRIDGE(pci_host)->bus;
>           }
> @@ -2009,7 +2018,7 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
>       Object *pci_host;
>       QObject *o;
>   
> -    pci_host = acpi_get_i386_pci_host();
> +    pci_host = acpi_get_pci_host();
>       g_assert(pci_host);
>   
>       o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_BASE, NULL);
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 09/19] hw: acpi: Export and generalize the PCI host AML API
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 09/19] hw: acpi: Export and generalize the PCI host AML API Samuel Ortiz
@ 2018-10-29 19:23   ` Philippe Mathieu-Daudé
  2018-10-29 19:29     ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 47+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-10-29 19:23 UTC (permalink / raw)
  To: Samuel Ortiz, qemu-devel
  Cc: Yang Zhong, Eduardo Habkost, Rob Bradford, Michael S. Tsirkin,
	Paolo Bonzini, Igor Mammedov, Richard Henderson

On 29/10/18 18:01, Samuel Ortiz wrote:
> From: Yang Zhong <yang.zhong@intel.com>
> 
> The AML build routines for the PCI host bridge and the corresponding
> DSDT addition are neither x86 nor PC machine type specific.
> We can move them to the architecture agnostic hw/acpi folder, and by
> carrying all the needed information through a new AcpiPciBus structure,
> we can make them PC machine type independent.
> 
> Signed-off-by: Yang Zhong <yang.zhong@intel.com>
> Signed-off-by: Rob Bradford <robert.bradford@intel.com>
> ---
>   hw/acpi/aml-build.c         | 208 ++++++++++++++++++++++++++++++++++++
>   hw/i386/acpi-build.c        | 167 ++---------------------------
>   include/hw/acpi/aml-build.h |  10 ++
>   3 files changed, 226 insertions(+), 159 deletions(-)
> 
> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> index 52ac39acdb..aa72b5459c 100644
> --- a/hw/acpi/aml-build.c
> +++ b/hw/acpi/aml-build.c
> @@ -29,6 +29,25 @@
>   #include "hw/pci/pci_bus.h"
>   #include "qemu/range.h"
>   #include "hw/pci/pci_bridge.h"
> +#include "hw/i386/pc.h"
> +#include "sysemu/tpm.h"
> +#include "hw/acpi/tpm.h"
> +
> +#define PCI_HOST_BRIDGE_CONFIG_ADDR        0xcf8
> +#define PCI_HOST_BRIDGE_IO_0_MIN_ADDR      0x0000
> +#define PCI_HOST_BRIDGE_IO_0_MAX_ADDR      0x0cf7
> +#define PCI_HOST_BRIDGE_IO_1_MIN_ADDR      0x0d00
> +#define PCI_HOST_BRIDGE_IO_1_MAX_ADDR      0xffff
> +#define PCI_VGA_MEM_BASE_ADDR              0x000a0000
> +#define PCI_VGA_MEM_MAX_ADDR               0x000bffff
> +#define IO_0_LEN                           0xcf8
> +#define VGA_MEM_LEN                        0x20000
> +
> +static const char *pci_hosts[] = {

This array should stay in hw/i386/acpi-build.c.

> +   "/machine/i440fx",
> +   "/machine/q35",
> +   NULL,
> +};
>   
>   static GArray *build_alloc_array(void)
>   {
> @@ -1601,6 +1620,51 @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
>       g_array_free(tables->vmgenid, mfre);
>   }
>   
> +/*
> + * Because of the PXB hosts we cannot simply query TYPE_PCI_HOST_BRIDGE.
> + */
> +Object *acpi_get_pci_host(void)

This function should take the machine_paths as argument.

> +{
> +    PCIHostState *host;
> +    int i = 0;
> +
> +    while (pci_hosts[i]) {
> +        host = OBJECT_CHECK(PCIHostState,
> +                            object_resolve_path(pci_hosts[i], NULL),
> +                            TYPE_PCI_HOST_BRIDGE);
> +        if (host) {
> +            return OBJECT(host);
> +        }
> +
> +        i++;
> +    }
> +
> +    return NULL;
> +}
> +
> +void acpi_get_pci_holes(Range *hole, Range *hole64)

Ditto.

> +{
> +    Object *pci_host;
> +
> +    pci_host = acpi_get_pci_host();
> +    g_assert(pci_host);
> +
> +    range_set_bounds1(hole,
> +                      object_property_get_uint(pci_host,
> +                                               PCI_HOST_PROP_PCI_HOLE_START,
> +                                               NULL),
> +                      object_property_get_uint(pci_host,
> +                                               PCI_HOST_PROP_PCI_HOLE_END,
> +                                               NULL));
> +    range_set_bounds1(hole64,
> +                      object_property_get_uint(pci_host,
> +                                               PCI_HOST_PROP_PCI_HOLE64_START,
> +                                               NULL),
> +                      object_property_get_uint(pci_host,
> +                                               PCI_HOST_PROP_PCI_HOLE64_END,
> +                                               NULL));
> +}
> +
>   static void crs_range_insert(GPtrArray *ranges, uint64_t base, uint64_t limit)
>   {
>       CrsRangeEntry *entry;
> @@ -2099,6 +2163,150 @@ Aml *build_prt(bool is_pci0_prt)
>       return method;
>   }
>   
> +Aml *build_pci_host_bridge(Aml *table, AcpiPciBus *pci_host)
> +{
> +    CrsRangeEntry *entry;
> +    Aml *scope, *dev, *crs;
> +    CrsRangeSet crs_range_set;
> +    Range *pci_hole = NULL;
> +    Range *pci_hole64 = NULL;
> +    PCIBus *bus = NULL;
> +    int root_bus_limit = 0xFF;
> +    int i;
> +
> +    bus = pci_host->pci_bus;
> +    assert(bus);
> +    pci_hole = pci_host->pci_hole;
> +    pci_hole64 = pci_host->pci_hole64;
> +
> +    crs_range_set_init(&crs_range_set);
> +    QLIST_FOREACH(bus, &bus->child, sibling) {
> +        uint8_t bus_num = pci_bus_num(bus);
> +        uint8_t numa_node = pci_bus_numa_node(bus);
> +
> +        /* look only for expander root buses */
> +        if (!pci_bus_is_root(bus)) {
> +            continue;
> +        }
> +
> +        if (bus_num < root_bus_limit) {
> +            root_bus_limit = bus_num - 1;
> +        }
> +
> +        scope = aml_scope("\\_SB");
> +        dev = aml_device("PC%.02X", bus_num);
> +        aml_append(dev, aml_name_decl("_UID", aml_int(bus_num)));
> +        aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03")));
> +        aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
> +        if (pci_bus_is_express(bus)) {
> +            aml_append(dev, aml_name_decl("SUPP", aml_int(0)));
> +            aml_append(dev, aml_name_decl("CTRL", aml_int(0)));
> +            aml_append(dev, build_osc_method(0x1F));
> +        }
> +        if (numa_node != NUMA_NODE_UNASSIGNED) {
> +            aml_append(dev, aml_name_decl("_PXM", aml_int(numa_node)));
> +        }
> +
> +        aml_append(dev, build_prt(false));
> +        crs = build_crs(PCI_HOST_BRIDGE(BUS(bus)->parent), &crs_range_set);
> +        aml_append(dev, aml_name_decl("_CRS", crs));
> +        aml_append(scope, dev);
> +        aml_append(table, scope);
> +    }
> +    scope = aml_scope("\\_SB.PCI0");
> +    /* build PCI0._CRS */
> +    crs = aml_resource_template();
> +    /* set the pcie bus num */
> +    aml_append(crs,
> +        aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
> +                            0x0000, 0x0, root_bus_limit,
> +                            0x0000, root_bus_limit + 1));
> +    aml_append(crs, aml_io(AML_DECODE16, PCI_HOST_BRIDGE_CONFIG_ADDR,
> +                           PCI_HOST_BRIDGE_CONFIG_ADDR, 0x01, 0x08));
> +    /* set the io region 0 in pci host bridge */
> +    aml_append(crs,
> +        aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,
> +                    AML_POS_DECODE, AML_ENTIRE_RANGE,
> +                    0x0000, PCI_HOST_BRIDGE_IO_0_MIN_ADDR,
> +                    PCI_HOST_BRIDGE_IO_0_MAX_ADDR, 0x0000, IO_0_LEN));
> +
> +    /* set the io region 1 in pci host bridge */
> +    crs_replace_with_free_ranges(crs_range_set.io_ranges,
> +                                 PCI_HOST_BRIDGE_IO_1_MIN_ADDR,
> +                                 PCI_HOST_BRIDGE_IO_1_MAX_ADDR);
> +    for (i = 0; i < crs_range_set.io_ranges->len; i++) {
> +        entry = g_ptr_array_index(crs_range_set.io_ranges, i);
> +        aml_append(crs,
> +            aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,
> +                        AML_POS_DECODE, AML_ENTIRE_RANGE,
> +                        0x0000, entry->base, entry->limit,
> +                        0x0000, entry->limit - entry->base + 1));
> +    }
> +
> +    /* set the vga mem region(0) in pci host bridge */
> +    aml_append(crs,
> +        aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
> +                         AML_CACHEABLE, AML_READ_WRITE,
> +                         0, PCI_VGA_MEM_BASE_ADDR, PCI_VGA_MEM_MAX_ADDR,
> +                         0, VGA_MEM_LEN));
> +
> +    /* set the mem region 1 in pci host bridge */
> +    crs_replace_with_free_ranges(crs_range_set.mem_ranges,
> +                                 range_lob(pci_hole),
> +                                 range_upb(pci_hole));
> +    for (i = 0; i < crs_range_set.mem_ranges->len; i++) {
> +        entry = g_ptr_array_index(crs_range_set.mem_ranges, i);
> +        aml_append(crs,
> +            aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
> +                             AML_NON_CACHEABLE, AML_READ_WRITE,
> +                             0, entry->base, entry->limit,
> +                             0, entry->limit - entry->base + 1));
> +    }
> +
> +    /* set the mem region 2 in pci host bridge */
> +    if (!range_is_empty(pci_hole64)) {
> +        crs_replace_with_free_ranges(crs_range_set.mem_64bit_ranges,
> +                                     range_lob(pci_hole64),
> +                                     range_upb(pci_hole64));
> +        for (i = 0; i < crs_range_set.mem_64bit_ranges->len; i++) {
> +            entry = g_ptr_array_index(crs_range_set.mem_64bit_ranges, i);
> +            aml_append(crs,
> +                       aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED,
> +                                        AML_MAX_FIXED,
> +                                        AML_CACHEABLE, AML_READ_WRITE,
> +                                        0, entry->base, entry->limit,
> +                                        0, entry->limit - entry->base + 1));
> +        }
> +    }
> +
> +    if (TPM_IS_TIS(tpm_find())) {
> +        aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE,
> +                   TPM_TIS_ADDR_SIZE, AML_READ_WRITE));
> +    }
> +
> +    aml_append(scope, aml_name_decl("_CRS", crs));
> +    crs_range_set_free(&crs_range_set);
> +    return scope;
> +}
> +
> +void acpi_dsdt_add_pci_bus(Aml *dsdt, AcpiPciBus *pci_host)
> +{
> +    Aml *dev, *pci_scope;
> +
> +    dev = aml_device("\\_SB.PCI0");
> +    aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08")));
> +    aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03")));
> +    aml_append(dev, aml_name_decl("_ADR", aml_int(0)));
> +    aml_append(dev, aml_name_decl("_UID", aml_int(1)));
> +    aml_append(dev, aml_name_decl("SUPP", aml_int(0)));
> +    aml_append(dev, aml_name_decl("CTRL", aml_int(0)));
> +    aml_append(dev, build_osc_method(0x1F));
> +    aml_append(dsdt, dev);
> +
> +    pci_scope = build_pci_host_bridge(dsdt, pci_host);
> +    aml_append(dsdt, pci_scope);
> +}
> +
>   /* Build rsdt table */
>   void
>   build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 35f95baca7..12a8d8210a 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -114,12 +114,6 @@ typedef struct AcpiBuildPciBusHotplugState {
>       bool pcihp_bridge_en;
>   } AcpiBuildPciBusHotplugState;
>   
> -static const char *pci_hosts[] = {
> -   "/machine/i440fx",
> -   "/machine/q35",
> -   NULL,
> -};
> -
>   static void init_common_fadt_data(Object *o, AcpiFadtData *data)
>   {
>       uint32_t io = object_property_get_uint(o, ACPI_PM_PROP_PM_IO_BASE, NULL);
> @@ -240,52 +234,6 @@ static void acpi_get_misc_info(AcpiMiscInfo *info)
>       info->applesmc_io_base = applesmc_port();
>   }
>   
> -/*
> - * Because of the PXB hosts we cannot simply query TYPE_PCI_HOST_BRIDGE.
> - * On i386 arch we only have two pci hosts, so we can look only for them.
> - */
> -static Object *acpi_get_pci_host(void)
> -{
> -    PCIHostState *host;
> -    int i = 0;
> -
> -    while (pci_hosts[i]) {
> -        host = OBJECT_CHECK(PCIHostState,
> -                            object_resolve_path(pci_hosts[i], NULL),
> -                            TYPE_PCI_HOST_BRIDGE);
> -        if (host) {
> -            return OBJECT(host);
> -        }
> -
> -        i++;
> -    }
> -
> -    return NULL;
> -}
> -
> -static void acpi_get_pci_holes(Range *hole, Range *hole64)
> -{
> -    Object *pci_host;
> -
> -    pci_host = acpi_get_pci_host();
> -    g_assert(pci_host);
> -
> -    range_set_bounds1(hole,
> -                      object_property_get_uint(pci_host,
> -                                               PCI_HOST_PROP_PCI_HOLE_START,
> -                                               NULL),
> -                      object_property_get_uint(pci_host,
> -                                               PCI_HOST_PROP_PCI_HOLE_END,
> -                                               NULL));
> -    range_set_bounds1(hole64,
> -                      object_property_get_uint(pci_host,
> -                                               PCI_HOST_PROP_PCI_HOLE64_START,
> -                                               NULL),
> -                      object_property_get_uint(pci_host,
> -                                               PCI_HOST_PROP_PCI_HOLE64_END,
> -                                               NULL));
> -}
> -
>   /* FACS */
>   static void
>   build_facs(GArray *table_data, BIOSLinker *linker)
> @@ -1307,16 +1255,11 @@ static void build_piix4_pci_hotplug(Aml *table)
>   static void
>   build_dsdt(GArray *table_data, BIOSLinker *linker,
>              AcpiPmInfo *pm, AcpiMiscInfo *misc,
> -           Range *pci_hole, Range *pci_hole64,
> +           AcpiPciBus *pci_host,
>              MachineState *machine, AcpiConfiguration *conf)
>   {
> -    CrsRangeEntry *entry;
>       Aml *dsdt, *sb_scope, *scope, *dev, *method, *field, *pkg, *crs;
> -    CrsRangeSet crs_range_set;
>       uint32_t nr_mem = machine->ram_slots;
> -    int root_bus_limit = 0xFF;
> -    PCIBus *bus = NULL;
> -    int i;
>   
>       dsdt = init_aml_allocator();
>   
> @@ -1391,104 +1334,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
>       }
>       aml_append(dsdt, scope);
>   
> -    crs_range_set_init(&crs_range_set);
> -    bus = PC_MACHINE(machine)->bus;
> -    if (bus) {
> -        QLIST_FOREACH(bus, &bus->child, sibling) {
> -            uint8_t bus_num = pci_bus_num(bus);
> -            uint8_t numa_node = pci_bus_numa_node(bus);
> -
> -            /* look only for expander root buses */
> -            if (!pci_bus_is_root(bus)) {
> -                continue;
> -            }
> -
> -            if (bus_num < root_bus_limit) {
> -                root_bus_limit = bus_num - 1;
> -            }
> -
> -            scope = aml_scope("\\_SB");
> -            dev = aml_device("PC%.02X", bus_num);
> -            aml_append(dev, aml_name_decl("_UID", aml_int(bus_num)));
> -            aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03")));
> -            aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
> -            if (pci_bus_is_express(bus)) {
> -                aml_append(dev, build_osc_method(ACPI_OSC_CTRL_PCI_ALL));
> -            }
> -
> -            if (numa_node != NUMA_NODE_UNASSIGNED) {
> -                aml_append(dev, aml_name_decl("_PXM", aml_int(numa_node)));
> -            }
> -
> -            aml_append(dev, build_prt(false));
> -            crs = build_crs(PCI_HOST_BRIDGE(BUS(bus)->parent), &crs_range_set);
> -            aml_append(dev, aml_name_decl("_CRS", crs));
> -            aml_append(scope, dev);
> -            aml_append(dsdt, scope);
> -        }
> -    }
> -
> -    scope = aml_scope("\\_SB.PCI0");
> -    /* build PCI0._CRS */
> -    crs = aml_resource_template();
> -    aml_append(crs,
> -        aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
> -                            0x0000, 0x0, root_bus_limit,
> -                            0x0000, root_bus_limit + 1));
> -    aml_append(crs, aml_io(AML_DECODE16, 0x0CF8, 0x0CF8, 0x01, 0x08));
> -
> -    aml_append(crs,
> -        aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,
> -                    AML_POS_DECODE, AML_ENTIRE_RANGE,
> -                    0x0000, 0x0000, 0x0CF7, 0x0000, 0x0CF8));
> -
> -    crs_replace_with_free_ranges(crs_range_set.io_ranges, 0x0D00, 0xFFFF);
> -    for (i = 0; i < crs_range_set.io_ranges->len; i++) {
> -        entry = g_ptr_array_index(crs_range_set.io_ranges, i);
> -        aml_append(crs,
> -            aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,
> -                        AML_POS_DECODE, AML_ENTIRE_RANGE,
> -                        0x0000, entry->base, entry->limit,
> -                        0x0000, entry->limit - entry->base + 1));
> -    }
> -
> -    aml_append(crs,
> -        aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
> -                         AML_CACHEABLE, AML_READ_WRITE,
> -                         0, 0x000A0000, 0x000BFFFF, 0, 0x00020000));
> -
> -    crs_replace_with_free_ranges(crs_range_set.mem_ranges,
> -                                 range_lob(pci_hole),
> -                                 range_upb(pci_hole));
> -    for (i = 0; i < crs_range_set.mem_ranges->len; i++) {
> -        entry = g_ptr_array_index(crs_range_set.mem_ranges, i);
> -        aml_append(crs,
> -            aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
> -                             AML_NON_CACHEABLE, AML_READ_WRITE,
> -                             0, entry->base, entry->limit,
> -                             0, entry->limit - entry->base + 1));
> -    }
> -
> -    if (!range_is_empty(pci_hole64)) {
> -        crs_replace_with_free_ranges(crs_range_set.mem_64bit_ranges,
> -                                     range_lob(pci_hole64),
> -                                     range_upb(pci_hole64));
> -        for (i = 0; i < crs_range_set.mem_64bit_ranges->len; i++) {
> -            entry = g_ptr_array_index(crs_range_set.mem_64bit_ranges, i);
> -            aml_append(crs,
> -                       aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED,
> -                                        AML_MAX_FIXED,
> -                                        AML_CACHEABLE, AML_READ_WRITE,
> -                                        0, entry->base, entry->limit,
> -                                        0, entry->limit - entry->base + 1));
> -        }
> -    }
> -
> -    if (TPM_IS_TIS(tpm_find())) {
> -        aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE,
> -                   TPM_TIS_ADDR_SIZE, AML_READ_WRITE));
> -    }
> -    aml_append(scope, aml_name_decl("_CRS", crs));
> +    scope = build_pci_host_bridge(dsdt, pci_host);

Can we have the build_pci_host_bridge() extraction in a previous 
separated patch?

Otherwise patch looks good, nice refactor.

>   
>       /* reserve GPE0 block resources */
>       dev = aml_device("GPE0");
> @@ -1508,8 +1354,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
>       aml_append(dev, aml_name_decl("_CRS", crs));
>       aml_append(scope, dev);
>   
> -    crs_range_set_free(&crs_range_set);
> -
>       /* reserve PCIHP resources */
>       if (pm->pcihp_io_len) {
>           dev = aml_device("PHPR");
> @@ -2065,6 +1909,11 @@ void acpi_build(AcpiBuildTables *tables,
>                                64 /* Ensure FACS is aligned */,
>                                false /* high memory */);
>   
> +    AcpiPciBus pci_host = {
> +        .pci_bus    = PC_MACHINE(machine)->bus,
> +        .pci_hole   = &pci_hole,
> +        .pci_hole64 = &pci_hole64,
> +    };
>       /*
>        * FACS is pointed to by FADT.
>        * We place it first since it's the only table that has alignment
> @@ -2076,7 +1925,7 @@ void acpi_build(AcpiBuildTables *tables,
>       /* DSDT is pointed to by FADT */
>       dsdt = tables_blob->len;
>       build_dsdt(tables_blob, tables->linker, &pm, &misc,
> -               &pci_hole, &pci_hole64, machine, conf);
> +               &pci_host, machine, conf);
>   
>       /* Count the size of the DSDT and SSDT, we will need it for legacy
>        * sizing of ACPI tables.
> diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
> index 40b307c97d..cdd290dd70 100644
> --- a/include/hw/acpi/aml-build.h
> +++ b/include/hw/acpi/aml-build.h
> @@ -230,6 +230,12 @@ typedef struct AcpiMcfgInfo {
>       uint32_t mcfg_size;
>   } AcpiMcfgInfo;
>   
> +typedef struct AcpiPciBus {
> +    PCIBus *pci_bus;
> +    Range *pci_hole;
> +    Range *pci_hole64;
> +} AcpiPciBus;
> +
>   typedef struct CrsRangeEntry {
>       uint64_t base;
>       uint64_t limit;
> @@ -401,6 +407,8 @@ build_header(BIOSLinker *linker, GArray *table_data,
>                const char *oem_id, const char *oem_table_id);
>   void *acpi_data_push(GArray *table_data, unsigned size);
>   unsigned acpi_data_len(GArray *table);
> +Object *acpi_get_pci_host(void);
> +void acpi_get_pci_holes(Range *hole, Range *hole64);
>   void acpi_align_size(GArray *blob, unsigned align);
>   void acpi_add_table(GArray *table_offsets, GArray *table_data);
>   void acpi_build_tables_init(AcpiBuildTables *tables);
> @@ -409,6 +417,8 @@ Aml *build_osc_method(uint32_t value);
>   void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info);
>   Aml *build_gsi_link_dev(const char *name, uint8_t uid, uint8_t gsi);
>   Aml *build_prt(bool is_pci0_prt);
> +void acpi_dsdt_add_pci_bus(Aml *dsdt, AcpiPciBus *pci_host);
> +Aml *build_pci_host_bridge(Aml *table, AcpiPciBus *pci_host);
>   void crs_range_set_init(CrsRangeSet *range_set);
>   Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set);
>   void crs_replace_with_free_ranges(GPtrArray *ranges,
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 09/19] hw: acpi: Export and generalize the PCI host AML API
  2018-10-29 19:23   ` Philippe Mathieu-Daudé
@ 2018-10-29 19:29     ` Philippe Mathieu-Daudé
  2018-10-30 14:57       ` Samuel Ortiz
  0 siblings, 1 reply; 47+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-10-29 19:29 UTC (permalink / raw)
  To: Samuel Ortiz, qemu-devel
  Cc: Yang Zhong, Eduardo Habkost, Rob Bradford, Michael S. Tsirkin,
	Paolo Bonzini, Igor Mammedov, Richard Henderson

On 29/10/18 20:23, Philippe Mathieu-Daudé wrote:
> On 29/10/18 18:01, Samuel Ortiz wrote:
>> From: Yang Zhong <yang.zhong@intel.com>
>>
>> The AML build routines for the PCI host bridge and the corresponding
>> DSDT addition are neither x86 nor PC machine type specific.
>> We can move them to the architecture agnostic hw/acpi folder, and by
>> carrying all the needed information through a new AcpiPciBus structure,
>> we can make them PC machine type independent.
>>
>> Signed-off-by: Yang Zhong <yang.zhong@intel.com>
>> Signed-off-by: Rob Bradford <robert.bradford@intel.com>
>> ---
>>   hw/acpi/aml-build.c         | 208 ++++++++++++++++++++++++++++++++++++
>>   hw/i386/acpi-build.c        | 167 ++---------------------------
>>   include/hw/acpi/aml-build.h |  10 ++
>>   3 files changed, 226 insertions(+), 159 deletions(-)
>>
>> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
>> index 52ac39acdb..aa72b5459c 100644
>> --- a/hw/acpi/aml-build.c
>> +++ b/hw/acpi/aml-build.c
>> @@ -29,6 +29,25 @@
>>   #include "hw/pci/pci_bus.h"
>>   #include "qemu/range.h"
>>   #include "hw/pci/pci_bridge.h"
>> +#include "hw/i386/pc.h"

Err I just missed that, this include doesn't belong here, ...

>> +#include "sysemu/tpm.h"
>> +#include "hw/acpi/tpm.h"
>> +
>> +#define PCI_HOST_BRIDGE_CONFIG_ADDR        0xcf8
>> +#define PCI_HOST_BRIDGE_IO_0_MIN_ADDR      0x0000
>> +#define PCI_HOST_BRIDGE_IO_0_MAX_ADDR      0x0cf7
>> +#define PCI_HOST_BRIDGE_IO_1_MIN_ADDR      0x0d00
>> +#define PCI_HOST_BRIDGE_IO_1_MAX_ADDR      0xffff
>> +#define PCI_VGA_MEM_BASE_ADDR              0x000a0000
>> +#define PCI_VGA_MEM_MAX_ADDR               0x000bffff
>> +#define IO_0_LEN                           0xcf8
>> +#define VGA_MEM_LEN                        0x20000
>> +
>> +static const char *pci_hosts[] = {
> 
> This array should stay in hw/i386/acpi-build.c.
> 
>> +   "/machine/i440fx",
>> +   "/machine/q35",
>> +   NULL,
>> +};
>>   static GArray *build_alloc_array(void)
>>   {
>> @@ -1601,6 +1620,51 @@ void acpi_build_tables_cleanup(AcpiBuildTables 
>> *tables, bool mfre)
>>       g_array_free(tables->vmgenid, mfre);
>>   }
>> +/*
>> + * Because of the PXB hosts we cannot simply query TYPE_PCI_HOST_BRIDGE.
>> + */
>> +Object *acpi_get_pci_host(void)
> 
> This function should take the machine_paths as argument.
> 
>> +{
>> +    PCIHostState *host;
>> +    int i = 0;
>> +
>> +    while (pci_hosts[i]) {
>> +        host = OBJECT_CHECK(PCIHostState,
>> +                            object_resolve_path(pci_hosts[i], NULL),
>> +                            TYPE_PCI_HOST_BRIDGE);
>> +        if (host) {
>> +            return OBJECT(host);
>> +        }
>> +
>> +        i++;
>> +    }
>> +
>> +    return NULL;
>> +}
>> +
>> +void acpi_get_pci_holes(Range *hole, Range *hole64)

... and this function neither, it should stay in hw/i386/acpi-build.c, 
thus you don't need to modify the prototype and can call 
acpi_get_pci_host(x86_machine_paths) directly.

> 
> Ditto.
> 
>> +{
>> +    Object *pci_host;
>> +
>> +    pci_host = acpi_get_pci_host();
>> +    g_assert(pci_host);
>> +
>> +    range_set_bounds1(hole,
>> +                      object_property_get_uint(pci_host,
>> +                                               
>> PCI_HOST_PROP_PCI_HOLE_START,
>> +                                               NULL),
>> +                      object_property_get_uint(pci_host,
>> +                                               
>> PCI_HOST_PROP_PCI_HOLE_END,
>> +                                               NULL));
>> +    range_set_bounds1(hole64,
>> +                      object_property_get_uint(pci_host,
>> +                                               
>> PCI_HOST_PROP_PCI_HOLE64_START,
>> +                                               NULL),
>> +                      object_property_get_uint(pci_host,
>> +                                               
>> PCI_HOST_PROP_PCI_HOLE64_END,
>> +                                               NULL));
>> +}
>> +
>>   static void crs_range_insert(GPtrArray *ranges, uint64_t base, 
>> uint64_t limit)
>>   {
>>       CrsRangeEntry *entry;
>> @@ -2099,6 +2163,150 @@ Aml *build_prt(bool is_pci0_prt)
>>       return method;
>>   }
>> +Aml *build_pci_host_bridge(Aml *table, AcpiPciBus *pci_host)
>> +{
>> +    CrsRangeEntry *entry;
>> +    Aml *scope, *dev, *crs;
>> +    CrsRangeSet crs_range_set;
>> +    Range *pci_hole = NULL;
>> +    Range *pci_hole64 = NULL;
>> +    PCIBus *bus = NULL;
>> +    int root_bus_limit = 0xFF;
>> +    int i;
>> +
>> +    bus = pci_host->pci_bus;
>> +    assert(bus);
>> +    pci_hole = pci_host->pci_hole;
>> +    pci_hole64 = pci_host->pci_hole64;
>> +
>> +    crs_range_set_init(&crs_range_set);
>> +    QLIST_FOREACH(bus, &bus->child, sibling) {
>> +        uint8_t bus_num = pci_bus_num(bus);
>> +        uint8_t numa_node = pci_bus_numa_node(bus);
>> +
>> +        /* look only for expander root buses */
>> +        if (!pci_bus_is_root(bus)) {
>> +            continue;
>> +        }
>> +
>> +        if (bus_num < root_bus_limit) {
>> +            root_bus_limit = bus_num - 1;
>> +        }
>> +
>> +        scope = aml_scope("\\_SB");
>> +        dev = aml_device("PC%.02X", bus_num);
>> +        aml_append(dev, aml_name_decl("_UID", aml_int(bus_num)));
>> +        aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03")));
>> +        aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
>> +        if (pci_bus_is_express(bus)) {
>> +            aml_append(dev, aml_name_decl("SUPP", aml_int(0)));
>> +            aml_append(dev, aml_name_decl("CTRL", aml_int(0)));
>> +            aml_append(dev, build_osc_method(0x1F));
>> +        }
>> +        if (numa_node != NUMA_NODE_UNASSIGNED) {
>> +            aml_append(dev, aml_name_decl("_PXM", aml_int(numa_node)));
>> +        }
>> +
>> +        aml_append(dev, build_prt(false));
>> +        crs = build_crs(PCI_HOST_BRIDGE(BUS(bus)->parent), 
>> &crs_range_set);
>> +        aml_append(dev, aml_name_decl("_CRS", crs));
>> +        aml_append(scope, dev);
>> +        aml_append(table, scope);
>> +    }
>> +    scope = aml_scope("\\_SB.PCI0");
>> +    /* build PCI0._CRS */
>> +    crs = aml_resource_template();
>> +    /* set the pcie bus num */
>> +    aml_append(crs,
>> +        aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, 
>> AML_POS_DECODE,
>> +                            0x0000, 0x0, root_bus_limit,
>> +                            0x0000, root_bus_limit + 1));
>> +    aml_append(crs, aml_io(AML_DECODE16, PCI_HOST_BRIDGE_CONFIG_ADDR,
>> +                           PCI_HOST_BRIDGE_CONFIG_ADDR, 0x01, 0x08));
>> +    /* set the io region 0 in pci host bridge */
>> +    aml_append(crs,
>> +        aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,
>> +                    AML_POS_DECODE, AML_ENTIRE_RANGE,
>> +                    0x0000, PCI_HOST_BRIDGE_IO_0_MIN_ADDR,
>> +                    PCI_HOST_BRIDGE_IO_0_MAX_ADDR, 0x0000, IO_0_LEN));
>> +
>> +    /* set the io region 1 in pci host bridge */
>> +    crs_replace_with_free_ranges(crs_range_set.io_ranges,
>> +                                 PCI_HOST_BRIDGE_IO_1_MIN_ADDR,
>> +                                 PCI_HOST_BRIDGE_IO_1_MAX_ADDR);
>> +    for (i = 0; i < crs_range_set.io_ranges->len; i++) {
>> +        entry = g_ptr_array_index(crs_range_set.io_ranges, i);
>> +        aml_append(crs,
>> +            aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,
>> +                        AML_POS_DECODE, AML_ENTIRE_RANGE,
>> +                        0x0000, entry->base, entry->limit,
>> +                        0x0000, entry->limit - entry->base + 1));
>> +    }
>> +
>> +    /* set the vga mem region(0) in pci host bridge */
>> +    aml_append(crs,
>> +        aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
>> +                         AML_CACHEABLE, AML_READ_WRITE,
>> +                         0, PCI_VGA_MEM_BASE_ADDR, PCI_VGA_MEM_MAX_ADDR,
>> +                         0, VGA_MEM_LEN));
>> +
>> +    /* set the mem region 1 in pci host bridge */
>> +    crs_replace_with_free_ranges(crs_range_set.mem_ranges,
>> +                                 range_lob(pci_hole),
>> +                                 range_upb(pci_hole));
>> +    for (i = 0; i < crs_range_set.mem_ranges->len; i++) {
>> +        entry = g_ptr_array_index(crs_range_set.mem_ranges, i);
>> +        aml_append(crs,
>> +            aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, 
>> AML_MAX_FIXED,
>> +                             AML_NON_CACHEABLE, AML_READ_WRITE,
>> +                             0, entry->base, entry->limit,
>> +                             0, entry->limit - entry->base + 1));
>> +    }
>> +
>> +    /* set the mem region 2 in pci host bridge */
>> +    if (!range_is_empty(pci_hole64)) {
>> +        crs_replace_with_free_ranges(crs_range_set.mem_64bit_ranges,
>> +                                     range_lob(pci_hole64),
>> +                                     range_upb(pci_hole64));
>> +        for (i = 0; i < crs_range_set.mem_64bit_ranges->len; i++) {
>> +            entry = g_ptr_array_index(crs_range_set.mem_64bit_ranges, 
>> i);
>> +            aml_append(crs,
>> +                       aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED,
>> +                                        AML_MAX_FIXED,
>> +                                        AML_CACHEABLE, AML_READ_WRITE,
>> +                                        0, entry->base, entry->limit,
>> +                                        0, entry->limit - entry->base 
>> + 1));
>> +        }
>> +    }
>> +
>> +    if (TPM_IS_TIS(tpm_find())) {
>> +        aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE,
>> +                   TPM_TIS_ADDR_SIZE, AML_READ_WRITE));
>> +    }
>> +
>> +    aml_append(scope, aml_name_decl("_CRS", crs));
>> +    crs_range_set_free(&crs_range_set);
>> +    return scope;
>> +}
>> +
>> +void acpi_dsdt_add_pci_bus(Aml *dsdt, AcpiPciBus *pci_host)
>> +{
>> +    Aml *dev, *pci_scope;
>> +
>> +    dev = aml_device("\\_SB.PCI0");
>> +    aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08")));
>> +    aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03")));
>> +    aml_append(dev, aml_name_decl("_ADR", aml_int(0)));
>> +    aml_append(dev, aml_name_decl("_UID", aml_int(1)));
>> +    aml_append(dev, aml_name_decl("SUPP", aml_int(0)));
>> +    aml_append(dev, aml_name_decl("CTRL", aml_int(0)));
>> +    aml_append(dev, build_osc_method(0x1F));
>> +    aml_append(dsdt, dev);
>> +
>> +    pci_scope = build_pci_host_bridge(dsdt, pci_host);
>> +    aml_append(dsdt, pci_scope);
>> +}
>> +
>>   /* Build rsdt table */
>>   void
>>   build_rsdt(GArray *table_data, BIOSLinker *linker, GArray 
>> *table_offsets,
>> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
>> index 35f95baca7..12a8d8210a 100644
>> --- a/hw/i386/acpi-build.c
>> +++ b/hw/i386/acpi-build.c
>> @@ -114,12 +114,6 @@ typedef struct AcpiBuildPciBusHotplugState {
>>       bool pcihp_bridge_en;
>>   } AcpiBuildPciBusHotplugState;
>> -static const char *pci_hosts[] = {
>> -   "/machine/i440fx",
>> -   "/machine/q35",
>> -   NULL,
>> -};
>> -
>>   static void init_common_fadt_data(Object *o, AcpiFadtData *data)
>>   {
>>       uint32_t io = object_property_get_uint(o, 
>> ACPI_PM_PROP_PM_IO_BASE, NULL);
>> @@ -240,52 +234,6 @@ static void acpi_get_misc_info(AcpiMiscInfo *info)
>>       info->applesmc_io_base = applesmc_port();
>>   }
>> -/*
>> - * Because of the PXB hosts we cannot simply query TYPE_PCI_HOST_BRIDGE.
>> - * On i386 arch we only have two pci hosts, so we can look only for 
>> them.
>> - */
>> -static Object *acpi_get_pci_host(void)
>> -{
>> -    PCIHostState *host;
>> -    int i = 0;
>> -
>> -    while (pci_hosts[i]) {
>> -        host = OBJECT_CHECK(PCIHostState,
>> -                            object_resolve_path(pci_hosts[i], NULL),
>> -                            TYPE_PCI_HOST_BRIDGE);
>> -        if (host) {
>> -            return OBJECT(host);
>> -        }
>> -
>> -        i++;
>> -    }
>> -
>> -    return NULL;
>> -}
>> -
>> -static void acpi_get_pci_holes(Range *hole, Range *hole64)
>> -{
>> -    Object *pci_host;
>> -
>> -    pci_host = acpi_get_pci_host();
>> -    g_assert(pci_host);
>> -
>> -    range_set_bounds1(hole,
>> -                      object_property_get_uint(pci_host,
>> -                                               
>> PCI_HOST_PROP_PCI_HOLE_START,
>> -                                               NULL),
>> -                      object_property_get_uint(pci_host,
>> -                                               
>> PCI_HOST_PROP_PCI_HOLE_END,
>> -                                               NULL));
>> -    range_set_bounds1(hole64,
>> -                      object_property_get_uint(pci_host,
>> -                                               
>> PCI_HOST_PROP_PCI_HOLE64_START,
>> -                                               NULL),
>> -                      object_property_get_uint(pci_host,
>> -                                               
>> PCI_HOST_PROP_PCI_HOLE64_END,
>> -                                               NULL));
>> -}
>> -
>>   /* FACS */
>>   static void
>>   build_facs(GArray *table_data, BIOSLinker *linker)
>> @@ -1307,16 +1255,11 @@ static void build_piix4_pci_hotplug(Aml *table)
>>   static void
>>   build_dsdt(GArray *table_data, BIOSLinker *linker,
>>              AcpiPmInfo *pm, AcpiMiscInfo *misc,
>> -           Range *pci_hole, Range *pci_hole64,
>> +           AcpiPciBus *pci_host,
>>              MachineState *machine, AcpiConfiguration *conf)
>>   {
>> -    CrsRangeEntry *entry;
>>       Aml *dsdt, *sb_scope, *scope, *dev, *method, *field, *pkg, *crs;
>> -    CrsRangeSet crs_range_set;
>>       uint32_t nr_mem = machine->ram_slots;
>> -    int root_bus_limit = 0xFF;
>> -    PCIBus *bus = NULL;
>> -    int i;
>>       dsdt = init_aml_allocator();
>> @@ -1391,104 +1334,7 @@ build_dsdt(GArray *table_data, BIOSLinker 
>> *linker,
>>       }
>>       aml_append(dsdt, scope);
>> -    crs_range_set_init(&crs_range_set);
>> -    bus = PC_MACHINE(machine)->bus;
>> -    if (bus) {
>> -        QLIST_FOREACH(bus, &bus->child, sibling) {
>> -            uint8_t bus_num = pci_bus_num(bus);
>> -            uint8_t numa_node = pci_bus_numa_node(bus);
>> -
>> -            /* look only for expander root buses */
>> -            if (!pci_bus_is_root(bus)) {
>> -                continue;
>> -            }
>> -
>> -            if (bus_num < root_bus_limit) {
>> -                root_bus_limit = bus_num - 1;
>> -            }
>> -
>> -            scope = aml_scope("\\_SB");
>> -            dev = aml_device("PC%.02X", bus_num);
>> -            aml_append(dev, aml_name_decl("_UID", aml_int(bus_num)));
>> -            aml_append(dev, aml_name_decl("_HID", 
>> aml_eisaid("PNP0A03")));
>> -            aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
>> -            if (pci_bus_is_express(bus)) {
>> -                aml_append(dev, 
>> build_osc_method(ACPI_OSC_CTRL_PCI_ALL));
>> -            }
>> -
>> -            if (numa_node != NUMA_NODE_UNASSIGNED) {
>> -                aml_append(dev, aml_name_decl("_PXM", 
>> aml_int(numa_node)));
>> -            }
>> -
>> -            aml_append(dev, build_prt(false));
>> -            crs = build_crs(PCI_HOST_BRIDGE(BUS(bus)->parent), 
>> &crs_range_set);
>> -            aml_append(dev, aml_name_decl("_CRS", crs));
>> -            aml_append(scope, dev);
>> -            aml_append(dsdt, scope);
>> -        }
>> -    }
>> -
>> -    scope = aml_scope("\\_SB.PCI0");
>> -    /* build PCI0._CRS */
>> -    crs = aml_resource_template();
>> -    aml_append(crs,
>> -        aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, 
>> AML_POS_DECODE,
>> -                            0x0000, 0x0, root_bus_limit,
>> -                            0x0000, root_bus_limit + 1));
>> -    aml_append(crs, aml_io(AML_DECODE16, 0x0CF8, 0x0CF8, 0x01, 0x08));
>> -
>> -    aml_append(crs,
>> -        aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,
>> -                    AML_POS_DECODE, AML_ENTIRE_RANGE,
>> -                    0x0000, 0x0000, 0x0CF7, 0x0000, 0x0CF8));
>> -
>> -    crs_replace_with_free_ranges(crs_range_set.io_ranges, 0x0D00, 
>> 0xFFFF);
>> -    for (i = 0; i < crs_range_set.io_ranges->len; i++) {
>> -        entry = g_ptr_array_index(crs_range_set.io_ranges, i);
>> -        aml_append(crs,
>> -            aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,
>> -                        AML_POS_DECODE, AML_ENTIRE_RANGE,
>> -                        0x0000, entry->base, entry->limit,
>> -                        0x0000, entry->limit - entry->base + 1));
>> -    }
>> -
>> -    aml_append(crs,
>> -        aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
>> -                         AML_CACHEABLE, AML_READ_WRITE,
>> -                         0, 0x000A0000, 0x000BFFFF, 0, 0x00020000));
>> -
>> -    crs_replace_with_free_ranges(crs_range_set.mem_ranges,
>> -                                 range_lob(pci_hole),
>> -                                 range_upb(pci_hole));
>> -    for (i = 0; i < crs_range_set.mem_ranges->len; i++) {
>> -        entry = g_ptr_array_index(crs_range_set.mem_ranges, i);
>> -        aml_append(crs,
>> -            aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, 
>> AML_MAX_FIXED,
>> -                             AML_NON_CACHEABLE, AML_READ_WRITE,
>> -                             0, entry->base, entry->limit,
>> -                             0, entry->limit - entry->base + 1));
>> -    }
>> -
>> -    if (!range_is_empty(pci_hole64)) {
>> -        crs_replace_with_free_ranges(crs_range_set.mem_64bit_ranges,
>> -                                     range_lob(pci_hole64),
>> -                                     range_upb(pci_hole64));
>> -        for (i = 0; i < crs_range_set.mem_64bit_ranges->len; i++) {
>> -            entry = g_ptr_array_index(crs_range_set.mem_64bit_ranges, 
>> i);
>> -            aml_append(crs,
>> -                       aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED,
>> -                                        AML_MAX_FIXED,
>> -                                        AML_CACHEABLE, AML_READ_WRITE,
>> -                                        0, entry->base, entry->limit,
>> -                                        0, entry->limit - entry->base 
>> + 1));
>> -        }
>> -    }
>> -
>> -    if (TPM_IS_TIS(tpm_find())) {
>> -        aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE,
>> -                   TPM_TIS_ADDR_SIZE, AML_READ_WRITE));
>> -    }
>> -    aml_append(scope, aml_name_decl("_CRS", crs));
>> +    scope = build_pci_host_bridge(dsdt, pci_host);
> 
> Can we have the build_pci_host_bridge() extraction in a previous 
> separated patch?
> 
> Otherwise patch looks good, nice refactor.
> 
>>       /* reserve GPE0 block resources */
>>       dev = aml_device("GPE0");
>> @@ -1508,8 +1354,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
>>       aml_append(dev, aml_name_decl("_CRS", crs));
>>       aml_append(scope, dev);
>> -    crs_range_set_free(&crs_range_set);
>> -
>>       /* reserve PCIHP resources */
>>       if (pm->pcihp_io_len) {
>>           dev = aml_device("PHPR");
>> @@ -2065,6 +1909,11 @@ void acpi_build(AcpiBuildTables *tables,
>>                                64 /* Ensure FACS is aligned */,
>>                                false /* high memory */);
>> +    AcpiPciBus pci_host = {
>> +        .pci_bus    = PC_MACHINE(machine)->bus,
>> +        .pci_hole   = &pci_hole,
>> +        .pci_hole64 = &pci_hole64,
>> +    };
>>       /*
>>        * FACS is pointed to by FADT.
>>        * We place it first since it's the only table that has alignment
>> @@ -2076,7 +1925,7 @@ void acpi_build(AcpiBuildTables *tables,
>>       /* DSDT is pointed to by FADT */
>>       dsdt = tables_blob->len;
>>       build_dsdt(tables_blob, tables->linker, &pm, &misc,
>> -               &pci_hole, &pci_hole64, machine, conf);
>> +               &pci_host, machine, conf);
>>       /* Count the size of the DSDT and SSDT, we will need it for legacy
>>        * sizing of ACPI tables.
>> diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
>> index 40b307c97d..cdd290dd70 100644
>> --- a/include/hw/acpi/aml-build.h
>> +++ b/include/hw/acpi/aml-build.h
>> @@ -230,6 +230,12 @@ typedef struct AcpiMcfgInfo {
>>       uint32_t mcfg_size;
>>   } AcpiMcfgInfo;
>> +typedef struct AcpiPciBus {
>> +    PCIBus *pci_bus;
>> +    Range *pci_hole;
>> +    Range *pci_hole64;
>> +} AcpiPciBus;
>> +
>>   typedef struct CrsRangeEntry {
>>       uint64_t base;
>>       uint64_t limit;
>> @@ -401,6 +407,8 @@ build_header(BIOSLinker *linker, GArray *table_data,
>>                const char *oem_id, const char *oem_table_id);
>>   void *acpi_data_push(GArray *table_data, unsigned size);
>>   unsigned acpi_data_len(GArray *table);
>> +Object *acpi_get_pci_host(void);
>> +void acpi_get_pci_holes(Range *hole, Range *hole64);
>>   void acpi_align_size(GArray *blob, unsigned align);
>>   void acpi_add_table(GArray *table_offsets, GArray *table_data);
>>   void acpi_build_tables_init(AcpiBuildTables *tables);
>> @@ -409,6 +417,8 @@ Aml *build_osc_method(uint32_t value);
>>   void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo 
>> *info);
>>   Aml *build_gsi_link_dev(const char *name, uint8_t uid, uint8_t gsi);
>>   Aml *build_prt(bool is_pci0_prt);
>> +void acpi_dsdt_add_pci_bus(Aml *dsdt, AcpiPciBus *pci_host);
>> +Aml *build_pci_host_bridge(Aml *table, AcpiPciBus *pci_host);
>>   void crs_range_set_init(CrsRangeSet *range_set);
>>   Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set);
>>   void crs_replace_with_free_ranges(GPtrArray *ranges,
>>

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 10/19] hw: acpi: Export the MCFG getter
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 10/19] hw: acpi: Export the MCFG getter Samuel Ortiz
@ 2018-10-29 19:31   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 47+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-10-29 19:31 UTC (permalink / raw)
  To: Samuel Ortiz, qemu-devel
  Cc: Yang Zhong, Eduardo Habkost, Michael S. Tsirkin, Paolo Bonzini,
	Igor Mammedov, Richard Henderson

On 29/10/18 18:01, Samuel Ortiz wrote:
> From: Yang Zhong <yang.zhong@intel.com>
> 
> The ACPI MCFG getter is not x86 specific and could be called from
> anywhere within generic ACPI API, so let's export it.
> 
> Signed-off-by: Yang Zhong <yang.zhong@intel.com>

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>

> ---
>   hw/acpi/aml-build.c         | 24 ++++++++++++++++++++++++
>   hw/i386/acpi-build.c        | 22 ----------------------
>   include/hw/acpi/aml-build.h |  1 +
>   3 files changed, 25 insertions(+), 22 deletions(-)
> 
> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> index aa72b5459c..2110e18799 100644
> --- a/hw/acpi/aml-build.c
> +++ b/hw/acpi/aml-build.c
> @@ -32,6 +32,8 @@
>   #include "hw/i386/pc.h"
>   #include "sysemu/tpm.h"
>   #include "hw/acpi/tpm.h"
> +#include "qom/qom-qobject.h"
> +#include "qapi/qmp/qnum.h"
>   
>   #define PCI_HOST_BRIDGE_CONFIG_ADDR        0xcf8
>   #define PCI_HOST_BRIDGE_IO_0_MIN_ADDR      0x0000
> @@ -1665,6 +1667,28 @@ void acpi_get_pci_holes(Range *hole, Range *hole64)
>                                                  NULL));
>   }
>   
> +bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
> +{
> +    Object *pci_host;
> +    QObject *o;
> +
> +    pci_host = acpi_get_pci_host();
> +    g_assert(pci_host);
> +
> +    o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_BASE, NULL);
> +    if (!o) {
> +        return false;
> +    }
> +    mcfg->mcfg_base = qnum_get_uint(qobject_to(QNum, o));
> +    qobject_unref(o);
> +
> +    o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_SIZE, NULL);
> +    assert(o);
> +    mcfg->mcfg_size = qnum_get_uint(qobject_to(QNum, o));
> +    qobject_unref(o);
> +    return true;
> +}
> +
>   static void crs_range_insert(GPtrArray *ranges, uint64_t base, uint64_t limit)
>   {
>       CrsRangeEntry *entry;
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 12a8d8210a..414a6c4c4e 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -1857,28 +1857,6 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker)
>                    "IVRS", table_data->len - iommu_start, 1, NULL, NULL);
>   }
>   
> -static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
> -{
> -    Object *pci_host;
> -    QObject *o;
> -
> -    pci_host = acpi_get_pci_host();
> -    g_assert(pci_host);
> -
> -    o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_BASE, NULL);
> -    if (!o) {
> -        return false;
> -    }
> -    mcfg->mcfg_base = qnum_get_uint(qobject_to(QNum, o));
> -    qobject_unref(o);
> -
> -    o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_SIZE, NULL);
> -    assert(o);
> -    mcfg->mcfg_size = qnum_get_uint(qobject_to(QNum, o));
> -    qobject_unref(o);
> -    return true;
> -}
> -
>   static
>   void acpi_build(AcpiBuildTables *tables,
>                   MachineState *machine, AcpiConfiguration *conf)
> diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
> index cdd290dd70..1fabf58df2 100644
> --- a/include/hw/acpi/aml-build.h
> +++ b/include/hw/acpi/aml-build.h
> @@ -409,6 +409,7 @@ void *acpi_data_push(GArray *table_data, unsigned size);
>   unsigned acpi_data_len(GArray *table);
>   Object *acpi_get_pci_host(void);
>   void acpi_get_pci_holes(Range *hole, Range *hole64);
> +bool acpi_get_mcfg(AcpiMcfgInfo *mcfg);
>   void acpi_align_size(GArray *blob, unsigned align);
>   void acpi_add_table(GArray *table_offsets, GArray *table_data);
>   void acpi_build_tables_init(AcpiBuildTables *tables);
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 11/19] hw: acpi: Do not create hotplug method when handler is not defined
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 11/19] hw: acpi: Do not create hotplug method when handler is not defined Samuel Ortiz
@ 2018-10-29 19:33   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 47+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-10-29 19:33 UTC (permalink / raw)
  To: Samuel Ortiz, qemu-devel; +Cc: Igor Mammedov, Michael S. Tsirkin

On 29/10/18 18:01, Samuel Ortiz wrote:
> CPU and memory ACPI hotplug are not necessarily handled through SCI
> events. For example, with Hardware-reduced ACPI, the GED device will
> manage ACPI hotplug entirely.
> As a consequence, we make the CPU and memory specific events AML
> generation optional. The code will only be added when the method name is
> not NULL.

It makes sens.

> 
> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>

> ---
>   hw/acpi/cpu.c            |  8 +++++---
>   hw/acpi/memory_hotplug.c | 11 +++++++----
>   2 files changed, 12 insertions(+), 7 deletions(-)
> 
> diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
> index f10b190019..cd41377b5a 100644
> --- a/hw/acpi/cpu.c
> +++ b/hw/acpi/cpu.c
> @@ -569,9 +569,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
>       aml_append(sb_scope, cpus_dev);
>       aml_append(table, sb_scope);
>   
> -    method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED);
> -    aml_append(method, aml_call0("\\_SB.CPUS." CPU_SCAN_METHOD));
> -    aml_append(table, method);
> +    if (event_handler_method) {
> +        method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED);
> +        aml_append(method, aml_call0("\\_SB.CPUS." CPU_SCAN_METHOD));
> +        aml_append(table, method);
> +    }
>   
>       g_free(cphp_res_path);
>   }
> diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c
> index 8c7c1013f3..db2c4df961 100644
> --- a/hw/acpi/memory_hotplug.c
> +++ b/hw/acpi/memory_hotplug.c
> @@ -715,10 +715,13 @@ void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem,
>       }
>       aml_append(table, dev_container);
>   
> -    method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED);
> -    aml_append(method,
> -        aml_call0(MEMORY_DEVICES_CONTAINER "." MEMORY_SLOT_SCAN_METHOD));
> -    aml_append(table, method);
> +    if (event_handler_method) {
> +        method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED);
> +        aml_append(method,
> +                   aml_call0(MEMORY_DEVICES_CONTAINER "."
> +                             MEMORY_SLOT_SCAN_METHOD));
> +        aml_append(table, method);
> +    }
>   
>       g_free(mhp_res_path);
>   }
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 12/19] hw: i386: Make the hotpluggable memory size property more generic
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 12/19] hw: i386: Make the hotpluggable memory size property more generic Samuel Ortiz
@ 2018-10-29 19:38   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 47+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-10-29 19:38 UTC (permalink / raw)
  To: Samuel Ortiz, qemu-devel
  Cc: Eduardo Habkost, Michael S. Tsirkin, Paolo Bonzini,
	Igor Mammedov, Richard Henderson

On 29/10/18 18:01, Samuel Ortiz wrote:
> This property is currently defined under i386/pc while it only describes
> a region size that's eventually fetched from the AML ACPI code.
> 
> We can make it more generic and shareable across machine types by moving
> it to memory-device.h instead.

It makes sens if the next patch is accepted, which i'm not sure it will.

> 
> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
> ---
>   hw/i386/acpi-build.c           | 2 +-
>   hw/i386/pc.c                   | 3 ++-
>   include/hw/i386/pc.h           | 1 -
>   include/hw/mem/memory-device.h | 2 ++
>   4 files changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 414a6c4c4e..dfc02a8a85 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -1630,7 +1630,7 @@ build_srat(GArray *table_data, BIOSLinker *linker,
>       MachineClass *mc = MACHINE_GET_CLASS(machine);
>       const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(machine);
>       ram_addr_t hotplugabble_address_space_size =
> -        object_property_get_int(OBJECT(machine), PC_MACHINE_DEVMEM_REGION_SIZE,
> +        object_property_get_int(OBJECT(machine), MEMORY_DEVICE_REGION_SIZE,
>                                   NULL);
>   
>       srat_start = table_data->len;
> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> index bd4a77b856..1dcbbd5139 100644
> --- a/hw/i386/pc.c
> +++ b/hw/i386/pc.c
> @@ -67,6 +67,7 @@
>   #include "hw/boards.h"
>   #include "acpi-build.h"
>   #include "hw/mem/pc-dimm.h"
> +#include "hw/mem/memory-device.h"
>   #include "qapi/error.h"
>   #include "qapi/qapi-visit-common.h"
>   #include "qapi/visitor.h"
> @@ -2442,7 +2443,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
>       nc->nmi_monitor_handler = x86_nmi;
>       mc->default_cpu_type = TARGET_DEFAULT_CPU_TYPE;
>   
> -    object_class_property_add(oc, PC_MACHINE_DEVMEM_REGION_SIZE, "int",
> +    object_class_property_add(oc, MEMORY_DEVICE_REGION_SIZE, "int",
>           pc_machine_get_device_memory_region_size, NULL,
>           NULL, NULL, &error_abort);
>   
> diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
> index da0bd39741..7d177cd207 100644
> --- a/include/hw/i386/pc.h
> +++ b/include/hw/i386/pc.h
> @@ -62,7 +62,6 @@ struct PCMachineState {
>   };
>   
>   #define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device"
> -#define PC_MACHINE_DEVMEM_REGION_SIZE "device-memory-region-size"
>   #define PC_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g"
>   #define PC_MACHINE_VMPORT           "vmport"
>   #define PC_MACHINE_SMM              "smm"
> diff --git a/include/hw/mem/memory-device.h b/include/hw/mem/memory-device.h
> index e904e194d5..d9a4fc7c3e 100644
> --- a/include/hw/mem/memory-device.h
> +++ b/include/hw/mem/memory-device.h
> @@ -97,6 +97,8 @@ typedef struct MemoryDeviceClass {
>                                MemoryDeviceInfo *info);
>   } MemoryDeviceClass;
>   
> +#define MEMORY_DEVICE_REGION_SIZE "memory-device-region-size"
> +
>   MemoryDeviceInfoList *qmp_memory_device_list(void);
>   uint64_t get_plugged_memory_size(void);
>   void memory_device_pre_plug(MemoryDeviceState *md, MachineState *ms,
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 13/19] hw: acpi: Export the SRAT AML build API
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 13/19] hw: acpi: Export the SRAT AML build API Samuel Ortiz
@ 2018-10-29 19:40   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 47+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-10-29 19:40 UTC (permalink / raw)
  To: Samuel Ortiz, qemu-devel
  Cc: Yang Zhong, Peter Maydell, Eduardo Habkost, Michael S. Tsirkin,
	Paolo Bonzini, Shannon Zhao, Igor Mammedov,
	open list:ARM ACPI Subsystem, Richard Henderson

On 29/10/18 18:01, Samuel Ortiz wrote:
> From: Yang Zhong <yang.zhong@intel.com>
> 
> The SRAT ACPI table is not x86 specific and will be needed for the
> Hardware-reduced ACPI implementation. So we should export it through the
> architecture independent hw/acpi folder.
> 
> Also, now that the generic build_srat() API is exported, we have to
> rename the ARM static one in order to avoid build time conflicts.
> 
> Signed-off-by: Yang Zhong <yang.zhong@intel.com>
> ---
>   hw/acpi/aml-build.c         | 130 ++++++++++++++++++++++++++++++++++++
>   hw/arm/virt-acpi-build.c    |   4 +-
>   hw/i386/acpi-build.c        | 129 -----------------------------------
>   include/hw/acpi/aml-build.h |   3 +
>   4 files changed, 135 insertions(+), 131 deletions(-)
> 
> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> index 2110e18799..c3f652a68f 100644
> --- a/hw/acpi/aml-build.c
> +++ b/hw/acpi/aml-build.c
> @@ -22,6 +22,7 @@
>   #include "qemu/osdep.h"
>   #include <glib/gprintf.h>
>   #include "hw/acpi/aml-build.h"
> +#include "hw/mem/memory-device.h"
>   #include "qemu/bswap.h"
>   #include "qemu/bitops.h"
>   #include "sysemu/numa.h"
> @@ -2459,6 +2460,135 @@ void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base,
>       numamem->range_length = cpu_to_le64(len);
>   }
>   
> +#define HOLE_640K_START  (640 * KiB)
> +#define HOLE_640K_END   (1 * MiB)
> +
> +void
> +build_srat(GArray *table_data, BIOSLinker *linker,
> +           MachineState *machine, AcpiConfiguration *conf)
> +{
> +    AcpiSystemResourceAffinityTable *srat;
> +    AcpiSratMemoryAffinity *numamem;
> +
> +    int i;
> +    int srat_start, numa_start, slots;
> +    uint64_t mem_len, mem_base, next_base;
> +    MachineClass *mc = MACHINE_GET_CLASS(machine);
> +    const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(machine);
> +    ram_addr_t hotplugabble_address_space_size =
> +        object_property_get_int(OBJECT(machine), MEMORY_DEVICE_REGION_SIZE,
> +                                NULL);
> +
> +    srat_start = table_data->len;
> +
> +    srat = acpi_data_push(table_data, sizeof *srat);
> +    srat->reserved1 = cpu_to_le32(1);
> +
> +    for (i = 0; i < apic_ids->len; i++) {
> +        int node_id = apic_ids->cpus[i].props.node_id;
> +        uint32_t apic_id = apic_ids->cpus[i].arch_id;
> +
> +        if (apic_id < 255) {
> +            AcpiSratProcessorAffinity *core;
> +
> +            core = acpi_data_push(table_data, sizeof *core);
> +            core->type = ACPI_SRAT_PROCESSOR_APIC;
> +            core->length = sizeof(*core);
> +            core->local_apic_id = apic_id;
> +            core->proximity_lo = node_id;
> +            memset(core->proximity_hi, 0, 3);
> +            core->local_sapic_eid = 0;
> +            core->flags = cpu_to_le32(1);
> +        } else {
> +            AcpiSratProcessorX2ApicAffinity *core;
> +
> +            core = acpi_data_push(table_data, sizeof *core);
> +            core->type = ACPI_SRAT_PROCESSOR_x2APIC;
> +            core->length = sizeof(*core);
> +            core->x2apic_id = cpu_to_le32(apic_id);
> +            core->proximity_domain = cpu_to_le32(node_id);
> +            core->flags = cpu_to_le32(1);
> +        }
> +    }
> +
> +
> +    /* the memory map is a bit tricky, it contains at least one hole
> +     * from 640k-1M and possibly another one from 3.5G-4G.
> +     */
> +    next_base = 0;
> +    numa_start = table_data->len;
> +
> +    for (i = 1; i < conf->numa_nodes + 1; ++i) {
> +        mem_base = next_base;
> +        mem_len = conf->node_mem[i - 1];
> +        next_base = mem_base + mem_len;
> +
> +        /* Cut out the 640K hole */

It seems we are now using x86 specific code for a supposed arch agnostic 
file. I'm not very comfortable with this change.

> +        if (mem_base <= HOLE_640K_START &&
> +            next_base > HOLE_640K_START) {
> +            mem_len -= next_base - HOLE_640K_START;
> +            if (mem_len > 0) {
> +                numamem = acpi_data_push(table_data, sizeof *numamem);
> +                build_srat_memory(numamem, mem_base, mem_len, i - 1,
> +                                  MEM_AFFINITY_ENABLED);
> +            }
> +
> +            /* Check for the rare case: 640K < RAM < 1M */
> +            if (next_base <= HOLE_640K_END) {
> +                next_base = HOLE_640K_END;
> +                continue;
> +            }
> +            mem_base = HOLE_640K_END;
> +            mem_len = next_base - HOLE_640K_END;
> +        }
> +
> +        /* Cut out the ACPI_PCI hole */
> +        if (mem_base <= conf->below_4g_mem_size &&
> +            next_base > conf->below_4g_mem_size) {
> +            mem_len -= next_base - conf->below_4g_mem_size;
> +            if (mem_len > 0) {
> +                numamem = acpi_data_push(table_data, sizeof *numamem);
> +                build_srat_memory(numamem, mem_base, mem_len, i - 1,
> +                                  MEM_AFFINITY_ENABLED);
> +            }
> +            mem_base = 1ULL << 32;
> +            mem_len = next_base - conf->below_4g_mem_size;
> +            next_base = mem_base + mem_len;
> +        }
> +
> +        if (mem_len > 0) {
> +            numamem = acpi_data_push(table_data, sizeof *numamem);
> +            build_srat_memory(numamem, mem_base, mem_len, i - 1,
> +                              MEM_AFFINITY_ENABLED);
> +        }
> +    }
> +    slots = (table_data->len - numa_start) / sizeof *numamem;
> +    for (; slots < conf->numa_nodes + 2; slots++) {
> +        numamem = acpi_data_push(table_data, sizeof *numamem);
> +        build_srat_memory(numamem, 0, 0, 0, MEM_AFFINITY_NOFLAGS);
> +    }
> +
> +    /*
> +     * Entry is required for Windows to enable memory hotplug in OS
> +     * and for Linux to enable SWIOTLB when booted with less than
> +     * 4G of RAM. Windows works better if the entry sets proximity
> +     * to the highest NUMA node in the machine.
> +     * Memory devices may override proximity set by this entry,
> +     * providing _PXM method if necessary.
> +     */
> +    if (hotplugabble_address_space_size) {
> +        numamem = acpi_data_push(table_data, sizeof *numamem);
> +        build_srat_memory(numamem, machine->device_memory->base,
> +                          hotplugabble_address_space_size, conf->numa_nodes - 1,
> +                          MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
> +    }
> +
> +    build_header(linker, table_data,
> +                 (void *)(table_data->data + srat_start),
> +                 "SRAT",
> +                 table_data->len - srat_start, 1, NULL, NULL);
> +}
> +
>   /*
>    * ACPI spec 5.2.17 System Locality Distance Information Table
>    * (Revision 2.0 or later)
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index f9a60907f1..353aa55357 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -469,7 +469,7 @@ build_spcr(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>   }
>   
>   static void
> -build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> +virt_build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>   {
>       AcpiSystemResourceAffinityTable *srat;
>       AcpiSratProcessorGiccAffinity *core;
> @@ -759,7 +759,7 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
>   
>       if (nb_numa_nodes > 0) {
>           acpi_add_table(table_offsets, tables_blob);
> -        build_srat(tables_blob, tables->linker, vms);
> +        virt_build_srat(tables_blob, tables->linker, vms);
>           if (have_numa_distance) {
>               acpi_add_table(table_offsets, tables_blob);
>               build_slit(tables_blob, tables->linker);
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index dfc02a8a85..5932dbe825 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -1614,135 +1614,6 @@ build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog)
>                    (void *)tpm2_ptr, "TPM2", sizeof(*tpm2_ptr), 4, NULL, NULL);
>   }
>   
> -#define HOLE_640K_START  (640 * KiB)
> -#define HOLE_640K_END   (1 * MiB)
> -
> -static void
> -build_srat(GArray *table_data, BIOSLinker *linker,
> -           MachineState *machine, AcpiConfiguration *conf)
> -{
> -    AcpiSystemResourceAffinityTable *srat;
> -    AcpiSratMemoryAffinity *numamem;
> -
> -    int i;
> -    int srat_start, numa_start, slots;
> -    uint64_t mem_len, mem_base, next_base;
> -    MachineClass *mc = MACHINE_GET_CLASS(machine);
> -    const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(machine);
> -    ram_addr_t hotplugabble_address_space_size =
> -        object_property_get_int(OBJECT(machine), MEMORY_DEVICE_REGION_SIZE,
> -                                NULL);
> -
> -    srat_start = table_data->len;
> -
> -    srat = acpi_data_push(table_data, sizeof *srat);
> -    srat->reserved1 = cpu_to_le32(1);
> -
> -    for (i = 0; i < apic_ids->len; i++) {
> -        int node_id = apic_ids->cpus[i].props.node_id;
> -        uint32_t apic_id = apic_ids->cpus[i].arch_id;
> -
> -        if (apic_id < 255) {
> -            AcpiSratProcessorAffinity *core;
> -
> -            core = acpi_data_push(table_data, sizeof *core);
> -            core->type = ACPI_SRAT_PROCESSOR_APIC;
> -            core->length = sizeof(*core);
> -            core->local_apic_id = apic_id;
> -            core->proximity_lo = node_id;
> -            memset(core->proximity_hi, 0, 3);
> -            core->local_sapic_eid = 0;
> -            core->flags = cpu_to_le32(1);
> -        } else {
> -            AcpiSratProcessorX2ApicAffinity *core;
> -
> -            core = acpi_data_push(table_data, sizeof *core);
> -            core->type = ACPI_SRAT_PROCESSOR_x2APIC;
> -            core->length = sizeof(*core);
> -            core->x2apic_id = cpu_to_le32(apic_id);
> -            core->proximity_domain = cpu_to_le32(node_id);
> -            core->flags = cpu_to_le32(1);
> -        }
> -    }
> -
> -
> -    /* the memory map is a bit tricky, it contains at least one hole
> -     * from 640k-1M and possibly another one from 3.5G-4G.
> -     */
> -    next_base = 0;
> -    numa_start = table_data->len;
> -
> -    for (i = 1; i < conf->numa_nodes + 1; ++i) {
> -        mem_base = next_base;
> -        mem_len = conf->node_mem[i - 1];
> -        next_base = mem_base + mem_len;
> -
> -        /* Cut out the 640K hole */
> -        if (mem_base <= HOLE_640K_START &&
> -            next_base > HOLE_640K_START) {
> -            mem_len -= next_base - HOLE_640K_START;
> -            if (mem_len > 0) {
> -                numamem = acpi_data_push(table_data, sizeof *numamem);
> -                build_srat_memory(numamem, mem_base, mem_len, i - 1,
> -                                  MEM_AFFINITY_ENABLED);
> -            }
> -
> -            /* Check for the rare case: 640K < RAM < 1M */
> -            if (next_base <= HOLE_640K_END) {
> -                next_base = HOLE_640K_END;
> -                continue;
> -            }
> -            mem_base = HOLE_640K_END;
> -            mem_len = next_base - HOLE_640K_END;
> -        }
> -
> -        /* Cut out the ACPI_PCI hole */
> -        if (mem_base <= conf->below_4g_mem_size &&
> -            next_base > conf->below_4g_mem_size) {
> -            mem_len -= next_base - conf->below_4g_mem_size;
> -            if (mem_len > 0) {
> -                numamem = acpi_data_push(table_data, sizeof *numamem);
> -                build_srat_memory(numamem, mem_base, mem_len, i - 1,
> -                                  MEM_AFFINITY_ENABLED);
> -            }
> -            mem_base = 1ULL << 32;
> -            mem_len = next_base - conf->below_4g_mem_size;
> -            next_base = mem_base + mem_len;
> -        }
> -
> -        if (mem_len > 0) {
> -            numamem = acpi_data_push(table_data, sizeof *numamem);
> -            build_srat_memory(numamem, mem_base, mem_len, i - 1,
> -                              MEM_AFFINITY_ENABLED);
> -        }
> -    }
> -    slots = (table_data->len - numa_start) / sizeof *numamem;
> -    for (; slots < conf->numa_nodes + 2; slots++) {
> -        numamem = acpi_data_push(table_data, sizeof *numamem);
> -        build_srat_memory(numamem, 0, 0, 0, MEM_AFFINITY_NOFLAGS);
> -    }
> -
> -    /*
> -     * Entry is required for Windows to enable memory hotplug in OS
> -     * and for Linux to enable SWIOTLB when booted with less than
> -     * 4G of RAM. Windows works better if the entry sets proximity
> -     * to the highest NUMA node in the machine.
> -     * Memory devices may override proximity set by this entry,
> -     * providing _PXM method if necessary.
> -     */
> -    if (hotplugabble_address_space_size) {
> -        numamem = acpi_data_push(table_data, sizeof *numamem);
> -        build_srat_memory(numamem, machine->device_memory->base,
> -                          hotplugabble_address_space_size, conf->numa_nodes - 1,
> -                          MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
> -    }
> -
> -    build_header(linker, table_data,
> -                 (void *)(table_data->data + srat_start),
> -                 "SRAT",
> -                 table_data->len - srat_start, 1, NULL, NULL);
> -}
> -
>   /*
>    * VT-d spec 8.1 DMA Remapping Reporting Structure
>    * (version Oct. 2014 or later)
> diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
> index 1fabf58df2..654ce2ec26 100644
> --- a/include/hw/acpi/aml-build.h
> +++ b/include/hw/acpi/aml-build.h
> @@ -1,6 +1,7 @@
>   #ifndef HW_ACPI_AML_BUILD_H
>   #define HW_ACPI_AML_BUILD_H
>   
> +#include "hw/acpi/acpi.h"
>   #include "hw/acpi/acpi-defs.h"
>   #include "hw/acpi/bios-linker-loader.h"
>   #include "hw/pci/pcie_host.h"
> @@ -438,6 +439,8 @@ void
>   build_xsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
>              const char *oem_id, const char *oem_table_id);
>   
> +void build_srat(GArray *table_data, BIOSLinker *linker,
> +                MachineState *machine, AcpiConfiguration *conf);
>   int
>   build_append_named_dword(GArray *array, const char *name_format, ...)
>   GCC_FMT_ATTR(2, 3);
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 15/19] hw: acpi: Export the PCI hotplug API
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 15/19] hw: acpi: Export the PCI hotplug API Samuel Ortiz
@ 2018-10-29 19:46   ` Philippe Mathieu-Daudé
  2018-10-29 23:34     ` Boeuf, Sebastien
  0 siblings, 1 reply; 47+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-10-29 19:46 UTC (permalink / raw)
  To: Samuel Ortiz, qemu-devel
  Cc: Eduardo Habkost, Michael S. Tsirkin, Jing Liu, Sebastien Boeuf,
	Paolo Bonzini, Igor Mammedov, Richard Henderson

On 29/10/18 18:01, Samuel Ortiz wrote:
> From: Sebastien Boeuf <sebastien.boeuf@intel.com>
> 
> The ACPI hotplug support for PCI devices APIs are not x86 or even
> machine type specific. In order for future machine types to be able to
> re-use that code, we export it through the architecture agnostic
> hw/acpi folder.
> 
> Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
> Signed-off-by: Jing Liu <jing2.liu@linux.intel.com>
> ---
>   hw/acpi/aml-build.c         | 194 ++++++++++++++++++++++++++++++++++++
>   hw/i386/acpi-build.c        | 192 +----------------------------------
>   include/hw/acpi/aml-build.h |   3 +
>   3 files changed, 199 insertions(+), 190 deletions(-)
> 
> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> index c3f652a68f..1b057d1191 100644
> --- a/hw/acpi/aml-build.c
> +++ b/hw/acpi/aml-build.c
> @@ -35,6 +35,7 @@
>   #include "hw/acpi/tpm.h"
>   #include "qom/qom-qobject.h"
>   #include "qapi/qmp/qnum.h"
> +#include "hw/acpi/pcihp.h"
>   
>   #define PCI_HOST_BRIDGE_CONFIG_ADDR        0xcf8
>   #define PCI_HOST_BRIDGE_IO_0_MIN_ADDR      0x0000
> @@ -2314,6 +2315,199 @@ Aml *build_pci_host_bridge(Aml *table, AcpiPciBus *pci_host)
>       return scope;
>   }
>   
> +void build_acpi_pci_hotplug(Aml *scope)

Or build_acpi_pcihp() to match the header file name.

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>

> +{
> +    Aml *field;
> +    Aml *method;
> +
> +    aml_append(scope,
> +        aml_operation_region("PCST", AML_SYSTEM_IO, aml_int(0xae00), 0x08));
> +    field = aml_field("PCST", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
> +    aml_append(field, aml_named_field("PCIU", 32));
> +    aml_append(field, aml_named_field("PCID", 32));
> +    aml_append(scope, field);
> +
> +    aml_append(scope,
> +        aml_operation_region("SEJ", AML_SYSTEM_IO, aml_int(0xae08), 0x04));
> +    field = aml_field("SEJ", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
> +    aml_append(field, aml_named_field("B0EJ", 32));
> +    aml_append(scope, field);
> +
> +    aml_append(scope,
> +        aml_operation_region("BNMR", AML_SYSTEM_IO, aml_int(0xae10), 0x04));
> +    field = aml_field("BNMR", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
> +    aml_append(field, aml_named_field("BNUM", 32));
> +    aml_append(scope, field);
> +
> +    aml_append(scope, aml_mutex("BLCK", 0));
> +
> +    method = aml_method("PCEJ", 2, AML_NOTSERIALIZED);
> +    aml_append(method, aml_acquire(aml_name("BLCK"), 0xFFFF));
> +    aml_append(method, aml_store(aml_arg(0), aml_name("BNUM")));
> +    aml_append(method,
> +        aml_store(aml_shiftleft(aml_int(1), aml_arg(1)), aml_name("B0EJ")));
> +    aml_append(method, aml_release(aml_name("BLCK")));
> +    aml_append(method, aml_return(aml_int(0)));
> +    aml_append(scope, method);
> +}
> +
> +static void build_append_pcihp_notify_entry(Aml *method, int slot)
> +{
> +    Aml *if_ctx;
> +    int32_t devfn = PCI_DEVFN(slot, 0);
> +
> +    if_ctx = aml_if(aml_and(aml_arg(0), aml_int(0x1U << slot), NULL));
> +    aml_append(if_ctx, aml_notify(aml_name("S%.02X", devfn), aml_arg(1)));
> +    aml_append(method, if_ctx);
> +}
> +
> +void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
> +                                  bool pcihp_bridge_en)
> +{
> +    Aml *dev, *notify_method = NULL, *method;
> +    QObject *bsel;
> +    PCIBus *sec;
> +    int i;
> +
> +    bsel = object_property_get_qobject(OBJECT(bus), ACPI_PCIHP_PROP_BSEL, NULL);
> +    if (bsel) {
> +        uint64_t bsel_val = qnum_get_uint(qobject_to(QNum, bsel));
> +
> +        aml_append(parent_scope, aml_name_decl("BSEL", aml_int(bsel_val)));
> +        notify_method = aml_method("DVNT", 2, AML_NOTSERIALIZED);
> +    }
> +
> +    for (i = 0; i < ARRAY_SIZE(bus->devices); i += PCI_FUNC_MAX) {
> +        DeviceClass *dc;
> +        PCIDeviceClass *pc;
> +        PCIDevice *pdev = bus->devices[i];
> +        int slot = PCI_SLOT(i);
> +        bool hotplug_enabled_dev;
> +        bool bridge_in_acpi;
> +
> +        if (!pdev) {
> +            if (bsel) { /* add hotplug slots for non present devices */
> +                dev = aml_device("S%.02X", PCI_DEVFN(slot, 0));
> +                aml_append(dev, aml_name_decl("_SUN", aml_int(slot)));
> +                aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16)));
> +                method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
> +                aml_append(method,
> +                    aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN"))
> +                );
> +                aml_append(dev, method);
> +                aml_append(parent_scope, dev);
> +
> +                build_append_pcihp_notify_entry(notify_method, slot);
> +            }
> +            continue;
> +        }
> +
> +        pc = PCI_DEVICE_GET_CLASS(pdev);
> +        dc = DEVICE_GET_CLASS(pdev);
> +
> +        /* When hotplug for bridges is enabled, bridges are
> +         * described in ACPI separately (see build_pci_bus_end).
> +         * In this case they aren't themselves hot-pluggable.
> +         * Hotplugged bridges *are* hot-pluggable.
> +         */
> +        bridge_in_acpi = pc->is_bridge && pcihp_bridge_en &&
> +            !DEVICE(pdev)->hotplugged;
> +
> +        hotplug_enabled_dev = bsel && dc->hotpluggable && !bridge_in_acpi;
> +
> +        if (pc->class_id == PCI_CLASS_BRIDGE_ISA) {
> +            continue;
> +        }
> +
> +        /* start to compose PCI slot descriptor */
> +        dev = aml_device("S%.02X", PCI_DEVFN(slot, 0));
> +        aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16)));
> +
> +        if (pc->class_id == PCI_CLASS_DISPLAY_VGA) {
> +            /* add VGA specific AML methods */
> +            int s3d;
> +
> +            if (object_dynamic_cast(OBJECT(pdev), "qxl-vga")) {
> +                s3d = 3;
> +            } else {
> +                s3d = 0;
> +            }
> +
> +            method = aml_method("_S1D", 0, AML_NOTSERIALIZED);
> +            aml_append(method, aml_return(aml_int(0)));
> +            aml_append(dev, method);
> +
> +            method = aml_method("_S2D", 0, AML_NOTSERIALIZED);
> +            aml_append(method, aml_return(aml_int(0)));
> +            aml_append(dev, method);
> +
> +            method = aml_method("_S3D", 0, AML_NOTSERIALIZED);
> +            aml_append(method, aml_return(aml_int(s3d)));
> +            aml_append(dev, method);
> +        } else if (hotplug_enabled_dev) {
> +            /* add _SUN/_EJ0 to make slot hotpluggable  */
> +            aml_append(dev, aml_name_decl("_SUN", aml_int(slot)));
> +
> +            method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
> +            aml_append(method,
> +                aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN"))
> +            );
> +            aml_append(dev, method);
> +
> +            if (bsel) {
> +                build_append_pcihp_notify_entry(notify_method, slot);
> +            }
> +        } else if (bridge_in_acpi) {
> +            /*
> +             * device is coldplugged bridge,
> +             * add child device descriptions into its scope
> +             */
> +            PCIBus *sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(pdev));
> +
> +            build_append_pci_bus_devices(dev, sec_bus, pcihp_bridge_en);
> +        }
> +        /* slot descriptor has been composed, add it into parent context */
> +        aml_append(parent_scope, dev);
> +    }
> +
> +    if (bsel) {
> +        aml_append(parent_scope, notify_method);
> +    }
> +
> +    /* Append PCNT method to notify about events on local and child buses.
> +     * Add unconditionally for root since DSDT expects it.
> +     */
> +    method = aml_method("PCNT", 0, AML_NOTSERIALIZED);
> +
> +    /* If bus supports hotplug select it and notify about local events */
> +    if (bsel) {
> +        uint64_t bsel_val = qnum_get_uint(qobject_to(QNum, bsel));
> +
> +        aml_append(method, aml_store(aml_int(bsel_val), aml_name("BNUM")));
> +        aml_append(method,
> +            aml_call2("DVNT", aml_name("PCIU"), aml_int(1) /* Device Check */)
> +        );
> +        aml_append(method,
> +            aml_call2("DVNT", aml_name("PCID"), aml_int(3)/* Eject Request */)
> +        );
> +    }
> +
> +    /* Notify about child bus events in any case */
> +    if (pcihp_bridge_en) {
> +        QLIST_FOREACH(sec, &bus->child, sibling) {
> +            int32_t devfn = sec->parent_dev->devfn;
> +
> +            if (pci_bus_is_root(sec) || pci_bus_is_express(sec)) {
> +                continue;
> +            }
> +
> +            aml_append(method, aml_name("^S%.02X.PCNT", devfn));
> +        }
> +    }
> +    aml_append(parent_scope, method);
> +    qobject_unref(bsel);
> +}
> +
>   void acpi_dsdt_add_pci_bus(Aml *dsdt, AcpiPciBus *pci_host)
>   {
>       Aml *dev, *pci_scope;
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 5932dbe825..9cb739bf5c 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -362,163 +362,6 @@ build_madt(GArray *table_data, BIOSLinker *linker,
>                    table_data->len - madt_start, 1, NULL, NULL);
>   }
>   
> -static void build_append_pcihp_notify_entry(Aml *method, int slot)
> -{
> -    Aml *if_ctx;
> -    int32_t devfn = PCI_DEVFN(slot, 0);
> -
> -    if_ctx = aml_if(aml_and(aml_arg(0), aml_int(0x1U << slot), NULL));
> -    aml_append(if_ctx, aml_notify(aml_name("S%.02X", devfn), aml_arg(1)));
> -    aml_append(method, if_ctx);
> -}
> -
> -static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
> -                                         bool pcihp_bridge_en)
> -{
> -    Aml *dev, *notify_method = NULL, *method;
> -    QObject *bsel;
> -    PCIBus *sec;
> -    int i;
> -
> -    bsel = object_property_get_qobject(OBJECT(bus), ACPI_PCIHP_PROP_BSEL, NULL);
> -    if (bsel) {
> -        uint64_t bsel_val = qnum_get_uint(qobject_to(QNum, bsel));
> -
> -        aml_append(parent_scope, aml_name_decl("BSEL", aml_int(bsel_val)));
> -        notify_method = aml_method("DVNT", 2, AML_NOTSERIALIZED);
> -    }
> -
> -    for (i = 0; i < ARRAY_SIZE(bus->devices); i += PCI_FUNC_MAX) {
> -        DeviceClass *dc;
> -        PCIDeviceClass *pc;
> -        PCIDevice *pdev = bus->devices[i];
> -        int slot = PCI_SLOT(i);
> -        bool hotplug_enabled_dev;
> -        bool bridge_in_acpi;
> -
> -        if (!pdev) {
> -            if (bsel) { /* add hotplug slots for non present devices */
> -                dev = aml_device("S%.02X", PCI_DEVFN(slot, 0));
> -                aml_append(dev, aml_name_decl("_SUN", aml_int(slot)));
> -                aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16)));
> -                method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
> -                aml_append(method,
> -                    aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN"))
> -                );
> -                aml_append(dev, method);
> -                aml_append(parent_scope, dev);
> -
> -                build_append_pcihp_notify_entry(notify_method, slot);
> -            }
> -            continue;
> -        }
> -
> -        pc = PCI_DEVICE_GET_CLASS(pdev);
> -        dc = DEVICE_GET_CLASS(pdev);
> -
> -        /* When hotplug for bridges is enabled, bridges are
> -         * described in ACPI separately (see build_pci_bus_end).
> -         * In this case they aren't themselves hot-pluggable.
> -         * Hotplugged bridges *are* hot-pluggable.
> -         */
> -        bridge_in_acpi = pc->is_bridge && pcihp_bridge_en &&
> -            !DEVICE(pdev)->hotplugged;
> -
> -        hotplug_enabled_dev = bsel && dc->hotpluggable && !bridge_in_acpi;
> -
> -        if (pc->class_id == PCI_CLASS_BRIDGE_ISA) {
> -            continue;
> -        }
> -
> -        /* start to compose PCI slot descriptor */
> -        dev = aml_device("S%.02X", PCI_DEVFN(slot, 0));
> -        aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16)));
> -
> -        if (pc->class_id == PCI_CLASS_DISPLAY_VGA) {
> -            /* add VGA specific AML methods */
> -            int s3d;
> -
> -            if (object_dynamic_cast(OBJECT(pdev), "qxl-vga")) {
> -                s3d = 3;
> -            } else {
> -                s3d = 0;
> -            }
> -
> -            method = aml_method("_S1D", 0, AML_NOTSERIALIZED);
> -            aml_append(method, aml_return(aml_int(0)));
> -            aml_append(dev, method);
> -
> -            method = aml_method("_S2D", 0, AML_NOTSERIALIZED);
> -            aml_append(method, aml_return(aml_int(0)));
> -            aml_append(dev, method);
> -
> -            method = aml_method("_S3D", 0, AML_NOTSERIALIZED);
> -            aml_append(method, aml_return(aml_int(s3d)));
> -            aml_append(dev, method);
> -        } else if (hotplug_enabled_dev) {
> -            /* add _SUN/_EJ0 to make slot hotpluggable  */
> -            aml_append(dev, aml_name_decl("_SUN", aml_int(slot)));
> -
> -            method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
> -            aml_append(method,
> -                aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN"))
> -            );
> -            aml_append(dev, method);
> -
> -            if (bsel) {
> -                build_append_pcihp_notify_entry(notify_method, slot);
> -            }
> -        } else if (bridge_in_acpi) {
> -            /*
> -             * device is coldplugged bridge,
> -             * add child device descriptions into its scope
> -             */
> -            PCIBus *sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(pdev));
> -
> -            build_append_pci_bus_devices(dev, sec_bus, pcihp_bridge_en);
> -        }
> -        /* slot descriptor has been composed, add it into parent context */
> -        aml_append(parent_scope, dev);
> -    }
> -
> -    if (bsel) {
> -        aml_append(parent_scope, notify_method);
> -    }
> -
> -    /* Append PCNT method to notify about events on local and child buses.
> -     * Add unconditionally for root since DSDT expects it.
> -     */
> -    method = aml_method("PCNT", 0, AML_NOTSERIALIZED);
> -
> -    /* If bus supports hotplug select it and notify about local events */
> -    if (bsel) {
> -        uint64_t bsel_val = qnum_get_uint(qobject_to(QNum, bsel));
> -
> -        aml_append(method, aml_store(aml_int(bsel_val), aml_name("BNUM")));
> -        aml_append(method,
> -            aml_call2("DVNT", aml_name("PCIU"), aml_int(1) /* Device Check */)
> -        );
> -        aml_append(method,
> -            aml_call2("DVNT", aml_name("PCID"), aml_int(3)/* Eject Request */)
> -        );
> -    }
> -
> -    /* Notify about child bus events in any case */
> -    if (pcihp_bridge_en) {
> -        QLIST_FOREACH(sec, &bus->child, sibling) {
> -            int32_t devfn = sec->parent_dev->devfn;
> -
> -            if (pci_bus_is_root(sec) || pci_bus_is_express(sec)) {
> -                continue;
> -            }
> -
> -            aml_append(method, aml_name("^S%.02X.PCNT", devfn));
> -        }
> -    }
> -    aml_append(parent_scope, method);
> -    qobject_unref(bsel);
> -}
> -
>   static void build_hpet_aml(Aml *table)
>   {
>       Aml *crs;
> @@ -1214,41 +1057,10 @@ static void build_piix4_isa_bridge(Aml *table)
>   static void build_piix4_pci_hotplug(Aml *table)
>   {
>       Aml *scope;
> -    Aml *field;
> -    Aml *method;
> -
> -    scope =  aml_scope("_SB.PCI0");
> -
> -    aml_append(scope,
> -        aml_operation_region("PCST", AML_SYSTEM_IO, aml_int(0xae00), 0x08));
> -    field = aml_field("PCST", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
> -    aml_append(field, aml_named_field("PCIU", 32));
> -    aml_append(field, aml_named_field("PCID", 32));
> -    aml_append(scope, field);
>   
> -    aml_append(scope,
> -        aml_operation_region("SEJ", AML_SYSTEM_IO, aml_int(0xae08), 0x04));
> -    field = aml_field("SEJ", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
> -    aml_append(field, aml_named_field("B0EJ", 32));
> -    aml_append(scope, field);
> -
> -    aml_append(scope,
> -        aml_operation_region("BNMR", AML_SYSTEM_IO, aml_int(0xae10), 0x04));
> -    field = aml_field("BNMR", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
> -    aml_append(field, aml_named_field("BNUM", 32));
> -    aml_append(scope, field);
> -
> -    aml_append(scope, aml_mutex("BLCK", 0));
> -
> -    method = aml_method("PCEJ", 2, AML_NOTSERIALIZED);
> -    aml_append(method, aml_acquire(aml_name("BLCK"), 0xFFFF));
> -    aml_append(method, aml_store(aml_arg(0), aml_name("BNUM")));
> -    aml_append(method,
> -        aml_store(aml_shiftleft(aml_int(1), aml_arg(1)), aml_name("B0EJ")));
> -    aml_append(method, aml_release(aml_name("BLCK")));
> -    aml_append(method, aml_return(aml_int(0)));
> -    aml_append(scope, method);
> +    scope = aml_scope("_SB.PCI0");
>   
> +    build_acpi_pci_hotplug(scope);
>       aml_append(table, scope);
>   }
>   
> diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
> index 654ce2ec26..3ea2df5f83 100644
> --- a/include/hw/acpi/aml-build.h
> +++ b/include/hw/acpi/aml-build.h
> @@ -419,6 +419,9 @@ Aml *build_osc_method(uint32_t value);
>   void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info);
>   Aml *build_gsi_link_dev(const char *name, uint8_t uid, uint8_t gsi);
>   Aml *build_prt(bool is_pci0_prt);
> +void build_acpi_pci_hotplug(Aml *scope);
> +void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
> +                                  bool pcihp_bridge_en);
>   void acpi_dsdt_add_pci_bus(Aml *dsdt, AcpiPciBus *pci_host);
>   Aml *build_pci_host_bridge(Aml *table, AcpiPciBus *pci_host);
>   void crs_range_set_init(CrsRangeSet *range_set);
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 01/19] hw: i386: Decouple the ACPI build from the PC machine type
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 01/19] hw: i386: Decouple the ACPI build from the PC machine type Samuel Ortiz
@ 2018-10-29 19:50     ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 47+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-10-29 19:50 UTC (permalink / raw)
  To: Samuel Ortiz, qemu-devel
  Cc: Peter Maydell, Stefano Stabellini, Eduardo Habkost,
	Michael S. Tsirkin, open list:X86, Paolo Bonzini, Shannon Zhao,
	Anthony Perard, Igor Mammedov, open list:ARM ACPI Subsystem,
	Richard Henderson

Hi Samuel,

On 29/10/18 18:01, Samuel Ortiz wrote:
> ACPI tables are platform and machine type and even architecture
> agnostic, and as such we want to provide an internal ACPI API that
> only depends on platform agnostic information.
> 
> For the x86 architecture, in order to build ACPI tables independently
> from the PC or Q35 machine types, we are moving a few MachineState
> structure fields into a machine type agnostic structure called
> AcpiConfiguration. The structure fields we move are:
> 
>     HotplugHandler *acpi_dev
>     AcpiNVDIMMState acpi_nvdimm_state;
>     FWCfgState *fw_cfg
>     ram_addr_t below_4g_mem_size, above_4g_mem_size
>     bool apic_xrupt_override
>     unsigned apic_id_limit
>     uint64_t numa_nodes
>     uint64_t numa_mem
> 
> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
> ---
>   hw/acpi/cpu_hotplug.c    |   9 +-
>   hw/arm/virt-acpi-build.c |  10 ---
>   hw/i386/acpi-build.c     | 135 ++++++++++++++----------------
>   hw/i386/acpi-build.h     |   4 +-
>   hw/i386/pc.c             | 175 ++++++++++++++++++++++++---------------
>   hw/i386/pc_piix.c        |  21 ++---
>   hw/i386/pc_q35.c         |  21 ++---
>   hw/i386/xen/xen-hvm.c    |  19 +++--
>   include/hw/acpi/acpi.h   |  43 ++++++++++
>   include/hw/i386/pc.h     |  19 ++---
>   10 files changed, 254 insertions(+), 202 deletions(-)
> 
> diff --git a/hw/acpi/cpu_hotplug.c b/hw/acpi/cpu_hotplug.c
> index 5243918125..634dc3b846 100644
> --- a/hw/acpi/cpu_hotplug.c
> +++ b/hw/acpi/cpu_hotplug.c
> @@ -237,9 +237,9 @@ void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *machine,
>       /* The current AML generator can cover the APIC ID range [0..255],
>        * inclusive, for VCPU hotplug. */
>       QEMU_BUILD_BUG_ON(ACPI_CPU_HOTPLUG_ID_LIMIT > 256);
> -    if (pcms->apic_id_limit > ACPI_CPU_HOTPLUG_ID_LIMIT) {
> +    if (pcms->acpi_configuration.apic_id_limit > ACPI_CPU_HOTPLUG_ID_LIMIT) {
>           error_report("max_cpus is too large. APIC ID of last CPU is %u",
> -                     pcms->apic_id_limit - 1);
> +                     pcms->acpi_configuration.apic_id_limit - 1);
>           exit(1);
>       }
>   
> @@ -316,8 +316,9 @@ void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *machine,
>        * ith up to 255 elements. Windows guests up to win2k8 fail when
>        * VarPackageOp is used.
>        */
> -    pkg = pcms->apic_id_limit <= 255 ? aml_package(pcms->apic_id_limit) :
> -                                       aml_varpackage(pcms->apic_id_limit);
> +    pkg = pcms->acpi_configuration.apic_id_limit <= 255 ?
> +        aml_package(pcms->acpi_configuration.apic_id_limit) :
> +        aml_varpackage(pcms->acpi_configuration.apic_id_limit);
>   
>       for (i = 0, apic_idx = 0; i < apic_ids->len; i++) {
>           int apic_id = apic_ids->cpus[i].arch_id;
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index 5785fb697c..f28a2faa53 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -790,16 +790,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>       free_aml_allocator();
>   }
>   
> -typedef
> -struct AcpiBuildState {
> -    /* Copy of table in RAM (for patching). */
> -    MemoryRegion *table_mr;
> -    MemoryRegion *rsdp_mr;
> -    MemoryRegion *linker_mr;
> -    /* Is table patched? */
> -    bool patched;
> -} AcpiBuildState;
> -
>   static
>   void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
>   {
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 1599caa7c5..c8545238c4 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -338,13 +338,14 @@ void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
>   }
>   
>   static void
> -build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms)
> +build_madt(GArray *table_data, BIOSLinker *linker,
> +           MachineState *ms, AcpiConfiguration *conf)

Can you rename AcpiConfiguration *conf -> acpi_cfg/acpi_conf/acpi_config 
in the whole patch?

>   {
> -    MachineClass *mc = MACHINE_GET_CLASS(pcms);
> -    const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(pcms));
> +    MachineClass *mc = MACHINE_GET_CLASS(ms);
> +    const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(ms);
>       int madt_start = table_data->len;
> -    AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(pcms->acpi_dev);
> -    AcpiDeviceIf *adev = ACPI_DEVICE_IF(pcms->acpi_dev);
> +    AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(conf->acpi_dev);
> +    AcpiDeviceIf *adev = ACPI_DEVICE_IF(conf->acpi_dev);
>       bool x2apic_mode = false;
>   
>       AcpiMultipleApicTable *madt;
> @@ -370,7 +371,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms)
>       io_apic->address = cpu_to_le32(IO_APIC_DEFAULT_ADDRESS);
>       io_apic->interrupt = cpu_to_le32(0);
>   
> -    if (pcms->apic_xrupt_override) {
> +    if (conf->apic_xrupt_override) {
>           intsrcovr = acpi_data_push(table_data, sizeof *intsrcovr);
>           intsrcovr->type   = ACPI_APIC_XRUPT_OVERRIDE;
>           intsrcovr->length = sizeof(*intsrcovr);
> @@ -1786,13 +1787,12 @@ static Aml *build_q35_osc_method(void)
>   static void
>   build_dsdt(GArray *table_data, BIOSLinker *linker,
>              AcpiPmInfo *pm, AcpiMiscInfo *misc,
> -           Range *pci_hole, Range *pci_hole64, MachineState *machine)
> +           Range *pci_hole, Range *pci_hole64,
> +           MachineState *machine, AcpiConfiguration *conf)
>   {
>       CrsRangeEntry *entry;
>       Aml *dsdt, *sb_scope, *scope, *dev, *method, *field, *pkg, *crs;
>       CrsRangeSet crs_range_set;
> -    PCMachineState *pcms = PC_MACHINE(machine);
> -    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(machine);
>       uint32_t nr_mem = machine->ram_slots;
>       int root_bus_limit = 0xFF;
>       PCIBus *bus = NULL;
> @@ -1836,7 +1836,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
>           build_q35_pci0_int(dsdt);
>       }
>   
> -    if (pcmc->legacy_cpu_hotplug) {
> +    if (conf->legacy_cpu_hotplug) {
>           build_legacy_cpu_hotplug_aml(dsdt, machine, pm->cpu_hp_io_base);
>       } else {
>           CPUHotplugFeatures opts = {
> @@ -1860,7 +1860,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
>               aml_append(scope, method);
>           }
>   
> -        if (pcms->acpi_nvdimm_state.is_enabled) {
> +        if (conf->acpi_nvdimm_state.is_enabled) {
>               method = aml_method("_E04", 0, AML_NOTSERIALIZED);
>               aml_append(method, aml_notify(aml_name("\\_SB.NVDR"),
>                                             aml_int(0x80)));
> @@ -2041,7 +2041,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
>            * with half of the 16-bit control register. Hence, the total size
>            * of the i/o region used is FW_CFG_CTL_SIZE; when using DMA, the
>            * DMA control register is located at FW_CFG_DMA_IO_BASE + 4 */
> -        uint8_t io_size = object_property_get_bool(OBJECT(pcms->fw_cfg),
> +        uint8_t io_size = object_property_get_bool(OBJECT(conf->fw_cfg),
>                                                      "dma_enabled", NULL) ?
>                             ROUND_UP(FW_CFG_CTL_SIZE, 4) + sizeof(dma_addr_t) :
>                             FW_CFG_CTL_SIZE;
> @@ -2252,7 +2252,8 @@ build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog)
>   #define HOLE_640K_END   (1 * MiB)
>   
>   static void
> -build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
> +build_srat(GArray *table_data, BIOSLinker *linker,
> +           MachineState *machine, AcpiConfiguration *conf)
>   {
>       AcpiSystemResourceAffinityTable *srat;
>       AcpiSratMemoryAffinity *numamem;
> @@ -2262,9 +2263,8 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
>       uint64_t mem_len, mem_base, next_base;
>       MachineClass *mc = MACHINE_GET_CLASS(machine);
>       const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(machine);
> -    PCMachineState *pcms = PC_MACHINE(machine);
>       ram_addr_t hotplugabble_address_space_size =
> -        object_property_get_int(OBJECT(pcms), PC_MACHINE_DEVMEM_REGION_SIZE,
> +        object_property_get_int(OBJECT(machine), PC_MACHINE_DEVMEM_REGION_SIZE,
>                                   NULL);
>   
>       srat_start = table_data->len;
> @@ -2306,9 +2306,9 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
>       next_base = 0;
>       numa_start = table_data->len;
>   
> -    for (i = 1; i < pcms->numa_nodes + 1; ++i) {
> +    for (i = 1; i < conf->numa_nodes + 1; ++i) {
>           mem_base = next_base;
> -        mem_len = pcms->node_mem[i - 1];
> +        mem_len = conf->node_mem[i - 1];
>           next_base = mem_base + mem_len;
>   
>           /* Cut out the 640K hole */
> @@ -2331,16 +2331,16 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
>           }
>   
>           /* Cut out the ACPI_PCI hole */
> -        if (mem_base <= pcms->below_4g_mem_size &&
> -            next_base > pcms->below_4g_mem_size) {
> -            mem_len -= next_base - pcms->below_4g_mem_size;
> +        if (mem_base <= conf->below_4g_mem_size &&
> +            next_base > conf->below_4g_mem_size) {
> +            mem_len -= next_base - conf->below_4g_mem_size;
>               if (mem_len > 0) {
>                   numamem = acpi_data_push(table_data, sizeof *numamem);
>                   build_srat_memory(numamem, mem_base, mem_len, i - 1,
>                                     MEM_AFFINITY_ENABLED);
>               }
>               mem_base = 1ULL << 32;
> -            mem_len = next_base - pcms->below_4g_mem_size;
> +            mem_len = next_base - conf->below_4g_mem_size;
>               next_base = mem_base + mem_len;
>           }
>   
> @@ -2351,7 +2351,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
>           }
>       }
>       slots = (table_data->len - numa_start) / sizeof *numamem;
> -    for (; slots < pcms->numa_nodes + 2; slots++) {
> +    for (; slots < conf->numa_nodes + 2; slots++) {
>           numamem = acpi_data_push(table_data, sizeof *numamem);
>           build_srat_memory(numamem, 0, 0, 0, MEM_AFFINITY_NOFLAGS);
>       }
> @@ -2367,7 +2367,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
>       if (hotplugabble_address_space_size) {
>           numamem = acpi_data_push(table_data, sizeof *numamem);
>           build_srat_memory(numamem, machine->device_memory->base,
> -                          hotplugabble_address_space_size, pcms->numa_nodes - 1,
> +                          hotplugabble_address_space_size, conf->numa_nodes - 1,
>                             MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
>       }
>   
> @@ -2546,17 +2546,6 @@ build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset)
>       return rsdp_table;
>   }
>   
> -typedef
> -struct AcpiBuildState {
> -    /* Copy of table in RAM (for patching). */
> -    MemoryRegion *table_mr;
> -    /* Is table patched? */
> -    uint8_t patched;
> -    void *rsdp;
> -    MemoryRegion *rsdp_mr;
> -    MemoryRegion *linker_mr;
> -} AcpiBuildState;
> -
>   static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
>   {
>       Object *pci_host;
> @@ -2580,10 +2569,9 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
>   }
>   
>   static
> -void acpi_build(AcpiBuildTables *tables, MachineState *machine)
> +void acpi_build(AcpiBuildTables *tables,
> +                MachineState *machine, AcpiConfiguration *conf)
>   {
> -    PCMachineState *pcms = PC_MACHINE(machine);
> -    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
>       GArray *table_offsets;
>       unsigned facs, dsdt, rsdt, fadt;
>       AcpiPmInfo pm;
> @@ -2621,7 +2609,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
>       /* DSDT is pointed to by FADT */
>       dsdt = tables_blob->len;
>       build_dsdt(tables_blob, tables->linker, &pm, &misc,
> -               &pci_hole, &pci_hole64, machine);
> +               &pci_hole, &pci_hole64, machine, conf);
>   
>       /* Count the size of the DSDT and SSDT, we will need it for legacy
>        * sizing of ACPI tables.
> @@ -2639,7 +2627,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
>       aml_len += tables_blob->len - fadt;
>   
>       acpi_add_table(table_offsets, tables_blob);
> -    build_madt(tables_blob, tables->linker, pcms);
> +    build_madt(tables_blob, tables->linker, machine, conf);
>   
>       vmgenid_dev = find_vmgenid_dev();
>       if (vmgenid_dev) {
> @@ -2661,9 +2649,9 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
>               build_tpm2(tables_blob, tables->linker, tables->tcpalog);
>           }
>       }
> -    if (pcms->numa_nodes) {
> +    if (conf->numa_nodes) {
>           acpi_add_table(table_offsets, tables_blob);
> -        build_srat(tables_blob, tables->linker, machine);
> +        build_srat(tables_blob, tables->linker, machine, conf);
>           if (have_numa_distance) {
>               acpi_add_table(table_offsets, tables_blob);
>               build_slit(tables_blob, tables->linker);
> @@ -2683,9 +2671,9 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
>               build_dmar_q35(tables_blob, tables->linker);
>           }
>       }
> -    if (pcms->acpi_nvdimm_state.is_enabled) {
> +    if (conf->acpi_nvdimm_state.is_enabled) {
>           nvdimm_build_acpi(table_offsets, tables_blob, tables->linker,
> -                          &pcms->acpi_nvdimm_state, machine->ram_slots);
> +                          &conf->acpi_nvdimm_state, machine->ram_slots);
>       }
>   
>       /* Add tables supplied by user (if any) */
> @@ -2721,13 +2709,13 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
>        *
>        * All this is for PIIX4, since QEMU 2.0 didn't support Q35 migration.
>        */
> -    if (pcmc->legacy_acpi_table_size) {
> +    if (conf->legacy_acpi_table_size) {
>           /* Subtracting aml_len gives the size of fixed tables.  Then add the
>            * size of the PIIX4 DSDT/SSDT in QEMU 2.0.
>            */
>           int legacy_aml_len =
> -            pcmc->legacy_acpi_table_size +
> -            ACPI_BUILD_LEGACY_CPU_AML_SIZE * pcms->apic_id_limit;
> +            conf->legacy_acpi_table_size +
> +            ACPI_BUILD_LEGACY_CPU_AML_SIZE * conf->apic_id_limit;
>           int legacy_table_size =
>               ROUND_UP(tables_blob->len - aml_len + legacy_aml_len,
>                        ACPI_BUILD_ALIGN_SIZE);
> @@ -2772,9 +2760,17 @@ static void acpi_ram_update(MemoryRegion *mr, GArray *data)
>   
>   static void acpi_build_update(void *build_opaque)
>   {
> -    AcpiBuildState *build_state = build_opaque;
> +    AcpiConfiguration *conf = build_opaque;
> +    AcpiBuildState *build_state;
>       AcpiBuildTables tables;
>   
> +    /* No ACPI configuration? Nothing to do. */
> +    if (!conf) {
> +        return;
> +    }
> +
> +    build_state = conf->build_state;
> +
>       /* No state to update or already patched? Nothing to do. */
>       if (!build_state || build_state->patched) {
>           return;
> @@ -2783,7 +2779,7 @@ static void acpi_build_update(void *build_opaque)
>   
>       acpi_build_tables_init(&tables);
>   
> -    acpi_build(&tables, MACHINE(qdev_get_machine()));
> +    acpi_build(&tables, MACHINE(qdev_get_machine()), conf);
>   
>       acpi_ram_update(build_state->table_mr, tables.table_data);
>   
> @@ -2803,12 +2799,12 @@ static void acpi_build_reset(void *build_opaque)
>       build_state->patched = 0;
>   }
>   
> -static MemoryRegion *acpi_add_rom_blob(AcpiBuildState *build_state,
> +static MemoryRegion *acpi_add_rom_blob(AcpiConfiguration *conf,
>                                          GArray *blob, const char *name,
>                                          uint64_t max_size)
>   {
>       return rom_add_blob(name, blob->data, acpi_data_len(blob), max_size, -1,
> -                        name, acpi_build_update, build_state, NULL, true);
> +                        name, acpi_build_update, conf, NULL, true);
>   }
>   
>   static const VMStateDescription vmstate_acpi_build = {
> @@ -2816,59 +2812,48 @@ static const VMStateDescription vmstate_acpi_build = {
>       .version_id = 1,
>       .minimum_version_id = 1,
>       .fields = (VMStateField[]) {
> -        VMSTATE_UINT8(patched, AcpiBuildState),
> +        VMSTATE_BOOL(patched, AcpiBuildState),
>           VMSTATE_END_OF_LIST()
>       },
>   };
>   
> -void acpi_setup(void)
> +void acpi_setup(MachineState *machine, AcpiConfiguration *conf)
>   {
> -    PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
> -    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
>       AcpiBuildTables tables;
>       AcpiBuildState *build_state;
>       Object *vmgenid_dev;
>   
> -    if (!pcms->fw_cfg) {
> -        ACPI_BUILD_DPRINTF("No fw cfg. Bailing out.\n");
> -        return;
> -    }
> -
> -    if (!pcms->acpi_build_enabled) {
> -        ACPI_BUILD_DPRINTF("ACPI build disabled. Bailing out.\n");
> -        return;
> -    }
> -
> -    if (!acpi_enabled) {
> -        ACPI_BUILD_DPRINTF("ACPI disabled. Bailing out.\n");
> +    if (!conf) {
> +        ACPI_BUILD_DPRINTF("No ACPI config. Bailing out.\n");
>           return;
>       }
>   
>       build_state = g_malloc0(sizeof *build_state);
> +    conf->build_state = build_state;
>   
>       acpi_build_tables_init(&tables);
> -    acpi_build(&tables, MACHINE(pcms));
> +    acpi_build(&tables, machine, conf);
>   
>       /* Now expose it all to Guest */
> -    build_state->table_mr = acpi_add_rom_blob(build_state, tables.table_data,
> +    build_state->table_mr = acpi_add_rom_blob(conf, tables.table_data,
>                                                  ACPI_BUILD_TABLE_FILE,
>                                                  ACPI_BUILD_TABLE_MAX_SIZE);
>       assert(build_state->table_mr != NULL);
>   
>       build_state->linker_mr =
> -        acpi_add_rom_blob(build_state, tables.linker->cmd_blob,
> +        acpi_add_rom_blob(conf, tables.linker->cmd_blob,
>                             "etc/table-loader", 0);
>   
> -    fw_cfg_add_file(pcms->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
> +    fw_cfg_add_file(conf->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
>                       tables.tcpalog->data, acpi_data_len(tables.tcpalog));
>   
>       vmgenid_dev = find_vmgenid_dev();
>       if (vmgenid_dev) {
> -        vmgenid_add_fw_cfg(VMGENID(vmgenid_dev), pcms->fw_cfg,
> +        vmgenid_add_fw_cfg(VMGENID(vmgenid_dev), conf->fw_cfg,
>                              tables.vmgenid);
>       }
>   
> -    if (!pcmc->rsdp_in_ram) {
> +    if (!conf->rsdp_in_ram) {
>           /*
>            * Keep for compatibility with old machine types.
>            * Though RSDP is small, its contents isn't immutable, so
> @@ -2877,13 +2862,13 @@ void acpi_setup(void)
>           uint32_t rsdp_size = acpi_data_len(tables.rsdp);
>   
>           build_state->rsdp = g_memdup(tables.rsdp->data, rsdp_size);
> -        fw_cfg_add_file_callback(pcms->fw_cfg, ACPI_BUILD_RSDP_FILE,
> -                                 acpi_build_update, NULL, build_state,
> +        fw_cfg_add_file_callback(conf->fw_cfg, ACPI_BUILD_RSDP_FILE,
> +                                 acpi_build_update, NULL, conf,
>                                    build_state->rsdp, rsdp_size, true);
>           build_state->rsdp_mr = NULL;
>       } else {
>           build_state->rsdp = NULL;
> -        build_state->rsdp_mr = acpi_add_rom_blob(build_state, tables.rsdp,
> +        build_state->rsdp_mr = acpi_add_rom_blob(conf, tables.rsdp,
>                                                     ACPI_BUILD_RSDP_FILE, 0);
>       }
>   
> diff --git a/hw/i386/acpi-build.h b/hw/i386/acpi-build.h
> index 007332e51c..1e6b5a7c2e 100644
> --- a/hw/i386/acpi-build.h
> +++ b/hw/i386/acpi-build.h
> @@ -2,6 +2,8 @@
>   #ifndef HW_I386_ACPI_BUILD_H
>   #define HW_I386_ACPI_BUILD_H
>   
> -void acpi_setup(void);
> +#include "hw/acpi/acpi.h"
> +
> +void acpi_setup(MachineState *machine, AcpiConfiguration *conf);
>   
>   #endif
> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> index f095725dba..bd4a77b856 100644
> --- a/hw/i386/pc.c
> +++ b/hw/i386/pc.c
> @@ -444,17 +444,18 @@ void pc_cmos_init(PCMachineState *pcms,
>   {
>       int val;
>       static pc_cmos_init_late_arg arg;
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>   
>       /* various important CMOS locations needed by PC/Bochs bios */
>   
>       /* memory size */
>       /* base memory (first MiB) */
> -    val = MIN(pcms->below_4g_mem_size / KiB, 640);
> +    val = MIN(conf->below_4g_mem_size / KiB, 640);
>       rtc_set_memory(s, 0x15, val);
>       rtc_set_memory(s, 0x16, val >> 8);
>       /* extended memory (next 64MiB) */
> -    if (pcms->below_4g_mem_size > 1 * MiB) {
> -        val = (pcms->below_4g_mem_size - 1 * MiB) / KiB;
> +    if (conf->below_4g_mem_size > 1 * MiB) {
> +        val = (conf->below_4g_mem_size - 1 * MiB) / KiB;
>       } else {
>           val = 0;
>       }
> @@ -465,8 +466,8 @@ void pc_cmos_init(PCMachineState *pcms,
>       rtc_set_memory(s, 0x30, val);
>       rtc_set_memory(s, 0x31, val >> 8);
>       /* memory between 16MiB and 4GiB */
> -    if (pcms->below_4g_mem_size > 16 * MiB) {
> -        val = (pcms->below_4g_mem_size - 16 * MiB) / (64 * KiB);
> +    if (conf->below_4g_mem_size > 16 * MiB) {
> +        val = (conf->below_4g_mem_size - 16 * MiB) / (64 * KiB);
>       } else {
>           val = 0;
>       }
> @@ -475,7 +476,7 @@ void pc_cmos_init(PCMachineState *pcms,
>       rtc_set_memory(s, 0x34, val);
>       rtc_set_memory(s, 0x35, val >> 8);
>       /* memory above 4GiB */
> -    val = pcms->above_4g_mem_size / 65536;
> +    val = conf->above_4g_mem_size / 65536;
>       rtc_set_memory(s, 0x5b, val);
>       rtc_set_memory(s, 0x5c, val >> 8);
>       rtc_set_memory(s, 0x5d, val >> 16);
> @@ -714,13 +715,14 @@ static void pc_build_smbios(PCMachineState *pcms)
>       unsigned i, array_count;
>       MachineState *ms = MACHINE(pcms);
>       X86CPU *cpu = X86_CPU(ms->possible_cpus->cpus[0].cpu);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>   
>       /* tell smbios about cpuid version and features */
>       smbios_set_cpuid(cpu->env.cpuid_version, cpu->env.features[FEAT_1_EDX]);
>   
>       smbios_tables = smbios_get_table_legacy(&smbios_tables_len);
>       if (smbios_tables) {
> -        fw_cfg_add_bytes(pcms->fw_cfg, FW_CFG_SMBIOS_ENTRIES,
> +        fw_cfg_add_bytes(conf->fw_cfg, FW_CFG_SMBIOS_ENTRIES,
>                            smbios_tables, smbios_tables_len);
>       }
>   
> @@ -741,9 +743,9 @@ static void pc_build_smbios(PCMachineState *pcms)
>       g_free(mem_array);
>   
>       if (smbios_anchor) {
> -        fw_cfg_add_file(pcms->fw_cfg, "etc/smbios/smbios-tables",
> +        fw_cfg_add_file(conf->fw_cfg, "etc/smbios/smbios-tables",
>                           smbios_tables, smbios_tables_len);
> -        fw_cfg_add_file(pcms->fw_cfg, "etc/smbios/smbios-anchor",
> +        fw_cfg_add_file(conf->fw_cfg, "etc/smbios/smbios-anchor",
>                           smbios_anchor, smbios_anchor_len);
>       }
>   }
> @@ -755,6 +757,7 @@ static FWCfgState *bochs_bios_init(AddressSpace *as, PCMachineState *pcms)
>       int i;
>       const CPUArchIdList *cpus;
>       MachineClass *mc = MACHINE_GET_CLASS(pcms);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>   
>       fw_cfg = fw_cfg_init_io_dma(FW_CFG_IO_BASE, FW_CFG_IO_BASE + 4, as);
>       fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
> @@ -771,7 +774,7 @@ static FWCfgState *bochs_bios_init(AddressSpace *as, PCMachineState *pcms)
>        * So for compatibility reasons with old BIOSes we are stuck with
>        * "etc/max-cpus" actually being apic_id_limit
>        */
> -    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)pcms->apic_id_limit);
> +    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)conf->apic_id_limit);
>       fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
>       fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES,
>                        acpi_tables, acpi_tables_len);
> @@ -787,20 +790,20 @@ static FWCfgState *bochs_bios_init(AddressSpace *as, PCMachineState *pcms)
>        * of nodes, one word for each VCPU->node and one word for each node to
>        * hold the amount of memory.
>        */
> -    numa_fw_cfg = g_new0(uint64_t, 1 + pcms->apic_id_limit + nb_numa_nodes);
> +    numa_fw_cfg = g_new0(uint64_t, 1 + conf->apic_id_limit + nb_numa_nodes);
>       numa_fw_cfg[0] = cpu_to_le64(nb_numa_nodes);
>       cpus = mc->possible_cpu_arch_ids(MACHINE(pcms));
>       for (i = 0; i < cpus->len; i++) {
>           unsigned int apic_id = cpus->cpus[i].arch_id;
> -        assert(apic_id < pcms->apic_id_limit);
> +        assert(apic_id < conf->apic_id_limit);
>           numa_fw_cfg[apic_id + 1] = cpu_to_le64(cpus->cpus[i].props.node_id);
>       }
>       for (i = 0; i < nb_numa_nodes; i++) {
> -        numa_fw_cfg[pcms->apic_id_limit + 1 + i] =
> +        numa_fw_cfg[conf->apic_id_limit + 1 + i] =
>               cpu_to_le64(numa_info[i].node_mem);
>       }
>       fw_cfg_add_bytes(fw_cfg, FW_CFG_NUMA, numa_fw_cfg,
> -                     (1 + pcms->apic_id_limit + nb_numa_nodes) *
> +                     (1 + conf->apic_id_limit + nb_numa_nodes) *
>                        sizeof(*numa_fw_cfg));
>   
>       return fw_cfg;
> @@ -848,6 +851,7 @@ static void load_linux(PCMachineState *pcms,
>       char *vmode;
>       MachineState *machine = MACHINE(pcms);
>       PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>       struct setup_data *setup_data;
>       const char *kernel_filename = machine->kernel_filename;
>       const char *initrd_filename = machine->initrd_filename;
> @@ -917,8 +921,8 @@ static void load_linux(PCMachineState *pcms,
>           initrd_max = 0x37ffffff;
>       }
>   
> -    if (initrd_max >= pcms->below_4g_mem_size - pcmc->acpi_data_size) {
> -        initrd_max = pcms->below_4g_mem_size - pcmc->acpi_data_size - 1;
> +    if (initrd_max >= conf->below_4g_mem_size - pcmc->acpi_data_size) {
> +        initrd_max = conf->below_4g_mem_size - pcmc->acpi_data_size - 1;
>       }
>   
>       fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_ADDR, cmdline_addr);
> @@ -1154,7 +1158,8 @@ void pc_cpus_init(PCMachineState *pcms)
>        *
>        * This is used for FW_CFG_MAX_CPUS. See comments on bochs_bios_init().
>        */
> -    pcms->apic_id_limit = x86_cpu_apic_id_from_index(max_cpus - 1) + 1;
> +    pcms->acpi_configuration.apic_id_limit =
> +        x86_cpu_apic_id_from_index(max_cpus - 1) + 1;
>       possible_cpus = mc->possible_cpu_arch_ids(ms);
>       for (i = 0; i < smp_cpus; i++) {
>           pc_new_cpu(possible_cpus->cpus[i].type, possible_cpus->cpus[i].arch_id,
> @@ -1188,7 +1193,8 @@ static void pc_build_feature_control_file(PCMachineState *pcms)
>   
>       val = g_malloc(sizeof(*val));
>       *val = cpu_to_le64(feature_control_bits | FEATURE_CONTROL_LOCKED);
> -    fw_cfg_add_file(pcms->fw_cfg, "etc/msr_feature_control", val, sizeof(*val));
> +    fw_cfg_add_file(pcms->acpi_configuration.fw_cfg,
> +                    "etc/msr_feature_control", val, sizeof(*val));
>   }
>   
>   static void rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count)
> @@ -1204,11 +1210,26 @@ static void rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count)
>       }
>   }
>   
> +static void acpi_conf_pc_init(PCMachineState *pcms)
> +{
> +    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
> +
> +    /* Machine class settings */
> +    conf->legacy_acpi_table_size = pcmc->legacy_acpi_table_size;
> +    conf->legacy_cpu_hotplug = pcmc->legacy_cpu_hotplug;
> +    conf->rsdp_in_ram = pcmc->rsdp_in_ram;
> +
> +    /* ACPI build state */
> +    conf->build_state = NULL;
> +}
> +
>   static
>   void pc_machine_done(Notifier *notifier, void *data)
>   {
>       PCMachineState *pcms = container_of(notifier,
>                                           PCMachineState, machine_done);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>       PCIBus *bus = pcms->bus;
>   
>       /* set the number of CPUs */
> @@ -1223,23 +1244,27 @@ void pc_machine_done(Notifier *notifier, void *data)
>                   extra_hosts++;
>               }
>           }
> -        if (extra_hosts && pcms->fw_cfg) {
> +        if (extra_hosts && conf->fw_cfg) {
>               uint64_t *val = g_malloc(sizeof(*val));
>               *val = cpu_to_le64(extra_hosts);
> -            fw_cfg_add_file(pcms->fw_cfg,
> +            fw_cfg_add_file(conf->fw_cfg,
>                       "etc/extra-pci-roots", val, sizeof(*val));
>           }
>       }
>   
> -    acpi_setup();
> -    if (pcms->fw_cfg) {
> +    if (pcms->acpi_build_enabled) {
> +        acpi_conf_pc_init(pcms);
> +        acpi_setup(MACHINE(pcms), conf);
> +    }
> +
> +    if (conf->fw_cfg) {
>           pc_build_smbios(pcms);
>           pc_build_feature_control_file(pcms);
>           /* update FW_CFG_NB_CPUS to account for -device added CPUs */
> -        fw_cfg_modify_i16(pcms->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
> +        fw_cfg_modify_i16(conf->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
>       }
>   
> -    if (pcms->apic_id_limit > 255 && !xen_enabled()) {
> +    if (conf->apic_id_limit > 255 && !xen_enabled()) {
>           IntelIOMMUState *iommu = INTEL_IOMMU_DEVICE(x86_iommu_get_default());
>   
>           if (!iommu || !iommu->x86_iommu.intr_supported ||
> @@ -1256,13 +1281,14 @@ void pc_machine_done(Notifier *notifier, void *data)
>   void pc_guest_info_init(PCMachineState *pcms)
>   {
>       int i;
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>   
> -    pcms->apic_xrupt_override = kvm_allows_irq0_override();
> -    pcms->numa_nodes = nb_numa_nodes;
> -    pcms->node_mem = g_malloc0(pcms->numa_nodes *
> -                                    sizeof *pcms->node_mem);
> +    conf->apic_xrupt_override = kvm_allows_irq0_override();
> +    conf->numa_nodes = nb_numa_nodes;
> +    conf->node_mem = g_malloc0(conf->numa_nodes *
> +                                    sizeof *conf->node_mem);
>       for (i = 0; i < nb_numa_nodes; i++) {
> -        pcms->node_mem[i] = numa_info[i].node_mem;
> +        conf->node_mem[i] = numa_info[i].node_mem;
>       }
>   
>       pcms->machine_done.notify = pc_machine_done;
> @@ -1323,7 +1349,7 @@ void xen_load_linux(PCMachineState *pcms)
>                  !strcmp(option_rom[i].name, "multiboot.bin"));
>           rom_add_option(option_rom[i].name, option_rom[i].bootindex);
>       }
> -    pcms->fw_cfg = fw_cfg;
> +    pcms->acpi_configuration.fw_cfg = fw_cfg;
>   }
>   
>   void pc_memory_init(PCMachineState *pcms,
> @@ -1337,9 +1363,10 @@ void pc_memory_init(PCMachineState *pcms,
>       FWCfgState *fw_cfg;
>       MachineState *machine = MACHINE(pcms);
>       PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>   
> -    assert(machine->ram_size == pcms->below_4g_mem_size +
> -                                pcms->above_4g_mem_size);
> +    assert(machine->ram_size == conf->below_4g_mem_size +
> +                                conf->above_4g_mem_size);
>   
>       linux_boot = (machine->kernel_filename != NULL);
>   
> @@ -1353,17 +1380,17 @@ void pc_memory_init(PCMachineState *pcms,
>       *ram_memory = ram;
>       ram_below_4g = g_malloc(sizeof(*ram_below_4g));
>       memory_region_init_alias(ram_below_4g, NULL, "ram-below-4g", ram,
> -                             0, pcms->below_4g_mem_size);
> +                             0, conf->below_4g_mem_size);
>       memory_region_add_subregion(system_memory, 0, ram_below_4g);
> -    e820_add_entry(0, pcms->below_4g_mem_size, E820_RAM);
> -    if (pcms->above_4g_mem_size > 0) {
> +    e820_add_entry(0, conf->below_4g_mem_size, E820_RAM);
> +    if (conf->above_4g_mem_size > 0) {
>           ram_above_4g = g_malloc(sizeof(*ram_above_4g));
>           memory_region_init_alias(ram_above_4g, NULL, "ram-above-4g", ram,
> -                                 pcms->below_4g_mem_size,
> -                                 pcms->above_4g_mem_size);
> +                                 conf->below_4g_mem_size,
> +                                 conf->above_4g_mem_size);
>           memory_region_add_subregion(system_memory, 0x100000000ULL,
>                                       ram_above_4g);
> -        e820_add_entry(0x100000000ULL, pcms->above_4g_mem_size, E820_RAM);
> +        e820_add_entry(0x100000000ULL, conf->above_4g_mem_size, E820_RAM);
>       }
>   
>       if (!pcmc->has_reserved_memory &&
> @@ -1398,7 +1425,7 @@ void pc_memory_init(PCMachineState *pcms,
>           }
>   
>           machine->device_memory->base =
> -            ROUND_UP(0x100000000ULL + pcms->above_4g_mem_size, 1 * GiB);
> +            ROUND_UP(0x100000000ULL + conf->above_4g_mem_size, 1 * GiB);
>   
>           if (pcmc->enforce_aligned_dimm) {
>               /* size device region assuming 1G page max alignment per slot */
> @@ -1455,7 +1482,7 @@ void pc_memory_init(PCMachineState *pcms,
>       for (i = 0; i < nb_option_roms; i++) {
>           rom_add_option(option_rom[i].name, option_rom[i].bootindex);
>       }
> -    pcms->fw_cfg = fw_cfg;
> +    conf->fw_cfg = fw_cfg;
>   
>       /* Init default IOAPIC address space */
>       pcms->ioapic_as = &address_space_memory;
> @@ -1478,7 +1505,8 @@ uint64_t pc_pci_hole64_start(void)
>               hole64_start += memory_region_size(&ms->device_memory->mr);
>           }
>       } else {
> -        hole64_start = 0x100000000ULL + pcms->above_4g_mem_size;
> +        hole64_start =
> +            0x100000000ULL + pcms->acpi_configuration.above_4g_mem_size;
>       }
>   
>       return ROUND_UP(hole64_start, 1 * GiB);
> @@ -1685,21 +1713,22 @@ static void pc_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
>   {
>       const PCMachineState *pcms = PC_MACHINE(hotplug_dev);
>       const PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
> +    const AcpiConfiguration *conf = &pcms->acpi_configuration;
>       const bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
>       const uint64_t legacy_align = TARGET_PAGE_SIZE;
>   
>       /*
>        * When -no-acpi is used with Q35 machine type, no ACPI is built,
> -     * but pcms->acpi_dev is still created. Check !acpi_enabled in
> +     * but acpi_dev is still created. Check !acpi_enabled in
>        * addition to cover this case.
>        */
> -    if (!pcms->acpi_dev || !acpi_enabled) {
> +    if (!conf->acpi_dev || !acpi_enabled) {
>           error_setg(errp,
>                      "memory hotplug is not enabled: missing acpi device or acpi disabled");
>           return;
>       }
>   
> -    if (is_nvdimm && !pcms->acpi_nvdimm_state.is_enabled) {
> +    if (is_nvdimm && !conf->acpi_nvdimm_state.is_enabled) {
>           error_setg(errp, "nvdimm is not enabled: missing 'nvdimm' in '-M'");
>           return;
>       }
> @@ -1715,6 +1744,7 @@ static void pc_memory_plug(HotplugHandler *hotplug_dev,
>       Error *local_err = NULL;
>       PCMachineState *pcms = PC_MACHINE(hotplug_dev);
>       bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>   
>       pc_dimm_plug(PC_DIMM(dev), MACHINE(pcms), &local_err);
>       if (local_err) {
> @@ -1722,11 +1752,11 @@ static void pc_memory_plug(HotplugHandler *hotplug_dev,
>       }
>   
>       if (is_nvdimm) {
> -        nvdimm_plug(&pcms->acpi_nvdimm_state);
> +        nvdimm_plug(&conf->acpi_nvdimm_state);
>       }
>   
> -    hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
> -    hhc->plug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &error_abort);
> +    hhc = HOTPLUG_HANDLER_GET_CLASS(conf->acpi_dev);
> +    hhc->plug(HOTPLUG_HANDLER(conf->acpi_dev), dev, &error_abort);
>   out:
>       error_propagate(errp, local_err);
>   }
> @@ -1737,13 +1767,14 @@ static void pc_memory_unplug_request(HotplugHandler *hotplug_dev,
>       HotplugHandlerClass *hhc;
>       Error *local_err = NULL;
>       PCMachineState *pcms = PC_MACHINE(hotplug_dev);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>   
>       /*
>        * When -no-acpi is used with Q35 machine type, no ACPI is built,
> -     * but pcms->acpi_dev is still created. Check !acpi_enabled in
> +     * but acpi_dev is still created. Check !acpi_enabled in
>        * addition to cover this case.
>        */
> -    if (!pcms->acpi_dev || !acpi_enabled) {
> +    if (!conf->acpi_dev || !acpi_enabled) {
>           error_setg(&local_err,
>                      "memory hotplug is not enabled: missing acpi device or acpi disabled");
>           goto out;
> @@ -1755,8 +1786,8 @@ static void pc_memory_unplug_request(HotplugHandler *hotplug_dev,
>           goto out;
>       }
>   
> -    hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
> -    hhc->unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
> +    hhc = HOTPLUG_HANDLER_GET_CLASS(conf->acpi_dev);
> +    hhc->unplug_request(HOTPLUG_HANDLER(conf->acpi_dev), dev, &local_err);
>   
>   out:
>       error_propagate(errp, local_err);
> @@ -1766,11 +1797,12 @@ static void pc_memory_unplug(HotplugHandler *hotplug_dev,
>                                DeviceState *dev, Error **errp)
>   {
>       PCMachineState *pcms = PC_MACHINE(hotplug_dev);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>       HotplugHandlerClass *hhc;
>       Error *local_err = NULL;
>   
> -    hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
> -    hhc->unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
> +    hhc = HOTPLUG_HANDLER_GET_CLASS(conf->acpi_dev);
> +    hhc->unplug(HOTPLUG_HANDLER(conf->acpi_dev), dev, &local_err);
>   
>       if (local_err) {
>           goto out;
> @@ -1817,10 +1849,11 @@ static void pc_cpu_plug(HotplugHandler *hotplug_dev,
>       Error *local_err = NULL;
>       X86CPU *cpu = X86_CPU(dev);
>       PCMachineState *pcms = PC_MACHINE(hotplug_dev);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>   
> -    if (pcms->acpi_dev) {
> -        hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
> -        hhc->plug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
> +    if (conf->acpi_dev) {
> +        hhc = HOTPLUG_HANDLER_GET_CLASS(conf->acpi_dev);
> +        hhc->plug(HOTPLUG_HANDLER(conf->acpi_dev), dev, &local_err);
>           if (local_err) {
>               goto out;
>           }
> @@ -1831,8 +1864,8 @@ static void pc_cpu_plug(HotplugHandler *hotplug_dev,
>       if (pcms->rtc) {
>           rtc_set_cpus_count(pcms->rtc, pcms->boot_cpus);
>       }
> -    if (pcms->fw_cfg) {
> -        fw_cfg_modify_i16(pcms->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
> +    if (conf->fw_cfg) {
> +        fw_cfg_modify_i16(conf->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
>       }
>   
>       found_cpu = pc_find_cpu_slot(MACHINE(pcms), cpu->apic_id, NULL);
> @@ -1848,8 +1881,9 @@ static void pc_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
>       Error *local_err = NULL;
>       X86CPU *cpu = X86_CPU(dev);
>       PCMachineState *pcms = PC_MACHINE(hotplug_dev);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>   
> -    if (!pcms->acpi_dev) {
> +    if (!conf->acpi_dev) {
>           error_setg(&local_err, "CPU hot unplug not supported without ACPI");
>           goto out;
>       }
> @@ -1861,8 +1895,8 @@ static void pc_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
>           goto out;
>       }
>   
> -    hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
> -    hhc->unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
> +    hhc = HOTPLUG_HANDLER_GET_CLASS(conf->acpi_dev);
> +    hhc->unplug_request(HOTPLUG_HANDLER(conf->acpi_dev), dev, &local_err);
>   
>       if (local_err) {
>           goto out;
> @@ -1881,9 +1915,10 @@ static void pc_cpu_unplug_cb(HotplugHandler *hotplug_dev,
>       Error *local_err = NULL;
>       X86CPU *cpu = X86_CPU(dev);
>       PCMachineState *pcms = PC_MACHINE(hotplug_dev);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>   
> -    hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
> -    hhc->unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
> +    hhc = HOTPLUG_HANDLER_GET_CLASS(conf->acpi_dev);
> +    hhc->unplug(HOTPLUG_HANDLER(conf->acpi_dev), dev, &local_err);
>   
>       if (local_err) {
>           goto out;
> @@ -1897,7 +1932,7 @@ static void pc_cpu_unplug_cb(HotplugHandler *hotplug_dev,
>       pcms->boot_cpus--;
>       /* Update the number of CPUs in CMOS */
>       rtc_set_cpus_count(pcms->rtc, pcms->boot_cpus);
> -    fw_cfg_modify_i16(pcms->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
> +    fw_cfg_modify_i16(conf->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
>    out:
>       error_propagate(errp, local_err);
>   }
> @@ -2181,28 +2216,30 @@ static bool pc_machine_get_nvdimm(Object *obj, Error **errp)
>   {
>       PCMachineState *pcms = PC_MACHINE(obj);
>   
> -    return pcms->acpi_nvdimm_state.is_enabled;
> +    return pcms->acpi_configuration.acpi_nvdimm_state.is_enabled;
>   }
>   
>   static void pc_machine_set_nvdimm(Object *obj, bool value, Error **errp)
>   {
>       PCMachineState *pcms = PC_MACHINE(obj);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>   
> -    pcms->acpi_nvdimm_state.is_enabled = value;
> +    conf->acpi_nvdimm_state.is_enabled = value;
>   }
>   
>   static char *pc_machine_get_nvdimm_persistence(Object *obj, Error **errp)
>   {
>       PCMachineState *pcms = PC_MACHINE(obj);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>   
> -    return g_strdup(pcms->acpi_nvdimm_state.persistence_string);
> +    return g_strdup(conf->acpi_nvdimm_state.persistence_string);
>   }
>   
>   static void pc_machine_set_nvdimm_persistence(Object *obj, const char *value,
>                                                  Error **errp)
>   {
>       PCMachineState *pcms = PC_MACHINE(obj);
> -    AcpiNVDIMMState *nvdimm_state = &pcms->acpi_nvdimm_state;
> +    AcpiNVDIMMState *nvdimm_state = &pcms->acpi_configuration.acpi_nvdimm_state;
>   
>       if (strcmp(value, "cpu") == 0)
>           nvdimm_state->persistence = 3;
> @@ -2268,7 +2305,7 @@ static void pc_machine_initfn(Object *obj)
>       pcms->smm = ON_OFF_AUTO_AUTO;
>       pcms->vmport = ON_OFF_AUTO_AUTO;
>       /* nvdimm is disabled on default. */
> -    pcms->acpi_nvdimm_state.is_enabled = false;
> +    pcms->acpi_configuration.acpi_nvdimm_state.is_enabled = false;
>       /* acpi build is enabled by default if machine supports it */
>       pcms->acpi_build_enabled = PC_MACHINE_GET_CLASS(pcms)->has_acpi_build;
>       pcms->smbus = true;
> diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
> index dc09466b3e..1d10374dfa 100644
> --- a/hw/i386/pc_piix.c
> +++ b/hw/i386/pc_piix.c
> @@ -71,6 +71,7 @@ static void pc_init1(MachineState *machine,
>   {
>       PCMachineState *pcms = PC_MACHINE(machine);
>       PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>       MemoryRegion *system_memory = get_system_memory();
>       MemoryRegion *system_io = get_system_io();
>       int i;
> @@ -142,11 +143,11 @@ static void pc_init1(MachineState *machine,
>           }
>   
>           if (machine->ram_size >= lowmem) {
> -            pcms->above_4g_mem_size = machine->ram_size - lowmem;
> -            pcms->below_4g_mem_size = lowmem;
> +            conf->above_4g_mem_size = machine->ram_size - lowmem;
> +            conf->below_4g_mem_size = lowmem;
>           } else {
> -            pcms->above_4g_mem_size = 0;
> -            pcms->below_4g_mem_size = machine->ram_size;
> +            conf->above_4g_mem_size = 0;
> +            conf->below_4g_mem_size = machine->ram_size;
>           }
>       }
>   
> @@ -199,8 +200,8 @@ static void pc_init1(MachineState *machine,
>                                 pci_type,
>                                 &i440fx_state, &piix3_devfn, &isa_bus, pcms->gsi,
>                                 system_memory, system_io, machine->ram_size,
> -                              pcms->below_4g_mem_size,
> -                              pcms->above_4g_mem_size,
> +                              conf->below_4g_mem_size,
> +                              conf->above_4g_mem_size,
>                                 pci_memory, ram_memory);
>           pcms->bus = pci_bus;
>       } else {
> @@ -289,16 +290,16 @@ static void pc_init1(MachineState *machine,
>   
>           object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP,
>                                    TYPE_HOTPLUG_HANDLER,
> -                                 (Object **)&pcms->acpi_dev,
> +                                 (Object **)&conf->acpi_dev,
>                                    object_property_allow_set_link,
>                                    OBJ_PROP_LINK_STRONG, &error_abort);
>           object_property_set_link(OBJECT(machine), OBJECT(piix4_pm),
>                                    PC_MACHINE_ACPI_DEVICE_PROP, &error_abort);
>       }
>   
> -    if (pcms->acpi_nvdimm_state.is_enabled) {
> -        nvdimm_init_acpi_state(&pcms->acpi_nvdimm_state, system_io,
> -                               pcms->fw_cfg, OBJECT(pcms));
> +    if (conf->acpi_nvdimm_state.is_enabled) {
> +        nvdimm_init_acpi_state(&conf->acpi_nvdimm_state, system_io,
> +                               conf->fw_cfg, OBJECT(pcms));
>       }
>   }
>   
> diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
> index 532241e3f8..fb5c89bf7c 100644
> --- a/hw/i386/pc_q35.c
> +++ b/hw/i386/pc_q35.c
> @@ -63,6 +63,7 @@ static void pc_q35_init(MachineState *machine)
>   {
>       PCMachineState *pcms = PC_MACHINE(machine);
>       PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>       Q35PCIHost *q35_host;
>       PCIHostState *phb;
>       PCIBus *host_bus;
> @@ -116,11 +117,11 @@ static void pc_q35_init(MachineState *machine)
>       }
>   
>       if (machine->ram_size >= lowmem) {
> -        pcms->above_4g_mem_size = machine->ram_size - lowmem;
> -        pcms->below_4g_mem_size = lowmem;
> +        conf->above_4g_mem_size = machine->ram_size - lowmem;
> +        conf->below_4g_mem_size = lowmem;
>       } else {
> -        pcms->above_4g_mem_size = 0;
> -        pcms->below_4g_mem_size = machine->ram_size;
> +        conf->above_4g_mem_size = 0;
> +        conf->below_4g_mem_size = machine->ram_size;
>       }
>   
>       if (xen_enabled()) {
> @@ -179,9 +180,9 @@ static void pc_q35_init(MachineState *machine)
>                                MCH_HOST_PROP_SYSTEM_MEM, NULL);
>       object_property_set_link(OBJECT(q35_host), OBJECT(system_io),
>                                MCH_HOST_PROP_IO_MEM, NULL);
> -    object_property_set_int(OBJECT(q35_host), pcms->below_4g_mem_size,
> +    object_property_set_int(OBJECT(q35_host), conf->below_4g_mem_size,
>                               PCI_HOST_BELOW_4G_MEM_SIZE, NULL);
> -    object_property_set_int(OBJECT(q35_host), pcms->above_4g_mem_size,
> +    object_property_set_int(OBJECT(q35_host), conf->above_4g_mem_size,
>                               PCI_HOST_ABOVE_4G_MEM_SIZE, NULL);
>       /* pci */
>       qdev_init_nofail(DEVICE(q35_host));
> @@ -194,7 +195,7 @@ static void pc_q35_init(MachineState *machine)
>   
>       object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP,
>                                TYPE_HOTPLUG_HANDLER,
> -                             (Object **)&pcms->acpi_dev,
> +                             (Object **)&conf->acpi_dev,
>                                object_property_allow_set_link,
>                                OBJ_PROP_LINK_STRONG, &error_abort);
>       object_property_set_link(OBJECT(machine), OBJECT(lpc),
> @@ -276,9 +277,9 @@ static void pc_q35_init(MachineState *machine)
>       pc_vga_init(isa_bus, host_bus);
>       pc_nic_init(pcmc, isa_bus, host_bus);
>   
> -    if (pcms->acpi_nvdimm_state.is_enabled) {
> -        nvdimm_init_acpi_state(&pcms->acpi_nvdimm_state, system_io,
> -                               pcms->fw_cfg, OBJECT(pcms));
> +    if (conf->acpi_nvdimm_state.is_enabled) {
> +        nvdimm_init_acpi_state(&conf->acpi_nvdimm_state, system_io,
> +                               conf->fw_cfg, OBJECT(pcms));
>       }
>   }
>   
> diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
> index 935a3676c8..4ad5b10d64 100644
> --- a/hw/i386/xen/xen-hvm.c
> +++ b/hw/i386/xen/xen-hvm.c
> @@ -190,6 +190,7 @@ qemu_irq *xen_interrupt_controller_init(void)
>   static void xen_ram_init(PCMachineState *pcms,
>                            ram_addr_t ram_size, MemoryRegion **ram_memory_p)
>   {
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>       MemoryRegion *sysmem = get_system_memory();
>       ram_addr_t block_len;
>       uint64_t user_lowmem = object_property_get_uint(qdev_get_machine(),
> @@ -207,20 +208,20 @@ static void xen_ram_init(PCMachineState *pcms,
>       }
>   
>       if (ram_size >= user_lowmem) {
> -        pcms->above_4g_mem_size = ram_size - user_lowmem;
> -        pcms->below_4g_mem_size = user_lowmem;
> +        conf->above_4g_mem_size = ram_size - user_lowmem;
> +        conf->below_4g_mem_size = user_lowmem;
>       } else {
> -        pcms->above_4g_mem_size = 0;
> -        pcms->below_4g_mem_size = ram_size;
> +        conf->above_4g_mem_size = 0;
> +        conf->below_4g_mem_size = ram_size;
>       }
> -    if (!pcms->above_4g_mem_size) {
> +    if (!conf->above_4g_mem_size) {
>           block_len = ram_size;
>       } else {
>           /*
>            * Xen does not allocate the memory continuously, it keeps a
>            * hole of the size computed above or passed in.
>            */
> -        block_len = (1ULL << 32) + pcms->above_4g_mem_size;
> +        block_len = (1ULL << 32) + conf->above_4g_mem_size;
>       }
>       memory_region_init_ram(&ram_memory, NULL, "xen.ram", block_len,
>                              &error_fatal);
> @@ -237,12 +238,12 @@ static void xen_ram_init(PCMachineState *pcms,
>        */
>       memory_region_init_alias(&ram_lo, NULL, "xen.ram.lo",
>                                &ram_memory, 0xc0000,
> -                             pcms->below_4g_mem_size - 0xc0000);
> +                             conf->below_4g_mem_size - 0xc0000);
>       memory_region_add_subregion(sysmem, 0xc0000, &ram_lo);
> -    if (pcms->above_4g_mem_size > 0) {
> +    if (conf->above_4g_mem_size > 0) {
>           memory_region_init_alias(&ram_hi, NULL, "xen.ram.hi",
>                                    &ram_memory, 0x100000000ULL,
> -                                 pcms->above_4g_mem_size);
> +                                 conf->above_4g_mem_size);
>           memory_region_add_subregion(sysmem, 0x100000000ULL, &ram_hi);
>       }
>   }
> diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h
> index c20ace0d0b..6a94452928 100644
> --- a/include/hw/acpi/acpi.h
> +++ b/include/hw/acpi/acpi.h
> @@ -24,6 +24,8 @@
>   #include "exec/memory.h"
>   #include "hw/irq.h"
>   #include "hw/acpi/acpi_dev_interface.h"
> +#include "hw/hotplug.h"
> +#include "hw/mem/nvdimm.h"
>   
>   /*
>    * current device naming scheme supports up to 256 memory devices
> @@ -186,6 +188,47 @@ extern int acpi_enabled;
>   extern char unsigned *acpi_tables;
>   extern size_t acpi_tables_len;
>   
> +typedef
> +struct AcpiBuildState {
> +    /* Copy of table in RAM (for patching). */
> +    MemoryRegion *table_mr;
> +    /* Is table patched? */
> +    bool patched;
> +    void *rsdp;
> +    MemoryRegion *rsdp_mr;
> +    MemoryRegion *linker_mr;
> +} AcpiBuildState;
> +
> +typedef
> +struct AcpiConfiguration {
> +    /* Machine class ACPI settings */
> +    int legacy_acpi_table_size;
> +    bool rsdp_in_ram;
> +    unsigned acpi_data_size;
> +
> +    /* Machine state ACPI settings */
> +    HotplugHandler *acpi_dev;
> +    AcpiNVDIMMState acpi_nvdimm_state;
> +
> +    /*
> +     * The fields below are machine settings that
> +     * are not ACPI specific. However they are needed
> +     * for building ACPI tables and as such should be
> +     * carried through the ACPI configuration structure.
> +     */
> +    bool legacy_cpu_hotplug;
> +    bool linuxboot_dma_enabled;
> +    FWCfgState *fw_cfg;
> +    ram_addr_t below_4g_mem_size, above_4g_mem_size;;
> +    uint64_t numa_nodes;
> +    uint64_t *node_mem;
> +    bool apic_xrupt_override;
> +    unsigned apic_id_limit;
> +
> +    /* Build state */
> +    AcpiBuildState *build_state;
> +} AcpiConfiguration;
> +
>   uint8_t *acpi_table_first(void);
>   uint8_t *acpi_table_next(uint8_t *current);
>   unsigned acpi_table_len(void *current);
> diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
> index dfe6746692..da0bd39741 100644
> --- a/include/hw/i386/pc.h
> +++ b/include/hw/i386/pc.h
> @@ -12,6 +12,7 @@
>   #include "qemu/range.h"
>   #include "qemu/bitmap.h"
>   #include "sysemu/sysemu.h"
> +#include "hw/acpi/acpi.h"
>   #include "hw/pci/pci.h"
>   #include "hw/compat.h"
>   #include "hw/mem/pc-dimm.h"
> @@ -35,10 +36,8 @@ struct PCMachineState {
>       Notifier machine_done;
>   
>       /* Pointers to devices and objects: */
> -    HotplugHandler *acpi_dev;
>       ISADevice *rtc;
>       PCIBus *bus;
> -    FWCfgState *fw_cfg;
>       qemu_irq *gsi;
>   
>       /* Configuration options: */
> @@ -46,28 +45,20 @@ struct PCMachineState {
>       OnOffAuto vmport;
>       OnOffAuto smm;
>   
> -    AcpiNVDIMMState acpi_nvdimm_state;
> -
>       bool acpi_build_enabled;
>       bool smbus;
>       bool sata;
>       bool pit;
>   
> -    /* RAM information (sizes, addresses, configuration): */
> -    ram_addr_t below_4g_mem_size, above_4g_mem_size;
> -
> -    /* CPU and apic information: */
> -    bool apic_xrupt_override;
> -    unsigned apic_id_limit;
> +    /* CPU information */
>       uint16_t boot_cpus;
>   
> -    /* NUMA information: */
> -    uint64_t numa_nodes;
> -    uint64_t *node_mem;
> -
>       /* Address space used by IOAPIC device. All IOAPIC interrupts
>        * will be translated to MSI messages in the address space. */
>       AddressSpace *ioapic_as;
> +
> +    /* ACPI configuration */
> +    AcpiConfiguration acpi_configuration;

This one is fine although.

>   };
>   
>   #define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device"
> 

Thanks,

Phil.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 01/19] hw: i386: Decouple the ACPI build from the PC machine type
@ 2018-10-29 19:50     ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 47+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-10-29 19:50 UTC (permalink / raw)
  To: Samuel Ortiz, qemu-devel
  Cc: Peter Maydell, Stefano Stabellini, Eduardo Habkost,
	Michael S. Tsirkin, Shannon Zhao, Igor Mammedov,
	open list:ARM ACPI Subsystem, Paolo Bonzini, Anthony Perard,
	open list:X86, Richard Henderson

Hi Samuel,

On 29/10/18 18:01, Samuel Ortiz wrote:
> ACPI tables are platform and machine type and even architecture
> agnostic, and as such we want to provide an internal ACPI API that
> only depends on platform agnostic information.
> 
> For the x86 architecture, in order to build ACPI tables independently
> from the PC or Q35 machine types, we are moving a few MachineState
> structure fields into a machine type agnostic structure called
> AcpiConfiguration. The structure fields we move are:
> 
>     HotplugHandler *acpi_dev
>     AcpiNVDIMMState acpi_nvdimm_state;
>     FWCfgState *fw_cfg
>     ram_addr_t below_4g_mem_size, above_4g_mem_size
>     bool apic_xrupt_override
>     unsigned apic_id_limit
>     uint64_t numa_nodes
>     uint64_t numa_mem
> 
> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
> ---
>   hw/acpi/cpu_hotplug.c    |   9 +-
>   hw/arm/virt-acpi-build.c |  10 ---
>   hw/i386/acpi-build.c     | 135 ++++++++++++++----------------
>   hw/i386/acpi-build.h     |   4 +-
>   hw/i386/pc.c             | 175 ++++++++++++++++++++++++---------------
>   hw/i386/pc_piix.c        |  21 ++---
>   hw/i386/pc_q35.c         |  21 ++---
>   hw/i386/xen/xen-hvm.c    |  19 +++--
>   include/hw/acpi/acpi.h   |  43 ++++++++++
>   include/hw/i386/pc.h     |  19 ++---
>   10 files changed, 254 insertions(+), 202 deletions(-)
> 
> diff --git a/hw/acpi/cpu_hotplug.c b/hw/acpi/cpu_hotplug.c
> index 5243918125..634dc3b846 100644
> --- a/hw/acpi/cpu_hotplug.c
> +++ b/hw/acpi/cpu_hotplug.c
> @@ -237,9 +237,9 @@ void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *machine,
>       /* The current AML generator can cover the APIC ID range [0..255],
>        * inclusive, for VCPU hotplug. */
>       QEMU_BUILD_BUG_ON(ACPI_CPU_HOTPLUG_ID_LIMIT > 256);
> -    if (pcms->apic_id_limit > ACPI_CPU_HOTPLUG_ID_LIMIT) {
> +    if (pcms->acpi_configuration.apic_id_limit > ACPI_CPU_HOTPLUG_ID_LIMIT) {
>           error_report("max_cpus is too large. APIC ID of last CPU is %u",
> -                     pcms->apic_id_limit - 1);
> +                     pcms->acpi_configuration.apic_id_limit - 1);
>           exit(1);
>       }
>   
> @@ -316,8 +316,9 @@ void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *machine,
>        * ith up to 255 elements. Windows guests up to win2k8 fail when
>        * VarPackageOp is used.
>        */
> -    pkg = pcms->apic_id_limit <= 255 ? aml_package(pcms->apic_id_limit) :
> -                                       aml_varpackage(pcms->apic_id_limit);
> +    pkg = pcms->acpi_configuration.apic_id_limit <= 255 ?
> +        aml_package(pcms->acpi_configuration.apic_id_limit) :
> +        aml_varpackage(pcms->acpi_configuration.apic_id_limit);
>   
>       for (i = 0, apic_idx = 0; i < apic_ids->len; i++) {
>           int apic_id = apic_ids->cpus[i].arch_id;
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index 5785fb697c..f28a2faa53 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -790,16 +790,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>       free_aml_allocator();
>   }
>   
> -typedef
> -struct AcpiBuildState {
> -    /* Copy of table in RAM (for patching). */
> -    MemoryRegion *table_mr;
> -    MemoryRegion *rsdp_mr;
> -    MemoryRegion *linker_mr;
> -    /* Is table patched? */
> -    bool patched;
> -} AcpiBuildState;
> -
>   static
>   void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
>   {
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 1599caa7c5..c8545238c4 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -338,13 +338,14 @@ void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
>   }
>   
>   static void
> -build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms)
> +build_madt(GArray *table_data, BIOSLinker *linker,
> +           MachineState *ms, AcpiConfiguration *conf)

Can you rename AcpiConfiguration *conf -> acpi_cfg/acpi_conf/acpi_config 
in the whole patch?

>   {
> -    MachineClass *mc = MACHINE_GET_CLASS(pcms);
> -    const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(pcms));
> +    MachineClass *mc = MACHINE_GET_CLASS(ms);
> +    const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(ms);
>       int madt_start = table_data->len;
> -    AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(pcms->acpi_dev);
> -    AcpiDeviceIf *adev = ACPI_DEVICE_IF(pcms->acpi_dev);
> +    AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(conf->acpi_dev);
> +    AcpiDeviceIf *adev = ACPI_DEVICE_IF(conf->acpi_dev);
>       bool x2apic_mode = false;
>   
>       AcpiMultipleApicTable *madt;
> @@ -370,7 +371,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms)
>       io_apic->address = cpu_to_le32(IO_APIC_DEFAULT_ADDRESS);
>       io_apic->interrupt = cpu_to_le32(0);
>   
> -    if (pcms->apic_xrupt_override) {
> +    if (conf->apic_xrupt_override) {
>           intsrcovr = acpi_data_push(table_data, sizeof *intsrcovr);
>           intsrcovr->type   = ACPI_APIC_XRUPT_OVERRIDE;
>           intsrcovr->length = sizeof(*intsrcovr);
> @@ -1786,13 +1787,12 @@ static Aml *build_q35_osc_method(void)
>   static void
>   build_dsdt(GArray *table_data, BIOSLinker *linker,
>              AcpiPmInfo *pm, AcpiMiscInfo *misc,
> -           Range *pci_hole, Range *pci_hole64, MachineState *machine)
> +           Range *pci_hole, Range *pci_hole64,
> +           MachineState *machine, AcpiConfiguration *conf)
>   {
>       CrsRangeEntry *entry;
>       Aml *dsdt, *sb_scope, *scope, *dev, *method, *field, *pkg, *crs;
>       CrsRangeSet crs_range_set;
> -    PCMachineState *pcms = PC_MACHINE(machine);
> -    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(machine);
>       uint32_t nr_mem = machine->ram_slots;
>       int root_bus_limit = 0xFF;
>       PCIBus *bus = NULL;
> @@ -1836,7 +1836,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
>           build_q35_pci0_int(dsdt);
>       }
>   
> -    if (pcmc->legacy_cpu_hotplug) {
> +    if (conf->legacy_cpu_hotplug) {
>           build_legacy_cpu_hotplug_aml(dsdt, machine, pm->cpu_hp_io_base);
>       } else {
>           CPUHotplugFeatures opts = {
> @@ -1860,7 +1860,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
>               aml_append(scope, method);
>           }
>   
> -        if (pcms->acpi_nvdimm_state.is_enabled) {
> +        if (conf->acpi_nvdimm_state.is_enabled) {
>               method = aml_method("_E04", 0, AML_NOTSERIALIZED);
>               aml_append(method, aml_notify(aml_name("\\_SB.NVDR"),
>                                             aml_int(0x80)));
> @@ -2041,7 +2041,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
>            * with half of the 16-bit control register. Hence, the total size
>            * of the i/o region used is FW_CFG_CTL_SIZE; when using DMA, the
>            * DMA control register is located at FW_CFG_DMA_IO_BASE + 4 */
> -        uint8_t io_size = object_property_get_bool(OBJECT(pcms->fw_cfg),
> +        uint8_t io_size = object_property_get_bool(OBJECT(conf->fw_cfg),
>                                                      "dma_enabled", NULL) ?
>                             ROUND_UP(FW_CFG_CTL_SIZE, 4) + sizeof(dma_addr_t) :
>                             FW_CFG_CTL_SIZE;
> @@ -2252,7 +2252,8 @@ build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog)
>   #define HOLE_640K_END   (1 * MiB)
>   
>   static void
> -build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
> +build_srat(GArray *table_data, BIOSLinker *linker,
> +           MachineState *machine, AcpiConfiguration *conf)
>   {
>       AcpiSystemResourceAffinityTable *srat;
>       AcpiSratMemoryAffinity *numamem;
> @@ -2262,9 +2263,8 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
>       uint64_t mem_len, mem_base, next_base;
>       MachineClass *mc = MACHINE_GET_CLASS(machine);
>       const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(machine);
> -    PCMachineState *pcms = PC_MACHINE(machine);
>       ram_addr_t hotplugabble_address_space_size =
> -        object_property_get_int(OBJECT(pcms), PC_MACHINE_DEVMEM_REGION_SIZE,
> +        object_property_get_int(OBJECT(machine), PC_MACHINE_DEVMEM_REGION_SIZE,
>                                   NULL);
>   
>       srat_start = table_data->len;
> @@ -2306,9 +2306,9 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
>       next_base = 0;
>       numa_start = table_data->len;
>   
> -    for (i = 1; i < pcms->numa_nodes + 1; ++i) {
> +    for (i = 1; i < conf->numa_nodes + 1; ++i) {
>           mem_base = next_base;
> -        mem_len = pcms->node_mem[i - 1];
> +        mem_len = conf->node_mem[i - 1];
>           next_base = mem_base + mem_len;
>   
>           /* Cut out the 640K hole */
> @@ -2331,16 +2331,16 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
>           }
>   
>           /* Cut out the ACPI_PCI hole */
> -        if (mem_base <= pcms->below_4g_mem_size &&
> -            next_base > pcms->below_4g_mem_size) {
> -            mem_len -= next_base - pcms->below_4g_mem_size;
> +        if (mem_base <= conf->below_4g_mem_size &&
> +            next_base > conf->below_4g_mem_size) {
> +            mem_len -= next_base - conf->below_4g_mem_size;
>               if (mem_len > 0) {
>                   numamem = acpi_data_push(table_data, sizeof *numamem);
>                   build_srat_memory(numamem, mem_base, mem_len, i - 1,
>                                     MEM_AFFINITY_ENABLED);
>               }
>               mem_base = 1ULL << 32;
> -            mem_len = next_base - pcms->below_4g_mem_size;
> +            mem_len = next_base - conf->below_4g_mem_size;
>               next_base = mem_base + mem_len;
>           }
>   
> @@ -2351,7 +2351,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
>           }
>       }
>       slots = (table_data->len - numa_start) / sizeof *numamem;
> -    for (; slots < pcms->numa_nodes + 2; slots++) {
> +    for (; slots < conf->numa_nodes + 2; slots++) {
>           numamem = acpi_data_push(table_data, sizeof *numamem);
>           build_srat_memory(numamem, 0, 0, 0, MEM_AFFINITY_NOFLAGS);
>       }
> @@ -2367,7 +2367,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
>       if (hotplugabble_address_space_size) {
>           numamem = acpi_data_push(table_data, sizeof *numamem);
>           build_srat_memory(numamem, machine->device_memory->base,
> -                          hotplugabble_address_space_size, pcms->numa_nodes - 1,
> +                          hotplugabble_address_space_size, conf->numa_nodes - 1,
>                             MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
>       }
>   
> @@ -2546,17 +2546,6 @@ build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset)
>       return rsdp_table;
>   }
>   
> -typedef
> -struct AcpiBuildState {
> -    /* Copy of table in RAM (for patching). */
> -    MemoryRegion *table_mr;
> -    /* Is table patched? */
> -    uint8_t patched;
> -    void *rsdp;
> -    MemoryRegion *rsdp_mr;
> -    MemoryRegion *linker_mr;
> -} AcpiBuildState;
> -
>   static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
>   {
>       Object *pci_host;
> @@ -2580,10 +2569,9 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
>   }
>   
>   static
> -void acpi_build(AcpiBuildTables *tables, MachineState *machine)
> +void acpi_build(AcpiBuildTables *tables,
> +                MachineState *machine, AcpiConfiguration *conf)
>   {
> -    PCMachineState *pcms = PC_MACHINE(machine);
> -    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
>       GArray *table_offsets;
>       unsigned facs, dsdt, rsdt, fadt;
>       AcpiPmInfo pm;
> @@ -2621,7 +2609,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
>       /* DSDT is pointed to by FADT */
>       dsdt = tables_blob->len;
>       build_dsdt(tables_blob, tables->linker, &pm, &misc,
> -               &pci_hole, &pci_hole64, machine);
> +               &pci_hole, &pci_hole64, machine, conf);
>   
>       /* Count the size of the DSDT and SSDT, we will need it for legacy
>        * sizing of ACPI tables.
> @@ -2639,7 +2627,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
>       aml_len += tables_blob->len - fadt;
>   
>       acpi_add_table(table_offsets, tables_blob);
> -    build_madt(tables_blob, tables->linker, pcms);
> +    build_madt(tables_blob, tables->linker, machine, conf);
>   
>       vmgenid_dev = find_vmgenid_dev();
>       if (vmgenid_dev) {
> @@ -2661,9 +2649,9 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
>               build_tpm2(tables_blob, tables->linker, tables->tcpalog);
>           }
>       }
> -    if (pcms->numa_nodes) {
> +    if (conf->numa_nodes) {
>           acpi_add_table(table_offsets, tables_blob);
> -        build_srat(tables_blob, tables->linker, machine);
> +        build_srat(tables_blob, tables->linker, machine, conf);
>           if (have_numa_distance) {
>               acpi_add_table(table_offsets, tables_blob);
>               build_slit(tables_blob, tables->linker);
> @@ -2683,9 +2671,9 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
>               build_dmar_q35(tables_blob, tables->linker);
>           }
>       }
> -    if (pcms->acpi_nvdimm_state.is_enabled) {
> +    if (conf->acpi_nvdimm_state.is_enabled) {
>           nvdimm_build_acpi(table_offsets, tables_blob, tables->linker,
> -                          &pcms->acpi_nvdimm_state, machine->ram_slots);
> +                          &conf->acpi_nvdimm_state, machine->ram_slots);
>       }
>   
>       /* Add tables supplied by user (if any) */
> @@ -2721,13 +2709,13 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
>        *
>        * All this is for PIIX4, since QEMU 2.0 didn't support Q35 migration.
>        */
> -    if (pcmc->legacy_acpi_table_size) {
> +    if (conf->legacy_acpi_table_size) {
>           /* Subtracting aml_len gives the size of fixed tables.  Then add the
>            * size of the PIIX4 DSDT/SSDT in QEMU 2.0.
>            */
>           int legacy_aml_len =
> -            pcmc->legacy_acpi_table_size +
> -            ACPI_BUILD_LEGACY_CPU_AML_SIZE * pcms->apic_id_limit;
> +            conf->legacy_acpi_table_size +
> +            ACPI_BUILD_LEGACY_CPU_AML_SIZE * conf->apic_id_limit;
>           int legacy_table_size =
>               ROUND_UP(tables_blob->len - aml_len + legacy_aml_len,
>                        ACPI_BUILD_ALIGN_SIZE);
> @@ -2772,9 +2760,17 @@ static void acpi_ram_update(MemoryRegion *mr, GArray *data)
>   
>   static void acpi_build_update(void *build_opaque)
>   {
> -    AcpiBuildState *build_state = build_opaque;
> +    AcpiConfiguration *conf = build_opaque;
> +    AcpiBuildState *build_state;
>       AcpiBuildTables tables;
>   
> +    /* No ACPI configuration? Nothing to do. */
> +    if (!conf) {
> +        return;
> +    }
> +
> +    build_state = conf->build_state;
> +
>       /* No state to update or already patched? Nothing to do. */
>       if (!build_state || build_state->patched) {
>           return;
> @@ -2783,7 +2779,7 @@ static void acpi_build_update(void *build_opaque)
>   
>       acpi_build_tables_init(&tables);
>   
> -    acpi_build(&tables, MACHINE(qdev_get_machine()));
> +    acpi_build(&tables, MACHINE(qdev_get_machine()), conf);
>   
>       acpi_ram_update(build_state->table_mr, tables.table_data);
>   
> @@ -2803,12 +2799,12 @@ static void acpi_build_reset(void *build_opaque)
>       build_state->patched = 0;
>   }
>   
> -static MemoryRegion *acpi_add_rom_blob(AcpiBuildState *build_state,
> +static MemoryRegion *acpi_add_rom_blob(AcpiConfiguration *conf,
>                                          GArray *blob, const char *name,
>                                          uint64_t max_size)
>   {
>       return rom_add_blob(name, blob->data, acpi_data_len(blob), max_size, -1,
> -                        name, acpi_build_update, build_state, NULL, true);
> +                        name, acpi_build_update, conf, NULL, true);
>   }
>   
>   static const VMStateDescription vmstate_acpi_build = {
> @@ -2816,59 +2812,48 @@ static const VMStateDescription vmstate_acpi_build = {
>       .version_id = 1,
>       .minimum_version_id = 1,
>       .fields = (VMStateField[]) {
> -        VMSTATE_UINT8(patched, AcpiBuildState),
> +        VMSTATE_BOOL(patched, AcpiBuildState),
>           VMSTATE_END_OF_LIST()
>       },
>   };
>   
> -void acpi_setup(void)
> +void acpi_setup(MachineState *machine, AcpiConfiguration *conf)
>   {
> -    PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
> -    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
>       AcpiBuildTables tables;
>       AcpiBuildState *build_state;
>       Object *vmgenid_dev;
>   
> -    if (!pcms->fw_cfg) {
> -        ACPI_BUILD_DPRINTF("No fw cfg. Bailing out.\n");
> -        return;
> -    }
> -
> -    if (!pcms->acpi_build_enabled) {
> -        ACPI_BUILD_DPRINTF("ACPI build disabled. Bailing out.\n");
> -        return;
> -    }
> -
> -    if (!acpi_enabled) {
> -        ACPI_BUILD_DPRINTF("ACPI disabled. Bailing out.\n");
> +    if (!conf) {
> +        ACPI_BUILD_DPRINTF("No ACPI config. Bailing out.\n");
>           return;
>       }
>   
>       build_state = g_malloc0(sizeof *build_state);
> +    conf->build_state = build_state;
>   
>       acpi_build_tables_init(&tables);
> -    acpi_build(&tables, MACHINE(pcms));
> +    acpi_build(&tables, machine, conf);
>   
>       /* Now expose it all to Guest */
> -    build_state->table_mr = acpi_add_rom_blob(build_state, tables.table_data,
> +    build_state->table_mr = acpi_add_rom_blob(conf, tables.table_data,
>                                                  ACPI_BUILD_TABLE_FILE,
>                                                  ACPI_BUILD_TABLE_MAX_SIZE);
>       assert(build_state->table_mr != NULL);
>   
>       build_state->linker_mr =
> -        acpi_add_rom_blob(build_state, tables.linker->cmd_blob,
> +        acpi_add_rom_blob(conf, tables.linker->cmd_blob,
>                             "etc/table-loader", 0);
>   
> -    fw_cfg_add_file(pcms->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
> +    fw_cfg_add_file(conf->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
>                       tables.tcpalog->data, acpi_data_len(tables.tcpalog));
>   
>       vmgenid_dev = find_vmgenid_dev();
>       if (vmgenid_dev) {
> -        vmgenid_add_fw_cfg(VMGENID(vmgenid_dev), pcms->fw_cfg,
> +        vmgenid_add_fw_cfg(VMGENID(vmgenid_dev), conf->fw_cfg,
>                              tables.vmgenid);
>       }
>   
> -    if (!pcmc->rsdp_in_ram) {
> +    if (!conf->rsdp_in_ram) {
>           /*
>            * Keep for compatibility with old machine types.
>            * Though RSDP is small, its contents isn't immutable, so
> @@ -2877,13 +2862,13 @@ void acpi_setup(void)
>           uint32_t rsdp_size = acpi_data_len(tables.rsdp);
>   
>           build_state->rsdp = g_memdup(tables.rsdp->data, rsdp_size);
> -        fw_cfg_add_file_callback(pcms->fw_cfg, ACPI_BUILD_RSDP_FILE,
> -                                 acpi_build_update, NULL, build_state,
> +        fw_cfg_add_file_callback(conf->fw_cfg, ACPI_BUILD_RSDP_FILE,
> +                                 acpi_build_update, NULL, conf,
>                                    build_state->rsdp, rsdp_size, true);
>           build_state->rsdp_mr = NULL;
>       } else {
>           build_state->rsdp = NULL;
> -        build_state->rsdp_mr = acpi_add_rom_blob(build_state, tables.rsdp,
> +        build_state->rsdp_mr = acpi_add_rom_blob(conf, tables.rsdp,
>                                                     ACPI_BUILD_RSDP_FILE, 0);
>       }
>   
> diff --git a/hw/i386/acpi-build.h b/hw/i386/acpi-build.h
> index 007332e51c..1e6b5a7c2e 100644
> --- a/hw/i386/acpi-build.h
> +++ b/hw/i386/acpi-build.h
> @@ -2,6 +2,8 @@
>   #ifndef HW_I386_ACPI_BUILD_H
>   #define HW_I386_ACPI_BUILD_H
>   
> -void acpi_setup(void);
> +#include "hw/acpi/acpi.h"
> +
> +void acpi_setup(MachineState *machine, AcpiConfiguration *conf);
>   
>   #endif
> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> index f095725dba..bd4a77b856 100644
> --- a/hw/i386/pc.c
> +++ b/hw/i386/pc.c
> @@ -444,17 +444,18 @@ void pc_cmos_init(PCMachineState *pcms,
>   {
>       int val;
>       static pc_cmos_init_late_arg arg;
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>   
>       /* various important CMOS locations needed by PC/Bochs bios */
>   
>       /* memory size */
>       /* base memory (first MiB) */
> -    val = MIN(pcms->below_4g_mem_size / KiB, 640);
> +    val = MIN(conf->below_4g_mem_size / KiB, 640);
>       rtc_set_memory(s, 0x15, val);
>       rtc_set_memory(s, 0x16, val >> 8);
>       /* extended memory (next 64MiB) */
> -    if (pcms->below_4g_mem_size > 1 * MiB) {
> -        val = (pcms->below_4g_mem_size - 1 * MiB) / KiB;
> +    if (conf->below_4g_mem_size > 1 * MiB) {
> +        val = (conf->below_4g_mem_size - 1 * MiB) / KiB;
>       } else {
>           val = 0;
>       }
> @@ -465,8 +466,8 @@ void pc_cmos_init(PCMachineState *pcms,
>       rtc_set_memory(s, 0x30, val);
>       rtc_set_memory(s, 0x31, val >> 8);
>       /* memory between 16MiB and 4GiB */
> -    if (pcms->below_4g_mem_size > 16 * MiB) {
> -        val = (pcms->below_4g_mem_size - 16 * MiB) / (64 * KiB);
> +    if (conf->below_4g_mem_size > 16 * MiB) {
> +        val = (conf->below_4g_mem_size - 16 * MiB) / (64 * KiB);
>       } else {
>           val = 0;
>       }
> @@ -475,7 +476,7 @@ void pc_cmos_init(PCMachineState *pcms,
>       rtc_set_memory(s, 0x34, val);
>       rtc_set_memory(s, 0x35, val >> 8);
>       /* memory above 4GiB */
> -    val = pcms->above_4g_mem_size / 65536;
> +    val = conf->above_4g_mem_size / 65536;
>       rtc_set_memory(s, 0x5b, val);
>       rtc_set_memory(s, 0x5c, val >> 8);
>       rtc_set_memory(s, 0x5d, val >> 16);
> @@ -714,13 +715,14 @@ static void pc_build_smbios(PCMachineState *pcms)
>       unsigned i, array_count;
>       MachineState *ms = MACHINE(pcms);
>       X86CPU *cpu = X86_CPU(ms->possible_cpus->cpus[0].cpu);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>   
>       /* tell smbios about cpuid version and features */
>       smbios_set_cpuid(cpu->env.cpuid_version, cpu->env.features[FEAT_1_EDX]);
>   
>       smbios_tables = smbios_get_table_legacy(&smbios_tables_len);
>       if (smbios_tables) {
> -        fw_cfg_add_bytes(pcms->fw_cfg, FW_CFG_SMBIOS_ENTRIES,
> +        fw_cfg_add_bytes(conf->fw_cfg, FW_CFG_SMBIOS_ENTRIES,
>                            smbios_tables, smbios_tables_len);
>       }
>   
> @@ -741,9 +743,9 @@ static void pc_build_smbios(PCMachineState *pcms)
>       g_free(mem_array);
>   
>       if (smbios_anchor) {
> -        fw_cfg_add_file(pcms->fw_cfg, "etc/smbios/smbios-tables",
> +        fw_cfg_add_file(conf->fw_cfg, "etc/smbios/smbios-tables",
>                           smbios_tables, smbios_tables_len);
> -        fw_cfg_add_file(pcms->fw_cfg, "etc/smbios/smbios-anchor",
> +        fw_cfg_add_file(conf->fw_cfg, "etc/smbios/smbios-anchor",
>                           smbios_anchor, smbios_anchor_len);
>       }
>   }
> @@ -755,6 +757,7 @@ static FWCfgState *bochs_bios_init(AddressSpace *as, PCMachineState *pcms)
>       int i;
>       const CPUArchIdList *cpus;
>       MachineClass *mc = MACHINE_GET_CLASS(pcms);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>   
>       fw_cfg = fw_cfg_init_io_dma(FW_CFG_IO_BASE, FW_CFG_IO_BASE + 4, as);
>       fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
> @@ -771,7 +774,7 @@ static FWCfgState *bochs_bios_init(AddressSpace *as, PCMachineState *pcms)
>        * So for compatibility reasons with old BIOSes we are stuck with
>        * "etc/max-cpus" actually being apic_id_limit
>        */
> -    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)pcms->apic_id_limit);
> +    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)conf->apic_id_limit);
>       fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
>       fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES,
>                        acpi_tables, acpi_tables_len);
> @@ -787,20 +790,20 @@ static FWCfgState *bochs_bios_init(AddressSpace *as, PCMachineState *pcms)
>        * of nodes, one word for each VCPU->node and one word for each node to
>        * hold the amount of memory.
>        */
> -    numa_fw_cfg = g_new0(uint64_t, 1 + pcms->apic_id_limit + nb_numa_nodes);
> +    numa_fw_cfg = g_new0(uint64_t, 1 + conf->apic_id_limit + nb_numa_nodes);
>       numa_fw_cfg[0] = cpu_to_le64(nb_numa_nodes);
>       cpus = mc->possible_cpu_arch_ids(MACHINE(pcms));
>       for (i = 0; i < cpus->len; i++) {
>           unsigned int apic_id = cpus->cpus[i].arch_id;
> -        assert(apic_id < pcms->apic_id_limit);
> +        assert(apic_id < conf->apic_id_limit);
>           numa_fw_cfg[apic_id + 1] = cpu_to_le64(cpus->cpus[i].props.node_id);
>       }
>       for (i = 0; i < nb_numa_nodes; i++) {
> -        numa_fw_cfg[pcms->apic_id_limit + 1 + i] =
> +        numa_fw_cfg[conf->apic_id_limit + 1 + i] =
>               cpu_to_le64(numa_info[i].node_mem);
>       }
>       fw_cfg_add_bytes(fw_cfg, FW_CFG_NUMA, numa_fw_cfg,
> -                     (1 + pcms->apic_id_limit + nb_numa_nodes) *
> +                     (1 + conf->apic_id_limit + nb_numa_nodes) *
>                        sizeof(*numa_fw_cfg));
>   
>       return fw_cfg;
> @@ -848,6 +851,7 @@ static void load_linux(PCMachineState *pcms,
>       char *vmode;
>       MachineState *machine = MACHINE(pcms);
>       PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>       struct setup_data *setup_data;
>       const char *kernel_filename = machine->kernel_filename;
>       const char *initrd_filename = machine->initrd_filename;
> @@ -917,8 +921,8 @@ static void load_linux(PCMachineState *pcms,
>           initrd_max = 0x37ffffff;
>       }
>   
> -    if (initrd_max >= pcms->below_4g_mem_size - pcmc->acpi_data_size) {
> -        initrd_max = pcms->below_4g_mem_size - pcmc->acpi_data_size - 1;
> +    if (initrd_max >= conf->below_4g_mem_size - pcmc->acpi_data_size) {
> +        initrd_max = conf->below_4g_mem_size - pcmc->acpi_data_size - 1;
>       }
>   
>       fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_ADDR, cmdline_addr);
> @@ -1154,7 +1158,8 @@ void pc_cpus_init(PCMachineState *pcms)
>        *
>        * This is used for FW_CFG_MAX_CPUS. See comments on bochs_bios_init().
>        */
> -    pcms->apic_id_limit = x86_cpu_apic_id_from_index(max_cpus - 1) + 1;
> +    pcms->acpi_configuration.apic_id_limit =
> +        x86_cpu_apic_id_from_index(max_cpus - 1) + 1;
>       possible_cpus = mc->possible_cpu_arch_ids(ms);
>       for (i = 0; i < smp_cpus; i++) {
>           pc_new_cpu(possible_cpus->cpus[i].type, possible_cpus->cpus[i].arch_id,
> @@ -1188,7 +1193,8 @@ static void pc_build_feature_control_file(PCMachineState *pcms)
>   
>       val = g_malloc(sizeof(*val));
>       *val = cpu_to_le64(feature_control_bits | FEATURE_CONTROL_LOCKED);
> -    fw_cfg_add_file(pcms->fw_cfg, "etc/msr_feature_control", val, sizeof(*val));
> +    fw_cfg_add_file(pcms->acpi_configuration.fw_cfg,
> +                    "etc/msr_feature_control", val, sizeof(*val));
>   }
>   
>   static void rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count)
> @@ -1204,11 +1210,26 @@ static void rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count)
>       }
>   }
>   
> +static void acpi_conf_pc_init(PCMachineState *pcms)
> +{
> +    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
> +
> +    /* Machine class settings */
> +    conf->legacy_acpi_table_size = pcmc->legacy_acpi_table_size;
> +    conf->legacy_cpu_hotplug = pcmc->legacy_cpu_hotplug;
> +    conf->rsdp_in_ram = pcmc->rsdp_in_ram;
> +
> +    /* ACPI build state */
> +    conf->build_state = NULL;
> +}
> +
>   static
>   void pc_machine_done(Notifier *notifier, void *data)
>   {
>       PCMachineState *pcms = container_of(notifier,
>                                           PCMachineState, machine_done);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>       PCIBus *bus = pcms->bus;
>   
>       /* set the number of CPUs */
> @@ -1223,23 +1244,27 @@ void pc_machine_done(Notifier *notifier, void *data)
>                   extra_hosts++;
>               }
>           }
> -        if (extra_hosts && pcms->fw_cfg) {
> +        if (extra_hosts && conf->fw_cfg) {
>               uint64_t *val = g_malloc(sizeof(*val));
>               *val = cpu_to_le64(extra_hosts);
> -            fw_cfg_add_file(pcms->fw_cfg,
> +            fw_cfg_add_file(conf->fw_cfg,
>                       "etc/extra-pci-roots", val, sizeof(*val));
>           }
>       }
>   
> -    acpi_setup();
> -    if (pcms->fw_cfg) {
> +    if (pcms->acpi_build_enabled) {
> +        acpi_conf_pc_init(pcms);
> +        acpi_setup(MACHINE(pcms), conf);
> +    }
> +
> +    if (conf->fw_cfg) {
>           pc_build_smbios(pcms);
>           pc_build_feature_control_file(pcms);
>           /* update FW_CFG_NB_CPUS to account for -device added CPUs */
> -        fw_cfg_modify_i16(pcms->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
> +        fw_cfg_modify_i16(conf->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
>       }
>   
> -    if (pcms->apic_id_limit > 255 && !xen_enabled()) {
> +    if (conf->apic_id_limit > 255 && !xen_enabled()) {
>           IntelIOMMUState *iommu = INTEL_IOMMU_DEVICE(x86_iommu_get_default());
>   
>           if (!iommu || !iommu->x86_iommu.intr_supported ||
> @@ -1256,13 +1281,14 @@ void pc_machine_done(Notifier *notifier, void *data)
>   void pc_guest_info_init(PCMachineState *pcms)
>   {
>       int i;
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>   
> -    pcms->apic_xrupt_override = kvm_allows_irq0_override();
> -    pcms->numa_nodes = nb_numa_nodes;
> -    pcms->node_mem = g_malloc0(pcms->numa_nodes *
> -                                    sizeof *pcms->node_mem);
> +    conf->apic_xrupt_override = kvm_allows_irq0_override();
> +    conf->numa_nodes = nb_numa_nodes;
> +    conf->node_mem = g_malloc0(conf->numa_nodes *
> +                                    sizeof *conf->node_mem);
>       for (i = 0; i < nb_numa_nodes; i++) {
> -        pcms->node_mem[i] = numa_info[i].node_mem;
> +        conf->node_mem[i] = numa_info[i].node_mem;
>       }
>   
>       pcms->machine_done.notify = pc_machine_done;
> @@ -1323,7 +1349,7 @@ void xen_load_linux(PCMachineState *pcms)
>                  !strcmp(option_rom[i].name, "multiboot.bin"));
>           rom_add_option(option_rom[i].name, option_rom[i].bootindex);
>       }
> -    pcms->fw_cfg = fw_cfg;
> +    pcms->acpi_configuration.fw_cfg = fw_cfg;
>   }
>   
>   void pc_memory_init(PCMachineState *pcms,
> @@ -1337,9 +1363,10 @@ void pc_memory_init(PCMachineState *pcms,
>       FWCfgState *fw_cfg;
>       MachineState *machine = MACHINE(pcms);
>       PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>   
> -    assert(machine->ram_size == pcms->below_4g_mem_size +
> -                                pcms->above_4g_mem_size);
> +    assert(machine->ram_size == conf->below_4g_mem_size +
> +                                conf->above_4g_mem_size);
>   
>       linux_boot = (machine->kernel_filename != NULL);
>   
> @@ -1353,17 +1380,17 @@ void pc_memory_init(PCMachineState *pcms,
>       *ram_memory = ram;
>       ram_below_4g = g_malloc(sizeof(*ram_below_4g));
>       memory_region_init_alias(ram_below_4g, NULL, "ram-below-4g", ram,
> -                             0, pcms->below_4g_mem_size);
> +                             0, conf->below_4g_mem_size);
>       memory_region_add_subregion(system_memory, 0, ram_below_4g);
> -    e820_add_entry(0, pcms->below_4g_mem_size, E820_RAM);
> -    if (pcms->above_4g_mem_size > 0) {
> +    e820_add_entry(0, conf->below_4g_mem_size, E820_RAM);
> +    if (conf->above_4g_mem_size > 0) {
>           ram_above_4g = g_malloc(sizeof(*ram_above_4g));
>           memory_region_init_alias(ram_above_4g, NULL, "ram-above-4g", ram,
> -                                 pcms->below_4g_mem_size,
> -                                 pcms->above_4g_mem_size);
> +                                 conf->below_4g_mem_size,
> +                                 conf->above_4g_mem_size);
>           memory_region_add_subregion(system_memory, 0x100000000ULL,
>                                       ram_above_4g);
> -        e820_add_entry(0x100000000ULL, pcms->above_4g_mem_size, E820_RAM);
> +        e820_add_entry(0x100000000ULL, conf->above_4g_mem_size, E820_RAM);
>       }
>   
>       if (!pcmc->has_reserved_memory &&
> @@ -1398,7 +1425,7 @@ void pc_memory_init(PCMachineState *pcms,
>           }
>   
>           machine->device_memory->base =
> -            ROUND_UP(0x100000000ULL + pcms->above_4g_mem_size, 1 * GiB);
> +            ROUND_UP(0x100000000ULL + conf->above_4g_mem_size, 1 * GiB);
>   
>           if (pcmc->enforce_aligned_dimm) {
>               /* size device region assuming 1G page max alignment per slot */
> @@ -1455,7 +1482,7 @@ void pc_memory_init(PCMachineState *pcms,
>       for (i = 0; i < nb_option_roms; i++) {
>           rom_add_option(option_rom[i].name, option_rom[i].bootindex);
>       }
> -    pcms->fw_cfg = fw_cfg;
> +    conf->fw_cfg = fw_cfg;
>   
>       /* Init default IOAPIC address space */
>       pcms->ioapic_as = &address_space_memory;
> @@ -1478,7 +1505,8 @@ uint64_t pc_pci_hole64_start(void)
>               hole64_start += memory_region_size(&ms->device_memory->mr);
>           }
>       } else {
> -        hole64_start = 0x100000000ULL + pcms->above_4g_mem_size;
> +        hole64_start =
> +            0x100000000ULL + pcms->acpi_configuration.above_4g_mem_size;
>       }
>   
>       return ROUND_UP(hole64_start, 1 * GiB);
> @@ -1685,21 +1713,22 @@ static void pc_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
>   {
>       const PCMachineState *pcms = PC_MACHINE(hotplug_dev);
>       const PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
> +    const AcpiConfiguration *conf = &pcms->acpi_configuration;
>       const bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
>       const uint64_t legacy_align = TARGET_PAGE_SIZE;
>   
>       /*
>        * When -no-acpi is used with Q35 machine type, no ACPI is built,
> -     * but pcms->acpi_dev is still created. Check !acpi_enabled in
> +     * but acpi_dev is still created. Check !acpi_enabled in
>        * addition to cover this case.
>        */
> -    if (!pcms->acpi_dev || !acpi_enabled) {
> +    if (!conf->acpi_dev || !acpi_enabled) {
>           error_setg(errp,
>                      "memory hotplug is not enabled: missing acpi device or acpi disabled");
>           return;
>       }
>   
> -    if (is_nvdimm && !pcms->acpi_nvdimm_state.is_enabled) {
> +    if (is_nvdimm && !conf->acpi_nvdimm_state.is_enabled) {
>           error_setg(errp, "nvdimm is not enabled: missing 'nvdimm' in '-M'");
>           return;
>       }
> @@ -1715,6 +1744,7 @@ static void pc_memory_plug(HotplugHandler *hotplug_dev,
>       Error *local_err = NULL;
>       PCMachineState *pcms = PC_MACHINE(hotplug_dev);
>       bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>   
>       pc_dimm_plug(PC_DIMM(dev), MACHINE(pcms), &local_err);
>       if (local_err) {
> @@ -1722,11 +1752,11 @@ static void pc_memory_plug(HotplugHandler *hotplug_dev,
>       }
>   
>       if (is_nvdimm) {
> -        nvdimm_plug(&pcms->acpi_nvdimm_state);
> +        nvdimm_plug(&conf->acpi_nvdimm_state);
>       }
>   
> -    hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
> -    hhc->plug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &error_abort);
> +    hhc = HOTPLUG_HANDLER_GET_CLASS(conf->acpi_dev);
> +    hhc->plug(HOTPLUG_HANDLER(conf->acpi_dev), dev, &error_abort);
>   out:
>       error_propagate(errp, local_err);
>   }
> @@ -1737,13 +1767,14 @@ static void pc_memory_unplug_request(HotplugHandler *hotplug_dev,
>       HotplugHandlerClass *hhc;
>       Error *local_err = NULL;
>       PCMachineState *pcms = PC_MACHINE(hotplug_dev);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>   
>       /*
>        * When -no-acpi is used with Q35 machine type, no ACPI is built,
> -     * but pcms->acpi_dev is still created. Check !acpi_enabled in
> +     * but acpi_dev is still created. Check !acpi_enabled in
>        * addition to cover this case.
>        */
> -    if (!pcms->acpi_dev || !acpi_enabled) {
> +    if (!conf->acpi_dev || !acpi_enabled) {
>           error_setg(&local_err,
>                      "memory hotplug is not enabled: missing acpi device or acpi disabled");
>           goto out;
> @@ -1755,8 +1786,8 @@ static void pc_memory_unplug_request(HotplugHandler *hotplug_dev,
>           goto out;
>       }
>   
> -    hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
> -    hhc->unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
> +    hhc = HOTPLUG_HANDLER_GET_CLASS(conf->acpi_dev);
> +    hhc->unplug_request(HOTPLUG_HANDLER(conf->acpi_dev), dev, &local_err);
>   
>   out:
>       error_propagate(errp, local_err);
> @@ -1766,11 +1797,12 @@ static void pc_memory_unplug(HotplugHandler *hotplug_dev,
>                                DeviceState *dev, Error **errp)
>   {
>       PCMachineState *pcms = PC_MACHINE(hotplug_dev);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>       HotplugHandlerClass *hhc;
>       Error *local_err = NULL;
>   
> -    hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
> -    hhc->unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
> +    hhc = HOTPLUG_HANDLER_GET_CLASS(conf->acpi_dev);
> +    hhc->unplug(HOTPLUG_HANDLER(conf->acpi_dev), dev, &local_err);
>   
>       if (local_err) {
>           goto out;
> @@ -1817,10 +1849,11 @@ static void pc_cpu_plug(HotplugHandler *hotplug_dev,
>       Error *local_err = NULL;
>       X86CPU *cpu = X86_CPU(dev);
>       PCMachineState *pcms = PC_MACHINE(hotplug_dev);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>   
> -    if (pcms->acpi_dev) {
> -        hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
> -        hhc->plug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
> +    if (conf->acpi_dev) {
> +        hhc = HOTPLUG_HANDLER_GET_CLASS(conf->acpi_dev);
> +        hhc->plug(HOTPLUG_HANDLER(conf->acpi_dev), dev, &local_err);
>           if (local_err) {
>               goto out;
>           }
> @@ -1831,8 +1864,8 @@ static void pc_cpu_plug(HotplugHandler *hotplug_dev,
>       if (pcms->rtc) {
>           rtc_set_cpus_count(pcms->rtc, pcms->boot_cpus);
>       }
> -    if (pcms->fw_cfg) {
> -        fw_cfg_modify_i16(pcms->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
> +    if (conf->fw_cfg) {
> +        fw_cfg_modify_i16(conf->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
>       }
>   
>       found_cpu = pc_find_cpu_slot(MACHINE(pcms), cpu->apic_id, NULL);
> @@ -1848,8 +1881,9 @@ static void pc_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
>       Error *local_err = NULL;
>       X86CPU *cpu = X86_CPU(dev);
>       PCMachineState *pcms = PC_MACHINE(hotplug_dev);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>   
> -    if (!pcms->acpi_dev) {
> +    if (!conf->acpi_dev) {
>           error_setg(&local_err, "CPU hot unplug not supported without ACPI");
>           goto out;
>       }
> @@ -1861,8 +1895,8 @@ static void pc_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
>           goto out;
>       }
>   
> -    hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
> -    hhc->unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
> +    hhc = HOTPLUG_HANDLER_GET_CLASS(conf->acpi_dev);
> +    hhc->unplug_request(HOTPLUG_HANDLER(conf->acpi_dev), dev, &local_err);
>   
>       if (local_err) {
>           goto out;
> @@ -1881,9 +1915,10 @@ static void pc_cpu_unplug_cb(HotplugHandler *hotplug_dev,
>       Error *local_err = NULL;
>       X86CPU *cpu = X86_CPU(dev);
>       PCMachineState *pcms = PC_MACHINE(hotplug_dev);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>   
> -    hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
> -    hhc->unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
> +    hhc = HOTPLUG_HANDLER_GET_CLASS(conf->acpi_dev);
> +    hhc->unplug(HOTPLUG_HANDLER(conf->acpi_dev), dev, &local_err);
>   
>       if (local_err) {
>           goto out;
> @@ -1897,7 +1932,7 @@ static void pc_cpu_unplug_cb(HotplugHandler *hotplug_dev,
>       pcms->boot_cpus--;
>       /* Update the number of CPUs in CMOS */
>       rtc_set_cpus_count(pcms->rtc, pcms->boot_cpus);
> -    fw_cfg_modify_i16(pcms->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
> +    fw_cfg_modify_i16(conf->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
>    out:
>       error_propagate(errp, local_err);
>   }
> @@ -2181,28 +2216,30 @@ static bool pc_machine_get_nvdimm(Object *obj, Error **errp)
>   {
>       PCMachineState *pcms = PC_MACHINE(obj);
>   
> -    return pcms->acpi_nvdimm_state.is_enabled;
> +    return pcms->acpi_configuration.acpi_nvdimm_state.is_enabled;
>   }
>   
>   static void pc_machine_set_nvdimm(Object *obj, bool value, Error **errp)
>   {
>       PCMachineState *pcms = PC_MACHINE(obj);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>   
> -    pcms->acpi_nvdimm_state.is_enabled = value;
> +    conf->acpi_nvdimm_state.is_enabled = value;
>   }
>   
>   static char *pc_machine_get_nvdimm_persistence(Object *obj, Error **errp)
>   {
>       PCMachineState *pcms = PC_MACHINE(obj);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>   
> -    return g_strdup(pcms->acpi_nvdimm_state.persistence_string);
> +    return g_strdup(conf->acpi_nvdimm_state.persistence_string);
>   }
>   
>   static void pc_machine_set_nvdimm_persistence(Object *obj, const char *value,
>                                                  Error **errp)
>   {
>       PCMachineState *pcms = PC_MACHINE(obj);
> -    AcpiNVDIMMState *nvdimm_state = &pcms->acpi_nvdimm_state;
> +    AcpiNVDIMMState *nvdimm_state = &pcms->acpi_configuration.acpi_nvdimm_state;
>   
>       if (strcmp(value, "cpu") == 0)
>           nvdimm_state->persistence = 3;
> @@ -2268,7 +2305,7 @@ static void pc_machine_initfn(Object *obj)
>       pcms->smm = ON_OFF_AUTO_AUTO;
>       pcms->vmport = ON_OFF_AUTO_AUTO;
>       /* nvdimm is disabled on default. */
> -    pcms->acpi_nvdimm_state.is_enabled = false;
> +    pcms->acpi_configuration.acpi_nvdimm_state.is_enabled = false;
>       /* acpi build is enabled by default if machine supports it */
>       pcms->acpi_build_enabled = PC_MACHINE_GET_CLASS(pcms)->has_acpi_build;
>       pcms->smbus = true;
> diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
> index dc09466b3e..1d10374dfa 100644
> --- a/hw/i386/pc_piix.c
> +++ b/hw/i386/pc_piix.c
> @@ -71,6 +71,7 @@ static void pc_init1(MachineState *machine,
>   {
>       PCMachineState *pcms = PC_MACHINE(machine);
>       PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>       MemoryRegion *system_memory = get_system_memory();
>       MemoryRegion *system_io = get_system_io();
>       int i;
> @@ -142,11 +143,11 @@ static void pc_init1(MachineState *machine,
>           }
>   
>           if (machine->ram_size >= lowmem) {
> -            pcms->above_4g_mem_size = machine->ram_size - lowmem;
> -            pcms->below_4g_mem_size = lowmem;
> +            conf->above_4g_mem_size = machine->ram_size - lowmem;
> +            conf->below_4g_mem_size = lowmem;
>           } else {
> -            pcms->above_4g_mem_size = 0;
> -            pcms->below_4g_mem_size = machine->ram_size;
> +            conf->above_4g_mem_size = 0;
> +            conf->below_4g_mem_size = machine->ram_size;
>           }
>       }
>   
> @@ -199,8 +200,8 @@ static void pc_init1(MachineState *machine,
>                                 pci_type,
>                                 &i440fx_state, &piix3_devfn, &isa_bus, pcms->gsi,
>                                 system_memory, system_io, machine->ram_size,
> -                              pcms->below_4g_mem_size,
> -                              pcms->above_4g_mem_size,
> +                              conf->below_4g_mem_size,
> +                              conf->above_4g_mem_size,
>                                 pci_memory, ram_memory);
>           pcms->bus = pci_bus;
>       } else {
> @@ -289,16 +290,16 @@ static void pc_init1(MachineState *machine,
>   
>           object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP,
>                                    TYPE_HOTPLUG_HANDLER,
> -                                 (Object **)&pcms->acpi_dev,
> +                                 (Object **)&conf->acpi_dev,
>                                    object_property_allow_set_link,
>                                    OBJ_PROP_LINK_STRONG, &error_abort);
>           object_property_set_link(OBJECT(machine), OBJECT(piix4_pm),
>                                    PC_MACHINE_ACPI_DEVICE_PROP, &error_abort);
>       }
>   
> -    if (pcms->acpi_nvdimm_state.is_enabled) {
> -        nvdimm_init_acpi_state(&pcms->acpi_nvdimm_state, system_io,
> -                               pcms->fw_cfg, OBJECT(pcms));
> +    if (conf->acpi_nvdimm_state.is_enabled) {
> +        nvdimm_init_acpi_state(&conf->acpi_nvdimm_state, system_io,
> +                               conf->fw_cfg, OBJECT(pcms));
>       }
>   }
>   
> diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
> index 532241e3f8..fb5c89bf7c 100644
> --- a/hw/i386/pc_q35.c
> +++ b/hw/i386/pc_q35.c
> @@ -63,6 +63,7 @@ static void pc_q35_init(MachineState *machine)
>   {
>       PCMachineState *pcms = PC_MACHINE(machine);
>       PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>       Q35PCIHost *q35_host;
>       PCIHostState *phb;
>       PCIBus *host_bus;
> @@ -116,11 +117,11 @@ static void pc_q35_init(MachineState *machine)
>       }
>   
>       if (machine->ram_size >= lowmem) {
> -        pcms->above_4g_mem_size = machine->ram_size - lowmem;
> -        pcms->below_4g_mem_size = lowmem;
> +        conf->above_4g_mem_size = machine->ram_size - lowmem;
> +        conf->below_4g_mem_size = lowmem;
>       } else {
> -        pcms->above_4g_mem_size = 0;
> -        pcms->below_4g_mem_size = machine->ram_size;
> +        conf->above_4g_mem_size = 0;
> +        conf->below_4g_mem_size = machine->ram_size;
>       }
>   
>       if (xen_enabled()) {
> @@ -179,9 +180,9 @@ static void pc_q35_init(MachineState *machine)
>                                MCH_HOST_PROP_SYSTEM_MEM, NULL);
>       object_property_set_link(OBJECT(q35_host), OBJECT(system_io),
>                                MCH_HOST_PROP_IO_MEM, NULL);
> -    object_property_set_int(OBJECT(q35_host), pcms->below_4g_mem_size,
> +    object_property_set_int(OBJECT(q35_host), conf->below_4g_mem_size,
>                               PCI_HOST_BELOW_4G_MEM_SIZE, NULL);
> -    object_property_set_int(OBJECT(q35_host), pcms->above_4g_mem_size,
> +    object_property_set_int(OBJECT(q35_host), conf->above_4g_mem_size,
>                               PCI_HOST_ABOVE_4G_MEM_SIZE, NULL);
>       /* pci */
>       qdev_init_nofail(DEVICE(q35_host));
> @@ -194,7 +195,7 @@ static void pc_q35_init(MachineState *machine)
>   
>       object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP,
>                                TYPE_HOTPLUG_HANDLER,
> -                             (Object **)&pcms->acpi_dev,
> +                             (Object **)&conf->acpi_dev,
>                                object_property_allow_set_link,
>                                OBJ_PROP_LINK_STRONG, &error_abort);
>       object_property_set_link(OBJECT(machine), OBJECT(lpc),
> @@ -276,9 +277,9 @@ static void pc_q35_init(MachineState *machine)
>       pc_vga_init(isa_bus, host_bus);
>       pc_nic_init(pcmc, isa_bus, host_bus);
>   
> -    if (pcms->acpi_nvdimm_state.is_enabled) {
> -        nvdimm_init_acpi_state(&pcms->acpi_nvdimm_state, system_io,
> -                               pcms->fw_cfg, OBJECT(pcms));
> +    if (conf->acpi_nvdimm_state.is_enabled) {
> +        nvdimm_init_acpi_state(&conf->acpi_nvdimm_state, system_io,
> +                               conf->fw_cfg, OBJECT(pcms));
>       }
>   }
>   
> diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
> index 935a3676c8..4ad5b10d64 100644
> --- a/hw/i386/xen/xen-hvm.c
> +++ b/hw/i386/xen/xen-hvm.c
> @@ -190,6 +190,7 @@ qemu_irq *xen_interrupt_controller_init(void)
>   static void xen_ram_init(PCMachineState *pcms,
>                            ram_addr_t ram_size, MemoryRegion **ram_memory_p)
>   {
> +    AcpiConfiguration *conf = &pcms->acpi_configuration;
>       MemoryRegion *sysmem = get_system_memory();
>       ram_addr_t block_len;
>       uint64_t user_lowmem = object_property_get_uint(qdev_get_machine(),
> @@ -207,20 +208,20 @@ static void xen_ram_init(PCMachineState *pcms,
>       }
>   
>       if (ram_size >= user_lowmem) {
> -        pcms->above_4g_mem_size = ram_size - user_lowmem;
> -        pcms->below_4g_mem_size = user_lowmem;
> +        conf->above_4g_mem_size = ram_size - user_lowmem;
> +        conf->below_4g_mem_size = user_lowmem;
>       } else {
> -        pcms->above_4g_mem_size = 0;
> -        pcms->below_4g_mem_size = ram_size;
> +        conf->above_4g_mem_size = 0;
> +        conf->below_4g_mem_size = ram_size;
>       }
> -    if (!pcms->above_4g_mem_size) {
> +    if (!conf->above_4g_mem_size) {
>           block_len = ram_size;
>       } else {
>           /*
>            * Xen does not allocate the memory continuously, it keeps a
>            * hole of the size computed above or passed in.
>            */
> -        block_len = (1ULL << 32) + pcms->above_4g_mem_size;
> +        block_len = (1ULL << 32) + conf->above_4g_mem_size;
>       }
>       memory_region_init_ram(&ram_memory, NULL, "xen.ram", block_len,
>                              &error_fatal);
> @@ -237,12 +238,12 @@ static void xen_ram_init(PCMachineState *pcms,
>        */
>       memory_region_init_alias(&ram_lo, NULL, "xen.ram.lo",
>                                &ram_memory, 0xc0000,
> -                             pcms->below_4g_mem_size - 0xc0000);
> +                             conf->below_4g_mem_size - 0xc0000);
>       memory_region_add_subregion(sysmem, 0xc0000, &ram_lo);
> -    if (pcms->above_4g_mem_size > 0) {
> +    if (conf->above_4g_mem_size > 0) {
>           memory_region_init_alias(&ram_hi, NULL, "xen.ram.hi",
>                                    &ram_memory, 0x100000000ULL,
> -                                 pcms->above_4g_mem_size);
> +                                 conf->above_4g_mem_size);
>           memory_region_add_subregion(sysmem, 0x100000000ULL, &ram_hi);
>       }
>   }
> diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h
> index c20ace0d0b..6a94452928 100644
> --- a/include/hw/acpi/acpi.h
> +++ b/include/hw/acpi/acpi.h
> @@ -24,6 +24,8 @@
>   #include "exec/memory.h"
>   #include "hw/irq.h"
>   #include "hw/acpi/acpi_dev_interface.h"
> +#include "hw/hotplug.h"
> +#include "hw/mem/nvdimm.h"
>   
>   /*
>    * current device naming scheme supports up to 256 memory devices
> @@ -186,6 +188,47 @@ extern int acpi_enabled;
>   extern char unsigned *acpi_tables;
>   extern size_t acpi_tables_len;
>   
> +typedef
> +struct AcpiBuildState {
> +    /* Copy of table in RAM (for patching). */
> +    MemoryRegion *table_mr;
> +    /* Is table patched? */
> +    bool patched;
> +    void *rsdp;
> +    MemoryRegion *rsdp_mr;
> +    MemoryRegion *linker_mr;
> +} AcpiBuildState;
> +
> +typedef
> +struct AcpiConfiguration {
> +    /* Machine class ACPI settings */
> +    int legacy_acpi_table_size;
> +    bool rsdp_in_ram;
> +    unsigned acpi_data_size;
> +
> +    /* Machine state ACPI settings */
> +    HotplugHandler *acpi_dev;
> +    AcpiNVDIMMState acpi_nvdimm_state;
> +
> +    /*
> +     * The fields below are machine settings that
> +     * are not ACPI specific. However they are needed
> +     * for building ACPI tables and as such should be
> +     * carried through the ACPI configuration structure.
> +     */
> +    bool legacy_cpu_hotplug;
> +    bool linuxboot_dma_enabled;
> +    FWCfgState *fw_cfg;
> +    ram_addr_t below_4g_mem_size, above_4g_mem_size;;
> +    uint64_t numa_nodes;
> +    uint64_t *node_mem;
> +    bool apic_xrupt_override;
> +    unsigned apic_id_limit;
> +
> +    /* Build state */
> +    AcpiBuildState *build_state;
> +} AcpiConfiguration;
> +
>   uint8_t *acpi_table_first(void);
>   uint8_t *acpi_table_next(uint8_t *current);
>   unsigned acpi_table_len(void *current);
> diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
> index dfe6746692..da0bd39741 100644
> --- a/include/hw/i386/pc.h
> +++ b/include/hw/i386/pc.h
> @@ -12,6 +12,7 @@
>   #include "qemu/range.h"
>   #include "qemu/bitmap.h"
>   #include "sysemu/sysemu.h"
> +#include "hw/acpi/acpi.h"
>   #include "hw/pci/pci.h"
>   #include "hw/compat.h"
>   #include "hw/mem/pc-dimm.h"
> @@ -35,10 +36,8 @@ struct PCMachineState {
>       Notifier machine_done;
>   
>       /* Pointers to devices and objects: */
> -    HotplugHandler *acpi_dev;
>       ISADevice *rtc;
>       PCIBus *bus;
> -    FWCfgState *fw_cfg;
>       qemu_irq *gsi;
>   
>       /* Configuration options: */
> @@ -46,28 +45,20 @@ struct PCMachineState {
>       OnOffAuto vmport;
>       OnOffAuto smm;
>   
> -    AcpiNVDIMMState acpi_nvdimm_state;
> -
>       bool acpi_build_enabled;
>       bool smbus;
>       bool sata;
>       bool pit;
>   
> -    /* RAM information (sizes, addresses, configuration): */
> -    ram_addr_t below_4g_mem_size, above_4g_mem_size;
> -
> -    /* CPU and apic information: */
> -    bool apic_xrupt_override;
> -    unsigned apic_id_limit;
> +    /* CPU information */
>       uint16_t boot_cpus;
>   
> -    /* NUMA information: */
> -    uint64_t numa_nodes;
> -    uint64_t *node_mem;
> -
>       /* Address space used by IOAPIC device. All IOAPIC interrupts
>        * will be translated to MSI messages in the address space. */
>       AddressSpace *ioapic_as;
> +
> +    /* ACPI configuration */
> +    AcpiConfiguration acpi_configuration;

This one is fine although.

>   };
>   
>   #define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device"
> 

Thanks,

Phil.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 16/19] hw: acpi: Retrieve the PCI bus from AcpiPciHpState
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 16/19] hw: acpi: Retrieve the PCI bus from AcpiPciHpState Samuel Ortiz
@ 2018-10-29 21:02   ` Philippe Mathieu-Daudé
  2018-10-29 23:35     ` Boeuf, Sebastien
  0 siblings, 1 reply; 47+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-10-29 21:02 UTC (permalink / raw)
  To: Samuel Ortiz, qemu-devel
  Cc: Michael S. Tsirkin, Jing Liu, Sebastien Boeuf, Paolo Bonzini,
	Igor Mammedov

On 29/10/18 18:01, Samuel Ortiz wrote:
> From: Sebastien Boeuf <sebastien.boeuf@intel.com>
> 
> Instead of using the machine type specific method find_i440fx() to
> retrieve the PCI bus, this commit aims to rely on the fact that the
> PCI bus is known by the structure AcpiPciHpState.
> 
> When the structure is initialized through acpi_pcihp_init() call,
> it saves the PCI bus, which means there is no need to invoke a
> special function later on.
> 
> Based on the fact that find_i440fx() was only used there, this
> patch also removes the function find_i440fx() itself from the
> entire codebase.

Nice :)

> 
> Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
> Signed-off-by: Jing Liu <jing2.liu@linux.intel.com>

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>

> ---
>   hw/acpi/pcihp.c       | 10 ++++------
>   hw/pci-host/piix.c    |  8 --------
>   include/hw/i386/pc.h  |  1 -
>   stubs/Makefile.objs   |  1 -
>   stubs/pci-host-piix.c |  6 ------
>   5 files changed, 4 insertions(+), 22 deletions(-)
>   delete mode 100644 stubs/pci-host-piix.c
> 
> diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
> index 80d42e12ff..254b2e50ab 100644
> --- a/hw/acpi/pcihp.c
> +++ b/hw/acpi/pcihp.c
> @@ -93,10 +93,9 @@ static void *acpi_set_bsel(PCIBus *bus, void *opaque)
>       return bsel_alloc;
>   }
>   
> -static void acpi_set_pci_info(void)
> +static void acpi_set_pci_info(AcpiPciHpState *s)
>   {
>       static bool bsel_is_set;
> -    PCIBus *bus;
>       unsigned bsel_alloc = ACPI_PCIHP_BSEL_DEFAULT;
>   
>       if (bsel_is_set) {
> @@ -104,10 +103,9 @@ static void acpi_set_pci_info(void)
>       }
>       bsel_is_set = true;
>   
> -    bus = find_i440fx(); /* TODO: Q35 support */
> -    if (bus) {
> +    if (s->root) {
>           /* Scan all PCI buses. Set property to enable acpi based hotplug. */
> -        pci_for_each_bus_depth_first(bus, acpi_set_bsel, NULL, &bsel_alloc);
> +        pci_for_each_bus_depth_first(s->root, acpi_set_bsel, NULL, &bsel_alloc);
>       }
>   }
>   
> @@ -213,7 +211,7 @@ static void acpi_pcihp_update(AcpiPciHpState *s)
>   
>   void acpi_pcihp_reset(AcpiPciHpState *s)
>   {
> -    acpi_set_pci_info();
> +    acpi_set_pci_info(s);
>       acpi_pcihp_update(s);
>   }
>   
> diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
> index da73743fa2..4940f59c9b 100644
> --- a/hw/pci-host/piix.c
> +++ b/hw/pci-host/piix.c
> @@ -445,14 +445,6 @@ PCIBus *i440fx_init(const char *host_type, const char *pci_type,
>       return b;
>   }
>   
> -PCIBus *find_i440fx(void)
> -{
> -    PCIHostState *s = OBJECT_CHECK(PCIHostState,
> -                                   object_resolve_path("/machine/i440fx", NULL),
> -                                   TYPE_PCI_HOST_BRIDGE);
> -    return s ? s->bus : NULL;
> -}
> -
>   /* PIIX3 PCI to ISA bridge */
>   static void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq)
>   {
> diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
> index 7d177cd207..f6b2649cf8 100644
> --- a/include/hw/i386/pc.h
> +++ b/include/hw/i386/pc.h
> @@ -260,7 +260,6 @@ PCIBus *i440fx_init(const char *host_type, const char *pci_type,
>                       MemoryRegion *pci_memory,
>                       MemoryRegion *ram_memory);
>   
> -PCIBus *find_i440fx(void);
>   /* piix4.c */
>   extern PCIDevice *piix4_dev;
>   int piix4_init(PCIBus *bus, ISABus **isa_bus, int devfn);
> diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
> index 5dd0aeeec6..725f78bedc 100644
> --- a/stubs/Makefile.objs
> +++ b/stubs/Makefile.objs
> @@ -41,6 +41,5 @@ stub-obj-y += pc_madt_cpu_entry.o
>   stub-obj-y += vmgenid.o
>   stub-obj-y += xen-common.o
>   stub-obj-y += xen-hvm.o
> -stub-obj-y += pci-host-piix.o
>   stub-obj-y += ram-block.o
>   stub-obj-y += ramfb.o
> diff --git a/stubs/pci-host-piix.c b/stubs/pci-host-piix.c
> deleted file mode 100644
> index 6ed81b1f21..0000000000
> --- a/stubs/pci-host-piix.c
> +++ /dev/null
> @@ -1,6 +0,0 @@
> -#include "qemu/osdep.h"
> -#include "hw/i386/pc.h"
> -PCIBus *find_i440fx(void)
> -{
> -    return NULL;
> -}
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 17/19] hw: acpi: Define ACPI tables builder interface
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 17/19] hw: acpi: Define ACPI tables builder interface Samuel Ortiz
@ 2018-10-29 21:06   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 47+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-10-29 21:06 UTC (permalink / raw)
  To: Samuel Ortiz, qemu-devel
  Cc: Igor Mammedov, Eduardo Habkost, Michael S. Tsirkin

Hi Samuel,

On 29/10/18 18:01, Samuel Ortiz wrote:
> In order to decouple ACPI APIs from specific machine types, we are
> creating an ACPI builder interface that each ACPI platform can choose to
> implement.
> This way, a new machine type can re-use the high level ACPI APIs and
> define some custom table build methods, without having to duplicate most
> of the existing implementation only to add small variations to it.
> 
> Cc: Eduardo Habkost <ehabkost@redhat.com>
> Cc: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
> ---
>   hw/acpi/Makefile.objs     |  1 +
>   hw/acpi/builder.c         | 97 +++++++++++++++++++++++++++++++++++++++
>   include/hw/acpi/builder.h | 97 +++++++++++++++++++++++++++++++++++++++
>   3 files changed, 195 insertions(+)
>   create mode 100644 hw/acpi/builder.c
>   create mode 100644 include/hw/acpi/builder.h
> 
> diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
> index 11c35bcb44..2f383adc6f 100644
> --- a/hw/acpi/Makefile.objs
> +++ b/hw/acpi/Makefile.objs
> @@ -11,6 +11,7 @@ common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o
>   common-obj-y += acpi_interface.o
>   common-obj-y += bios-linker-loader.o
>   common-obj-y += aml-build.o
> +common-obj-y += builder.o
>   
>   common-obj-$(CONFIG_IPMI) += ipmi.o
>   common-obj-$(call lnot,$(CONFIG_IPMI)) += ipmi-stub.o
> diff --git a/hw/acpi/builder.c b/hw/acpi/builder.c
> new file mode 100644
> index 0000000000..c29a614793
> --- /dev/null
> +++ b/hw/acpi/builder.c
> @@ -0,0 +1,97 @@
> +/*
> + *
> + * Copyright (c) 2018 Intel Corporation
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2 or later, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/module.h"
> +#include "qom/object.h"
> +#include "hw/acpi/builder.h"
> +
> +void acpi_builder_rsdp(AcpiBuilder *builder,
> +                       GArray *table_data, BIOSLinker *linker,
> +                       unsigned rsdt_tbl_offset)
> +{
> +    AcpiBuilderMethods *abm = ACPI_BUILDER_GET_METHODS(builder);
> +
> +    if (abm && abm->rsdp) {
> +        abm->rsdp(table_data, linker, rsdt_tbl_offset);
> +    }
> +}
> +
> +void acpi_builder_madt(AcpiBuilder *builder,
> +                       GArray *table_data, BIOSLinker *linker,
> +                       MachineState *ms, AcpiConfiguration *conf)
> +{
> +    AcpiBuilderMethods *abm = ACPI_BUILDER_GET_METHODS(builder);
> +
> +    if (abm && abm->madt) {
> +        abm->madt(table_data, linker, ms, conf);
> +    }
> +}
> +
> +void acpi_builder_mcfg(AcpiBuilder *builder,
> +                       GArray *table_data, BIOSLinker *linker,
> +                       AcpiMcfgInfo *info)
> +{
> +    AcpiBuilderMethods *abm = ACPI_BUILDER_GET_METHODS(builder);
> +
> +    if (abm && abm->mcfg) {
> +        abm->mcfg(table_data, linker, info);
> +    }
> +}
> +
> +void acpi_builder_srat(AcpiBuilder *builder,
> +                       GArray *table_data, BIOSLinker *linker,
> +                       MachineState *machine, AcpiConfiguration *conf)
> +{
> +    AcpiBuilderMethods *abm = ACPI_BUILDER_GET_METHODS(builder);
> +
> +    if (abm && abm->srat) {
> +        abm->srat(table_data, linker, machine, conf);
> +    }
> +}
> +
> +void acpi_builder_slit(AcpiBuilder *builder,
> +                       GArray *table_data, BIOSLinker *linker)
> +{
> +    AcpiBuilderMethods *abm = ACPI_BUILDER_GET_METHODS(builder);
> +
> +    if (abm && abm->slit) {
> +        abm->slit(table_data, linker);
> +    }
> +}
> +
> +AcpiConfiguration *acpi_builder_configuration(AcpiBuilder *builder)
> +{
> +    AcpiBuilderMethods *abm = ACPI_BUILDER_GET_METHODS(builder);
> +    if (abm && abm->configuration) {
> +        return abm->configuration(builder);
> +    }
> +    return NULL;
> +}
> +
> +static const TypeInfo acpi_builder_info = {
> +    .name          = TYPE_ACPI_BUILDER,
> +    .parent        = TYPE_INTERFACE,
> +    .class_size    = sizeof(AcpiBuilderMethods),
> +};
> +
> +static void acpi_builder_register_type(void)
> +{
> +    type_register_static(&acpi_builder_info);
> +}
> +
> +type_init(acpi_builder_register_type)
> diff --git a/include/hw/acpi/builder.h b/include/hw/acpi/builder.h
> new file mode 100644
> index 0000000000..639b554de3
> --- /dev/null
> +++ b/include/hw/acpi/builder.h
> @@ -0,0 +1,97 @@
> +/*
> + *
> + * Copyright (c) 2018 Intel Corporation
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2 or later, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef ACPI_BUILDER_H
> +#define ACPI_BUILDER_H
> +
> +#include "qemu/osdep.h"
> +#include "hw/acpi/bios-linker-loader.h"
> +#include "qom/object.h"
> +
> +#define TYPE_ACPI_BUILDER "acpi-builder"
> +
> +#define ACPI_BUILDER_METHODS(klass) \
> +     OBJECT_CLASS_CHECK(AcpiBuilderMethods, (klass), TYPE_ACPI_BUILDER)
> +#define ACPI_BUILDER_GET_METHODS(obj) \
> +     OBJECT_GET_CLASS(AcpiBuilderMethods, (obj), TYPE_ACPI_BUILDER)
> +#define ACPI_BUILDER(obj)                                       \
> +     INTERFACE_CHECK(AcpiBuilder, (obj), TYPE_ACPI_BUILDER)
> +
> +typedef struct AcpiConfiguration AcpiConfiguration;
> +typedef struct AcpiBuildState AcpiBuildState;
> +typedef struct AcpiMcfgInfo AcpiMcfgInfo;
> +
> +typedef struct AcpiBuilder {
> +    /* <private> */
> +    Object Parent;
> +} AcpiBuilder;
> +
> +/**
> + * AcpiBuildMethods:
> + *
> + * Interface to be implemented by a machine type that needs to provide
> + * custom ACPI tables build method.
> + *
> + * @parent: Opaque parent interface.
> + *
> + * @rsdp:
> + * @madt:
> + * @mcfg:
> + * @srat:
> + * @slit:
> + * @setup:

It seems your forgot to fill the doc here.

Otherwise:
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>

> + */
> +typedef struct AcpiBuilderMethods {
> +    /* <private> */
> +    InterfaceClass parent;
> +
> +    /* <public> */
> +    void (*rsdp)(GArray *table_data, BIOSLinker *linker,
> +                 unsigned rsdt_tbl_offset);
> +    void (*madt)(GArray *table_data, BIOSLinker *linker,
> +                 MachineState *ms, AcpiConfiguration *conf);
> +    void (*mcfg)(GArray *table_data, BIOSLinker *linker,
> +                 AcpiMcfgInfo *info);
> +    void (*srat)(GArray *table_data, BIOSLinker *linker,
> +                 MachineState *machine, AcpiConfiguration *conf);
> +    void (*slit)(GArray *table_data, BIOSLinker *linker);
> +
> +    AcpiConfiguration *(*configuration)(AcpiBuilder *builder);
> +} AcpiBuilderMethods;
> +
> +void acpi_builder_rsdp(AcpiBuilder *builder,
> +                       GArray *table_data, BIOSLinker *linker,
> +                       unsigned rsdt_tbl_offset);
> +
> +void acpi_builder_madt(AcpiBuilder *builder,
> +                       GArray *table_data, BIOSLinker *linker,
> +                       MachineState *ms, AcpiConfiguration *conf);
> +
> +void acpi_builder_mcfg(AcpiBuilder *builder,
> +                       GArray *table_data, BIOSLinker *linker,
> +                       AcpiMcfgInfo *info);
> +
> +void acpi_builder_srat(AcpiBuilder *builder,
> +                       GArray *table_data, BIOSLinker *linker,
> +                       MachineState *machine, AcpiConfiguration *conf);
> +
> +void acpi_builder_slit(AcpiBuilder *builder,
> +                       GArray *table_data, BIOSLinker *linker);
> +
> +AcpiConfiguration *acpi_builder_configuration(AcpiBuilder *builder);
> +
> +#endif
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 18/19] hw: i386: Export the MADT build method
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 18/19] hw: i386: Export the MADT build method Samuel Ortiz
@ 2018-10-29 21:18   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 47+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-10-29 21:18 UTC (permalink / raw)
  To: Samuel Ortiz, qemu-devel
  Cc: Peter Maydell, Eduardo Habkost, Michael S. Tsirkin,
	Paolo Bonzini, Shannon Zhao, Igor Mammedov,
	open list:ARM ACPI Subsystem, Richard Henderson

Hi Samuel,

On 29/10/18 18:01, Samuel Ortiz wrote:
> It is going to be used by the PC machine type as the MADT table builder
> method and thus needs to be exported outside of acpi-build.c
> 
> Also, now that the generic build_madt() API is exported, we have to
> rename the ARM static one in order to avoid build time conflicts.
> 
> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
> ---
>   hw/arm/virt-acpi-build.c |  4 ++--
>   hw/i386/acpi-build.c     |  3 ++-
>   include/hw/i386/acpi.h   | 27 +++++++++++++++++++++++++++
>   3 files changed, 31 insertions(+), 3 deletions(-)
>   create mode 100644 include/hw/i386/acpi.h
> 
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index 353aa55357..0c349e1c60 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -565,7 +565,7 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>   
>   /* MADT */
>   static void
> -build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> +virt_build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>   {
>       VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
>       int madt_start = table_data->len;
> @@ -746,7 +746,7 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
>       build_fadt_rev5(tables_blob, tables->linker, vms, dsdt);
>   
>       acpi_add_table(table_offsets, tables_blob);
> -    build_madt(tables_blob, tables->linker, vms);
> +    virt_build_madt(tables_blob, tables->linker, vms);
>   
>       acpi_add_table(table_offsets, tables_blob);
>       build_gtdt(tables_blob, tables->linker, vms);
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 9cb739bf5c..5035dac556 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -62,6 +62,7 @@
>   #include "qom/qom-qobject.h"
>   #include "hw/i386/amd_iommu.h"
>   #include "hw/i386/intel_iommu.h"
> +#include "hw/i386/acpi.h"
>   
>   #include "hw/acpi/ipmi.h"
>   
> @@ -281,7 +282,7 @@ void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
>       }
>   }
>   
> -static void
> +void
>   build_madt(GArray *table_data, BIOSLinker *linker,
>              MachineState *ms, AcpiConfiguration *conf)
>   {
> diff --git a/include/hw/i386/acpi.h b/include/hw/i386/acpi.h
> new file mode 100644
> index 0000000000..53bf94c3ca
> --- /dev/null
> +++ b/include/hw/i386/acpi.h
> @@ -0,0 +1,27 @@
> +/*
> + *
> + * Copyright (c) 2018 Intel Corportation
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2 or later, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef QEMU_I386_ACPI_H
> +#define QEMU_I386_ACPI_H

Please use HW_I386_ACPI_H.

> +
> +#include "hw/acpi/acpi.h"

Also:

  #include "hw/acpi/bios-linker-loader.h"

> +
> +/* Build methods */

  /* Build the ACPI MADT (Multiple APIC Description Table) methods */

> +void build_madt(GArray *table_data, BIOSLinker *linker,
> +                MachineState *ms, AcpiConfiguration *conf);
> +
> +#endif
> 

With changes:
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 19/19] hw: i386: Implement the ACPI builder interface for PC
  2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 19/19] hw: i386: Implement the ACPI builder interface for PC Samuel Ortiz
  2018-10-29 17:28   ` Paolo Bonzini
@ 2018-10-29 21:23   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 47+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-10-29 21:23 UTC (permalink / raw)
  To: Samuel Ortiz, qemu-devel
  Cc: Eduardo Habkost, Michael S. Tsirkin, Paolo Bonzini,
	Igor Mammedov, Richard Henderson

On 29/10/18 18:01, Samuel Ortiz wrote:
> All PC machine type derivatives will use the same ACPI table build
> methods. But with that change in place, any new x86 machine type will be
> able to re-use the acpi-build API and customize part of it by defining
> its own ACPI table build methods.
> 
> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
> ---
>   hw/i386/acpi-build.c | 15 ++++++++++-----
>   hw/i386/pc.c         | 19 +++++++++++++++++++
>   2 files changed, 29 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 5035dac556..d40599e6d1 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -35,6 +35,7 @@
>   #include "hw/acpi/acpi-defs.h"
>   #include "hw/acpi/acpi.h"
>   #include "hw/acpi/cpu.h"
> +#include "hw/acpi/builder.h"
>   #include "hw/nvram/fw_cfg.h"
>   #include "hw/acpi/bios-linker-loader.h"
>   #include "hw/loader.h"
> @@ -1556,6 +1557,7 @@ void acpi_build(AcpiBuildTables *tables,
>       GArray *tables_blob = tables->table_data;
>       AcpiSlicOem slic_oem = { .id = NULL, .table_id = NULL };
>       Object *vmgenid_dev;
> +    AcpiBuilder *ab = ACPI_BUILDER(machine);
>   
>       acpi_get_pm_info(&pm);
>       acpi_get_misc_info(&misc);
> @@ -1605,7 +1607,8 @@ void acpi_build(AcpiBuildTables *tables,
>       aml_len += tables_blob->len - fadt;
>   
>       acpi_add_table(table_offsets, tables_blob);
> -    build_madt(tables_blob, tables->linker, machine, conf);
> +    acpi_builder_madt(ab, tables_blob, tables->linker,
> +                      machine, conf);
>   
>       vmgenid_dev = find_vmgenid_dev();
>       if (vmgenid_dev) {
> @@ -1629,15 +1632,17 @@ void acpi_build(AcpiBuildTables *tables,
>       }
>       if (conf->numa_nodes) {
>           acpi_add_table(table_offsets, tables_blob);
> -        build_srat(tables_blob, tables->linker, machine, conf);
> +
> +        acpi_builder_srat(ab, tables_blob, tables->linker,
> +                          machine, conf);
>           if (have_numa_distance) {
>               acpi_add_table(table_offsets, tables_blob);
> -            build_slit(tables_blob, tables->linker);
> +            acpi_builder_slit(ab, tables_blob, tables->linker);
>           }
>       }
>       if (acpi_get_mcfg(&mcfg)) {
>           acpi_add_table(table_offsets, tables_blob);
> -        build_mcfg(tables_blob, tables->linker, &mcfg);
> +        acpi_builder_mcfg(ab, tables_blob, tables->linker, &mcfg);
>       }
>       if (x86_iommu_get_default()) {
>           IommuType IOMMUType = x86_iommu_get_type();
> @@ -1668,7 +1673,7 @@ void acpi_build(AcpiBuildTables *tables,
>                  slic_oem.id, slic_oem.table_id);
>   
>       /* RSDP is in FSEG memory, so allocate it separately */
> -    build_rsdp_rsdt(tables->rsdp, tables->linker, rsdt);
> +    acpi_builder_rsdp(ab, tables->rsdp, tables->linker, rsdt);
>   
>       /* We'll expose it all to Guest so we want to reduce
>        * chance of size changes.
> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> index 1dcbbd5139..986ed0eabd 100644
> --- a/hw/i386/pc.c
> +++ b/hw/i386/pc.c
> @@ -64,6 +64,7 @@
>   #include "qemu/option.h"
>   #include "hw/acpi/acpi.h"
>   #include "hw/acpi/cpu_hotplug.h"
> +#include "hw/acpi/builder.h"
>   #include "hw/boards.h"
>   #include "acpi-build.h"
>   #include "hw/mem/pc-dimm.h"
> @@ -75,6 +76,7 @@
>   #include "hw/nmi.h"
>   #include "hw/i386/intel_iommu.h"
>   #include "hw/net/ne2000-isa.h"
> +#include "hw/i386/acpi.h"
>   
>   /* debug PC/ISA interrupts */
>   //#define DEBUG_IRQ
> @@ -2403,12 +2405,20 @@ static void x86_nmi(NMIState *n, int cpu_index, Error **errp)
>       }
>   }
>   
> +static AcpiConfiguration *pc_acpi_configuration(AcpiBuilder *builder)
> +{
> +    PCMachineState *pcms = PC_MACHINE(builder);
> +
> +    return &pcms->acpi_configuration;
> +}
> +
>   static void pc_machine_class_init(ObjectClass *oc, void *data)
>   {
>       MachineClass *mc = MACHINE_CLASS(oc);
>       PCMachineClass *pcmc = PC_MACHINE_CLASS(oc);
>       HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
>       NMIClass *nc = NMI_CLASS(oc);
> +    AcpiBuilderMethods *abm = ACPI_BUILDER_METHODS(oc);
>   
>       pcmc->pci_enabled = true;
>       pcmc->has_acpi_build = true;
> @@ -2443,6 +2453,14 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
>       nc->nmi_monitor_handler = x86_nmi;
>       mc->default_cpu_type = TARGET_DEFAULT_CPU_TYPE;
>   
> +    /* ACPI building methods */
> +    abm->madt = build_madt;
> +    abm->rsdp = build_rsdp_rsdt;

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>

> +    abm->mcfg = build_mcfg;
> +    abm->srat = build_srat;
> +    abm->slit = build_slit;
> +    abm->configuration = pc_acpi_configuration;
> +
>       object_class_property_add(oc, MEMORY_DEVICE_REGION_SIZE, "int",
>           pc_machine_get_device_memory_region_size, NULL,
>           NULL, NULL, &error_abort);
> @@ -2494,6 +2512,7 @@ static const TypeInfo pc_machine_info = {
>       .interfaces = (InterfaceInfo[]) {
>            { TYPE_HOTPLUG_HANDLER },
>            { TYPE_NMI },
> +         { TYPE_ACPI_BUILDER },
>            { }
>       },
>   };
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 15/19] hw: acpi: Export the PCI hotplug API
  2018-10-29 19:46   ` Philippe Mathieu-Daudé
@ 2018-10-29 23:34     ` Boeuf, Sebastien
  0 siblings, 0 replies; 47+ messages in thread
From: Boeuf, Sebastien @ 2018-10-29 23:34 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, Samuel Ortiz, qemu-devel
  Cc: Eduardo Habkost, Michael S. Tsirkin, Jing Liu, Paolo Bonzini,
	Igor Mammedov, Richard Henderson

Yes makes sense. Let's change the naming.

Thanks,
Sebastien
________________________________________
From: Philippe Mathieu-Daudé [philmd@redhat.com]
Sent: Monday, October 29, 2018 12:46 PM
To: Samuel Ortiz; qemu-devel@nongnu.org
Cc: Eduardo Habkost; Michael S. Tsirkin; Jing Liu; Boeuf, Sebastien; Paolo Bonzini; Igor Mammedov; Richard Henderson
Subject: Re: [Qemu-devel] [PATCH v3 15/19] hw: acpi: Export the PCI hotplug API

On 29/10/18 18:01, Samuel Ortiz wrote:
> From: Sebastien Boeuf <sebastien.boeuf@intel.com>
>
> The ACPI hotplug support for PCI devices APIs are not x86 or even
> machine type specific. In order for future machine types to be able to
> re-use that code, we export it through the architecture agnostic
> hw/acpi folder.
>
> Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
> Signed-off-by: Jing Liu <jing2.liu@linux.intel.com>
> ---
>   hw/acpi/aml-build.c         | 194 ++++++++++++++++++++++++++++++++++++
>   hw/i386/acpi-build.c        | 192 +----------------------------------
>   include/hw/acpi/aml-build.h |   3 +
>   3 files changed, 199 insertions(+), 190 deletions(-)
>
> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> index c3f652a68f..1b057d1191 100644
> --- a/hw/acpi/aml-build.c
> +++ b/hw/acpi/aml-build.c
> @@ -35,6 +35,7 @@
>   #include "hw/acpi/tpm.h"
>   #include "qom/qom-qobject.h"
>   #include "qapi/qmp/qnum.h"
> +#include "hw/acpi/pcihp.h"
>
>   #define PCI_HOST_BRIDGE_CONFIG_ADDR        0xcf8
>   #define PCI_HOST_BRIDGE_IO_0_MIN_ADDR      0x0000
> @@ -2314,6 +2315,199 @@ Aml *build_pci_host_bridge(Aml *table, AcpiPciBus *pci_host)
>       return scope;
>   }
>
> +void build_acpi_pci_hotplug(Aml *scope)

Or build_acpi_pcihp() to match the header file name.

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>

> +{
> +    Aml *field;
> +    Aml *method;
> +
> +    aml_append(scope,
> +        aml_operation_region("PCST", AML_SYSTEM_IO, aml_int(0xae00), 0x08));
> +    field = aml_field("PCST", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
> +    aml_append(field, aml_named_field("PCIU", 32));
> +    aml_append(field, aml_named_field("PCID", 32));
> +    aml_append(scope, field);
> +
> +    aml_append(scope,
> +        aml_operation_region("SEJ", AML_SYSTEM_IO, aml_int(0xae08), 0x04));
> +    field = aml_field("SEJ", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
> +    aml_append(field, aml_named_field("B0EJ", 32));
> +    aml_append(scope, field);
> +
> +    aml_append(scope,
> +        aml_operation_region("BNMR", AML_SYSTEM_IO, aml_int(0xae10), 0x04));
> +    field = aml_field("BNMR", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
> +    aml_append(field, aml_named_field("BNUM", 32));
> +    aml_append(scope, field);
> +
> +    aml_append(scope, aml_mutex("BLCK", 0));
> +
> +    method = aml_method("PCEJ", 2, AML_NOTSERIALIZED);
> +    aml_append(method, aml_acquire(aml_name("BLCK"), 0xFFFF));
> +    aml_append(method, aml_store(aml_arg(0), aml_name("BNUM")));
> +    aml_append(method,
> +        aml_store(aml_shiftleft(aml_int(1), aml_arg(1)), aml_name("B0EJ")));
> +    aml_append(method, aml_release(aml_name("BLCK")));
> +    aml_append(method, aml_return(aml_int(0)));
> +    aml_append(scope, method);
> +}
> +
> +static void build_append_pcihp_notify_entry(Aml *method, int slot)
> +{
> +    Aml *if_ctx;
> +    int32_t devfn = PCI_DEVFN(slot, 0);
> +
> +    if_ctx = aml_if(aml_and(aml_arg(0), aml_int(0x1U << slot), NULL));
> +    aml_append(if_ctx, aml_notify(aml_name("S%.02X", devfn), aml_arg(1)));
> +    aml_append(method, if_ctx);
> +}
> +
> +void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
> +                                  bool pcihp_bridge_en)
> +{
> +    Aml *dev, *notify_method = NULL, *method;
> +    QObject *bsel;
> +    PCIBus *sec;
> +    int i;
> +
> +    bsel = object_property_get_qobject(OBJECT(bus), ACPI_PCIHP_PROP_BSEL, NULL);
> +    if (bsel) {
> +        uint64_t bsel_val = qnum_get_uint(qobject_to(QNum, bsel));
> +
> +        aml_append(parent_scope, aml_name_decl("BSEL", aml_int(bsel_val)));
> +        notify_method = aml_method("DVNT", 2, AML_NOTSERIALIZED);
> +    }
> +
> +    for (i = 0; i < ARRAY_SIZE(bus->devices); i += PCI_FUNC_MAX) {
> +        DeviceClass *dc;
> +        PCIDeviceClass *pc;
> +        PCIDevice *pdev = bus->devices[i];
> +        int slot = PCI_SLOT(i);
> +        bool hotplug_enabled_dev;
> +        bool bridge_in_acpi;
> +
> +        if (!pdev) {
> +            if (bsel) { /* add hotplug slots for non present devices */
> +                dev = aml_device("S%.02X", PCI_DEVFN(slot, 0));
> +                aml_append(dev, aml_name_decl("_SUN", aml_int(slot)));
> +                aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16)));
> +                method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
> +                aml_append(method,
> +                    aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN"))
> +                );
> +                aml_append(dev, method);
> +                aml_append(parent_scope, dev);
> +
> +                build_append_pcihp_notify_entry(notify_method, slot);
> +            }
> +            continue;
> +        }
> +
> +        pc = PCI_DEVICE_GET_CLASS(pdev);
> +        dc = DEVICE_GET_CLASS(pdev);
> +
> +        /* When hotplug for bridges is enabled, bridges are
> +         * described in ACPI separately (see build_pci_bus_end).
> +         * In this case they aren't themselves hot-pluggable.
> +         * Hotplugged bridges *are* hot-pluggable.
> +         */
> +        bridge_in_acpi = pc->is_bridge && pcihp_bridge_en &&
> +            !DEVICE(pdev)->hotplugged;
> +
> +        hotplug_enabled_dev = bsel && dc->hotpluggable && !bridge_in_acpi;
> +
> +        if (pc->class_id == PCI_CLASS_BRIDGE_ISA) {
> +            continue;
> +        }
> +
> +        /* start to compose PCI slot descriptor */
> +        dev = aml_device("S%.02X", PCI_DEVFN(slot, 0));
> +        aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16)));
> +
> +        if (pc->class_id == PCI_CLASS_DISPLAY_VGA) {
> +            /* add VGA specific AML methods */
> +            int s3d;
> +
> +            if (object_dynamic_cast(OBJECT(pdev), "qxl-vga")) {
> +                s3d = 3;
> +            } else {
> +                s3d = 0;
> +            }
> +
> +            method = aml_method("_S1D", 0, AML_NOTSERIALIZED);
> +            aml_append(method, aml_return(aml_int(0)));
> +            aml_append(dev, method);
> +
> +            method = aml_method("_S2D", 0, AML_NOTSERIALIZED);
> +            aml_append(method, aml_return(aml_int(0)));
> +            aml_append(dev, method);
> +
> +            method = aml_method("_S3D", 0, AML_NOTSERIALIZED);
> +            aml_append(method, aml_return(aml_int(s3d)));
> +            aml_append(dev, method);
> +        } else if (hotplug_enabled_dev) {
> +            /* add _SUN/_EJ0 to make slot hotpluggable  */
> +            aml_append(dev, aml_name_decl("_SUN", aml_int(slot)));
> +
> +            method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
> +            aml_append(method,
> +                aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN"))
> +            );
> +            aml_append(dev, method);
> +
> +            if (bsel) {
> +                build_append_pcihp_notify_entry(notify_method, slot);
> +            }
> +        } else if (bridge_in_acpi) {
> +            /*
> +             * device is coldplugged bridge,
> +             * add child device descriptions into its scope
> +             */
> +            PCIBus *sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(pdev));
> +
> +            build_append_pci_bus_devices(dev, sec_bus, pcihp_bridge_en);
> +        }
> +        /* slot descriptor has been composed, add it into parent context */
> +        aml_append(parent_scope, dev);
> +    }
> +
> +    if (bsel) {
> +        aml_append(parent_scope, notify_method);
> +    }
> +
> +    /* Append PCNT method to notify about events on local and child buses.
> +     * Add unconditionally for root since DSDT expects it.
> +     */
> +    method = aml_method("PCNT", 0, AML_NOTSERIALIZED);
> +
> +    /* If bus supports hotplug select it and notify about local events */
> +    if (bsel) {
> +        uint64_t bsel_val = qnum_get_uint(qobject_to(QNum, bsel));
> +
> +        aml_append(method, aml_store(aml_int(bsel_val), aml_name("BNUM")));
> +        aml_append(method,
> +            aml_call2("DVNT", aml_name("PCIU"), aml_int(1) /* Device Check */)
> +        );
> +        aml_append(method,
> +            aml_call2("DVNT", aml_name("PCID"), aml_int(3)/* Eject Request */)
> +        );
> +    }
> +
> +    /* Notify about child bus events in any case */
> +    if (pcihp_bridge_en) {
> +        QLIST_FOREACH(sec, &bus->child, sibling) {
> +            int32_t devfn = sec->parent_dev->devfn;
> +
> +            if (pci_bus_is_root(sec) || pci_bus_is_express(sec)) {
> +                continue;
> +            }
> +
> +            aml_append(method, aml_name("^S%.02X.PCNT", devfn));
> +        }
> +    }
> +    aml_append(parent_scope, method);
> +    qobject_unref(bsel);
> +}
> +
>   void acpi_dsdt_add_pci_bus(Aml *dsdt, AcpiPciBus *pci_host)
>   {
>       Aml *dev, *pci_scope;
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 5932dbe825..9cb739bf5c 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -362,163 +362,6 @@ build_madt(GArray *table_data, BIOSLinker *linker,
>                    table_data->len - madt_start, 1, NULL, NULL);
>   }
>
> -static void build_append_pcihp_notify_entry(Aml *method, int slot)
> -{
> -    Aml *if_ctx;
> -    int32_t devfn = PCI_DEVFN(slot, 0);
> -
> -    if_ctx = aml_if(aml_and(aml_arg(0), aml_int(0x1U << slot), NULL));
> -    aml_append(if_ctx, aml_notify(aml_name("S%.02X", devfn), aml_arg(1)));
> -    aml_append(method, if_ctx);
> -}
> -
> -static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
> -                                         bool pcihp_bridge_en)
> -{
> -    Aml *dev, *notify_method = NULL, *method;
> -    QObject *bsel;
> -    PCIBus *sec;
> -    int i;
> -
> -    bsel = object_property_get_qobject(OBJECT(bus), ACPI_PCIHP_PROP_BSEL, NULL);
> -    if (bsel) {
> -        uint64_t bsel_val = qnum_get_uint(qobject_to(QNum, bsel));
> -
> -        aml_append(parent_scope, aml_name_decl("BSEL", aml_int(bsel_val)));
> -        notify_method = aml_method("DVNT", 2, AML_NOTSERIALIZED);
> -    }
> -
> -    for (i = 0; i < ARRAY_SIZE(bus->devices); i += PCI_FUNC_MAX) {
> -        DeviceClass *dc;
> -        PCIDeviceClass *pc;
> -        PCIDevice *pdev = bus->devices[i];
> -        int slot = PCI_SLOT(i);
> -        bool hotplug_enabled_dev;
> -        bool bridge_in_acpi;
> -
> -        if (!pdev) {
> -            if (bsel) { /* add hotplug slots for non present devices */
> -                dev = aml_device("S%.02X", PCI_DEVFN(slot, 0));
> -                aml_append(dev, aml_name_decl("_SUN", aml_int(slot)));
> -                aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16)));
> -                method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
> -                aml_append(method,
> -                    aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN"))
> -                );
> -                aml_append(dev, method);
> -                aml_append(parent_scope, dev);
> -
> -                build_append_pcihp_notify_entry(notify_method, slot);
> -            }
> -            continue;
> -        }
> -
> -        pc = PCI_DEVICE_GET_CLASS(pdev);
> -        dc = DEVICE_GET_CLASS(pdev);
> -
> -        /* When hotplug for bridges is enabled, bridges are
> -         * described in ACPI separately (see build_pci_bus_end).
> -         * In this case they aren't themselves hot-pluggable.
> -         * Hotplugged bridges *are* hot-pluggable.
> -         */
> -        bridge_in_acpi = pc->is_bridge && pcihp_bridge_en &&
> -            !DEVICE(pdev)->hotplugged;
> -
> -        hotplug_enabled_dev = bsel && dc->hotpluggable && !bridge_in_acpi;
> -
> -        if (pc->class_id == PCI_CLASS_BRIDGE_ISA) {
> -            continue;
> -        }
> -
> -        /* start to compose PCI slot descriptor */
> -        dev = aml_device("S%.02X", PCI_DEVFN(slot, 0));
> -        aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16)));
> -
> -        if (pc->class_id == PCI_CLASS_DISPLAY_VGA) {
> -            /* add VGA specific AML methods */
> -            int s3d;
> -
> -            if (object_dynamic_cast(OBJECT(pdev), "qxl-vga")) {
> -                s3d = 3;
> -            } else {
> -                s3d = 0;
> -            }
> -
> -            method = aml_method("_S1D", 0, AML_NOTSERIALIZED);
> -            aml_append(method, aml_return(aml_int(0)));
> -            aml_append(dev, method);
> -
> -            method = aml_method("_S2D", 0, AML_NOTSERIALIZED);
> -            aml_append(method, aml_return(aml_int(0)));
> -            aml_append(dev, method);
> -
> -            method = aml_method("_S3D", 0, AML_NOTSERIALIZED);
> -            aml_append(method, aml_return(aml_int(s3d)));
> -            aml_append(dev, method);
> -        } else if (hotplug_enabled_dev) {
> -            /* add _SUN/_EJ0 to make slot hotpluggable  */
> -            aml_append(dev, aml_name_decl("_SUN", aml_int(slot)));
> -
> -            method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
> -            aml_append(method,
> -                aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN"))
> -            );
> -            aml_append(dev, method);
> -
> -            if (bsel) {
> -                build_append_pcihp_notify_entry(notify_method, slot);
> -            }
> -        } else if (bridge_in_acpi) {
> -            /*
> -             * device is coldplugged bridge,
> -             * add child device descriptions into its scope
> -             */
> -            PCIBus *sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(pdev));
> -
> -            build_append_pci_bus_devices(dev, sec_bus, pcihp_bridge_en);
> -        }
> -        /* slot descriptor has been composed, add it into parent context */
> -        aml_append(parent_scope, dev);
> -    }
> -
> -    if (bsel) {
> -        aml_append(parent_scope, notify_method);
> -    }
> -
> -    /* Append PCNT method to notify about events on local and child buses.
> -     * Add unconditionally for root since DSDT expects it.
> -     */
> -    method = aml_method("PCNT", 0, AML_NOTSERIALIZED);
> -
> -    /* If bus supports hotplug select it and notify about local events */
> -    if (bsel) {
> -        uint64_t bsel_val = qnum_get_uint(qobject_to(QNum, bsel));
> -
> -        aml_append(method, aml_store(aml_int(bsel_val), aml_name("BNUM")));
> -        aml_append(method,
> -            aml_call2("DVNT", aml_name("PCIU"), aml_int(1) /* Device Check */)
> -        );
> -        aml_append(method,
> -            aml_call2("DVNT", aml_name("PCID"), aml_int(3)/* Eject Request */)
> -        );
> -    }
> -
> -    /* Notify about child bus events in any case */
> -    if (pcihp_bridge_en) {
> -        QLIST_FOREACH(sec, &bus->child, sibling) {
> -            int32_t devfn = sec->parent_dev->devfn;
> -
> -            if (pci_bus_is_root(sec) || pci_bus_is_express(sec)) {
> -                continue;
> -            }
> -
> -            aml_append(method, aml_name("^S%.02X.PCNT", devfn));
> -        }
> -    }
> -    aml_append(parent_scope, method);
> -    qobject_unref(bsel);
> -}
> -
>   static void build_hpet_aml(Aml *table)
>   {
>       Aml *crs;
> @@ -1214,41 +1057,10 @@ static void build_piix4_isa_bridge(Aml *table)
>   static void build_piix4_pci_hotplug(Aml *table)
>   {
>       Aml *scope;
> -    Aml *field;
> -    Aml *method;
> -
> -    scope =  aml_scope("_SB.PCI0");
> -
> -    aml_append(scope,
> -        aml_operation_region("PCST", AML_SYSTEM_IO, aml_int(0xae00), 0x08));
> -    field = aml_field("PCST", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
> -    aml_append(field, aml_named_field("PCIU", 32));
> -    aml_append(field, aml_named_field("PCID", 32));
> -    aml_append(scope, field);
>
> -    aml_append(scope,
> -        aml_operation_region("SEJ", AML_SYSTEM_IO, aml_int(0xae08), 0x04));
> -    field = aml_field("SEJ", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
> -    aml_append(field, aml_named_field("B0EJ", 32));
> -    aml_append(scope, field);
> -
> -    aml_append(scope,
> -        aml_operation_region("BNMR", AML_SYSTEM_IO, aml_int(0xae10), 0x04));
> -    field = aml_field("BNMR", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
> -    aml_append(field, aml_named_field("BNUM", 32));
> -    aml_append(scope, field);
> -
> -    aml_append(scope, aml_mutex("BLCK", 0));
> -
> -    method = aml_method("PCEJ", 2, AML_NOTSERIALIZED);
> -    aml_append(method, aml_acquire(aml_name("BLCK"), 0xFFFF));
> -    aml_append(method, aml_store(aml_arg(0), aml_name("BNUM")));
> -    aml_append(method,
> -        aml_store(aml_shiftleft(aml_int(1), aml_arg(1)), aml_name("B0EJ")));
> -    aml_append(method, aml_release(aml_name("BLCK")));
> -    aml_append(method, aml_return(aml_int(0)));
> -    aml_append(scope, method);
> +    scope = aml_scope("_SB.PCI0");
>
> +    build_acpi_pci_hotplug(scope);
>       aml_append(table, scope);
>   }
>
> diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
> index 654ce2ec26..3ea2df5f83 100644
> --- a/include/hw/acpi/aml-build.h
> +++ b/include/hw/acpi/aml-build.h
> @@ -419,6 +419,9 @@ Aml *build_osc_method(uint32_t value);
>   void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info);
>   Aml *build_gsi_link_dev(const char *name, uint8_t uid, uint8_t gsi);
>   Aml *build_prt(bool is_pci0_prt);
> +void build_acpi_pci_hotplug(Aml *scope);
> +void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
> +                                  bool pcihp_bridge_en);
>   void acpi_dsdt_add_pci_bus(Aml *dsdt, AcpiPciBus *pci_host);
>   Aml *build_pci_host_bridge(Aml *table, AcpiPciBus *pci_host);
>   void crs_range_set_init(CrsRangeSet *range_set);
>

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 16/19] hw: acpi: Retrieve the PCI bus from AcpiPciHpState
  2018-10-29 21:02   ` Philippe Mathieu-Daudé
@ 2018-10-29 23:35     ` Boeuf, Sebastien
  0 siblings, 0 replies; 47+ messages in thread
From: Boeuf, Sebastien @ 2018-10-29 23:35 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, Samuel Ortiz, qemu-devel
  Cc: Michael S. Tsirkin, Jing Liu, Paolo Bonzini, Igor Mammedov

Glad you think it's worth it.

Thanks,
Sebastien
________________________________________
From: Philippe Mathieu-Daudé [philmd@redhat.com]
Sent: Monday, October 29, 2018 2:02 PM
To: Samuel Ortiz; qemu-devel@nongnu.org
Cc: Michael S. Tsirkin; Jing Liu; Boeuf, Sebastien; Paolo Bonzini; Igor Mammedov
Subject: Re: [Qemu-devel] [PATCH v3 16/19] hw: acpi: Retrieve the PCI bus from AcpiPciHpState

On 29/10/18 18:01, Samuel Ortiz wrote:
> From: Sebastien Boeuf <sebastien.boeuf@intel.com>
>
> Instead of using the machine type specific method find_i440fx() to
> retrieve the PCI bus, this commit aims to rely on the fact that the
> PCI bus is known by the structure AcpiPciHpState.
>
> When the structure is initialized through acpi_pcihp_init() call,
> it saves the PCI bus, which means there is no need to invoke a
> special function later on.
>
> Based on the fact that find_i440fx() was only used there, this
> patch also removes the function find_i440fx() itself from the
> entire codebase.

Nice :)

>
> Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
> Signed-off-by: Jing Liu <jing2.liu@linux.intel.com>

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>

> ---
>   hw/acpi/pcihp.c       | 10 ++++------
>   hw/pci-host/piix.c    |  8 --------
>   include/hw/i386/pc.h  |  1 -
>   stubs/Makefile.objs   |  1 -
>   stubs/pci-host-piix.c |  6 ------
>   5 files changed, 4 insertions(+), 22 deletions(-)
>   delete mode 100644 stubs/pci-host-piix.c
>
> diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
> index 80d42e12ff..254b2e50ab 100644
> --- a/hw/acpi/pcihp.c
> +++ b/hw/acpi/pcihp.c
> @@ -93,10 +93,9 @@ static void *acpi_set_bsel(PCIBus *bus, void *opaque)
>       return bsel_alloc;
>   }
>
> -static void acpi_set_pci_info(void)
> +static void acpi_set_pci_info(AcpiPciHpState *s)
>   {
>       static bool bsel_is_set;
> -    PCIBus *bus;
>       unsigned bsel_alloc = ACPI_PCIHP_BSEL_DEFAULT;
>
>       if (bsel_is_set) {
> @@ -104,10 +103,9 @@ static void acpi_set_pci_info(void)
>       }
>       bsel_is_set = true;
>
> -    bus = find_i440fx(); /* TODO: Q35 support */
> -    if (bus) {
> +    if (s->root) {
>           /* Scan all PCI buses. Set property to enable acpi based hotplug. */
> -        pci_for_each_bus_depth_first(bus, acpi_set_bsel, NULL, &bsel_alloc);
> +        pci_for_each_bus_depth_first(s->root, acpi_set_bsel, NULL, &bsel_alloc);
>       }
>   }
>
> @@ -213,7 +211,7 @@ static void acpi_pcihp_update(AcpiPciHpState *s)
>
>   void acpi_pcihp_reset(AcpiPciHpState *s)
>   {
> -    acpi_set_pci_info();
> +    acpi_set_pci_info(s);
>       acpi_pcihp_update(s);
>   }
>
> diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
> index da73743fa2..4940f59c9b 100644
> --- a/hw/pci-host/piix.c
> +++ b/hw/pci-host/piix.c
> @@ -445,14 +445,6 @@ PCIBus *i440fx_init(const char *host_type, const char *pci_type,
>       return b;
>   }
>
> -PCIBus *find_i440fx(void)
> -{
> -    PCIHostState *s = OBJECT_CHECK(PCIHostState,
> -                                   object_resolve_path("/machine/i440fx", NULL),
> -                                   TYPE_PCI_HOST_BRIDGE);
> -    return s ? s->bus : NULL;
> -}
> -
>   /* PIIX3 PCI to ISA bridge */
>   static void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq)
>   {
> diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
> index 7d177cd207..f6b2649cf8 100644
> --- a/include/hw/i386/pc.h
> +++ b/include/hw/i386/pc.h
> @@ -260,7 +260,6 @@ PCIBus *i440fx_init(const char *host_type, const char *pci_type,
>                       MemoryRegion *pci_memory,
>                       MemoryRegion *ram_memory);
>
> -PCIBus *find_i440fx(void);
>   /* piix4.c */
>   extern PCIDevice *piix4_dev;
>   int piix4_init(PCIBus *bus, ISABus **isa_bus, int devfn);
> diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
> index 5dd0aeeec6..725f78bedc 100644
> --- a/stubs/Makefile.objs
> +++ b/stubs/Makefile.objs
> @@ -41,6 +41,5 @@ stub-obj-y += pc_madt_cpu_entry.o
>   stub-obj-y += vmgenid.o
>   stub-obj-y += xen-common.o
>   stub-obj-y += xen-hvm.o
> -stub-obj-y += pci-host-piix.o
>   stub-obj-y += ram-block.o
>   stub-obj-y += ramfb.o
> diff --git a/stubs/pci-host-piix.c b/stubs/pci-host-piix.c
> deleted file mode 100644
> index 6ed81b1f21..0000000000
> --- a/stubs/pci-host-piix.c
> +++ /dev/null
> @@ -1,6 +0,0 @@
> -#include "qemu/osdep.h"
> -#include "hw/i386/pc.h"
> -PCIBus *find_i440fx(void)
> -{
> -    return NULL;
> -}
>

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 19/19] hw: i386: Implement the ACPI builder interface for PC
  2018-10-29 17:28   ` Paolo Bonzini
@ 2018-10-30 14:13     ` Samuel Ortiz
  2018-10-30 16:03       ` Paolo Bonzini
  0 siblings, 1 reply; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-30 14:13 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: qemu-devel, Eduardo Habkost, Michael S. Tsirkin, Igor Mammedov,
	Richard Henderson

Hi Paolo,

On Mon, Oct 29, 2018 at 06:28:39PM +0100, Paolo Bonzini wrote:
> On 29/10/2018 18:01, Samuel Ortiz wrote:
> > @@ -1556,6 +1557,7 @@ void acpi_build(AcpiBuildTables *tables,
> >      GArray *tables_blob = tables->table_data;
> >      AcpiSlicOem slic_oem = { .id = NULL, .table_id = NULL };
> >      Object *vmgenid_dev;
> > +    AcpiBuilder *ab = ACPI_BUILDER(machine);
> >  
> >      acpi_get_pm_info(&pm);
> >      acpi_get_misc_info(&misc);
> > @@ -1605,7 +1607,8 @@ void acpi_build(AcpiBuildTables *tables,
> >      aml_len += tables_blob->len - fadt;
> >  
> >      acpi_add_table(table_offsets, tables_blob);
> > -    build_madt(tables_blob, tables->linker, machine, conf);
> > +    acpi_builder_madt(ab, tables_blob, tables->linker,
> > +                      machine, conf);
> >  
> >      vmgenid_dev = find_vmgenid_dev();
> >      if (vmgenid_dev) {
> 
> Just a quick question before I go and actually apply the patches to look
> at the resulting code: is there any reason why you didn't add the
> MachineState and/or AcpiBuilder to AcpiBuildState, similar to how it was
> in v1?
With v1 I was not adding MachineState to AcpiBuildState, I may be
missing your point.
Do you mean adding an AcpiBuilder pointer to AcpiConfiguration?

Cheers,
Samuel.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 09/19] hw: acpi: Export and generalize the PCI host AML API
  2018-10-29 19:29     ` Philippe Mathieu-Daudé
@ 2018-10-30 14:57       ` Samuel Ortiz
  2018-10-30 18:04         ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-30 14:57 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: qemu-devel, Yang Zhong, Eduardo Habkost, Rob Bradford,
	Michael S. Tsirkin, Igor Mammedov, Paolo Bonzini,
	Richard Henderson

Hi Philippe,

On Mon, Oct 29, 2018 at 08:29:38PM +0100, Philippe Mathieu-Daudé wrote:
> On 29/10/18 20:23, Philippe Mathieu-Daudé wrote:
> > On 29/10/18 18:01, Samuel Ortiz wrote:
> > > From: Yang Zhong <yang.zhong@intel.com>
> > > 
> > > The AML build routines for the PCI host bridge and the corresponding
> > > DSDT addition are neither x86 nor PC machine type specific.
> > > We can move them to the architecture agnostic hw/acpi folder, and by
> > > carrying all the needed information through a new AcpiPciBus structure,
> > > we can make them PC machine type independent.
> > > 
> > > Signed-off-by: Yang Zhong <yang.zhong@intel.com>
> > > Signed-off-by: Rob Bradford <robert.bradford@intel.com>
> > > ---
> > >   hw/acpi/aml-build.c         | 208 ++++++++++++++++++++++++++++++++++++
> > >   hw/i386/acpi-build.c        | 167 ++---------------------------
> > >   include/hw/acpi/aml-build.h |  10 ++
> > >   3 files changed, 226 insertions(+), 159 deletions(-)
> > > 
> > > diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> > > index 52ac39acdb..aa72b5459c 100644
> > > --- a/hw/acpi/aml-build.c
> > > +++ b/hw/acpi/aml-build.c
> > > @@ -29,6 +29,25 @@
> > >   #include "hw/pci/pci_bus.h"
> > >   #include "qemu/range.h"
> > >   #include "hw/pci/pci_bridge.h"
> > > +#include "hw/i386/pc.h"
> 
> Err I just missed that, this include doesn't belong here, ...
> 
> > > +#include "sysemu/tpm.h"
> > > +#include "hw/acpi/tpm.h"
> > > +
> > > +#define PCI_HOST_BRIDGE_CONFIG_ADDR        0xcf8
> > > +#define PCI_HOST_BRIDGE_IO_0_MIN_ADDR      0x0000
> > > +#define PCI_HOST_BRIDGE_IO_0_MAX_ADDR      0x0cf7
> > > +#define PCI_HOST_BRIDGE_IO_1_MIN_ADDR      0x0d00
> > > +#define PCI_HOST_BRIDGE_IO_1_MAX_ADDR      0xffff
> > > +#define PCI_VGA_MEM_BASE_ADDR              0x000a0000
> > > +#define PCI_VGA_MEM_MAX_ADDR               0x000bffff
> > > +#define IO_0_LEN                           0xcf8
> > > +#define VGA_MEM_LEN                        0x20000
> > > +
> > > +static const char *pci_hosts[] = {
> > 
> > This array should stay in hw/i386/acpi-build.c.
> > 
> > > +   "/machine/i440fx",
> > > +   "/machine/q35",
> > > +   NULL,
> > > +};
> > >   static GArray *build_alloc_array(void)
> > >   {
> > > @@ -1601,6 +1620,51 @@ void
> > > acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
> > >       g_array_free(tables->vmgenid, mfre);
> > >   }
> > > +/*
> > > + * Because of the PXB hosts we cannot simply query TYPE_PCI_HOST_BRIDGE.
> > > + */
> > > +Object *acpi_get_pci_host(void)
> > 
> > This function should take the machine_paths as argument.
> > 
> > > +{
> > > +    PCIHostState *host;
> > > +    int i = 0;
> > > +
> > > +    while (pci_hosts[i]) {
> > > +        host = OBJECT_CHECK(PCIHostState,
> > > +                            object_resolve_path(pci_hosts[i], NULL),
> > > +                            TYPE_PCI_HOST_BRIDGE);
> > > +        if (host) {
> > > +            return OBJECT(host);
> > > +        }
> > > +
> > > +        i++;
> > > +    }
> > > +
> > > +    return NULL;
> > > +}
> > > +
> > > +void acpi_get_pci_holes(Range *hole, Range *hole64)
> 
> ... and this function neither, it should stay in hw/i386/acpi-build.c, thus
> you don't need to modify the prototype and can call
> acpi_get_pci_host(x86_machine_paths) directly.
>
So the idea for those routines is that they're not x86 specific. As a
matter of fact, they will eventually get called from architecture
agnostic code like e.g. hw/acpi/reduced.c. So I don't think they should
live under hw/i386/

Moreover adding an argument to acpi_get_pci_host() means the caller should
know which potential machines it needs to go through. And once both
arm/virt and i386/virt calls into hw/acpi/reduced.c, we need to somehow
pass a relevant set of machines paths to this API.
So I think a more robust way to do so would be for each machine instance to
be able to set its own PCI host pointer instead of having to maintain
a per architecture set of potential PCI machine paths. I'm thinking
about adding that to the AcpiConfiguration structure and let each
machine fills it if/when it builds its PCI host.

Cheers,
Samuel.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 19/19] hw: i386: Implement the ACPI builder interface for PC
  2018-10-30 14:13     ` Samuel Ortiz
@ 2018-10-30 16:03       ` Paolo Bonzini
  2018-10-31  1:02         ` Samuel Ortiz
  0 siblings, 1 reply; 47+ messages in thread
From: Paolo Bonzini @ 2018-10-30 16:03 UTC (permalink / raw)
  To: Samuel Ortiz
  Cc: qemu-devel, Eduardo Habkost, Michael S. Tsirkin, Igor Mammedov,
	Richard Henderson

On 30/10/2018 15:13, Samuel Ortiz wrote:
>> Just a quick question before I go and actually apply the patches to look
>> at the resulting code: is there any reason why you didn't add the
>> MachineState and/or AcpiBuilder to AcpiBuildState, similar to how it was
>> in v1?
>
> With v1 I was not adding MachineState to AcpiBuildState, I may be
> missing your point.
> Do you mean adding an AcpiBuilder pointer to AcpiConfiguration?

No, what I was remembering is the FirmwareBuildState, which you have
removed according to my review.  Sorry, KVM Forum was a bit exhausting. :)

I think adding the MachineState or AcpiBuilder to AcpiBuildState instead
of using qdev_get_machine() makes sense, but it is an independent cleanup.

Paolo

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 09/19] hw: acpi: Export and generalize the PCI host AML API
  2018-10-30 14:57       ` Samuel Ortiz
@ 2018-10-30 18:04         ` Philippe Mathieu-Daudé
  2018-10-31 10:46           ` Samuel Ortiz
  0 siblings, 1 reply; 47+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-10-30 18:04 UTC (permalink / raw)
  To: Samuel Ortiz
  Cc: qemu-devel, Yang Zhong, Eduardo Habkost, Rob Bradford,
	Michael S. Tsirkin, Igor Mammedov, Paolo Bonzini,
	Richard Henderson

Hi Samuel,

On 30/10/18 15:57, Samuel Ortiz wrote:
> Hi Philippe,
> 
> On Mon, Oct 29, 2018 at 08:29:38PM +0100, Philippe Mathieu-Daudé wrote:
>> On 29/10/18 20:23, Philippe Mathieu-Daudé wrote:
>>> On 29/10/18 18:01, Samuel Ortiz wrote:
>>>> From: Yang Zhong <yang.zhong@intel.com>
>>>>
>>>> The AML build routines for the PCI host bridge and the corresponding
>>>> DSDT addition are neither x86 nor PC machine type specific.
>>>> We can move them to the architecture agnostic hw/acpi folder, and by
>>>> carrying all the needed information through a new AcpiPciBus structure,
>>>> we can make them PC machine type independent.
>>>>
>>>> Signed-off-by: Yang Zhong <yang.zhong@intel.com>
>>>> Signed-off-by: Rob Bradford <robert.bradford@intel.com>
>>>> ---
>>>>    hw/acpi/aml-build.c         | 208 ++++++++++++++++++++++++++++++++++++
>>>>    hw/i386/acpi-build.c        | 167 ++---------------------------
>>>>    include/hw/acpi/aml-build.h |  10 ++
>>>>    3 files changed, 226 insertions(+), 159 deletions(-)
>>>>
>>>> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
>>>> index 52ac39acdb..aa72b5459c 100644
>>>> --- a/hw/acpi/aml-build.c
>>>> +++ b/hw/acpi/aml-build.c
>>>> @@ -29,6 +29,25 @@
>>>>    #include "hw/pci/pci_bus.h"
>>>>    #include "qemu/range.h"
>>>>    #include "hw/pci/pci_bridge.h"
>>>> +#include "hw/i386/pc.h"
>>
>> Err I just missed that, this include doesn't belong here, ...
>>
>>>> +#include "sysemu/tpm.h"
>>>> +#include "hw/acpi/tpm.h"
>>>> +
>>>> +#define PCI_HOST_BRIDGE_CONFIG_ADDR        0xcf8
>>>> +#define PCI_HOST_BRIDGE_IO_0_MIN_ADDR      0x0000
>>>> +#define PCI_HOST_BRIDGE_IO_0_MAX_ADDR      0x0cf7
>>>> +#define PCI_HOST_BRIDGE_IO_1_MIN_ADDR      0x0d00
>>>> +#define PCI_HOST_BRIDGE_IO_1_MAX_ADDR      0xffff
>>>> +#define PCI_VGA_MEM_BASE_ADDR              0x000a0000
>>>> +#define PCI_VGA_MEM_MAX_ADDR               0x000bffff
>>>> +#define IO_0_LEN                           0xcf8
>>>> +#define VGA_MEM_LEN                        0x20000
>>>> +
>>>> +static const char *pci_hosts[] = {
>>>
>>> This array should stay in hw/i386/acpi-build.c.
>>>
>>>> +   "/machine/i440fx",
>>>> +   "/machine/q35",
>>>> +   NULL,
>>>> +};
>>>>    static GArray *build_alloc_array(void)
>>>>    {
>>>> @@ -1601,6 +1620,51 @@ void
>>>> acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
>>>>        g_array_free(tables->vmgenid, mfre);
>>>>    }
>>>> +/*
>>>> + * Because of the PXB hosts we cannot simply query TYPE_PCI_HOST_BRIDGE.
>>>> + */
>>>> +Object *acpi_get_pci_host(void)
>>>
>>> This function should take the machine_paths as argument.
>>>
>>>> +{
>>>> +    PCIHostState *host;
>>>> +    int i = 0;
>>>> +
>>>> +    while (pci_hosts[i]) {
>>>> +        host = OBJECT_CHECK(PCIHostState,
>>>> +                            object_resolve_path(pci_hosts[i], NULL),
>>>> +                            TYPE_PCI_HOST_BRIDGE);
>>>> +        if (host) {
>>>> +            return OBJECT(host);
>>>> +        }
>>>> +
>>>> +        i++;
>>>> +    }
>>>> +
>>>> +    return NULL;
>>>> +}
>>>> +
>>>> +void acpi_get_pci_holes(Range *hole, Range *hole64)
>>
>> ... and this function neither, it should stay in hw/i386/acpi-build.c, thus
>> you don't need to modify the prototype and can call
>> acpi_get_pci_host(x86_machine_paths) directly.
>>
> So the idea for those routines is that they're not x86 specific. As a
> matter of fact, they will eventually get called from architecture
> agnostic code like e.g. hw/acpi/reduced.c. So I don't think they should
> live under hw/i386/

But PCI_HOST_PROP_PCI_HOLE_START is only defined in "hw/i386/pc.h"... 
This file is no more arch agnostic.

I can understand/accept a acpi_get_pci_holes() function, but the ranges 
shouldn't be i386 based.

> 
> Moreover adding an argument to acpi_get_pci_host() means the caller should
> know which potential machines it needs to go through. And once both
> arm/virt and i386/virt calls into hw/acpi/reduced.c, we need to somehow
> pass a relevant set of machines paths to this API.
> So I think a more robust way to do so would be for each machine instance to
> be able to set its own PCI host pointer instead of having to maintain
> a per architecture set of potential PCI machine paths. I'm thinking
> about adding that to the AcpiConfiguration structure and let each
> machine fills it if/when it builds its PCI host.
> 
> Cheers,
> Samuel.
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 19/19] hw: i386: Implement the ACPI builder interface for PC
  2018-10-30 16:03       ` Paolo Bonzini
@ 2018-10-31  1:02         ` Samuel Ortiz
  0 siblings, 0 replies; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-31  1:02 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Igor Mammedov, Richard Henderson, Michael S. Tsirkin, qemu-devel,
	Eduardo Habkost

On Tue, Oct 30, 2018 at 05:03:28PM +0100, Paolo Bonzini wrote:
> On 30/10/2018 15:13, Samuel Ortiz wrote:
> >> Just a quick question before I go and actually apply the patches to look
> >> at the resulting code: is there any reason why you didn't add the
> >> MachineState and/or AcpiBuilder to AcpiBuildState, similar to how it was
> >> in v1?
> >
> > With v1 I was not adding MachineState to AcpiBuildState, I may be
> > missing your point.
> > Do you mean adding an AcpiBuilder pointer to AcpiConfiguration?
> 
> No, what I was remembering is the FirmwareBuildState, which you have
> removed according to my review.  Sorry, KVM Forum was a bit exhausting. :)
No worries, it was exhausting indeed :)

Cheers,
Samuel.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH v3 09/19] hw: acpi: Export and generalize the PCI host AML API
  2018-10-30 18:04         ` Philippe Mathieu-Daudé
@ 2018-10-31 10:46           ` Samuel Ortiz
  0 siblings, 0 replies; 47+ messages in thread
From: Samuel Ortiz @ 2018-10-31 10:46 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: qemu-devel, Yang Zhong, Eduardo Habkost, Rob Bradford,
	Michael S. Tsirkin, Igor Mammedov, Paolo Bonzini,
	Richard Henderson

Hi Philippe,

On Tue, Oct 30, 2018 at 07:04:15PM +0100, Philippe Mathieu-Daudé wrote:
> > > > > +void acpi_get_pci_holes(Range *hole, Range *hole64)
> > > 
> > > ... and this function neither, it should stay in hw/i386/acpi-build.c, thus
> > > you don't need to modify the prototype and can call
> > > acpi_get_pci_host(x86_machine_paths) directly.
> > > 
> > So the idea for those routines is that they're not x86 specific. As a
> > matter of fact, they will eventually get called from architecture
> > agnostic code like e.g. hw/acpi/reduced.c. So I don't think they should
> > live under hw/i386/
> 
> But PCI_HOST_PROP_PCI_HOLE_START is only defined in "hw/i386/pc.h"... This
> file is no more arch agnostic.
> 
> I can understand/accept a acpi_get_pci_holes() function, but the ranges
> shouldn't be i386 based.
Agreed, and your reviews thankfully highlighted that part.
Neither acpi_get_pci_host nor acpi_get_pci_holes should be arch specific
and I'll fix that.

Cheers,
Samuel.

^ permalink raw reply	[flat|nested] 47+ messages in thread

end of thread, other threads:[~2018-10-31 10:47 UTC | newest]

Thread overview: 47+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-29 17:01 [Qemu-devel] [PATCH v3 00/19] ACPI reorganization for hardware-reduced support Samuel Ortiz
2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 01/19] hw: i386: Decouple the ACPI build from the PC machine type Samuel Ortiz
2018-10-29 19:50   ` Philippe Mathieu-Daudé
2018-10-29 19:50     ` Philippe Mathieu-Daudé
2018-10-29 17:01 ` Samuel Ortiz
2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 02/19] hw: acpi: Export ACPI build alignment API Samuel Ortiz
2018-10-29 19:01   ` Philippe Mathieu-Daudé
2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 03/19] hw: acpi: Export the RSDP build API Samuel Ortiz
2018-10-29 18:58   ` Philippe Mathieu-Daudé
2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 04/19] hw: acpi: Implement XSDT support for RSDP Samuel Ortiz
2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 05/19] hw: arm: Switch to the AML build RSDP building routine Samuel Ortiz
2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 06/19] hw: acpi: Generalize AML build routines Samuel Ortiz
2018-10-29 19:09   ` Philippe Mathieu-Daudé
2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 07/19] hw: acpi: Factorize _OSC AML across architectures Samuel Ortiz
2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 08/19] hw: i386: Refactor PCI host getter Samuel Ortiz
2018-10-29 19:18   ` Philippe Mathieu-Daudé
2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 09/19] hw: acpi: Export and generalize the PCI host AML API Samuel Ortiz
2018-10-29 19:23   ` Philippe Mathieu-Daudé
2018-10-29 19:29     ` Philippe Mathieu-Daudé
2018-10-30 14:57       ` Samuel Ortiz
2018-10-30 18:04         ` Philippe Mathieu-Daudé
2018-10-31 10:46           ` Samuel Ortiz
2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 10/19] hw: acpi: Export the MCFG getter Samuel Ortiz
2018-10-29 19:31   ` Philippe Mathieu-Daudé
2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 11/19] hw: acpi: Do not create hotplug method when handler is not defined Samuel Ortiz
2018-10-29 19:33   ` Philippe Mathieu-Daudé
2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 12/19] hw: i386: Make the hotpluggable memory size property more generic Samuel Ortiz
2018-10-29 19:38   ` Philippe Mathieu-Daudé
2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 13/19] hw: acpi: Export the SRAT AML build API Samuel Ortiz
2018-10-29 19:40   ` Philippe Mathieu-Daudé
2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 14/19] hw: acpi: Fix memory hotplug AML generation error Samuel Ortiz
2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 15/19] hw: acpi: Export the PCI hotplug API Samuel Ortiz
2018-10-29 19:46   ` Philippe Mathieu-Daudé
2018-10-29 23:34     ` Boeuf, Sebastien
2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 16/19] hw: acpi: Retrieve the PCI bus from AcpiPciHpState Samuel Ortiz
2018-10-29 21:02   ` Philippe Mathieu-Daudé
2018-10-29 23:35     ` Boeuf, Sebastien
2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 17/19] hw: acpi: Define ACPI tables builder interface Samuel Ortiz
2018-10-29 21:06   ` Philippe Mathieu-Daudé
2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 18/19] hw: i386: Export the MADT build method Samuel Ortiz
2018-10-29 21:18   ` Philippe Mathieu-Daudé
2018-10-29 17:01 ` [Qemu-devel] [PATCH v3 19/19] hw: i386: Implement the ACPI builder interface for PC Samuel Ortiz
2018-10-29 17:28   ` Paolo Bonzini
2018-10-30 14:13     ` Samuel Ortiz
2018-10-30 16:03       ` Paolo Bonzini
2018-10-31  1:02         ` Samuel Ortiz
2018-10-29 21:23   ` Philippe Mathieu-Daudé

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.