The MMIO regions should not be destroyed and recreated on the fly, because they might have I/O in progress. Instead, create an area that is as large as possible, and then map a window of it into system memory. This is safe because containers and aliases are never the destination of I/O, and can be safely deleted at any time. It is also similar to how PAM maps windows of system RAM.
Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> --- hw/pci/pcie_host.c | 23 +++++++++++++++++------ include/hw/pci/pcie_host.h | 1 + 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/hw/pci/pcie_host.c b/hw/pci/pcie_host.c index b70e5ad..bb676a9 100644 --- a/hw/pci/pcie_host.c +++ b/hw/pci/pcie_host.c @@ -110,19 +110,26 @@ static const MemoryRegionOps pcie_mmcfg_ops = { int pcie_host_init(PCIExpressHost *e) { e->base_addr = PCIE_BASE_ADDR_UNMAPPED; - + memory_region_init_io(&e->mmio, OBJECT(e), &pcie_mmcfg_ops, e, "pcie-mmcfg-mmio", + PCIE_MMCFG_SIZE_MAX); return 0; } void pcie_host_mmcfg_unmap(PCIExpressHost *e) { if (e->base_addr != PCIE_BASE_ADDR_UNMAPPED) { - memory_region_del_subregion(get_system_memory(), &e->mmio); - memory_region_destroy(&e->mmio); + memory_region_del_subregion(get_system_memory(), &e->mapped_mmio); + memory_region_destroy(&e->mapped_mmio); e->base_addr = PCIE_BASE_ADDR_UNMAPPED; } } +static void pcie_host_instance_finalize(Object *obj) +{ + PCIExpressHost *e = PCIE_HOST_BRIDGE(obj); + memory_region_destroy(&e->mmio); +} + void pcie_host_mmcfg_map(PCIExpressHost *e, hwaddr addr, uint32_t size) { @@ -130,10 +137,13 @@ void pcie_host_mmcfg_map(PCIExpressHost *e, hwaddr addr, assert(size >= PCIE_MMCFG_SIZE_MIN); assert(size <= PCIE_MMCFG_SIZE_MAX); e->size = size; - memory_region_init_io(&e->mmio, OBJECT(e), &pcie_mmcfg_ops, e, - "pcie-mmcfg", e->size); e->base_addr = addr; - memory_region_add_subregion(get_system_memory(), e->base_addr, &e->mmio); + + memory_region_init_alias(&e->mapped_mmio, OBJECT(e), + "pcie-mmcfg", &e->mmio, + 0, e->size); + + memory_region_add_subregion(get_system_memory(), e->base_addr, &e->mapped_mmio); } void pcie_host_mmcfg_update(PCIExpressHost *e, @@ -152,6 +162,7 @@ static const TypeInfo pcie_host_type_info = { .parent = TYPE_PCI_HOST_BRIDGE, .abstract = true, .instance_size = sizeof(PCIExpressHost), + .instance_finalize = pcie_host_instance_finalize, }; static void pcie_host_register_types(void) diff --git a/include/hw/pci/pcie_host.h b/include/hw/pci/pcie_host.h index 1228e36..1656bde 100644 --- a/include/hw/pci/pcie_host.h +++ b/include/hw/pci/pcie_host.h @@ -41,6 +41,7 @@ struct PCIExpressHost { /* MMCONFIG mmio area */ MemoryRegion mmio; + MemoryRegion mapped_mmio; }; int pcie_host_init(PCIExpressHost *e); -- 1.8.3.1