summaryrefslogtreecommitdiff
path: root/include/linux/pci_liveupdate.h
AgeCommit message (Collapse)Author
6 daysPCI: liveupdate: Freeze preservation status during shutdownDavid Matlack
Freeze a device's outgoing preservation status (preserved or not preserved) during shutdown. This enables the PCI core and drivers to safely make decisions based on the device's preservation status during shutdown. Note that pci_liveupdate_freeze() is triggered by the PCI core rather than from drivers participating in Live Update so that all devices can have their status frozen (i.e. prevent non-preserved devices from getting preserved late). Reviewed-by: Pranjal Shrivastava <praan@google.com> Reviewed-by: Pasha Tatashin <pasha.tatashin@soleen.com> Reviewed-by: Samiullah Khawaja <skhawaja@google.com> Reviewed-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: David Matlack <dmatlack@google.com> Link: https://patch.msgid.link/20260918200640.887030-12-dmatlack@google.com Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
6 daysPCI: liveupdate: Preserve bus numbers during Live UpdateDavid Matlack
Keep the secondary and subordinate bus numbers that the previous kernel programmed into bridges, rather than assigning new ones, if the previous kernel preserved any device across a Live Update. Do this even on architectures that would otherwise always assign bus numbers themselves, e.g. when pci=assign-busses is passed. Preserved devices must be allowed to continue performing memory transactions across a Live Update, so the kernel cannot change the fabric topology. Changing the bus numbers of a bridge changes the RequesterIDs of the devices below it, which would require disabling and flushing any in-flight memory transactions first. Apply the policy globally rather than only to the paths that contain preserved devices. Bus numbers have to be preserved above a preserved device anyway, since an upstream bridge cannot expand its window. A global policy matches the scope of pcibios_assign_all_busses(), and gives an answer that cannot change part way through the two passes of a bridge scan. Bridges that do not have bus numbers are still assigned new ones, so hot-adding a bridge keeps working, both during and after a Live Update. The two-pass bridge scan guarantees such bridges are only assigned bus numbers above those already claimed by preserved bridges. The exception is a bridge that was preserved but comes up without a valid bus number configuration, e.g. because it was reset during kexec. Refuse to assign it new bus numbers, since that would silently change the BDF of every preserved device in its hierarchy. Also refuse to assign bus numbers to the other bridges on the same bus, since the bus numbers of the failed bridge can no longer be read from hardware and handing them out would let an unrelated device inherit the BDF of a preserved device. Require that CONFIG_CARDBUS is not enabled to enable CONFIG_PCI_LIVEUPDATE since preserving bus numbers on PCI-to-CardBus bridges requires additional work but is not a priority at the moment. Signed-off-by: David Matlack <dmatlack@google.com> Reviewed-by: Bjorn Helgaas <bhelgaas@google.com> Link: https://patch.msgid.link/20260918200640.887030-7-dmatlack@google.com Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
6 daysPCI: liveupdate: Track incoming preserved PCI devicesDavid Matlack
During PCI enumeration, the previous kernel might have passed state about devices that were preserved across kexec. The PCI core needs to fetch this state to identify which devices are "incoming" and require special handling. Add pci_liveupdate_setup_device() which is called during device setup to fetch the serialized state (struct pci_ser) from the Live Update Orchestrator. The first time this happens, pci_flb_retrieve() will run and convert the array of pci_dev_ser structs into an xarray so that it can be looked up efficiently. If a device is found in the xarray, the PCI core stores a pointer to its state in dev->liveupdate_incoming until pci_liveupdate_finish() is called by the driver. This pointer allows the PCI core and drivers to apply Live Update-specific logic to incoming devices in subsequent commits. Drivers can check if a device is an incoming preserved device (e.g. during probe) by calling pci_liveupdate_is_incoming(). Note that any error during pci_flb_retrieve() must be treated as fatal. The previous kernel handed off PCI devices that are performing DMA and the current kernel cannot safely take over those devices without this state. CONFIG_64BIT is now required to enable CONFIG_PCI_LIVEUPDATE so that the domain and bdf can be guaranteed to fit in an unsigned long and be used as the xarray key. Reviewed-by: Pranjal Shrivastava <praan@google.com> Reviewed-by: Samiullah Khawaja <skhawaja@google.com> Signed-off-by: David Matlack <dmatlack@google.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Link: https://patch.msgid.link/20260918200640.887030-4-dmatlack@google.com Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
6 daysPCI: liveupdate: Track outgoing preserved PCI devicesDavid Matlack
Add APIs to allow drivers to notify the PCI core of which devices are being preserved across a Live Update for the next kernel, i.e. "outgoing" devices. Drivers must notify the PCI core when devices are preserved so that the PCI core can update its FLB data (struct pci_ser) and track the list of outgoing devices. pci_liveupdate_preserve() notifies the PCI core that a device must be preserved across Live Update. pci_liveupdate_unpreserve() reverses this (cancels the preservation of the device). This tracking ensures the PCI core is fully aware of which devices may need special handling during shutdown and kexec, and so the list of preserved devices can be handed off to the next kernel. For now, the API only supports preserving non-VF devices on a root bus (not behind an PCI-to-PCI bridges). Reviewed-by: Pranjal Shrivastava <praan@google.com> Reviewed-by: Pasha Tatashin <pasha.tatashin@soleen.com> Reviewed-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Samiullah Khawaja <skhawaja@google.com> Signed-off-by: David Matlack <dmatlack@google.com> Link: https://patch.msgid.link/20260918200640.887030-3-dmatlack@google.com Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
6 daysPCI: liveupdate: Set up FLB handler for the PCI coreDavid Matlack
Set up a File-Lifecycle-Bound (FLB) handler so that the PCI core can preserve its own state across a Live Update kexec. Preserving a PCI device across kexec requires preserving two independent sets of state: - Driver state, e.g. everything vfio-pci needs so that userspace can keep using the device in the new kernel. The driver preserves this itself and the PCI core is not involved. - PCI core state, e.g. which devices are preserved, so that the new kernel knows not to disturb them while they are still running and doing DMA. That is what this commit adds, serialized into struct pci_ser. Userspace, not the kernel, decides which devices are preserved, and it does so through the Live Update Orchestrator's (LUO) support for file preservation: a driver exposes a file that represents a single PCI device, and userspace preserves that device with ioctl(LIVEUPDATE_SESSION_PRESERVE_FD) on that file. Binding preservation to a file gives it proper lifecycle management, e.g. the preservation is undone if userspace cancels it or goes away. How a driver exposes that file is up to the driver and invisible to the PCI core (vfio-pci variant drivers, the first intended use-case, use their per-device cdev). LUO only knows that a file was preserved; it does not know that it represents a PCI device, or which one. Bridging that gap, drivers register their liveupdate_file_handler with the PCI core: pci_liveupdate_register_flb(driver_file_handler); pci_liveupdate_unregister_flb(driver_file_handler); LUO then refcounts the PCI core's FLB against the files preserved by that handler, and that refcount drives the lifetime of struct pci_ser: - On the first preserved file, luo_flb_file_preserve_one() calls pci_flb_preserve(), which allocates struct pci_ser and preserves it with KHO. - On the last unpreserved file (i.e. preservation cancelled), liveupdate_flb_put_outgoing() calls pci_flb_unpreserve(), which unpreserves and frees struct pci_ser. - In the next kernel, pci_flb_retrieve() hands the PCI core the struct pci_ser built by the previous kernel, whenever the PCI core asks for it (e.g. during enumeration), and pci_flb_finish() frees it once the PCI core is done with it. So the flow for preserving a device, once a driver has registered, looks like this: ioctl(LIVEUPDATE_SESSION_PRESERVE_FD) luo_session_preserve_fd() luo_preserve_file() luo_flb_file_preserve() luo_flb_file_preserve_one() # only on the first preserved file pci_flb_preserve() # alloc + KHO-preserve pci_ser fh->ops->preserve() # driver callback, e.g. vfio-pci Note that struct pci_ser is deliberately not allocated when a driver calls pci_liveupdate_register_flb(). A driver can be loaded for the lifetime of the machine without ever preserving a device, and there is no reason to allocate memory and hand it to the next kernel in that case. Letting LUO own the lifetime also means the PCI core does not have to duplicate LUO's refcounting and unwind logic for preservation failures, session aborts and fd close, and the incoming side (retrieve/finish) comes from the same object rather than requiring a separate KHO FDT entry owned by the PCI core. Note: This commit only allocates struct pci_ser and preserves it across Live Update. A subsequent commit adds pci_liveupdate_preserve(), the API drivers call from their fh->ops->preserve() callback to tell the PCI core exactly which devices are being preserved. Note: There is no reason to check for kho_is_enabled() since it can be assumed to return true. If KHO was not enabled then Live Update would not be enabled and these routines would never run. Reviewed-by: Pranjal Shrivastava <praan@google.com> Reviewed-by: Samiullah Khawaja <skhawaja@google.com> Signed-off-by: David Matlack <dmatlack@google.com> Reviewed-by: Bjorn Helgaas <bhelgaas@google.com> Link: https://patch.msgid.link/20260918200640.887030-2-dmatlack@google.com Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>