From nobody Fri Nov 7 04:06:17 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1545352817201856.2195223484935; Thu, 20 Dec 2018 16:40:17 -0800 (PST) Received: from localhost ([::1]:41671 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ga8rP-0008My-MK for importer@patchew.org; Thu, 20 Dec 2018 19:40:15 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59409) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ga8nV-0005CZ-MJ for qemu-devel@nongnu.org; Thu, 20 Dec 2018 19:36:14 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ga8nQ-0005qC-Og for qemu-devel@nongnu.org; Thu, 20 Dec 2018 19:36:13 -0500 Received: from 3.mo2.mail-out.ovh.net ([46.105.58.226]:37287) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ga8nQ-0005og-Gj for qemu-devel@nongnu.org; Thu, 20 Dec 2018 19:36:08 -0500 Received: from player157.ha.ovh.net (unknown [10.109.143.18]) by mo2.mail-out.ovh.net (Postfix) with ESMTP id 87A01177065 for ; Fri, 21 Dec 2018 01:36:07 +0100 (CET) Received: from kaod.org (lns-bzn-46-82-253-208-248.adsl.proxad.net [82.253.208.248]) (Authenticated sender: groug@kaod.org) by player157.ha.ovh.net (Postfix) with ESMTPSA id 5CCB6FCCC45; Fri, 21 Dec 2018 00:35:52 +0000 (UTC) From: Greg Kurz To: qemu-devel@nongnu.org Date: Fri, 21 Dec 2018 01:35:52 +0100 Message-ID: <154535255201.862554.4906401457640454977.stgit@bahia.lan> In-Reply-To: <154535246529.862554.6113740443866753456.stgit@bahia.lan> References: <154535246529.862554.6113740443866753456.stgit@bahia.lan> User-Agent: StGit/unknown-version MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Ovh-Tracer-Id: 3852548009610287554 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedtkedrudejgedgvdduucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecuhedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 46.105.58.226 Subject: [Qemu-devel] [PATCH 04/15] spapr_pci: add proper rollback on PHB realize error path X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Cornelia Huck , Gerd Hoffmann , Eduardo Habkost , "Michael S. Tsirkin" , Alexey Kardashevskiy , David Hildenbrand , Michael Roth , qemu-s390x@nongnu.org, Dmitry Fleytman , qemu-ppc@nongnu.org, =?utf-8?q?C=C3=A9dric?= Le Goater , Marcel Apfelbaum , Paolo Bonzini , David Gibson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" The current realize code assumes the PHB is coldplugged, ie, QEMU will terminate if an error is detected, and does not bother to free anything it has already allocated. In order to support PHB hotplug, let's first ensure spapr_phb_realize() doesn't leak anything in case of error. Signed-off-by: Greg Kurz --- hw/ppc/spapr_pci.c | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index e59adbe706bb..46d7062dd143 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1570,6 +1570,7 @@ static void spapr_phb_realize(DeviceState *dev, Error= **errp) sPAPRTCETable *tcet; const unsigned windows_supported =3D sphb->ddw_enabled ? SPAPR_PCI_DMA_MAX_WINDOWS : 1; + Object *drcs[PCI_SLOT_MAX * 8]; =20 if (!spapr) { error_setg(errp, TYPE_SPAPR_PCI_HOST_BRIDGE " needs a pseries mach= ine"); @@ -1733,7 +1734,10 @@ static void spapr_phb_realize(DeviceState *dev, Erro= r **errp) spapr_irq_claim(spapr, irq, true, &local_err); if (local_err) { error_propagate_prepend(errp, local_err, "can't allocate LSIs:= "); - return; + while (--i >=3D 0) { + spapr_irq_free(spapr, sphb->lsi_table[i].irq, 1); + } + goto fail_del_msiwindow; } =20 sphb->lsi_table[i].irq =3D irq; @@ -1741,9 +1745,10 @@ static void spapr_phb_realize(DeviceState *dev, Erro= r **errp) =20 /* allocate connectors for child PCI devices */ if (sphb->dr_enabled) { - for (i =3D 0; i < PCI_SLOT_MAX * 8; i++) { - spapr_dr_connector_new(OBJECT(phb), TYPE_SPAPR_DRC_PCI, - (sphb->index << 16) | i); + for (i =3D 0; i < ARRAY_SIZE(drcs); i++) { + drcs[i] =3D + OBJECT(spapr_dr_connector_new(OBJECT(phb), TYPE_SPAPR_DRC_= PCI, + (sphb->index << 16) | i)); } } =20 @@ -1753,13 +1758,38 @@ static void spapr_phb_realize(DeviceState *dev, Err= or **errp) if (!tcet) { error_setg(errp, "Creating window#%d failed for %s", i, sphb->dtbusname); - return; + while (--i >=3D 0) { + tcet =3D spapr_tce_find_by_liobn(sphb->dma_liobn[i]); + assert(tcet); + memory_region_del_subregion(&sphb->iommu_root, + spapr_tce_get_iommu(tcet)); + object_unparent(OBJECT(tcet)); + } + goto fail_free_drcs; } memory_region_add_subregion(&sphb->iommu_root, 0, spapr_tce_get_iommu(tcet)); } =20 sphb->msi =3D g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g= _free); + return; + +fail_free_drcs: + if (sphb->dr_enabled) { + for (i =3D 0; i < ARRAY_SIZE(drcs); i++) { + object_unparent(drcs[i]); + } + } +fail_del_msiwindow: + memory_region_del_subregion(&sphb->iommu_root, &sphb->msiwindow); + address_space_destroy(&sphb->iommu_as); + qbus_set_hotplug_handler(BUS(phb->bus), NULL, &error_abort); + pci_unregister_root_bus(phb->bus); + memory_region_del_subregion(get_system_memory(), &sphb->iowindow); + if (sphb->mem64_win_pciaddr !=3D (hwaddr)-1) { + memory_region_del_subregion(get_system_memory(), &sphb->mem64windo= w); + } + memory_region_del_subregion(get_system_memory(), &sphb->mem32window); } =20 static int spapr_phb_children_reset(Object *child, void *opaque)