From nobody Thu Oct 2 14:11:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 11EFC2EAB66; Tue, 16 Sep 2025 07:45:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758008716; cv=none; b=UhdRt4ghx9YV8kWouRNArIxJT14ZYdm4n53CaKqkEqMS5u27z3Llz9cuYYdkBWcwdIR/c4jieEpF9XGv4VxppoMad5qcjH52Y10xKX3pvX9vgB+qO+8zz9Swqugomnh3R6utF0GKPUkH3DaPzK7ubEaCndc5rBVmO6LZeI6vkJY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758008716; c=relaxed/simple; bh=lEhfWp7QYoAPVlmQF5giE1FuFrKDQ7XoZLDtcD0EBGI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mtq/zpAu77ISfSf1ptn5ZqyBZ4WVRt9zeIjApGgXS/aE6XwU0Y8f8qqO1buJ9BC6CU0F0eKqX3QBSHtoHJG08mOY4sBMBjyTWhtRxAU6S2FTFypTSXRFAP50A6z1TxABdlu9rZg1IAKSjDf2EUylvDkgn7TUF5EAWYxXrUD7yAM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UngFFcwG; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="UngFFcwG" Received: by smtp.kernel.org (Postfix) with ESMTPSA id ED75FC4CEFC; Tue, 16 Sep 2025 07:45:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758008715; bh=lEhfWp7QYoAPVlmQF5giE1FuFrKDQ7XoZLDtcD0EBGI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=UngFFcwGtQVT8n+N524LZAYDVOBivzm+ZqbfJ2nhtSZlSaaPlIsA7TzSRsWZ3T0Xt QDqhzuhCKE/IY69zaqwf0lT1v30sMUKyy+dr/iixg9LF1zsvFIs7y5a5sigyey4GCu 6yjFPr84scN1slzlYrb5Do9EqhkV6Af4FV5j6fddMLf2QpnHN7Fx0JjCYvq07Xl+fC f0+G0x7TZTGCzNM3utPUcL4ybMnmTwRU5BJ/rL5wySc7ZdFEPP5mIaDl4STPceMSmm ByZns/Pc4ecg8ahRpynQdDPExQDyzoSMjUlC+GJ0ARROXUros2AdKKAcPYk03Nu8i5 LFTAbaMbzYIUw== From: Chris Li Date: Tue, 16 Sep 2025 00:45:09 -0700 Subject: [PATCH v2 01/10] PCI/LUO: Register with Liveupdate Orchestrator Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250916-luo-pci-v2-1-c494053c3c08@kernel.org> References: <20250916-luo-pci-v2-0-c494053c3c08@kernel.org> In-Reply-To: <20250916-luo-pci-v2-0-c494053c3c08@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown , Pasha Tatashin Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 Register PCI subsystem with the Liveupdate Orchestrator and provide noop liveupdate callbacks. Signed-off-by: Chris Li --- MAINTAINERS | 2 ++ drivers/pci/Makefile | 1 + drivers/pci/liveupdate.c | 54 ++++++++++++++++++++++++++++++++++++++++++++= ++++ 3 files changed, 57 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 91cec3288cc81aea199f730924eee1f5fda1fd72..85749a5da69f88544ccc749e9d7= 23b1b54c0e3b7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14014,11 +14014,13 @@ F: tools/testing/selftests/livepatch/ =20 LIVE UPDATE M: Pasha Tatashin +M: Chris Li L: linux-kernel@vger.kernel.org S: Maintained F: Documentation/ABI/testing/sysfs-kernel-liveupdate F: Documentation/admin-guide/liveupdate.rst F: drivers/misc/liveupdate/ +F: drivers/pci/liveupdate/ F: include/linux/liveupdate.h F: include/uapi/linux/liveupdate.h F: tools/testing/selftests/liveupdate/ diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 67647f1880fb8fb0629d680398f5b88d69aac660..aa1bac7aed7d12c641a6b55e561= 76fb3cdde4c91 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_PCI_DOE) +=3D doe.o obj-$(CONFIG_PCI_DYNAMIC_OF_NODES) +=3D of_property.o obj-$(CONFIG_PCI_NPEM) +=3D npem.o obj-$(CONFIG_PCIE_TPH) +=3D tph.o +obj-$(CONFIG_LIVEUPDATE) +=3D liveupdate.o =20 # Endpoint library must be initialized before its users obj-$(CONFIG_PCI_ENDPOINT) +=3D endpoint/ diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c new file mode 100644 index 0000000000000000000000000000000000000000..86b4f3a2fb44781c6e323ba029d= b510450556fa9 --- /dev/null +++ b/drivers/pci/liveupdate.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Copyright (c) 2025, Google LLC. + * Chris Li + */ + +#define pr_fmt(fmt) "PCI liveupdate: " fmt + +#include + +#define PCI_SUBSYSTEM_NAME "pci" + +static int pci_liveupdate_prepare(void *arg, u64 *data) +{ + pr_info("prepare data[%llx]\n", *data); + return 0; +} + +static int pci_liveupdate_freeze(void *arg, u64 *data) +{ + pr_info("freeze data[%llx]\n", *data); + return 0; +} + +static void pci_liveupdate_cancel(void *arg, u64 data) +{ + pr_info("cancel data[%llx]\n", data); +} + +static void pci_liveupdate_finish(void *arg, u64 data) +{ + pr_info("finish data[%llx]\n", data); +} + +struct liveupdate_subsystem pci_liveupdate_ops =3D { + .prepare =3D pci_liveupdate_prepare, + .freeze =3D pci_liveupdate_freeze, + .cancel =3D pci_liveupdate_cancel, + .finish =3D pci_liveupdate_finish, + .name =3D PCI_SUBSYSTEM_NAME, +}; + +static int __init pci_liveupdate_init(void) +{ + int ret; + + ret =3D liveupdate_register_subsystem(&pci_liveupdate_ops); + if (ret && liveupdate_state_updated()) + panic("PCI liveupdate: Register subsystem failed: %d", ret); + WARN(ret, "PCI liveupdate: Register subsystem failed %d", ret); + return 0; +} +late_initcall_sync(pci_liveupdate_init); --=20 2.51.0.384.g4c02a37b29-goog From nobody Thu Oct 2 14:11:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F315C2EB853; Tue, 16 Sep 2025 07:45:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758008717; cv=none; b=li33mjKmESICu9Yk5r9C9+26J7GbFYS6BWARybuHpBMa9KvATM4SQ35EjkBWRtUIdaTwaQCbipmvemo+0U6ufhDAhz8S5h7A2gc7ln7ETHyD9MsqbfffHJhLBJ6jYUsAOurAGgA/1Qu3D3nPDERDriZAheMxl1u9TZXGT2GZHWw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758008717; c=relaxed/simple; bh=L+rmVaZTkoNGFXRnqwO/2ib3IwA5h8QBXMSTU4xtLN8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Xy5jUjtyYuL0ibjYSktAlw1GbxzI0VVM6OlKAzxps7JUHH7SXdD1EWvS5l94nMYjg0/3sQ4aw30pL3OWFYsLdIbT3wOQ692Y6fFcF26lpx/YlH/6JeM2PNHcXGzaxavzt2JYQB6I38/Hr42ZGZA4NY7iroXApDlfBM4mM6ZUuTY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=e38VY6JO; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="e38VY6JO" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C4005C113CF; Tue, 16 Sep 2025 07:45:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758008716; bh=L+rmVaZTkoNGFXRnqwO/2ib3IwA5h8QBXMSTU4xtLN8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=e38VY6JOPJo8UuZYtPEECUL7Sw/4CSkLvPNdCJL/OUPpO3qWgUHYKn9tdv3dfCnVi Q3g7pSb5YGuMXOK8eC0uMzqFPcXxoBIbX7Zx12JyDR/0jg3TeuEbCXP7VLUezaeaFF vKpdJBjm09itIrRHudKVTTfYd8QyRse7K5mqk8Luzy8iGyrqFYfTPr0AyN7VXcHnce gt9JAK/pKiD5EDm6FVjF9JbmbY6G0bEhZXt8dGBUQ4YQy2QdTE5PvJs7rQtXaPEIc8 Jv8JI7koO3EHE44JI2lTz20QOBi7l1Hwrv5R7FuRpkbV7xMusY4UF1no04DeNH5eGf PsRp24a2b8mdg== From: Chris Li Date: Tue, 16 Sep 2025 00:45:10 -0700 Subject: [PATCH v2 02/10] PCI/LUO: Create requested liveupdate device list Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250916-luo-pci-v2-2-c494053c3c08@kernel.org> References: <20250916-luo-pci-v2-0-c494053c3c08@kernel.org> In-Reply-To: <20250916-luo-pci-v2-0-c494053c3c08@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown , Pasha Tatashin Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 Introduce struct dev_liveupdate and add it to struct device. Use the new struct to track a device's liveupdate states. - flags: If not zero, the device participate the live update. Currently the "flags" has two possible bit: LU_BUSMASTER: The device is requested for perserving the bus master. LU_BUSMASTER_BRIDGE: A child device is requested for preserving the bus master. The bridge will need to preserve bus master as well. In the PCI subsystem prepare callback, create the requested device list as per the following rules: - If the device is requested for liveupdate LU_BUSMASTER, then the parent bridge will be set LU_BUSMASTER_BRIDGE The list of PCI root bus and its children bus lists form a tree of all PCI buses. The tree is walked in postorder traversal, so that the device on the child bus can mark the parent bridge for LU_BUSMASTER_BRIDGE. After the postorder traversal of the bus tree then reverse order enumerates the devices in the bus, all device marks either requested or depended will be added to the requested device list. This list of devices will be used in the next change to forward the liveupdate call back into individual devices. Note that collect_liveupdate_devices() returns the number of devices it added to request_devices. This will be used in a subsequent commit so that the PCI subsystem can calculate what size folio to allocate for its save Signed-off-by: Chris Li --- MAINTAINERS | 1 + drivers/pci/liveupdate.c | 80 ++++++++++++++++++++++++++++++++++++++= ++++ drivers/pci/pcie/portdrv.c | 1 + drivers/pci/probe.c | 4 ++- include/linux/dev_liveupdate.h | 44 +++++++++++++++++++++++ include/linux/device.h | 15 ++++++++ 6 files changed, 144 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 85749a5da69f88544ccc749e9d723b1b54c0e3b7..1ae3d166cd35ec5c7818f202079= ed5d10c09144b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14021,6 +14021,7 @@ F: Documentation/ABI/testing/sysfs-kernel-liveupdate F: Documentation/admin-guide/liveupdate.rst F: drivers/misc/liveupdate/ F: drivers/pci/liveupdate/ +F: include/linux/dev_liveupdate.h F: include/linux/liveupdate.h F: include/uapi/linux/liveupdate.h F: tools/testing/selftests/liveupdate/ diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c index 86b4f3a2fb44781c6e323ba029db510450556fa9..e8891844b8194dabf8d1e8e2d74= d9c701bd741ca 100644 --- a/drivers/pci/liveupdate.c +++ b/drivers/pci/liveupdate.c @@ -6,14 +6,94 @@ */ =20 #define pr_fmt(fmt) "PCI liveupdate: " fmt +#define dev_fmt(fmt) "PCI liveupdate: " fmt =20 +#include #include +#include "pci.h" =20 #define PCI_SUBSYSTEM_NAME "pci" =20 +static void stack_push_buses(struct list_head *stack, struct list_head *bu= ses) +{ + struct pci_bus *bus; + + list_for_each_entry(bus, buses, node) + list_move_tail(&bus->dev.lu.lu_next, stack); +} + +static void liveupdate_add_dev(struct device *dev, struct list_head *head) +{ + dev_info(dev, "collect liveupdate device: flags %x\n", dev->lu.flags); + list_move_tail(&dev->lu.lu_next, head); +} + +static int collect_bus_devices_reverse(struct pci_bus *bus, struct list_he= ad *head) +{ + struct pci_dev *pdev; + int count =3D 0; + + list_for_each_entry_reverse(pdev, &bus->devices, bus_list) { + if (pdev->dev.lu.flags & LU_BUSMASTER && pdev->dev.parent) + pdev->dev.parent->lu.flags |=3D LU_BUSMASTER_BRIDGE; + if (pdev->dev.lu.flags) { + liveupdate_add_dev(&pdev->dev, head); + count++; + } + } + return count; +} + +static int build_liveupdate_devices(struct list_head *head) +{ + LIST_HEAD(bus_stack); + int count =3D 0; + + stack_push_buses(&bus_stack, &pci_root_buses); + + while (!list_empty(&bus_stack)) { + struct device *busdev; + struct pci_bus *bus; + + busdev =3D list_last_entry(&bus_stack, struct device, lu.lu_next); + bus =3D to_pci_bus(busdev); + if (!busdev->lu.visited && !list_empty(&bus->children)) { + stack_push_buses(&bus_stack, &bus->children); + busdev->lu.visited =3D 1; + continue; + } + + count +=3D collect_bus_devices_reverse(bus, head); + busdev->lu.visited =3D 0; + list_del_init(&busdev->lu.lu_next); + } + return count; +} + +static void cleanup_liveupdate_devices(struct list_head *head) +{ + struct device *d, *n; + + list_for_each_entry_safe(d, n, head, lu.lu_next) { + d->lu.flags &=3D ~LU_DEPENDED; + list_del_init(&d->lu.lu_next); + } +} + static int pci_liveupdate_prepare(void *arg, u64 *data) { + LIST_HEAD(requested_devices); + pr_info("prepare data[%llx]\n", *data); + + pci_lock_rescan_remove(); + down_write(&pci_bus_sem); + + build_liveupdate_devices(&requested_devices); + cleanup_liveupdate_devices(&requested_devices); + + up_write(&pci_bus_sem); + pci_unlock_rescan_remove(); return 0; } =20 diff --git a/drivers/pci/pcie/portdrv.c b/drivers/pci/pcie/portdrv.c index e8318fd5f6ed537a1b236a3a0f054161d5710abd..0e9ef387182856771d857181d88= f376632b46f0d 100644 --- a/drivers/pci/pcie/portdrv.c +++ b/drivers/pci/pcie/portdrv.c @@ -304,6 +304,7 @@ static int pcie_device_init(struct pci_dev *pdev, int s= ervice, int irq) device =3D &pcie->device; device->bus =3D &pcie_port_bus_type; device->release =3D release_pcie_device; /* callback to free pcie dev */ + dev_liveupdate_init(device); dev_set_name(device, "%s:pcie%03x", pci_name(pdev), get_descriptor_id(pci_pcie_type(pdev), service)); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 4b8693ec9e4c67fc1655e0057b3b96b4098e6630..dddd7ebc03d1a6e6ee456e0bf02= ab9833a819509 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -614,6 +614,7 @@ static struct pci_bus *pci_alloc_bus(struct pci_bus *pa= rent) INIT_LIST_HEAD(&b->devices); INIT_LIST_HEAD(&b->slots); INIT_LIST_HEAD(&b->resources); + dev_liveupdate_init(&b->dev); b->max_bus_speed =3D PCI_SPEED_UNKNOWN; b->cur_bus_speed =3D PCI_SPEED_UNKNOWN; #ifdef CONFIG_PCI_DOMAINS_GENERIC @@ -1985,6 +1986,7 @@ int pci_setup_device(struct pci_dev *dev) dev->sysdata =3D dev->bus->sysdata; dev->dev.parent =3D dev->bus->bridge; dev->dev.bus =3D &pci_bus_type; + dev_liveupdate_init(&dev->dev); dev->hdr_type =3D hdr_type & 0x7f; dev->multifunction =3D !!(hdr_type & 0x80); dev->error_state =3D pci_channel_io_normal; @@ -3184,7 +3186,7 @@ struct pci_bus *pci_create_root_bus(struct device *pa= rent, int bus, return NULL; =20 bridge->dev.parent =3D parent; - + dev_liveupdate_init(&bridge->dev); list_splice_init(resources, &bridge->windows); bridge->sysdata =3D sysdata; bridge->busnr =3D bus; diff --git a/include/linux/dev_liveupdate.h b/include/linux/dev_liveupdate.h new file mode 100644 index 0000000000000000000000000000000000000000..72297cba08a999e89f7bc0997da= bdbe14e0aa12c --- /dev/null +++ b/include/linux/dev_liveupdate.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Copyright (c) 2025, Google LLC. + * Pasha Tatashin + * Chris Li + */ +#ifndef _LINUX_DEV_LIVEUPDATE_H +#define _LINUX_DEV_LIVEUPDATE_H + +#include + +#ifdef CONFIG_LIVEUPDATE + +enum liveupdate_flag { + LU_BUSMASTER =3D 1 << 0, + LU_BUSMASTER_BRIDGE =3D 2 << 0, +}; + +#define LU_REQUESTED (LU_BUSMASTER) +#define LU_DEPENDED (LU_BUSMASTER_BRIDGE) + +/** + * struct dev_liveupdate - Device state for live update operations + * @lu_next: List head for linking the device into live update + * related lists (e.g., a list of devices participating + * in a live update sequence). + * @flags: Indicate what liveupdate feature does the device + * participtate. + * @visited: Only used by the bus devices when travese the PCI buses + * to build the liveupdate devices list. Set if the child + * buses have been pushed into the pending stack. + * + * This structure holds the state information required for performing + * live update operations on a device. It is embedded within a struct devi= ce. + */ +struct dev_liveupdate { + struct list_head lu_next; + enum liveupdate_flag flags; + bool visited:1; +}; + +#endif /* CONFIG_LIVEUPDATE */ +#endif /* _LINUX_DEV_LIVEUPDATE_H */ diff --git a/include/linux/device.h b/include/linux/device.h index 4940db137fffff4ceacf819b32433a0f4898b125..e0b35c723239f1254a3b6152f43= 3e0412cd3fb34 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -508,6 +509,7 @@ struct device_physical_location { * @pm_domain: Provide callbacks that are executed during system suspend, * hibernation, system resume and during runtime PM transitions * along with subsystem-level and driver-level callbacks. + * @lu: Live update state. * @em_pd: device's energy model performance domain * @pins: For device pin management. * See Documentation/driver-api/pin-control.rst for details. @@ -603,6 +605,10 @@ struct device { struct dev_pm_info power; struct dev_pm_domain *pm_domain; =20 +#ifdef CONFIG_LIVEUPDATE + struct dev_liveupdate lu; +#endif + #ifdef CONFIG_ENERGY_MODEL struct em_perf_domain *em_pd; #endif @@ -1168,4 +1174,13 @@ void device_link_wait_removal(void); #define MODULE_ALIAS_CHARDEV_MAJOR(major) \ MODULE_ALIAS("char-major-" __stringify(major) "-*") =20 +#ifdef CONFIG_LIVEUPDATE +static inline void dev_liveupdate_init(struct device *dev) +{ + INIT_LIST_HEAD(&dev->lu.lu_next); +} +#else +static inline void dev_liveupdate_init(struct device *dev) {} +#endif + #endif /* _DEVICE_H_ */ --=20 2.51.0.384.g4c02a37b29-goog From nobody Thu Oct 2 14:11:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BF2742E9EA0; Tue, 16 Sep 2025 07:45:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758008717; cv=none; b=GhOvfnoRHhcCSOEgj+gTCB6xP5O+zXt0hgndVt/IzJY7wWHcbUkEts/XgfGY0SStttX9YE8iNOI9M6odrZxU6qP9MtDxFycYLLohLeiiaZg/qqrdr5FbYJRiv4UDrwBgy5Jn5G1pvG+qci5Z2aGOmjAOcv3ML7UShRYME3Ef5/Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758008717; c=relaxed/simple; bh=TDPjKbP6JuxBf+E8pj9xVBmtW5mDyqaBa2s3+wF1yxs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=TRi0X55V+9+YLJuMAXovlhvHsvLfJdN3+vN8/uQBq5hswdW7KRCM3HHhVgDJQGfsAx611FRMKm4HdchhMQ46dqDJJq+T3f29yelvh+ffX5Qzb2Zsqwb/TYkKeUaK9g9ANaYihiTvm3zgGrxpOmw1L2jykqKXCTCXkH3N34BwZ5s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=seoqjGSf; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="seoqjGSf" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9BAA3C113D0; Tue, 16 Sep 2025 07:45:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758008717; bh=TDPjKbP6JuxBf+E8pj9xVBmtW5mDyqaBa2s3+wF1yxs=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=seoqjGSfcad+F4LQlY4eypPy7RmGTApX8ESLhazqzEN1HqQT31hDXGjAN+ZV0YC82 l8J7wJ6sNdBc1Dqg/ONUUBlJ5WGVZNdLKxmjQpay4BFTwlU52E1GUGaAsmZwUCTxmM HgWiKrQtvKegIxpfvR6+899VfqhZSoZVHYBYTl3owjcsBibjXIeyBn1U3vfToX2erT nlNetMwECfwqULyQTTmrliyQ7t8HlFc8fvyNC2xlfFt2SS5PIkKQO45CH45JXSQnww LHVWVcKzhxcqXP/JFfcRujFiDGFlcqW8QuNtOCyjtfLTXWG1W3rBub25RAId2LQEEj TNAlua9tSPk5Q== From: Chris Li Date: Tue, 16 Sep 2025 00:45:11 -0700 Subject: [PATCH v2 03/10] PCI/LUO: Forward prepare()/freeze()/cancel() callbacks to driver Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250916-luo-pci-v2-3-c494053c3c08@kernel.org> References: <20250916-luo-pci-v2-0-c494053c3c08@kernel.org> In-Reply-To: <20250916-luo-pci-v2-0-c494053c3c08@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown , Pasha Tatashin Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 After the list of preserved devices is constructed, the PCI subsystem can now forward the liveupdate request to the driver. The PCI subsystem saves and restores a u64 data from LUO callback. For each device, the PCI subsystem preserve a "dev_state" struct, which contains the path (domain + bus + devfn) and a per device u64 data. The device driver will use such a u64 data area to store the device driver state. The device live update callback looks very similar to the LUO subsystem callback, with the "void *arg" change to "struct device *dev". In the prepare callback, the PCI subsystem allocates then preserves a folio big enough to hold all requested device state (struct pci_dev_ser) in an array and the count. The PCI sub system will just forward the liveupdate call back with u64 data point to the u64 field of the device state array. If some device fails the prepare callback, all previous devices that already successfully finished the prepare call back will get the cancel call back to clean up the saved state. That clean up is the special case that not the full list will be walked. In other live update callbacks, all the devices in the preserved device list will get the callback with their own u64 data field. Signed-off-by: Chris Li --- drivers/pci/liveupdate.c | 203 +++++++++++++++++++++++++++++++++++++= ++-- include/linux/dev_liveupdate.h | 23 +++++ include/linux/device/driver.h | 6 ++ 3 files changed, 223 insertions(+), 9 deletions(-) diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c index e8891844b8194dabf8d1e8e2d74d9c701bd741ca..2b215c224fb78c908579b0d22be= 713e1dc7ca21f 100644 --- a/drivers/pci/liveupdate.c +++ b/drivers/pci/liveupdate.c @@ -9,11 +9,25 @@ #define dev_fmt(fmt) "PCI liveupdate: " fmt =20 #include +#include #include #include "pci.h" =20 #define PCI_SUBSYSTEM_NAME "pci" =20 +static LIST_HEAD(preserved_devices); + +struct pci_dev_ser { + u32 path; /* domain + bus + slot + fn */ + u32 flags; + u64 driver_data; /* driver data */ +}; + +struct pci_ser { + u32 count; + struct pci_dev_ser devs[]; +}; + static void stack_push_buses(struct list_head *stack, struct list_head *bu= ses) { struct pci_bus *bus; @@ -70,42 +84,213 @@ static int build_liveupdate_devices(struct list_head *= head) return count; } =20 +static void dev_cleanup_liveupdate(struct device *dev) +{ + dev->lu.flags &=3D ~LU_DEPENDED; + list_del_init(&dev->lu.lu_next); +} + static void cleanup_liveupdate_devices(struct list_head *head) { struct device *d, *n; =20 - list_for_each_entry_safe(d, n, head, lu.lu_next) { - d->lu.flags &=3D ~LU_DEPENDED; - list_del_init(&d->lu.lu_next); + list_for_each_entry_safe(d, n, head, lu.lu_next) + dev_cleanup_liveupdate(d); +} + +static void cleanup_liveupdate_state(struct pci_ser *pci_state) +{ + struct folio *folio =3D virt_to_folio(pci_state); + + kho_unpreserve_folio(folio); + folio_put(folio); +} + +static void pci_call_cancel(struct pci_ser *pci_state) +{ + struct pci_dev_ser *si =3D pci_state->devs; + struct device *dev, *next; + + list_for_each_entry_safe(dev, next, &preserved_devices, lu.lu_next) { + struct pci_dev_ser *s =3D si++; + + if (!dev->driver) + panic("PCI liveupdate cancel: %s has no driver", dev_name(dev)); + if (!dev->driver->lu) + panic("PCI liveupdate cancel: %s driver %s does not support liveupdate", + dev_name(dev), dev->driver->name ? : "(null name)"); + if (dev->driver->lu->cancel) + dev->driver->lu->cancel(dev, s->driver_data); + dev_cleanup_liveupdate(dev); } } =20 -static int pci_liveupdate_prepare(void *arg, u64 *data) +static int pci_get_device_path(struct pci_dev *pdev) +{ + return (pci_domain_nr(pdev->bus) << 16) | pci_dev_id(pdev); +} + +static int pci_save_device_state(struct device *dev, struct pci_dev_ser *s) +{ + struct pci_dev *pdev =3D to_pci_dev(dev); + + s->path =3D pci_get_device_path(pdev); + s->flags =3D dev->lu.flags; + return 0; +} + +static int pci_call_prepare(struct pci_ser *pci_state, + struct list_head *devices) +{ + struct pci_dev_ser *pdev_state_current =3D pci_state->devs; + struct device *dev, *next; + int ret; + char *reason; + + list_for_each_entry_safe(dev, next, devices, lu.lu_next) { + struct pci_dev_ser *s =3D pdev_state_current++; + + if (!dev->driver) { + reason =3D "no driver"; + ret =3D -ENOENT; + goto cancel; + } + if (!dev->driver->lu) { + reason =3D "driver does not support liveupdate"; + ret =3D -EPERM; + goto cancel; + } + ret =3D pci_save_device_state(dev, s); + if (ret) { + reason =3D "save device state failed"; + goto cancel; + } + if (dev->driver->lu->prepare) { + ret =3D dev->driver->lu->prepare(dev, &s->driver_data); + if (ret) { + reason =3D "prepare() failed"; + goto cancel; + } + } + list_move_tail(&dev->lu.lu_next, &preserved_devices); + } + return 0; + +cancel: + dev_err(dev, "luo prepare failed %d (%s)\n", ret, reason); + pci_call_cancel(pci_state); + return ret; +} + +static int __pci_liveupdate_prepare(void *arg, u64 *data) { LIST_HEAD(requested_devices); + struct pci_ser *pci_state; + int ret; + int count =3D build_liveupdate_devices(&requested_devices); + int size =3D sizeof(*pci_state) + sizeof(pci_state->devs[0]) * count; + int order =3D get_order(size); + struct folio *folio; =20 - pr_info("prepare data[%llx]\n", *data); + folio =3D folio_alloc(GFP_KERNEL | __GFP_ZERO, order); + if (!folio) { + ret =3D -ENOMEM; + goto cleanup_device; + } =20 - pci_lock_rescan_remove(); - down_write(&pci_bus_sem); + pci_state =3D folio_address(folio); + pci_state->count =3D count; + + ret =3D kho_preserve_folio(folio); + if (ret) { + pr_err("liveupdate_preserve_folio failed\n"); + goto release_folio; + } + + ret =3D pci_call_prepare(pci_state, &requested_devices); + if (ret) + goto unpreserve; =20 - build_liveupdate_devices(&requested_devices); + *data =3D __pa(pci_state); + pr_info("prepare data[%llx]\n", *data); + return 0; + +unpreserve: + kho_unpreserve_folio(folio); +release_folio: + folio_put(folio); +cleanup_device: cleanup_liveupdate_devices(&requested_devices); + return ret; +} =20 +static int pci_liveupdate_prepare(void *arg, u64 *data) +{ + int ret; + + pci_lock_rescan_remove(); + down_write(&pci_bus_sem); + ret =3D __pci_liveupdate_prepare(arg, data); up_write(&pci_bus_sem); pci_unlock_rescan_remove(); + return ret; +} + +static int pci_call_freeze(struct pci_ser *pci_state, struct list_head *de= vlist) +{ + struct pci_dev_ser *n =3D pci_state->devs; + struct device *dev; + int ret =3D 0; + + list_for_each_entry(dev, devlist, lu.lu_next) { + struct pci_dev_ser *s =3D n++; + + if (!dev->driver) { + if (!dev->parent) + continue; + panic("PCI liveupdate freeze: %s has no driver", dev_name(dev)); + } + if (!dev->driver->lu->freeze) + continue; + ret =3D dev->driver->lu->freeze(dev, &s->driver_data); + if (ret) { + dev_err(dev, "luo freeze failed %d\n", ret); + pci_call_cancel(pci_state); + return ret; + } + } return 0; } =20 static int pci_liveupdate_freeze(void *arg, u64 *data) { + struct pci_ser *pci_state =3D phys_to_virt(*data); + int ret; + pr_info("freeze data[%llx]\n", *data); - return 0; + pci_lock_rescan_remove(); + down_write(&pci_bus_sem); + + ret =3D pci_call_freeze(pci_state, &preserved_devices); + + up_write(&pci_bus_sem); + pci_unlock_rescan_remove(); + return ret; } =20 static void pci_liveupdate_cancel(void *arg, u64 data) { + struct pci_ser *pci_state =3D phys_to_virt(data); + pr_info("cancel data[%llx]\n", data); + pci_lock_rescan_remove(); + down_write(&pci_bus_sem); + + pci_call_cancel(pci_state); + cleanup_liveupdate_state(pci_state); + + up_write(&pci_bus_sem); + pci_unlock_rescan_remove(); } =20 static void pci_liveupdate_finish(void *arg, u64 data) diff --git a/include/linux/dev_liveupdate.h b/include/linux/dev_liveupdate.h index 72297cba08a999e89f7bc0997dabdbe14e0aa12c..80a723c7701ac4ddc2ddd03d0ff= c9cc5a62a6083 100644 --- a/include/linux/dev_liveupdate.h +++ b/include/linux/dev_liveupdate.h @@ -20,6 +20,8 @@ enum liveupdate_flag { #define LU_REQUESTED (LU_BUSMASTER) #define LU_DEPENDED (LU_BUSMASTER_BRIDGE) =20 +struct device; + /** * struct dev_liveupdate - Device state for live update operations * @lu_next: List head for linking the device into live update @@ -40,5 +42,26 @@ struct dev_liveupdate { bool visited:1; }; =20 +/** + * struct dev_liveupdate_ops - Live Update callback functions + * @prepare: Prepare device for the upcoming state transition. Driver = and + * buses should save the necessary device state. + * @freeze: A final notification before the system jumps to the new k= ernel. + * Called from reboot() syscall. + * @cancel: Cancel the live update process. Driver should clean + * up any saved state if necessary. + * @finish: The system has completed a transition. Drivers and buses = should + * have already restored the previously saved device state. + * Clean-up any saved state or reset unreclaimed device. + * + * This structure is used by drivers and buses to hold the callback from L= UO. + */ +struct dev_liveupdate_ops { + int (*prepare)(struct device *dev, u64 *data); + int (*freeze)(struct device *dev, u64 *data); + void (*cancel)(struct device *dev, u64 data); + void (*finish)(struct device *dev, u64 data); +}; + #endif /* CONFIG_LIVEUPDATE */ #endif /* _LINUX_DEV_LIVEUPDATE_H */ diff --git a/include/linux/device/driver.h b/include/linux/device/driver.h index cd8e0f0a634be9ea63ff22e89d66ada3b1a9eaf2..b2ba469cc3065a412f02230c62e= 811af19c4d2c6 100644 --- a/include/linux/device/driver.h +++ b/include/linux/device/driver.h @@ -19,6 +19,7 @@ #include #include #include +#include =20 /** * enum probe_type - device driver probe type to try @@ -80,6 +81,8 @@ enum probe_type { * it is bound to the driver. * @pm: Power management operations of the device which matched * this driver. + * @lu: Live update callbacks, notify device of the live + * update state, and allow preserve device across reboot. * @coredump: Called when sysfs entry is written to. The device driver * is expected to call the dev_coredump API resulting in a * uevent. @@ -116,6 +119,9 @@ struct device_driver { const struct attribute_group **dev_groups; =20 const struct dev_pm_ops *pm; +#ifdef CONFIG_LIVEUPDATE + const struct dev_liveupdate_ops *lu; +#endif void (*coredump) (struct device *dev); =20 struct driver_private *p; --=20 2.51.0.384.g4c02a37b29-goog From nobody Thu Oct 2 14:11:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 924C12EA477; Tue, 16 Sep 2025 07:45:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758008718; cv=none; b=snPaWjrus7nt/aBP29A6KWZp/VFgQVCRlwTMAS8DlfijWBFBviiw7RPtQ8Zh8X1aTiMGcpQPgqiimP+Woy86k4qB3i6oouWqTTWwFWGyeTgyKkwC03g3plWV/pfELORztq1KMp1ajfcuGhC+4g3DM9Ym7oV2d37hr7MYEq5vOSQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758008718; c=relaxed/simple; bh=AoDEFamLdoU16RXgLYuUZAK+JS2ppkS61fpcFpEu8Jo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=uQoInm4eb7f2iQSQai8kyhXHwnQOi95UDm10hlHR2NVTZHwZhGgfoy3LjTLZajAk8pJehijXzd1wYWI35P5TdyuDKVVJqbUPYBwy3RuuucmPUJ8ubideiNItMcD0F0QRGiSC6jcZcUGBkqpBroQw+29gi2z3cwV6sb+eIvKZSqo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jm4+6PR+; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="jm4+6PR+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 71D54C4CEFA; Tue, 16 Sep 2025 07:45:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758008718; bh=AoDEFamLdoU16RXgLYuUZAK+JS2ppkS61fpcFpEu8Jo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=jm4+6PR+bA9KcdnpoH0iTa7QOP/UAC402hf7Os8CZH5UZp9JJqtrOrainrqMdpQCi 6w2iURFLBHdsVHrIqj5tW5J4qR6492tFcqQUa7CbCkb7S8TJSTDSZfd8G5laU84y2J VMXxijvfZ2ZXUY5X22Jy7tNDNabJwaduPHemiwL6cP0FEUW6KoNG3L5VxSQojuaDeQ GziR95uZcXv4Ytu0D4aekvnTKuXGjSfeTa4+Q3fhPRYBxsQuhi8arNzOuHdioSsOsw kWd+Bz88Exa/w6hk25NTrMERzEWQCIIgk0vqmYeHIfloXcu1E1h8i1TQA9ehCy1DRn c70+zvslrJimw== From: Chris Li Date: Tue, 16 Sep 2025 00:45:12 -0700 Subject: [PATCH v2 04/10] PCI/LUO: Restore state at PCI enumeration Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250916-luo-pci-v2-4-c494053c3c08@kernel.org> References: <20250916-luo-pci-v2-0-c494053c3c08@kernel.org> In-Reply-To: <20250916-luo-pci-v2-0-c494053c3c08@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown , Pasha Tatashin Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 Add a PCI device saved state member to indicate the device is requested vs depended. Restore the PCI subsystem saved state folio during PCI enumeration. When a new PCI device is created, restore the per device state pointer into the dev->lu.dev_state if the device is found in the saved devices array, by matching the device path. Restore the dev->lu.flags from the saved flags field. Add such devices to the "probed_devices" list. Signed-off-by: Chris Li --- drivers/pci/liveupdate.c | 50 ++++++++++++++++++++++++++++++++++++++= ++++ drivers/pci/pci.h | 6 +++++ drivers/pci/probe.c | 2 ++ include/linux/dev_liveupdate.h | 2 ++ 4 files changed, 60 insertions(+) diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c index 2b215c224fb78c908579b0d22be713e1dc7ca21f..305c5e85aba6bac9d02f97c83e7= b3250298d2eff 100644 --- a/drivers/pci/liveupdate.c +++ b/drivers/pci/liveupdate.c @@ -16,6 +16,7 @@ #define PCI_SUBSYSTEM_NAME "pci" =20 static LIST_HEAD(preserved_devices); +static LIST_HEAD(probe_devices); =20 struct pci_dev_ser { u32 path; /* domain + bus + slot + fn */ @@ -87,6 +88,7 @@ static int build_liveupdate_devices(struct list_head *hea= d) static void dev_cleanup_liveupdate(struct device *dev) { dev->lu.flags &=3D ~LU_DEPENDED; + dev->lu.dev_state =3D NULL; list_del_init(&dev->lu.lu_next); } =20 @@ -306,6 +308,54 @@ struct liveupdate_subsystem pci_liveupdate_ops =3D { .name =3D PCI_SUBSYSTEM_NAME, }; =20 +static struct pci_ser *pci_state_get(void) +{ + static struct pci_ser *pci_state; + struct folio *folio; + phys_addr_t data =3D 0; + int ret; + + if (pci_state) + return pci_state; + + ret =3D liveupdate_get_subsystem_data(&pci_liveupdate_ops, &data); + if (ret || !data) + panic("PCI liveupdate: get subsystem data: [%llx] ret: %d", data, ret); + + folio =3D kho_restore_folio(data); + if (!folio) + panic("PCI liveupdate: restore folio from %llx failed", data); + + /* Cache the value for future callers. */ + pci_state =3D folio_address(folio); + return pci_state; +} + +static void pci_dev_do_restore(struct pci_dev *dev, struct pci_dev_ser *s) +{ + dev->dev.lu.dev_state =3D s; + dev->dev.lu.flags =3D s->flags; + pci_info(dev, "liveupdate restore flags %x data: [%llx]\n", + s->flags, s->driver_data); + list_move_tail(&dev->dev.lu.lu_next, &probe_devices); +} + +void pci_liveupdate_restore(struct pci_dev *dev) +{ + int path; + struct pci_dev_ser *s, *end; + + if (!liveupdate_state_updated()) + return; + + path =3D pci_get_device_path(dev); + s =3D pci_state_get()->devs; + end =3D s + pci_state_get()->count; + for (; s < end; s++) + if (s->path =3D=3D path) + return pci_dev_do_restore(dev, s); +} + static int __init pci_liveupdate_init(void) { int ret; diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 12215ee72afb682b669c0e3a582b5379828e70c4..c9a7383753949994e031dc36292= 0286a475fe2ab 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -1159,4 +1159,10 @@ static inline int pci_msix_write_tph_tag(struct pci_= dev *pdev, unsigned int inde (PCI_CONF1_ADDRESS(bus, dev, func, reg) | \ PCI_CONF1_EXT_REG(reg)) =20 +#ifdef CONFIG_LIVEUPDATE +void pci_liveupdate_restore(struct pci_dev *dev); +#else +static inline void pci_liveupdate_restore(struct pci_dev *dev) {} +#endif + #endif /* DRIVERS_PCI_H */ diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index dddd7ebc03d1a6e6ee456e0bf02ab9833a819509..a0605af1a699cd07b0989717280= 3dcba1d2da9f9 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2017,6 +2017,8 @@ int pci_setup_device(struct pci_dev *dev) if (pci_early_dump) early_dump_pci_device(dev); =20 + pci_liveupdate_restore(dev); + /* Need to have dev->class ready */ dev->cfg_size =3D pci_cfg_space_size(dev); =20 diff --git a/include/linux/dev_liveupdate.h b/include/linux/dev_liveupdate.h index 80a723c7701ac4ddc2ddd03d0ffc9cc5a62a6083..bb7ecf159dfa82e3779d9388115= 41dddcf8f40af 100644 --- a/include/linux/dev_liveupdate.h +++ b/include/linux/dev_liveupdate.h @@ -27,6 +27,7 @@ struct device; * @lu_next: List head for linking the device into live update * related lists (e.g., a list of devices participating * in a live update sequence). + * @dev_state: Set to the device state at restore. * @flags: Indicate what liveupdate feature does the device * participtate. * @visited: Only used by the bus devices when travese the PCI buses @@ -38,6 +39,7 @@ struct device; */ struct dev_liveupdate { struct list_head lu_next; + void *dev_state; enum liveupdate_flag flags; bool visited:1; }; --=20 2.51.0.384.g4c02a37b29-goog From nobody Thu Oct 2 14:11:13 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5B41C2E7162; Tue, 16 Sep 2025 07:45:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758008719; cv=none; b=Ae3unLTPxietE//G1AZ0hbGa5WH5lyNFy/L+1S978bKzR/h87SepkfLHbpunLqJaPQxJE3+OaahSVcXNTxL0uG9pdxlWd1LOT0tuy6PUovWwGqDuF2xJVg0KzYGMKICJ5kJLPP1Q0gcbSz19XAFSeQr98L3MQ8IFVyKQ2h4FWRA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758008719; c=relaxed/simple; bh=atC+NDqa0LfxetrMUXV/684PEhjI9J/4qvzS5Tca4rs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=d8g2Yy7ePfHcv60S8J5+Ni3C0Itk/vjunyWD6mZcPPQgvjRjfMwcPwOUzTdETa9dR7n4ayGEVF0WSV41j0Zy2wpDtLUVAPiYvQTbfGbXCEbFccYzIRgoDAMgVYlegu1SA3onDkCU5RkT8/tCX49pHsf4frLjnxdbPYl3T0M5/Wo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IS9MKNvf; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="IS9MKNvf" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 48640C4CEF9; Tue, 16 Sep 2025 07:45:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758008719; bh=atC+NDqa0LfxetrMUXV/684PEhjI9J/4qvzS5Tca4rs=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=IS9MKNvfFLZU41niOvXE3SkO9rfzHIaY/zKX+XP+Gc1gWTyHpXzP9g3XPj6oYYWB8 KSOsc03KLVc7m3vZaGq+uqILXJh/PYBWLb3kQS1TmveEbv7wQIRBOPhaGOjk9juxU5 3eIAyjLx3dmquiqWOxAjzXIGxqpkWpAfsog0iWqIi9v9LIxV+6W0KH3+OfFa6HhbQw dhBfdf82t+Sll0efDNNSkHlzIr2sbmD6IWXEO0MMJytB76wfxJ0gktwcxi3qbNuE2v i1VQnoAA7J/HUH3oUF1qQh5PiDb7izn/ahhnBktvPsyA2uH8aU4fR0ocHswt+47sjJ o/M7pSyX0EK8A== From: Chris Li Date: Tue, 16 Sep 2025 00:45:13 -0700 Subject: [PATCH v2 05/10] PCI/LUO: Forward finish callbacks to drivers Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250916-luo-pci-v2-5-c494053c3c08@kernel.org> References: <20250916-luo-pci-v2-0-c494053c3c08@kernel.org> In-Reply-To: <20250916-luo-pci-v2-0-c494053c3c08@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown , Pasha Tatashin Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 When PCI receives the LUO finish callback. The PCI subsystem forwards the finish callback to the driver with restored dev->lu.dev_state->data. Tested: In qemu, request a virtio net device as requested. Perform luo prepare then kexec. Verify the new kernel boot up dmesg shows the requested device has per device live update state restored. Perform liveupdate finish and see the device finish callback gets invoked. Signed-off-by: Chris Li --- drivers/pci/liveupdate.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c index 305c5e85aba6bac9d02f97c83e7b3250298d2eff..41606df346f751c78f6c69caa27= 5b4a76be72510 100644 --- a/drivers/pci/liveupdate.c +++ b/drivers/pci/liveupdate.c @@ -264,6 +264,29 @@ static int pci_call_freeze(struct pci_ser *pci_state, = struct list_head *devlist) return 0; } =20 +static void pci_call_finish(struct list_head *devlist) +{ + struct device *dev; + + pci_lock_rescan_remove(); + down_write(&pci_bus_sem); + + list_for_each_entry(dev, devlist, lu.lu_next) { + struct pci_dev_ser *s =3D dev->lu.dev_state; + + if (!dev->driver) + panic("PCI luo finish: dev %s does not have driver", dev_name(dev)); + if (!dev->driver->lu) + panic("PCI luo finish: dev %s does not support liveupdate", + dev_name(dev)); + if (!dev->driver->lu->finish) + continue; + dev->driver->lu->finish(dev, s->driver_data); + } + up_write(&pci_bus_sem); + pci_unlock_rescan_remove(); +} + static int pci_liveupdate_freeze(void *arg, u64 *data) { struct pci_ser *pci_state =3D phys_to_virt(*data); @@ -297,7 +320,12 @@ static void pci_liveupdate_cancel(void *arg, u64 data) =20 static void pci_liveupdate_finish(void *arg, u64 data) { + struct pci_ser *pci_state =3D phys_to_virt(data); + pr_info("finish data[%llx]\n", data); + pci_call_finish(&probe_devices); + cleanup_liveupdate_devices(&probe_devices); + cleanup_liveupdate_state(pci_state); } =20 struct liveupdate_subsystem pci_liveupdate_ops =3D { --=20 2.51.0.384.g4c02a37b29-goog From nobody Thu Oct 2 14:11:13 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 444061D555; Tue, 16 Sep 2025 07:45:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758008720; cv=none; b=sc82zGTJu3ke9Ne2i55W2ShWLeayjz6LZWYyHebhNpVgLBBJvML7NICmeVXHwWKVwU7DTOi7L74PzDPLzpRojh1Tw35NisQKoWzTTfUCH8uRYqe0sEkWI4APqo12pR44sWN+qi9sCFo113cTxAd8bLJegVJKIat3sVT0ZND20xI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758008720; c=relaxed/simple; bh=65rvMZdqXLBpj1Exfk5pfS+Pgfc+xgvPUvlb1n7tdnA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=oQKIYhCGmjF/i83xjFTKsBllPkpytQ8VGLA1uTyYFCs6+HNwYM6g4vyj/ZKVh0tlda42Evf5ocGvhwY7VsXKfq8PY118rpaSZBCZ5yX9P8lnZhB/C9SEH2S8VbVTXuLvy7f/Wr6exbVi7DDOeYwDzbEjlQEHCdNaXhZx/wqqNds= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RHMQCVS9; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RHMQCVS9" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 24529C116D0; Tue, 16 Sep 2025 07:45:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758008719; bh=65rvMZdqXLBpj1Exfk5pfS+Pgfc+xgvPUvlb1n7tdnA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=RHMQCVS9DCY11dGc5jbT0rNwEips3RlTFz5Cy50elxzpxpEHsFtjjHvoriHkaSDw7 VJjuPNY57tIq3J5xu2yhnJOAnDPTgDxFg7jmeARwKhxN7XCHLK/xBN7OK4H6kV318P DQFSurbywiNtJ+RsSLa0a8Y3SEXbQ76iXRlLOhIDybLGfUatvloR4A5NdIckXoeL/B pLI5KFvW64faYB19Z7Eqc4bR69KggbXl635xKT0hOP/u+VQ5UIo7546stdlqjvb7PW fOIP6D7TyV9IXy4YnpHkA8nq09mO4RZEGA396YeFc8NOe2Y2hDNitEcNyI+eGFUOj6 I9RdeyZHgmCLQ== From: Chris Li Date: Tue, 16 Sep 2025 00:45:14 -0700 Subject: [PATCH v2 06/10] PCI/LUO: Save and restore driver name Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250916-luo-pci-v2-6-c494053c3c08@kernel.org> References: <20250916-luo-pci-v2-0-c494053c3c08@kernel.org> In-Reply-To: <20250916-luo-pci-v2-0-c494053c3c08@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown , Pasha Tatashin Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 Save the PCI driver name into "struct pci_dev_ser" during the PCI prepare callback. After kexec, use driver_set_override() to ensure the device is bound only to the saved driver. Clear the override after the finish callback. Signed-off-by: Chris Li --- drivers/pci/liveupdate.c | 36 ++++++++++++++++++++++++++++++++++-- drivers/pci/pci.h | 2 ++ drivers/pci/probe.c | 2 ++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c index 41606df346f751c78f6c69caa275b4a76be72510..ae8f4dc5cf92577a4da83743c3b= 80bc72974a43e 100644 --- a/drivers/pci/liveupdate.c +++ b/drivers/pci/liveupdate.c @@ -21,6 +21,7 @@ static LIST_HEAD(probe_devices); struct pci_dev_ser { u32 path; /* domain + bus + slot + fn */ u32 flags; + char driver_name[63]; u64 driver_data; /* driver data */ }; =20 @@ -87,6 +88,10 @@ static int build_liveupdate_devices(struct list_head *he= ad) =20 static void dev_cleanup_liveupdate(struct device *dev) { + struct pci_dev *pdev =3D to_pci_dev(dev); + + if (liveupdate_state_updated()) + WARN_ON(driver_set_override(dev, &pdev->driver_override, "", 0)); dev->lu.flags &=3D ~LU_DEPENDED; dev->lu.dev_state =3D NULL; list_del_init(&dev->lu.lu_next); @@ -135,7 +140,13 @@ static int pci_get_device_path(struct pci_dev *pdev) static int pci_save_device_state(struct device *dev, struct pci_dev_ser *s) { struct pci_dev *pdev =3D to_pci_dev(dev); + const char *name =3D dev->driver->name; =20 + if (!name) + return -ENXIO; + if (strlen(name) > sizeof(s->driver_name) - 1) + return -ENOSPC; + strscpy(s->driver_name, name, sizeof(s->driver_name)); s->path =3D pci_get_device_path(pdev); s->flags =3D dev->lu.flags; return 0; @@ -363,8 +374,8 @@ static void pci_dev_do_restore(struct pci_dev *dev, str= uct pci_dev_ser *s) { dev->dev.lu.dev_state =3D s; dev->dev.lu.flags =3D s->flags; - pci_info(dev, "liveupdate restore flags %x data: [%llx]\n", - s->flags, s->driver_data); + pci_info(dev, "liveupdate restore flags %x driver: %s data: [%llx]\n", + s->flags, s->driver_name, s->driver_data); list_move_tail(&dev->dev.lu.lu_next, &probe_devices); } =20 @@ -384,6 +395,27 @@ void pci_liveupdate_restore(struct pci_dev *dev) return pci_dev_do_restore(dev, s); } =20 +void pci_liveupdate_override_driver(struct pci_dev *dev) +{ + struct pci_dev_ser *s =3D dev->dev.lu.dev_state; + int ret; + int len; + + if (!s) + return; + + len =3D strlen(s->driver_name); + if (!len) + return; + + ret =3D driver_set_override(&dev->dev, + &dev->driver_override, + s->driver_name, len); + if (ret) + panic("PCI Liveupdate override driver failed: %s", s->driver_name); +} + + static int __init pci_liveupdate_init(void) { int ret; diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index c9a7383753949994e031dc362920286a475fe2ab..b79a18c5e948980fe2ef3f0a10e= 0d795b1eee6d7 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -1161,8 +1161,10 @@ static inline int pci_msix_write_tph_tag(struct pci_= dev *pdev, unsigned int inde =20 #ifdef CONFIG_LIVEUPDATE void pci_liveupdate_restore(struct pci_dev *dev); +void pci_liveupdate_override_driver(struct pci_dev *dev); #else static inline void pci_liveupdate_restore(struct pci_dev *dev) {} +static inline void pci_liveupdate_override_driver(struct pci_dev *dev) {} #endif =20 #endif /* DRIVERS_PCI_H */ diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index a0605af1a699cd07b09897172803dcba1d2da9f9..e41a1bef2083aa9184fd1c894d5= de964f19d5c01 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2714,6 +2714,8 @@ void pci_device_add(struct pci_dev *dev, struct pci_b= us *bus) /* Set up MSI IRQ domain */ pci_set_msi_domain(dev); =20 + pci_liveupdate_override_driver(dev); + /* Notifier could use PCI capabilities */ ret =3D device_add(&dev->dev); WARN_ON(ret < 0); --=20 2.51.0.384.g4c02a37b29-goog From nobody Thu Oct 2 14:11:13 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1C3F627E7FC; Tue, 16 Sep 2025 07:45:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758008721; cv=none; b=YzY9Tp3iDaw3/Ooc14x6drW2lvebxw5Bs53QmeGCNZmNVSkbRDKo+wP1po/dQj8nxrW9eY39J+jP90Ib1kH+6sCEE1+WmrShbtFq/TUzJBZ5mt6Q3ms2s7R49T4Xf1x8S89EMI6I3RBpJ/KAmtOrkewDqftahoWV4KwueMyIOrs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758008721; c=relaxed/simple; bh=S/SAVcOuL1qr6u1V0slNP0sdoMJObAMYCW0npcEpXBc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VvjTLxefMY8BU3dzWXJeUYKQHeymAk7jB6/T4l502bVmvS/mPIDWdwl9yVFB6u+GBZlRkEFM9gAEIvdbEh8RRqf50geC7GbrUgfbm5pmq8RLLbcC3I9xkGx0oSRNVIVoAaL37wY5VA02WtbKxwIUmqBlh+VU9JYwgk9ZbjZGlE8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ltGV8J4z; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ltGV8J4z" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F2A38C4CEEB; Tue, 16 Sep 2025 07:45:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758008720; bh=S/SAVcOuL1qr6u1V0slNP0sdoMJObAMYCW0npcEpXBc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ltGV8J4zvBd4mKlAWEM116fuQfCWh8sFGFgitaYemXSNlWf+nJFWFOlWeN/XMgWRW ty3syVGvznfQ2ShFevWf2CSF7ChkCBj3rE7ongw3eZN1OLXsD8LLKE862i2fPM+tyQ 4abt64w6NpoZ5iJ3GG9t+oTMWf/FvJUpQM0fc+LbpOQwXTSnB9gMvz6CRAtrHz7fys lbTiMMIAlaFKveziJLKVjZZ86WvuJDCAYi4RbvD6IZCDDpjFUFiYGL1EGfZSexQiQD UFinip2ItQTuWSR6IpwbEpYSnbxJjKZ9NUEufmsVrKZBWEeP3q8udQu2gYPYZ0joe3 bsi+euoz9ZIIw== From: Chris Li Date: Tue, 16 Sep 2025 00:45:15 -0700 Subject: [PATCH v2 07/10] PCI/LUO: Add liveupdate to pcieport driver Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250916-luo-pci-v2-7-c494053c3c08@kernel.org> References: <20250916-luo-pci-v2-0-c494053c3c08@kernel.org> In-Reply-To: <20250916-luo-pci-v2-0-c494053c3c08@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown , Pasha Tatashin Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 The PCIe port driver is the driver bound to the PCI-PCI bridge. The PCIe port device is depended on by its PCI children devices. Add the empty liveupdate callback to the pcieport driver to indicate this driver supports liveupdate. Otherwise it can fail the liveupdate operation if the PCI-PCI bridge is depended.. Signed-off-by: Chris Li --- drivers/pci/pcie/portdrv.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/pci/pcie/portdrv.c b/drivers/pci/pcie/portdrv.c index 0e9ef387182856771d857181d88f376632b46f0d..fd43c1ebfb9d2852fbc460b0390= dd7fb016226d2 100644 --- a/drivers/pci/pcie/portdrv.c +++ b/drivers/pci/pcie/portdrv.c @@ -789,6 +789,15 @@ static const struct pci_error_handlers pcie_portdrv_er= r_handler =3D { .mmio_enabled =3D pcie_portdrv_mmio_enabled, }; =20 +#ifdef CONFIG_LIVEUPDATE + +/* + * Empty pcie_port_lu_ops to indicate this driver support liveupdate. + */ +static struct dev_liveupdate_ops pcie_port_lu_ops; + +#endif /* CONFIG_LIVEUPDATE */ + static struct pci_driver pcie_portdriver =3D { .name =3D "pcieport", .id_table =3D port_pci_ids, @@ -802,6 +811,9 @@ static struct pci_driver pcie_portdriver =3D { .driver_managed_dma =3D true, =20 .driver.pm =3D PCIE_PORTDRV_PM_OPS, +#ifdef CONFIG_LIVEUPDATE + .driver.lu =3D &pcie_port_lu_ops, +#endif }; =20 static int __init dmi_pcie_pme_disable_msi(const struct dmi_system_id *d) --=20 2.51.0.384.g4c02a37b29-goog From nobody Thu Oct 2 14:11:13 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A2E7E28315D; Tue, 16 Sep 2025 07:45:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758008721; cv=none; b=NPUAq9UfZKe5C6hmTpFFHdqxP2xsYwHm/PhxHIqoVbl030xaKKjjAxbNrfnbT/hOVje9zSOL4P3lSiLZFrByMBwzIn/gBciFwMZ9mwDV3384cfWZHhKHGHgzHTWDbx3WivnXsaHiZf0jZ8//BusmdpaD1ul3DP0igwjJcd6N37w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758008721; c=relaxed/simple; bh=ruILf0f+2IGG4simAnF8+HVvvX3jTzt4/RPGtC8FTFk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=j1QgT5U/s6Ne1u51qMoX15H2JMH9b/+nvO5msoMpbwwaJxFbJV/X2xGgIDQ6+tgyDFTItTWvUsMoy8trW5Pa26/f845xFlGb537pXaUKief8bYf3+Dqa11KqevPH3RZBCe6Z2pf4Z2yEO2ZfPHkoXLoTEIytMC6C3bfj0VUV6qw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=inkYiJxx; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="inkYiJxx" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C9122C4AF09; Tue, 16 Sep 2025 07:45:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758008721; bh=ruILf0f+2IGG4simAnF8+HVvvX3jTzt4/RPGtC8FTFk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=inkYiJxxixU8FzK+JezaaEYGBHOPiEfY43ZDFH413sF5U0C3yaFApc3x2iDdnVCKL 79zwtEz97JLJPUkxciW1TIN7+y+LO37xc2WtZ1xx7RzFqNYCuX7LciT0vOfhkEzDf7 1ndWiG0ailCvob7pkhvMRIye6cF1kTL/JvvwnFx3jTy8H3djXhXYgUpHTRUXEw/clD KG3RXLd2YozJ3cNMaxAcsoS5nSh0ERWoEv2I4D4NVLlXuTJlsvH8pBXFm2XtcrIZmt LJNFdKmkeAaU7HdXn41b7WXNaXa45L11ftptry+3JetADK1VT5EKU1Fs+70nPdNxP3 Q9e7zkRgB+oBw== From: Chris Li Date: Tue, 16 Sep 2025 00:45:16 -0700 Subject: [PATCH v2 08/10] PCI/LUO: Add pci_liveupdate_get_driver_data() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250916-luo-pci-v2-8-c494053c3c08@kernel.org> References: <20250916-luo-pci-v2-0-c494053c3c08@kernel.org> In-Reply-To: <20250916-luo-pci-v2-0-c494053c3c08@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown , Pasha Tatashin Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 Similar to liveupdate_get_subsystem_data(), the PCI subsystem provide pci_liveupdate_get_driver_data() for the driver to receive the driver data during new kernel boot up, in the liveupdate updated state. This function =C2=A0will return an error on any other liveupdate state. For example, vfio-pci will use this API in probe() to access the liveupdate state from the previous kernel. Signed-off-by: Chris Li --- drivers/pci/liveupdate.c | 15 +++++++++++++++ include/linux/pci.h | 9 +++++++++ 2 files changed, 24 insertions(+) diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c index ae8f4dc5cf92577a4da83743c3b80bc72974a43e..1b12fc0649f479c6f45ffb26e6e= 3754f41054ea8 100644 --- a/drivers/pci/liveupdate.c +++ b/drivers/pci/liveupdate.c @@ -395,6 +395,21 @@ void pci_liveupdate_restore(struct pci_dev *dev) return pci_dev_do_restore(dev, s); } =20 +int pci_liveupdate_get_driver_data(struct pci_dev *pdev, u64 *data) +{ + struct dev_liveupdate *lu =3D &pdev->dev.lu; + struct pci_dev_ser *s =3D lu->dev_state; + + if (!liveupdate_state_updated()) + return -EINVAL; + + if (!lu->dev_state) + return -ENOENT; + + *data =3D s->driver_data; + return 0; +} + void pci_liveupdate_override_driver(struct pci_dev *dev) { struct pci_dev_ser *s =3D dev->dev.lu.dev_state; diff --git a/include/linux/pci.h b/include/linux/pci.h index 05e68f35f39238f8b9ce08df97b384d1c1e89bbe..50296bb04aaa7f2bbd2260f8ec4= 670533e019e38 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -2767,4 +2767,13 @@ void pci_uevent_ers(struct pci_dev *pdev, enum pci_= ers_result err_type); WARN_ONCE(condition, "%s %s: " fmt, \ dev_driver_string(&(pdev)->dev), pci_name(pdev), ##arg) =20 +#ifdef CONFIG_LIVEUPDATE +int pci_liveupdate_get_driver_data(struct pci_dev *pdev, u64 *data); +#else +static inline int pci_liveupdate_get_driver_data(struct pci_dev *pdev, + u64 *data) +{ + return 0; +} +#endif #endif /* LINUX_PCI_H */ --=20 2.51.0.384.g4c02a37b29-goog From nobody Thu Oct 2 14:11:13 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C74FB284886; Tue, 16 Sep 2025 07:45:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758008722; cv=none; b=aEBBy1XxK3VHUNgVPK25JFjyfCF9chtUykDkJG6gpx+O7bJ5au9y58wX5dytJpbm6WZuddbR/rSziRhZZKFA1r4d69QUleF9uwQL2zmrl4+iSH6TZB/tLRTtr9EZ5shAcOJ5ZomzJ9PFZEYRztZ62AqUPKqQ5Dq4W0SZwH2qsYE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758008722; c=relaxed/simple; bh=dUcb/BZPkxNt0dROS5Ezcx5T/Q+ckLs6aaqzBb/B6HE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=P/gx6pRPLKGscUhfKSU62IGhgAzKdoGQFRM4wKOZ/WEsVHOKPd/eg4MJ6uKRr+vAHG4ooznwco9iNLmNQ1xsNJ6KfxiP2TyGGnR7IZ6p/2Q8QAzBSqu8US1Di2b7hdfzWo4Z3BX9cGS9hTwHzzsIDo0jKYsGwaTQLk/pb8CzMt8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=kfJj6eYA; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="kfJj6eYA" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9F4ECC4CEF7; Tue, 16 Sep 2025 07:45:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758008722; bh=dUcb/BZPkxNt0dROS5Ezcx5T/Q+ckLs6aaqzBb/B6HE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=kfJj6eYA+tLSMezqd0KiYus0yp3bie9xOgk+GfPWahtZRQvZjgZlTcjGn/STIxTD8 0qwJRe49489Bv10hjZG1jWCMpipFrp4T0qezlYe6jhf3fbhLF1a4ftx9zFUJwUsXKo dq7b9zG92b11RYPw1/JHI365Joe5UU1QEL9e2yxm/DDdsR7zOvG8NzY/E+suCeuTJU 9+1eBMUs+NJbiQBAzf6uEE84/7KSApMQ9xImInIfzTbs5nz+W/+hxTdQDYEMyty8HK FiZkx2TXltr/gN0FwX9kasawVXXyTY1Ew4Rhx94XU8gP9rvlQq7efSHgl3XybxUmZH LtoW8YDnzSXRA== From: Chris Li Date: Tue, 16 Sep 2025 00:45:17 -0700 Subject: [PATCH v2 09/10] PCI/LUO: Avoid write to bus master at boot Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250916-luo-pci-v2-9-c494053c3c08@kernel.org> References: <20250916-luo-pci-v2-0-c494053c3c08@kernel.org> In-Reply-To: <20250916-luo-pci-v2-0-c494053c3c08@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown , Pasha Tatashin Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 If the liveupdate flag has LU_BUSMASTER or LU_BUSMASTER_BRIDGE, the device is participating in the liveupdate preserving bus master bit in the PCI config space command register. Avoid writing to the PCI command register for the bus master bit during boot up. Signed-off-by: Chris Li --- drivers/pci/liveupdate.c | 6 ++++++ drivers/pci/pci.c | 7 +++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c index 1b12fc0649f479c6f45ffb26e6e3754f41054ea8..a09a166b6ee271b96bce763716c= 3b62b24f3edbb 100644 --- a/drivers/pci/liveupdate.c +++ b/drivers/pci/liveupdate.c @@ -377,6 +377,12 @@ static void pci_dev_do_restore(struct pci_dev *dev, st= ruct pci_dev_ser *s) pci_info(dev, "liveupdate restore flags %x driver: %s data: [%llx]\n", s->flags, s->driver_name, s->driver_data); list_move_tail(&dev->dev.lu.lu_next, &probe_devices); + if (s->flags & (LU_BUSMASTER | LU_BUSMASTER_BRIDGE)) { + u16 pci_command; + + pci_read_config_word(dev, PCI_COMMAND, &pci_command); + WARN_ON(!(pci_command & PCI_COMMAND_MASTER)); + } } =20 void pci_liveupdate_restore(struct pci_dev *dev) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 9e42090fb108920995ebe34bd2535a0e23fef7fd..2339ac1bd57616a78d2105ba3a4= fc72bbf49973e 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2248,7 +2248,8 @@ static void do_pci_disable_device(struct pci_dev *dev) pci_read_config_word(dev, PCI_COMMAND, &pci_command); if (pci_command & PCI_COMMAND_MASTER) { pci_command &=3D ~PCI_COMMAND_MASTER; - pci_write_config_word(dev, PCI_COMMAND, pci_command); + if (!(dev->dev.lu.flags & (LU_BUSMASTER | LU_BUSMASTER_BRIDGE))) + pci_write_config_word(dev, PCI_COMMAND, pci_command); } =20 pcibios_disable_device(dev); @@ -4276,7 +4277,9 @@ static void __pci_set_master(struct pci_dev *dev, boo= l enable) if (cmd !=3D old_cmd) { pci_dbg(dev, "%s bus mastering\n", enable ? "enabling" : "disabling"); - pci_write_config_word(dev, PCI_COMMAND, cmd); + + if (!(dev->dev.lu.flags & (LU_BUSMASTER | LU_BUSMASTER_BRIDGE))) + pci_write_config_word(dev, PCI_COMMAND, cmd); } dev->is_busmaster =3D enable; } --=20 2.51.0.384.g4c02a37b29-goog From nobody Thu Oct 2 14:11:13 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 60048285404; Tue, 16 Sep 2025 07:45:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758008723; cv=none; b=ZZHpe0cQWmAK7AkdDYkZBwvw3bliRAtpqpu0x89C7aB2kxifZYGh+7AUHeRTXz00GGPCz+aBtaRKi0xvs2mE0J15UmNAcT2qISfSQP9QPlxKo3W3RzpOD7LCdnB5bHLVzWC0mXYvO6Asw6B6+N+Ccj53lj/fUTlnK7R7VgJSqyQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758008723; c=relaxed/simple; bh=16j+gt48AZcP2m8b1g7nP5m8FD/QP8fJ6B1kWd7m3OM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=cLupNLF/+rXk++4evMx2TdzySPsrEHT9tEGnWSpGbiQRaBwx1DveOrHTUu/CcLyqu7JeSzQxCl8g/NH/29MZEW9bS3lfTCFy877km2x8YphqS5PihEEvrUZTEx/YhXjHR2GMi43dWc1Vl2AiwHFCmhQSXb91BmKx+wvcCGryuX4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jyUBKcwr; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="jyUBKcwr" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 79E0CC4CEFA; Tue, 16 Sep 2025 07:45:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758008723; bh=16j+gt48AZcP2m8b1g7nP5m8FD/QP8fJ6B1kWd7m3OM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=jyUBKcwrTYXXxzot4Z4yMuvQP1+VUMFjbHmoZNwR4GbEWAwHtp7sRJjhj/aJ7UUTk nj2WkIbSIAvaA4z9qS2/GY6RNS703FAizetwzIwIqQSNNrxEjr6NpWwFWJi3tEMMwz 0eA72vGnK6Dp2dTPodtHqxkVcAumoB5gdIE0V1U53ilDVT7icKVnBdBy11e40Lg6ir hNV5X6Eb8xjUWywF9t1lwZVv5K1XHaGHa6ZFgnKXStdS5k3qKtGCOD7jfqU56NwdkG k5j8b8YGyVjX/Aoihqu/xvh9dd+8xoza8DImJJsX70iOBhKhJta7IGwnweHI4BlNi4 GdfyfH98k4bqQ== From: Chris Li Date: Tue, 16 Sep 2025 00:45:18 -0700 Subject: [PATCH v2 10/10] PCI: pci-lu-stub: Add a stub driver for Live Update testing Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250916-luo-pci-v2-10-c494053c3c08@kernel.org> References: <20250916-luo-pci-v2-0-c494053c3c08@kernel.org> In-Reply-To: <20250916-luo-pci-v2-0-c494053c3c08@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown , Pasha Tatashin Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 Introduce a new driver, pci-lu-stub, that can be bound to any PCI device and used to test the PCI subsystem support for Live Update. This driver gives developers a way to opt-in a device for Live Update and driver interaction with the PCI subsystem. This driver is only intended for testing purposes. In the future this driver can be extended to test other scenarios (such as failing prepare() on purpose). Signed-off-by: David Matlack Signed-off-by: Chris Li --- MAINTAINERS | 1 + drivers/pci/Kconfig | 10 ++++ drivers/pci/Makefile | 1 + drivers/pci/pci-lu-stub.c | 140 ++++++++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 152 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 1ae3d166cd35ec5c7818f202079ed5d10c09144b..43e5813e6f030a80c2c109b38e3= 32eef536707d6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14021,6 +14021,7 @@ F: Documentation/ABI/testing/sysfs-kernel-liveupdate F: Documentation/admin-guide/liveupdate.rst F: drivers/misc/liveupdate/ F: drivers/pci/liveupdate/ +F: drivers/pci/pci-lu-stub.c F: include/linux/dev_liveupdate.h F: include/linux/liveupdate.h F: include/uapi/linux/liveupdate.h diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 9c0e4aaf4e8cb7fecd9f80ac6289b8d854ce03aa..37e44782fa35c64c2eba6a0f694= 2d44d8003a499 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -327,3 +327,13 @@ source "drivers/pci/switch/Kconfig" source "drivers/pci/pwrctrl/Kconfig" =20 endif + +config PCI_LU_STUB + tristate "PCI Live Update Stub Driver" + depends on LIVEUPDATE + help + Say Y or M here if you want to enable support for the Live Update stub + driver. This driver can be used to test the PCI subsystem support for + Live Updates. + + When in doubt, say N. diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index aa1bac7aed7d12c641a6b55e56176fb3cdde4c91..061e98d0411a951573e1996c61c= e5a98f2775e53 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_PCI_DYNAMIC_OF_NODES) +=3D of_property.o obj-$(CONFIG_PCI_NPEM) +=3D npem.o obj-$(CONFIG_PCIE_TPH) +=3D tph.o obj-$(CONFIG_LIVEUPDATE) +=3D liveupdate.o +obj-$(CONFIG_PCI_LU_STUB) +=3D pci-lu-stub.o =20 # Endpoint library must be initialized before its users obj-$(CONFIG_PCI_ENDPOINT) +=3D endpoint/ diff --git a/drivers/pci/pci-lu-stub.c b/drivers/pci/pci-lu-stub.c new file mode 100644 index 0000000000000000000000000000000000000000..aa0404d16336278d76b062d8126= dc5f45732403e --- /dev/null +++ b/drivers/pci/pci-lu-stub.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include + +struct pci_lu_stub_ser { + u16 dev_id; +} __packed; + +static const struct pci_device_id pci_lu_stub_id_table[] =3D { + /* Allow binding to any device but only via driver_override. */ + { PCI_DEVICE_DRIVER_OVERRIDE(PCI_ANY_ID, PCI_ANY_ID, 1) }, + {}, +}; + +static int validate_folio(struct pci_dev *dev, struct folio *folio) +{ + const struct pci_lu_stub_ser *ser =3D folio_address(folio); + + if (folio_order(folio) !=3D get_order(sizeof(*ser))) { + pci_err(dev, "Restored folio has unexpected order %u\n", folio_order(fol= io)); + return -ERANGE; + } + + if (ser->dev_id !=3D pci_dev_id(dev)) { + pci_err(dev, "Restored folio contains unexpected dev_id: 0x%x\n", ser->d= ev_id); + return -EINVAL; + } + + return 0; +} + +static int pci_lu_stub_probe(struct pci_dev *dev, const struct pci_device_= id *id) +{ + struct folio *folio; + u64 data; + int ret; + + if (liveupdate_state_normal()) { + pci_set_master(dev); + pci_info(dev, "Marking device liveupdate busmaster\n"); + dev->dev.lu.flags =3D LU_BUSMASTER; + return 0; + } + + if (!liveupdate_state_updated()) { + pci_err(dev, "Unable to handle probe() outside of normal and updated sta= tes.\n"); + return -EOPNOTSUPP; + } + + ret =3D pci_liveupdate_get_driver_data(dev, &data); + if (ret) { + pci_err(dev, "Failed to get driver data for device (%d)\n", ret); + return ret; + } + + pci_info(dev, "%s(): data: 0x%llx\n", __func__, data); + + folio =3D kho_restore_folio(data); + if (!folio) { + pci_err(dev, "Failed to restore folio at 0x%llx.\n", data); + return -ENOENT; + } + + return validate_folio(dev, folio); +} + +static void pci_lu_stub_remove(struct pci_dev *dev) +{ + WARN_ON(!liveupdate_state_normal()); + dev->dev.lu.flags =3D 0; +} + +static int pci_lu_stub_prepare(struct device *dev, u64 *data) +{ + struct pci_lu_stub_ser *ser; + struct folio *folio; + int ret; + + folio =3D folio_alloc(GFP_KERNEL | __GFP_ZERO, get_order(sizeof(*ser))); + if (!folio) + return -ENOMEM; + + ret =3D kho_preserve_folio(folio); + if (ret) { + dev_err(dev, "Failed to preserve folio (%d)\n", ret); + folio_put(folio); + return ret; + } + + ser =3D folio_address(folio); + ser->dev_id =3D pci_dev_id(to_pci_dev(dev)); + + *data =3D virt_to_phys(ser); + dev_info(dev, "%s(): data: 0x%llx\n", __func__, *data); + return 0; +} + +static int pci_lu_stub_freeze(struct device *dev, u64 *data) +{ + struct folio *folio =3D pfn_folio(PHYS_PFN(*data)); + + dev_info(dev, "%s(): data: 0x%llx\n", __func__, *data); + return validate_folio(to_pci_dev(dev), folio); +} + +static void pci_lu_stub_finish(struct device *dev, u64 data) +{ + struct folio *folio =3D pfn_folio(PHYS_PFN(data)); + + dev_info(dev, "%s(): data: 0x%llx\n", __func__, data); + WARN_ON(validate_folio(to_pci_dev(dev), folio)); + folio_put(folio); +} + +static void pci_lu_stub_cancel(struct device *dev, u64 data) +{ + dev_info(dev, "%s(): data: 0x%llx\n", __func__, data); + pci_lu_stub_finish(dev, data); +} + +static struct dev_liveupdate_ops liveupdate_ops =3D { + .prepare =3D pci_lu_stub_prepare, + .freeze =3D pci_lu_stub_freeze, + .finish =3D pci_lu_stub_finish, + .cancel =3D pci_lu_stub_cancel, +}; + +static struct pci_driver pci_lu_stub_driver =3D { + .name =3D "pci-lu-stub", + .id_table =3D pci_lu_stub_id_table, + .probe =3D pci_lu_stub_probe, + .remove =3D pci_lu_stub_remove, + .driver.lu =3D &liveupdate_ops, +}; + +module_pci_driver(pci_lu_stub_driver); +MODULE_LICENSE("GPL"); --=20 2.51.0.384.g4c02a37b29-goog