Set up the IO registers used to communicate between QEMU and ACPI. Move the create_pcie() call after the creation of the acpi ged device since hotplug callbacks will soon be called on gpex realize and will require the acpi pcihp state to be initialized.
The hacky thing is the root bus has not yet been created on acpi_pcihp_init() call so it is set later after the gpex realize. How to fix this chicken & egg issue? Signed-off-by: Eric Auger <eric.au...@redhat.com> --- include/hw/arm/virt.h | 1 + hw/arm/virt-acpi-build.c | 1 + hw/arm/virt.c | 42 +++++++++++++++++++++++++++++++++++----- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index 1b2e2e1284..a4c4e3a67a 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -35,6 +35,7 @@ #include "hw/boards.h" #include "hw/arm/boot.h" #include "hw/arm/bsa.h" +#include "hw/acpi/pcihp.h" #include "hw/block/flash.h" #include "system/kvm.h" #include "hw/intc/arm_gicv3_common.h" diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 2b642e2426..05a754d368 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -44,6 +44,7 @@ #include "hw/acpi/generic_event_device.h" #include "hw/acpi/tpm.h" #include "hw/acpi/hmat.h" +#include "hw/acpi/pcihp.h" #include "hw/pci/pcie_host.h" #include "hw/pci/pci.h" #include "hw/pci/pci_bus.h" diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 4aa40c8e8b..526c4c44be 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -682,6 +682,8 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms) { DeviceState *dev; MachineState *ms = MACHINE(vms); + SysBusDevice *sbdev; + int irq = vms->irqmap[VIRT_ACPI_GED]; uint32_t event = ACPI_GED_PWR_DOWN_EVT; @@ -693,12 +695,28 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms) event |= ACPI_GED_NVDIMM_HOTPLUG_EVT; } + if (vms->acpi_pcihp) { + event |= ACPI_GED_PCI_HOTPLUG_EVT; + } + dev = qdev_new(TYPE_ACPI_GED); qdev_prop_set_uint32(dev, "ged-event", event); - sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + sbdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(sbdev, &error_fatal); - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_ACPI_GED].base); - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, vms->memmap[VIRT_PCDIMM_ACPI].base); + sysbus_mmio_map(sbdev, 0, vms->memmap[VIRT_ACPI_GED].base); + sysbus_mmio_map(sbdev, 1, vms->memmap[VIRT_PCDIMM_ACPI].base); + if (vms->acpi_pcihp) { + AcpiGedState *acpi_ged_state = ACPI_GED(dev); + int i; + + i = sysbus_mmio_map_name(sbdev, "pcihp container", + vms->memmap[VIRT_ACPI_PCIHP].base); + assert(i >= 0); + acpi_pcihp_init(OBJECT(dev), &acpi_ged_state->pcihp_state, + vms->bus, sysbus_mmio_get_region(sbdev, i), 0); + acpi_ged_state->pcihp_state.use_acpi_hotplug_bridge = true; + } sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(vms->gic, irq)); return dev; @@ -1758,6 +1776,13 @@ void virt_machine_done(Notifier *notifier, void *data) pci_bus_add_fw_cfg_extra_pci_roots(vms->fw_cfg, vms->bus, &error_abort); + + if (vms->acpi_pcihp) { + AcpiGedState *acpi_ged_state = ACPI_GED(vms->acpi_dev); + + acpi_pcihp_reset(&acpi_ged_state->pcihp_state); + } + virt_acpi_setup(vms); virt_build_smbios(vms); } @@ -2395,8 +2420,6 @@ static void machvirt_init(MachineState *machine) create_rtc(vms); - create_pcie(vms); - if (has_ged && aarch64 && firmware_loaded && virt_is_acpi_enabled(vms)) { vms->acpi_pcihp &= !vmc->no_acpi_pcihp; vms->acpi_dev = create_acpi_ged(vms); @@ -2405,6 +2428,15 @@ static void machvirt_init(MachineState *machine) create_gpio_devices(vms, VIRT_GPIO, sysmem); } + create_pcie(vms); + + if (vms->acpi_dev) { + AcpiGedState *acpi_ged_state = ACPI_GED(vms->acpi_dev); + + acpi_ged_state = ACPI_GED(vms->acpi_dev); + acpi_ged_state->pcihp_state.root = vms->bus; + } + if (vms->secure && !vmc->no_secure_gpio) { create_gpio_devices(vms, VIRT_SECURE_GPIO, secure_sysmem); } -- 2.49.0