From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:43850) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1W7SA0-0004KY-IC for qemu-devel@nongnu.org; Sun, 26 Jan 2014 11:02:18 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1W7S9u-0000wN-Jz for qemu-devel@nongnu.org; Sun, 26 Jan 2014 11:02:12 -0500 Received: from mx1.redhat.com ([209.132.183.28]:32255) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1W7S9u-0000wJ-BK for qemu-devel@nongnu.org; Sun, 26 Jan 2014 11:02:06 -0500 Date: Sun, 26 Jan 2014 18:06:58 +0200 From: "Michael S. Tsirkin" Message-ID: <1390735289-15563-31-git-send-email-mst@redhat.com> References: <1390735289-15563-1-git-send-email-mst@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1390735289-15563-1-git-send-email-mst@redhat.com> Subject: [Qemu-devel] [PULL v2 30/35] hw/pci: fix error flow in pci multifunction init List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Anthony Liguori , Marcel Apfelbaum From: Marcel Apfelbaum Scenario: - There is a non multifunction pci device A on 00:0X.0. - Hot-plug another multifunction pci device B at 00:0X.1. - The operation will fail of course. - Try to hot-plug the B device 2-3 more times, qemu will crash. Reason: The error flow leaves the B's address space into global address spaces list, but the device object is freed. Fixed that. Signed-off-by: Marcel Apfelbaum Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/pci/pci.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 2aca8a4..1221f32 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -793,6 +793,15 @@ static void pci_config_free(PCIDevice *pci_dev) g_free(pci_dev->used); } +static void do_pci_unregister_device(PCIDevice *pci_dev) +{ + pci_dev->bus->devices[pci_dev->devfn] = NULL; + pci_config_free(pci_dev); + + address_space_destroy(&pci_dev->bus_master_as); + memory_region_destroy(&pci_dev->bus_master_enable_region); +} + /* -1 for devfn means auto assign */ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, const char *name, int devfn) @@ -858,7 +867,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, pci_init_mask_bridge(pci_dev); } if (pci_init_multifunction(bus, pci_dev)) { - pci_config_free(pci_dev); + do_pci_unregister_device(pci_dev); return NULL; } @@ -873,15 +882,6 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, return pci_dev; } -static void do_pci_unregister_device(PCIDevice *pci_dev) -{ - pci_dev->bus->devices[pci_dev->devfn] = NULL; - pci_config_free(pci_dev); - - address_space_destroy(&pci_dev->bus_master_as); - memory_region_destroy(&pci_dev->bus_master_enable_region); -} - static void pci_unregister_io_regions(PCIDevice *pci_dev) { PCIIORegion *r; -- MST