Signed-off-by: Eric Auger <eric.au...@redhat.com> --- v2 -> v3: - fix cohabitation with virtio-mem-pci device and tested hotplug/unplug of this latter (Igor) --- hw/arm/virt.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 3 deletions(-)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 8c882e0794..06b87e1050 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1747,6 +1747,22 @@ static void virt_build_smbios(VirtMachineState *vms) } } +static AcpiPciHpState *get_acpi_pcihp_state(VirtMachineState *vms) +{ + AcpiGedState *acpi_ged_state; + AcpiPciHpState *pcihp_state; + + if (!vms->acpi_dev) { + return NULL; + } + acpi_ged_state = ACPI_GED(vms->acpi_dev); + pcihp_state = &acpi_ged_state->pcihp_state; + if (pcihp_state->use_acpi_hotplug_bridge) { + return pcihp_state; + } + return NULL; +} + static void virt_machine_done(Notifier *notifier, void *data) { @@ -2907,6 +2923,13 @@ static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, { VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); + if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { + if (get_acpi_pcihp_state(vms)) { + acpi_pcihp_device_pre_plug_cb(HOTPLUG_HANDLER(vms->acpi_dev), + dev, errp); + } + } + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { virt_memory_pre_plug(hotplug_dev, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) { @@ -2961,6 +2984,15 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev, } } + if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { + AcpiPciHpState *pcihp_state = get_acpi_pcihp_state(vms); + + if (pcihp_state) { + acpi_pcihp_device_plug_cb(HOTPLUG_HANDLER(vms->acpi_dev), + pcihp_state, dev, errp); + } + } + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { virt_memory_plug(hotplug_dev, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) { @@ -3017,12 +3049,27 @@ out: static void virt_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { + bool supported = false; + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { virt_dimm_unplug_request(hotplug_dev, dev, errp); + supported = true; } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) { virtio_md_pci_unplug_request(VIRTIO_MD_PCI(dev), MACHINE(hotplug_dev), errp); - } else { + supported = true; + } + if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { + VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); + AcpiPciHpState *pcihp_state = get_acpi_pcihp_state(vms); + + if (pcihp_state) { + acpi_pcihp_device_unplug_request_cb(HOTPLUG_HANDLER(vms->acpi_dev), + pcihp_state, dev, errp); + supported = true; + } + } + if (!supported) { error_setg(errp, "device unplug request for unsupported device" " type: %s", object_get_typename(OBJECT(dev))); } @@ -3031,11 +3078,27 @@ static void virt_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev, static void virt_machine_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { + bool supported = false; + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { virt_dimm_unplug(hotplug_dev, dev, errp); + supported = true; } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) { virtio_md_pci_unplug(VIRTIO_MD_PCI(dev), MACHINE(hotplug_dev), errp); - } else { + supported = true; + } + if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { + VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); + + AcpiPciHpState *pcihp_state = get_acpi_pcihp_state(vms); + + if (pcihp_state) { + acpi_pcihp_device_unplug_cb(HOTPLUG_HANDLER(vms->acpi_dev), + pcihp_state, dev, errp); + supported = true; + } + } + if (!supported) { error_setg(errp, "virt: device unplug for unsupported device" " type: %s", object_get_typename(OBJECT(dev))); } @@ -3045,11 +3108,14 @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine, DeviceState *dev) { MachineClass *mc = MACHINE_GET_CLASS(machine); + VirtMachineState *vms = VIRT_MACHINE(machine); if (device_is_dynamic_sysbus(mc, dev) || object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI) || - object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { + object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI) || + (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE) && + get_acpi_pcihp_state(vms))) { return HOTPLUG_HANDLER(machine); } return NULL; -- 2.49.0