From nobody Tue Feb 10 10:59:12 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.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 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1547240665626147.88806580622963; Fri, 11 Jan 2019 13:04:25 -0800 (PST) Received: from localhost ([127.0.0.1]:57034 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gi3ya-0006J1-G5 for importer@patchew.org; Fri, 11 Jan 2019 16:04:24 -0500 Received: from eggs.gnu.org ([209.51.188.92]:49551) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gi3vw-0004np-PQ for qemu-devel@nongnu.org; Fri, 11 Jan 2019 16:01:42 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gi3vu-0001hR-Pg for qemu-devel@nongnu.org; Fri, 11 Jan 2019 16:01:40 -0500 Received: from 14.mo3.mail-out.ovh.net ([188.165.43.98]:43118) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gi3vs-0001dK-PR for qemu-devel@nongnu.org; Fri, 11 Jan 2019 16:01:38 -0500 Received: from player726.ha.ovh.net (unknown [10.109.143.216]) by mo3.mail-out.ovh.net (Postfix) with ESMTP id 10A631F0ACC for ; Fri, 11 Jan 2019 22:01:31 +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 player726.ha.ovh.net (Postfix) with ESMTPSA id D188A1806C1F; Fri, 11 Jan 2019 21:01:11 +0000 (UTC) From: Greg Kurz To: David Gibson Date: Fri, 11 Jan 2019 22:01:11 +0100 Message-ID: <154724047146.525985.16163962086149442020.stgit@bahia.lan> In-Reply-To: <154724039526.525985.3172545257507998890.stgit@bahia.lan> References: <154724039526.525985.3172545257507998890.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: 300052325358213426 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedtledrfeehgddugeeiucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecuhedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 188.165.43.98 Subject: [Qemu-devel] [PATCH v2 03/13] spapr_pci: add PHB unrealize 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: Thomas Huth , Cornelia Huck , Gerd Hoffmann , Michael Roth , "Michael S. Tsirkin" , Alexey Kardashevskiy , David Hildenbrand , qemu-devel@nongnu.org, Greg Kurz , qemu-s390x@nongnu.org, Dmitry Fleytman , qemu-ppc@nongnu.org, =?utf-8?q?C=C3=A9dric?= Le Goater , Marcel Apfelbaum , Paolo Bonzini , Eduardo Habkost Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" To support PHB hotplug we need to clean up lingering references, memory, child properties, etc. prior to the PHB object being finalized. Generally this will be called as a result of calling object_unparent() on the PHB object, which in turn would normally be called as the result of an unplug() operation. When the PHB is finalized, child objects will be unparented in turn, and finalized if the PHB was the only reference holder. so we don't bother to explicitly unparent child objects of the PHB (spapr_iommu, spapr_drc, etc). The formula that gives the number of DMA windows is moved to an inline function in the hw/pci-host/spapr.h header because it will have other users. The unrealize function is able to cope with partially realized PHBs. It is hence used to implement proper rollback on the realize error path. Signed-off-by: Michael Roth Signed-off-by: Greg Kurz --- v2: - implement rollback with unrealize function --- hw/ppc/spapr_pci.c | 73 +++++++++++++++++++++++++++++++++++++++= +--- include/hw/pci-host/spapr.h | 4 ++ 2 files changed, 72 insertions(+), 5 deletions(-) diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 24f95a400623..0d680b71b5d6 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1559,6 +1559,64 @@ static void spapr_pci_unplug_request(HotplugHandler = *plug_handler, } } =20 +static void spapr_phb_finalizefn(Object *obj) +{ + sPAPRPHBState *sphb =3D SPAPR_PCI_HOST_BRIDGE(obj); + + g_free(sphb->dtbusname); + sphb->dtbusname =3D NULL; +} + +static void spapr_phb_unrealize(DeviceState *dev, Error **errp) +{ + sPAPRMachineState *spapr =3D SPAPR_MACHINE(qdev_get_machine()); + SysBusDevice *s =3D SYS_BUS_DEVICE(dev); + PCIHostState *phb =3D PCI_HOST_BRIDGE(s); + sPAPRPHBState *sphb =3D SPAPR_PCI_HOST_BRIDGE(phb); + sPAPRTCETable *tcet; + int i; + const unsigned windows_supported =3D spapr_phb_windows_supported(sphb); + + if (sphb->msi) { + g_hash_table_unref(sphb->msi); + sphb->msi =3D NULL; + } + + /* + * Remove IO/MMIO subregions and aliases, rest should get cleaned + * via PHB's unrealize->object_finalize + */ + for (i =3D windows_supported - 1; i >=3D 0; i--) { + tcet =3D spapr_tce_find_by_liobn(sphb->dma_liobn[i]); + if (tcet) { + memory_region_del_subregion(&sphb->iommu_root, + spapr_tce_get_iommu(tcet)); + } + } + + for (i =3D PCI_NUM_PINS - 1; i >=3D 0; i--) { + if (sphb->lsi_table[i].irq) { + spapr_irq_free(spapr, sphb->lsi_table[i].irq, 1); + sphb->lsi_table[i].irq =3D 0; + } + } + + QLIST_REMOVE(sphb, list); + + 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); +} + static void spapr_phb_realize(DeviceState *dev, Error **errp) { /* We don't use SPAPR_MACHINE() in order to exit gracefully if the user @@ -1576,8 +1634,7 @@ static void spapr_phb_realize(DeviceState *dev, Error= **errp) PCIBus *bus; uint64_t msi_window_size =3D 4096; sPAPRTCETable *tcet; - const unsigned windows_supported =3D - sphb->ddw_enabled ? SPAPR_PCI_DMA_MAX_WINDOWS : 1; + const unsigned windows_supported =3D spapr_phb_windows_supported(sphb); =20 if (!spapr) { error_setg(errp, TYPE_SPAPR_PCI_HOST_BRIDGE " needs a pseries mach= ine"); @@ -1734,14 +1791,14 @@ static void spapr_phb_realize(DeviceState *dev, Err= or **errp) if (local_err) { error_propagate_prepend(errp, local_err, "can't allocate LSIs: "); - return; + goto unrealize; } } =20 spapr_irq_claim(spapr, irq, true, &local_err); if (local_err) { error_propagate_prepend(errp, local_err, "can't allocate LSIs:= "); - return; + goto unrealize; } =20 sphb->lsi_table[i].irq =3D irq; @@ -1761,13 +1818,17 @@ 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; + goto unrealize; } 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; + +unrealize: + spapr_phb_unrealize(dev, NULL); } =20 static int spapr_phb_children_reset(Object *child, void *opaque) @@ -1966,6 +2027,7 @@ static void spapr_phb_class_init(ObjectClass *klass, = void *data) =20 hc->root_bus_path =3D spapr_phb_root_bus_path; dc->realize =3D spapr_phb_realize; + dc->unrealize =3D spapr_phb_unrealize; dc->props =3D spapr_phb_properties; dc->reset =3D spapr_phb_reset; dc->vmsd =3D &vmstate_spapr_pci; @@ -1981,6 +2043,7 @@ static const TypeInfo spapr_phb_info =3D { .name =3D TYPE_SPAPR_PCI_HOST_BRIDGE, .parent =3D TYPE_PCI_HOST_BRIDGE, .instance_size =3D sizeof(sPAPRPHBState), + .instance_finalize =3D spapr_phb_finalizefn, .class_init =3D spapr_phb_class_init, .interfaces =3D (InterfaceInfo[]) { { TYPE_HOTPLUG_HANDLER }, diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h index e0e683c32469..16f42d0c0254 100644 --- a/include/hw/pci-host/spapr.h +++ b/include/hw/pci-host/spapr.h @@ -164,4 +164,8 @@ static inline void spapr_phb_vfio_reset(DeviceState *qd= ev) =20 void spapr_phb_dma_reset(sPAPRPHBState *sphb); =20 +static inline unsigned spapr_phb_windows_supported(sPAPRPHBState *sphb) +{ + return sphb->ddw_enabled ? SPAPR_PCI_DMA_MAX_WINDOWS : 1; +} #endif /* PCI_HOST_SPAPR_H */