lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250728-luo-pci-v1-22-955b078dd653@kernel.org>
Date: Mon, 28 Jul 2025 01:24:52 -0700
From: chrisl@...nel.org
To: Bjorn Helgaas <bhelgaas@...gle.com>, 
 Greg Kroah-Hartman <gregkh@...uxfoundation.org>, 
 "Rafael J. Wysocki" <rafael@...nel.org>, Danilo Krummrich <dakr@...nel.org>, 
 Len Brown <lenb@...nel.org>
Cc: linux-kernel@...r.kernel.org, linux-pci@...r.kernel.org, 
 linux-acpi@...r.kernel.org, David Matlack <dmatlack@...gle.com>, 
 Pasha Tatashin <tatashin@...gle.com>, Jason Miu <jasonmiu@...gle.com>, 
 Vipin Sharma <vipinsh@...gle.com>, Saeed Mahameed <saeedm@...dia.com>, 
 Adithya Jayachandran <ajayachandra@...dia.com>, 
 Parav Pandit <parav@...dia.com>, William Tu <witu@...dia.com>, 
 Mike Rapoport <rppt@...nel.org>, Chris Li <chrisl@...nel.org>, 
 Jason Gunthorpe <jgg@...pe.ca>, Leon Romanovsky <leon@...nel.org>
Subject: [PATCH RFC 22/25] PCI/LUO: Save PCI bus and host bridge states

From: Jason Miu <jasonmiu@...gle.com>

In the LUO prepare phase, saves the PCI bus and host bridge states.

For a PCI bus, save the domain and bus numbers. Save the bridge types.
Save the upstream bus domain and bus numbers so we can verify the
relationship in the later restoration phase.

If the current bridge is a host bridge, save also the PCI bridge
resource. This is not needed by other PCI bridges as the resource is
already preserved by its associated struct pci_dev.

Tested:
  - QEMU VM boot test, preserve device with pci-lu-stub

Signed-off-by: Chris Li <chrisl@...nel.org>
---
 drivers/pci/liveupdate.c | 60 +++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 52 insertions(+), 8 deletions(-)

diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c
index 7fda7e4d409adce6bf92ef7af1167f7bda302c7e..be22af7a2db3a9bb06d8e100603a59f11b7fa5f8 100644
--- a/drivers/pci/liveupdate.c
+++ b/drivers/pci/liveupdate.c
@@ -20,9 +20,20 @@ static LIST_HEAD(preserved_buses);
 static LIST_HEAD(probe_devices);
 static LIST_HEAD(probe_buses);
 
+enum pci_bus_ser_bridge_type {
+	PCI_BUS_SER_NULL_BRIDGE, /* virtual bus */
+	PCI_BUS_SER_PCI_HOST_BRIDGE,
+	PCI_BUS_SER_PCI_BRIDGE,
+};
+
 struct pci_bus_ser {
 	u16	domain;
 	u8	number;
+	u16	parent_domain;
+	u8	parent_number;
+	enum pci_bus_ser_bridge_type bridge_type;
+	/* For a root bus, saves the host bridge PCI bridge resource */
+	struct pci_resource_ser resource[PCI_BRIDGE_RESOURCE_NUM];
 };
 
 struct pci_ser {
@@ -162,6 +173,16 @@ static int pci_get_device_path(struct pci_dev *pdev)
 	return (pci_domain_nr(pdev->bus) << 16) | pci_dev_id(pdev);
 }
 
+static void save_device_resource(struct pci_resource_ser *dest,
+				 struct resource *src)
+{
+	strscpy((char *)dest->name, src->name, sizeof(dest->name));
+	dest->start = src->start;
+	dest->end = src->end;
+	dest->flags = src->flags;
+	dest->desc = src->desc;
+}
+
 static int pci_save_device_state(struct device *dev, struct pci_dev_ser *s)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
@@ -205,13 +226,7 @@ static int pci_save_device_state(struct device *dev, struct pci_dev_ser *s)
 		    (strlen(pdev->resource[i].name) == 0))
 			continue;
 
-		s->resource[i].start = pdev->resource[i].start;
-		s->resource[i].end = pdev->resource[i].end;
-		s->resource[i].flags = pdev->resource[i].flags;
-		s->resource[i].desc = pdev->resource[i].desc;
-
-		strscpy((char *)s->resource[i].name, pci_name(pdev),
-			sizeof(s->resource[i].name));
+		save_device_resource(s->resource + i, pdev->resource + i);
 	}
 
 	return 0;
@@ -219,8 +234,37 @@ static int pci_save_device_state(struct device *dev, struct pci_dev_ser *s)
 
 static void pci_save_bus_state(struct pci_bus *bus, struct pci_bus_ser *s)
 {
-	s->number = bus->number;
+	int i;
+
 	s->domain = pci_domain_nr(bus);
+	s->number = bus->number;
+	if (bus->parent) {
+		s->parent_domain = pci_domain_nr(bus->parent);
+		s->parent_number = bus->parent->number;
+	}
+
+	/* This bus is a virtual bus if no physical bridge is being referred. */
+	if (!bus->bridge) {
+		s->bridge_type = PCI_BUS_SER_NULL_BRIDGE;
+		return;
+	}
+
+	if (!pci_is_root_bus(bus)) {
+		s->bridge_type = PCI_BUS_SER_PCI_BRIDGE;
+		return;
+	}
+
+	/* This bridge is a PCI host bridge. Saves its resource. */
+	for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) {
+		/* This resource region is not claimed, skip. */
+		if ((bus->resource[i] == NULL) ||
+		    (bus->resource[i]->name == NULL) ||
+		    (strlen(bus->resource[i]->name) == 0))
+			continue;
+
+		save_device_resource(s->resource + i, bus->resource[i]);
+	}
+	s->bridge_type = PCI_BUS_SER_PCI_HOST_BRIDGE;
 }
 
 static int pci_call_prepare(struct pci_ser *pci_state,

-- 
2.50.1.487.gc89ff58d15-goog


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ