From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:49088) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TSrOp-00075S-VT for qemu-devel@nongnu.org; Mon, 29 Oct 2012 11:37:13 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TSrOj-0000u7-VU for qemu-devel@nongnu.org; Mon, 29 Oct 2012 11:37:11 -0400 Received: from mail-ie0-f173.google.com ([209.85.223.173]:49674) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TSrOj-0000tx-Pw for qemu-devel@nongnu.org; Mon, 29 Oct 2012 11:37:05 -0400 Received: by mail-ie0-f173.google.com with SMTP id 17so7023663iea.4 for ; Mon, 29 Oct 2012 08:37:04 -0700 (PDT) Sender: fluxion From: Michael Roth Date: Mon, 29 Oct 2012 10:36:53 -0500 Message-Id: <1351525013-9829-1-git-send-email-mdroth@linux.vnet.ibm.com> Subject: [Qemu-devel] [PATCH] pci_bridge: fix abort due to memory region API violation List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: avi@redhat.com, mst@redhat.com 2be0e25f added an assertion that memory_region_destroy() is not called during a transaction. pci_bridge_update_mappings() wants to do this so that it can remove existing subregions and add new ones in their place as an atomic operation. Work around this by storing away the old subregions and destroying them after the transaction is complete. Signed-off-by: Michael Roth --- hw/pci_bridge.c | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/hw/pci_bridge.c b/hw/pci_bridge.c index 5c6455f..06f0082 100644 --- a/hw/pci_bridge.c +++ b/hw/pci_bridge.c @@ -151,10 +151,14 @@ static void pci_bridge_init_alias(PCIBridge *bridge, MemoryRegion *alias, memory_region_add_subregion_overlap(parent_space, base, alias, 1); } -static void pci_bridge_cleanup_alias(MemoryRegion *alias, - MemoryRegion *parent_space) +static void pci_bridge_remove_alias(MemoryRegion *alias, + MemoryRegion *parent_space) { memory_region_del_subregion(parent_space, alias); +} + +static void pci_bridge_destroy_alias(MemoryRegion *alias) +{ memory_region_destroy(alias); } @@ -187,22 +191,41 @@ static void pci_bridge_region_init(PCIBridge *br) static void pci_bridge_region_cleanup(PCIBridge *br) { PCIBus *parent = br->dev.bus; - pci_bridge_cleanup_alias(&br->alias_io, - parent->address_space_io); - pci_bridge_cleanup_alias(&br->alias_mem, - parent->address_space_mem); - pci_bridge_cleanup_alias(&br->alias_pref_mem, - parent->address_space_mem); + pci_bridge_remove_alias(&br->alias_io, + parent->address_space_io); + pci_bridge_destroy_alias(&br->alias_io); + pci_bridge_remove_alias(&br->alias_mem, + parent->address_space_mem); + pci_bridge_destroy_alias(&br->alias_mem); + pci_bridge_remove_alias(&br->alias_pref_mem, + parent->address_space_mem); + pci_bridge_destroy_alias(&br->alias_pref_mem); } static void pci_bridge_update_mappings(PCIBridge *br) { + PCIBus *parent = br->dev.bus; + MemoryRegion alias_io_old, alias_mem_old, alias_pref_mem_old; + + alias_io_old = br->alias_io; + alias_mem_old = br->alias_mem; + alias_pref_mem_old = br->alias_pref_mem; + /* Make updates atomic to: handle the case of one VCPU updating the bridge * while another accesses an unaffected region. */ memory_region_transaction_begin(); - pci_bridge_region_cleanup(br); + pci_bridge_remove_alias(&br->alias_io, + parent->address_space_io); + pci_bridge_remove_alias(&br->alias_mem, + parent->address_space_mem); + pci_bridge_remove_alias(&br->alias_pref_mem, + parent->address_space_mem); pci_bridge_region_init(br); memory_region_transaction_commit(); + + pci_bridge_destroy_alias(&alias_io_old); + pci_bridge_destroy_alias(&alias_mem_old); + pci_bridge_destroy_alias(&alias_pref_mem_old); } /* default write_config function for PCI-to-PCI bridge */ -- 1.7.9.5