From nobody Mon Sep 22 03:38:11 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=reject dis=none) header.from=rsg.ci.i.u-tokyo.ac.jp Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1758105568778373.65599257753286; Wed, 17 Sep 2025 03:39:28 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uypYw-0000Ru-92; Wed, 17 Sep 2025 06:38:58 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uypYr-0000Mx-Ub; Wed, 17 Sep 2025 06:38:54 -0400 Received: from www3579.sakura.ne.jp ([49.212.243.89]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uypYp-00074B-7S; Wed, 17 Sep 2025 06:38:53 -0400 Received: from h205.csg.ci.i.u-tokyo.ac.jp (h205.csg.ci.i.u-tokyo.ac.jp [133.11.54.205]) (authenticated bits=0) by www3579.sakura.ne.jp (8.16.1/8.16.1) with ESMTPSA id 58HAWmAZ099616 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Wed, 17 Sep 2025 19:32:56 +0900 (JST) (envelope-from odaki@rsg.ci.i.u-tokyo.ac.jp) DKIM-Signature: a=rsa-sha256; bh=jD8xXCxKpQezlTUVEU/kFhHTu8Hn9yOq/MDXRMgQpcc=; c=relaxed/relaxed; d=rsg.ci.i.u-tokyo.ac.jp; h=From:Date:Subject:Message-Id:To; s=rs20250326; t=1758105176; v=1; b=o1VexklQyWKJ2rNsvAOh3/KSWkheh8m1g1/WMhy88XinniJDifD194rHWkONKMN4 lbSM8iBx+M4mYKFhLnRrJ854S1uO62PsMeoHgZOLdXGwpUUBk0LvKLA5MpPqOiwd GUh7ueayJLdCVr38FH9XyCVTJdmSgZ8RDKJIAZKDSzF1/TRYeeVgbW4/boyEyffH ImuKc5hQ19/Hj/DJMRxnRh1sOfehGuBNA4DKqo1c+jOZix1UIsVGfI8oRpOePEni 5rYWUuj+7zajfPwOHKOADaZ2oC1gI8SvRguqqz9UElyATev5WFRfAZwsSZDT2gHI f9LrdC7gARGYK44/UjCgkw== From: Akihiko Odaki Date: Wed, 17 Sep 2025 19:32:47 +0900 Subject: [PATCH 01/14] hw/pci-bridge: Do not assume immediate MemoryRegion finalization MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250917-subregion-v1-1-bef37d9b4f73@rsg.ci.i.u-tokyo.ac.jp> References: <20250917-subregion-v1-0-bef37d9b4f73@rsg.ci.i.u-tokyo.ac.jp> In-Reply-To: <20250917-subregion-v1-0-bef37d9b4f73@rsg.ci.i.u-tokyo.ac.jp> To: qemu-devel@nongnu.org Cc: Alex Williamson , =?utf-8?q?C=C3=A9dric_Le_Goater?= , Paolo Bonzini , =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , Peter Xu , David Hildenbrand , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Richard Henderson , Helge Deller , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , "Michael S. Tsirkin" , Gerd Hoffmann , John Snow , qemu-block@nongnu.org, Keith Busch , Klaus Jensen , Jesper Devantier , Marcel Apfelbaum , Nicholas Piggin , qemu-ppc@nongnu.org, John Levon , Thanos Makatos , Yanan Wang , BALATON Zoltan , Jiaxun Yang , Daniel Henrique Barboza , David Gibson , Harsh Prateek Bora , Alexey Kardashevskiy , =?utf-8?q?Alex_Benn=C3=A9e?= , Fabiano Rosas , Thomas Huth , Laurent Vivier , Peter Maydell , Aurelien Jarno , Aleksandar Rikalo , Max Filippov , =?utf-8?q?Herv=C3=A9_Poussineau?= , Mark Cave-Ayland , Artyom Tarasenko , Akihiko Odaki X-Mailer: b4 0.15-dev-179e8 Received-SPF: pass (zohomail.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; Received-SPF: pass client-ip=49.212.243.89; envelope-from=odaki@rsg.ci.i.u-tokyo.ac.jp; helo=www3579.sakura.ne.jp X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1758105570441116600 When updating memory mappings, pci_bridge_update_mappings() performed the following operations: 1. Start a transaction 2. Delete the subregions from the container 3. Unparent the subregions 4. Initialize the subregions 5. End the transaction This assumes the old subregion instances are finalized immediately after 3, but it is not true; the finalization is delayed until 5. Remove the assumption by using functions to dynamically update MemoryRegions. Signed-off-by: Akihiko Odaki --- include/hw/pci/pci.h | 1 + hw/pci/pci.c | 2 +- hw/pci/pci_bridge.c | 96 ++++++++++++++++++++++++++++--------------------= ---- 3 files changed, 54 insertions(+), 45 deletions(-) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 6b7d3ac8a361..d0bd214b4e11 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -256,6 +256,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_nu= m, uint8_t attr, MemoryRegion *memory); void pci_register_vga(PCIDevice *pci_dev, MemoryRegion *mem, MemoryRegion *io_lo, MemoryRegion *io_hi); +void pci_update_vga(PCIDevice *pci_dev); void pci_unregister_vga(PCIDevice *pci_dev); pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num); =20 diff --git a/hw/pci/pci.c b/hw/pci/pci.c index c70b5ceebaf1..516029f66cda 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -1521,7 +1521,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_= num, } } =20 -static void pci_update_vga(PCIDevice *pci_dev) +void pci_update_vga(PCIDevice *pci_dev) { uint16_t cmd; =20 diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c index 76255c4cd892..240d0f904de9 100644 --- a/hw/pci/pci_bridge.c +++ b/hw/pci/pci_bridge.c @@ -145,11 +145,10 @@ pcibus_t pci_bridge_get_limit(const PCIDevice *bridge= , uint8_t type) return limit; } =20 -static void pci_bridge_init_alias(PCIBridge *bridge, MemoryRegion *alias, - uint8_t type, const char *name, - MemoryRegion *space, - MemoryRegion *parent_space, - bool enabled) +static void pci_bridge_update_alias(PCIBridge *bridge, bool init, + MemoryRegion *alias, uint8_t type, + const char *name, MemoryRegion *space, + MemoryRegion *parent_space, bool enabl= ed) { PCIDevice *bridge_dev =3D PCI_DEVICE(bridge); pcibus_t base =3D pci_bridge_get_base(bridge_dev, type); @@ -158,25 +157,37 @@ static void pci_bridge_init_alias(PCIBridge *bridge, = MemoryRegion *alias, * Apparently no way to do this with existing memory APIs. */ pcibus_t size =3D enabled && limit >=3D base ? limit + 1 - base : 0; =20 - memory_region_init_alias(alias, OBJECT(bridge), name, space, base, siz= e); + if (init) { + memory_region_init_alias(alias, OBJECT(bridge), name, space, base,= size); + } else { + memory_region_set_size(alias, size); + memory_region_set_alias_offset(alias, base); + } + memory_region_add_subregion_overlap(parent_space, base, alias, 1); } =20 -static void pci_bridge_init_vga_aliases(PCIBridge *br, PCIBus *parent, - MemoryRegion *alias_vga) +static void pci_bridge_update_vga_aliases(PCIBridge *br, bool init, + PCIBus *parent, + MemoryRegion *alias_vga) { PCIDevice *pd =3D PCI_DEVICE(br); uint16_t brctl =3D pci_get_word(pd->config + PCI_BRIDGE_CONTROL); =20 - memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_IO_LO], OBJECT(br), - "pci_bridge_vga_io_lo", &br->address_space_io, - QEMU_PCI_VGA_IO_LO_BASE, QEMU_PCI_VGA_IO_LO_S= IZE); - memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_IO_HI], OBJECT(br), - "pci_bridge_vga_io_hi", &br->address_space_io, - QEMU_PCI_VGA_IO_HI_BASE, QEMU_PCI_VGA_IO_HI_S= IZE); - memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_MEM], OBJECT(br), - "pci_bridge_vga_mem", &br->address_space_mem, - QEMU_PCI_VGA_MEM_BASE, QEMU_PCI_VGA_MEM_SIZE); + if (init) { + memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_IO_LO], OBJECT(br= ), + "pci_bridge_vga_io_lo", &br->address_spac= e_io, + QEMU_PCI_VGA_IO_LO_BASE, + QEMU_PCI_VGA_IO_LO_SIZE); + memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_IO_HI], OBJECT(br= ), + "pci_bridge_vga_io_hi", &br->address_spac= e_io, + QEMU_PCI_VGA_IO_HI_BASE, + QEMU_PCI_VGA_IO_HI_SIZE); + memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_MEM], OBJECT(br), + "pci_bridge_vga_mem", &br->address_space_= mem, + QEMU_PCI_VGA_MEM_BASE, + QEMU_PCI_VGA_MEM_SIZE); + } =20 if (brctl & PCI_BRIDGE_CTL_VGA) { pci_register_vga(pd, &alias_vga[QEMU_PCI_VGA_MEM], @@ -185,33 +196,33 @@ static void pci_bridge_init_vga_aliases(PCIBridge *br= , PCIBus *parent, } } =20 -static void pci_bridge_region_init(PCIBridge *br) +static void pci_bridge_region_update(PCIBridge *br, bool init) { PCIDevice *pd =3D PCI_DEVICE(br); PCIBus *parent =3D pci_get_bus(pd); PCIBridgeWindows *w =3D &br->windows; uint16_t cmd =3D pci_get_word(pd->config + PCI_COMMAND); =20 - pci_bridge_init_alias(br, &w->alias_pref_mem, - PCI_BASE_ADDRESS_MEM_PREFETCH, - "pci_bridge_pref_mem", - &br->address_space_mem, - parent->address_space_mem, - cmd & PCI_COMMAND_MEMORY); - pci_bridge_init_alias(br, &w->alias_mem, - PCI_BASE_ADDRESS_SPACE_MEMORY, - "pci_bridge_mem", - &br->address_space_mem, - parent->address_space_mem, - cmd & PCI_COMMAND_MEMORY); - pci_bridge_init_alias(br, &w->alias_io, - PCI_BASE_ADDRESS_SPACE_IO, - "pci_bridge_io", - &br->address_space_io, - parent->address_space_io, - cmd & PCI_COMMAND_IO); - - pci_bridge_init_vga_aliases(br, parent, w->alias_vga); + pci_bridge_update_alias(br, init, &w->alias_pref_mem, + PCI_BASE_ADDRESS_MEM_PREFETCH, + "pci_bridge_pref_mem", + &br->address_space_mem, + parent->address_space_mem, + cmd & PCI_COMMAND_MEMORY); + pci_bridge_update_alias(br, init, &w->alias_mem, + PCI_BASE_ADDRESS_SPACE_MEMORY, + "pci_bridge_mem", + &br->address_space_mem, + parent->address_space_mem, + cmd & PCI_COMMAND_MEMORY); + pci_bridge_update_alias(br, init, &w->alias_io, + PCI_BASE_ADDRESS_SPACE_IO, + "pci_bridge_io", + &br->address_space_io, + parent->address_space_io, + cmd & PCI_COMMAND_IO); + + pci_bridge_update_vga_aliases(br, init, parent, w->alias_vga); } =20 static void pci_bridge_region_del(PCIBridge *br, PCIBridgeWindows *w) @@ -237,14 +248,11 @@ static void pci_bridge_region_cleanup(PCIBridge *br, = PCIBridgeWindows *w) =20 void pci_bridge_update_mappings(PCIBridge *br) { - PCIBridgeWindows *w =3D &br->windows; - /* Make updates atomic to: handle the case of one VCPU updating the br= idge * while another accesses an unaffected region. */ memory_region_transaction_begin(); - pci_bridge_region_del(br, w); - pci_bridge_region_cleanup(br, w); - pci_bridge_region_init(br); + pci_bridge_region_del(br, &br->windows); + pci_bridge_region_update(br, false); memory_region_transaction_commit(); } =20 @@ -386,7 +394,7 @@ void pci_bridge_initfn(PCIDevice *dev, const char *type= name) memory_region_init(&br->address_space_io, OBJECT(br), "pci_bridge_io", 4 * GiB); address_space_init(&br->as_io, &br->address_space_io, "pci_bridge_pci_= io"); - pci_bridge_region_init(br); + pci_bridge_region_update(br, true); QLIST_INIT(&sec_bus->child); QLIST_INSERT_HEAD(&parent->child, sec_bus, sibling); =20 --=20 2.51.0