From: Bjorn Helgaas <helgaas@kernel.org>
To: David Matlack <dmatlack@google.com>
Cc: kexec@lists.infradead.org, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-mm@kvack.org,
linux-pci@vger.kernel.org,
Adithya Jayachandran <ajayachandra@nvidia.com>,
Alexander Graf <graf@amazon.com>,
Alex Williamson <alex@shazbot.org>,
Bjorn Helgaas <bhelgaas@google.com>, Chris Li <chrisl@kernel.org>,
David Rientjes <rientjes@google.com>,
Jacob Pan <jacob.pan@linux.microsoft.com>,
Jason Gunthorpe <jgg@nvidia.com>,
Jonathan Corbet <corbet@lwn.net>, Josh Hilke <jrhilke@google.com>,
Leon Romanovsky <leonro@nvidia.com>,
Lukas Wunner <lukas@wunner.de>, Mike Rapoport <rppt@kernel.org>,
Parav Pandit <parav@nvidia.com>,
Pasha Tatashin <pasha.tatashin@soleen.com>,
Pranjal Shrivastava <praan@google.com>,
Pratyush Yadav <pratyush@kernel.org>,
Saeed Mahameed <saeedm@nvidia.com>,
Samiullah Khawaja <skhawaja@google.com>,
Shuah Khan <skhan@linuxfoundation.org>,
Vipin Sharma <vipinsh@google.com>, William Tu <witu@nvidia.com>,
Yi Liu <yi.l.liu@intel.com>
Subject: Re: [PATCH v8 01/12] PCI: liveupdate: Set up FLB handler for the PCI core
Date: Fri, 18 Sep 2026 13:49:11 -0500 [thread overview]
Message-ID: <20260918184911.GA1172993@bhelgaas> (raw)
In-Reply-To: <aqyKVkIH58DK0EZO@google.com>
On Fri, Sep 18, 2026 at 12:48:22AM +0000, David Matlack wrote:
> On 2026-09-16 06:50 PM, Bjorn Helgaas wrote:
> > On Fri, Sep 11, 2026 at 04:44:02PM +0000, David Matlack wrote:
> > > On 2026-09-10 06:48 PM, Bjorn Helgaas wrote:
> > > > On Tue, Jul 28, 2026 at 10:09:55PM +0000, David Matlack wrote:
> > > > > Set up a File-Lifecycle-Bound (FLB) handler for the PCI core to enable
> > > > > it to participate in the preservation of PCI devices across Live Update.
> > > > > Essentially, this commit enables the PCI core to allocate a struct
> > > > > (struct pci_ser) and preserve it across a Live Update whenever at least
> > > > > one device is preserved.
> > > >
> > > > I assume pci_ser is the state the PCI core needs to preserve across
> > > > kexec so the new kernel's enumeration doesn't interrupt the device
> > > > operation. And that whatever state the endpoint drivers need to
> > > > adopt/inherit the device in the new kernel is managed without any help
> > > > from the PCI core?
> > >
> > > Yes.
> > >
> > > > > Preserving PCI devices across Live Update is built on top of the Live
> > > > > Update Orchestrator's (LUO) support for file preservation. Drivers are
> > > > > expected to expose a file to userspace to represent a single PCI device
> > > > > and support preservation of that file. This is intended primarily to
> > > > > support preservation of PCI devices bound to VFIO drivers.
> > > >
> > > > Where do drivers expose this file? sysfs? I guess it's a file per
> > > > preserved device? Thinking like a driver writer, I'm expecting a hint
> > > > about how to expose this file (should also be in the file doc somehere
> > > > if it's not already).
> > >
> > > There is no requirement about how drivers do this from the PCI core
> > > perspective. For all intents and purposes, the VFIO PCI variant drivers
> > > are the only drivers that are going to be supported in the next 1-2
> > > years. They expose a misc character device for each file.
> >
> > If this file isn't relevant to the PCI core, maybe we don't need to
> > mention it here. It doesn't seem like it motivates this patch.
> >
> > > > > This commit enables drivers to register their liveupdate_file_handler
> > > > > with the PCI core so that the PCI core can do its own tracking and
> > > > > enforcement of which devices are preserved.
> > > > >
> > > > > pci_liveupdate_register_flb(driver_file_handler);
> > > > > pci_liveupdate_unregister_flb(driver_file_handler);
> > > >
> > > > So a driver calls pci_liveupdate_register_flb() once, then
> > > > pci_liveupdate_preserve() once for each device it wants preserved?
> > >
> > > Yes
> > >
> > > > > When the first file (with a handler registered with the PCI core) is
> > > > > preserved, the PCI core will be notified to allocate its tracking struct
> > > > > (pci_ser).
> > > >
> > > > The passive voice here makes the actors a bit obscure. I guess a
> > > > LIVEUPDATE_SESSION_PRESERVE_FD ioctl on some per-device file kicks
> > > > this off?
> > >
> > > Yes. (And I will reduce the passive voice in the next version.)
> > >
> > > > I guess the pci_ser allocation is in
> > > > pci_liveupdate_flb_ops.preserve(), i.e., pci_flb_preserve()?
> > >
> > > Yes.
> > >
> > > > So the PCI core tracker (pci_ser) isn't actually allocated at the time
> > > > of pci_liveupdate_register_flb(); it's allocated on the first
> > > > LIVEUPDATE_SESSION_PRESERVE_FD ioctl for a driver that has called
> > > > pci_liveupdate_register_flb()?
> > >
> > > Yes. The first device that gets preserved triggers the allocation of
> > > struct pci_ser. And the last device that gets unpreserved (preservation
> > > cancelled) triggers the freeing of struct pci_ser.
> > >
> > > > IIUC the call tree for that ioctl looks something like this:
> > > >
> > > > <driver>
> > > > pci_liveupdate_register_flb
> > > > liveupdate_register_flb(fh, &pci_liveupdate_flb)
> > > >
> > > > luo_session_ioctl
> > > > op = &luo_session_ioctl_ops[...]
> > > > op->execute # eg luo_session_preserve_fd()
> > > > luo_session_preserve_fd
> > > > luo_preserve_file
> > > > luo_flb_file_preserve
> > > > luo_flb_file_preserve_one
> > > > if (outgoing_count == 0) # only for first FLB device
> > > > flb->ops->preserve # eg pci_flb_preserve()
> > > > pci_flb_preserve
> > > > ser = kho_alloc_preserve <-- alloc pci_ser
> > > > outgoing.count = 1
> > > > fh->ops->preserve # something not included here
> >
> > So IIUC this part of the path looks like this, which answers my
> > question below about ordering of pci_ser and
> > pci_liveupdate_preserve():
> >
> > fh->ops->preserve # eg vfio_pci_liveupdate_preserve()
> > vfio_pci_liveupdate_preserve
> > pci_liveupdate_preserve
> > pci_liveupdate_preserve_device
> > dev_ser = pci_flb_alloc_dev_ser <-- alloc per-dev PCI core serialized state
> > dev_ser->bdf = pci_dev_id(dev)
> >
> > > > Seems like kind of an awkward way to allocate pci_ser. Couldn't it be
> > > > allocated on the first call to pci_liveupdate_register_flb()? That
> > > > would be a lot easier for driver writers to trace through.
> > >
> > > I agree the LUO FLB API is a bit awkward, but this is how it works.
> > >
> > > If we allocated it during pci_liveupdate_register_flb() we would then
> > > need to stash it in a global variable to hand-off the LUO later. Despite
> > > the awkwardness of FLBs, it is useful to avoid globals and have LUO
> > > management the lifetime.
> >
> > It seems like pci_ser is a singleton by design, so a global variable
> > doesn't sound like it would be terrible to me.
> >
> > > > > When the last file is unpreserved (i.e. preservation
> > > > > cancelled) the PCI core will be notified to free struct pci_ser.
> > > >
> > > > There's a lot going on behind "PCI core will be notified". I assume
> > > > these refer to the first-time behavior of luo_flb_file_preserve_one()
> > > > and last-time behavior of liveupdate_flb_put_outgoing(), which is
> > > > honestly kind of hard to suss out.
> >
> > Could we say something specific and PCI-related here, to help connect
> > the dots? Most of these paths are outside the PCI core.
> >
> > IIUC luo_session essentially has a refcount (outgoing.count)
> > incremented by each LIVEUPDATE_SESSION_PRESERVE_FD ioctl, and the 0->1
> > transition in luo_flb_file_preserve_one() ends up calling
> > pci_flb_preserve(), where pci_ser is allocated.
> >
> > And the refcount is decremented by luo_flb_file_unpreserve() (in a
> > luo_session .release() function), where the 1->0 transition in
> > liveupdate_flb_put_outgoing() calls pci_flb_unpreserve() where pci_ser
> > is deallocated.
> >
> > That gets into a lot of detail, probably too much for a commit log.
> > Maybe mentioning the function names by which the PCI core is notified
> > to alloc/free pci_ser would be enough of a bread crumb.
> >
> > > > This series doesn't include a caller of pci_liveupdate_preserve() (or
> > > > pci_liveupdate_register_flb()), so I can't figure out the ordering.
> > > > Obviously pci_liveupdate_register_flb() must be first.
> > >
> > > In every version of this patch series I have sent I included a link to
> > > the vfio-pci driver changes that build on top of this, rebased that
> > > series on top of this one, uploaded it to my GitHub, and included a link
> > > in the cover letter. Here is the relevant section from the v8 cover
> > > letter:
> > >
> > > . This series was tested in conjunction with v5 of the VFIO PCI driver
> > > . series:
> > > .
> > > . https://lore.kernel.org/kvm/20260714151505.3466855-1-vipinsh@google.com/
> > > .
> > > . The full set of patches used for testing can be found on GitHub.
> > > .
> > > . https://github.com/dmatlack/linux/tree/liveupdate/pci/base/v8-with-vfio
> > >
> > >
> > > > I first thought pci_liveupdate_preserve() would be called via the
> > > > fh->ops->preserve() in the luo_session_preserve_fd() ioctl path, but
> > > > it's not. pci_liveupdate_preserve() is intended for the driver to
> > > > call it directly. But it looks like it has to be called *after* the
> > > > ioctl? Obviously I'm confused :)
> > >
> > > It is called by the driver during it's fh->ops->preserve() callback. In
> > > other words, it is called during the ioctl by the driver.
> >
> > I think the updated call tree above shows the connection?
>
> Yes the call tree you added above is correct. Here is an attempt at the
> complete picture that I plan to include in the kernel-doc in v9:
>
> * Call Flow
> * ---------
> *
> * ::
> *
> * # Driver initialization
> * pci_liveupdate_register_flb(fh)
> *
> * # Userspace: ioctl(LIVEUPDATE_SESSION_PRESERVE_FD, devfd)
> * luo_preserve_file()
> * luo_flb_file_preserve()
> * luo_flb_file_preserve_one() # first preserved file only
> * pci_flb_preserve() # alloc and preserve struct pci_ser
> * fh->ops->preserve() # driver callback
> * pci_liveupdate_preserve(dev) # record this device in struct pci_ser
> *
> * # Userspace: preservation cancelled or session torn down
> * luo_file_unpreserve_files()
> * luo_flb_file_unpreserve()
> * liveupdate_flb_put_outgoing() # last unpreserved file only
> * pci_flb_unpreserve() # free struct pci_ser
> *
> * # ---------------- kexec ----------------
> *
> * # New kernel: PCI enumeration
> * pci_setup_device()
> * pci_liveupdate_setup_device()
> * liveupdate_flb_get_incoming()
> * luo_flb_retrieve_one() # first request only
> * pci_flb_retrieve() # previous kernel's struct pci_ser
> *
> * # Userspace: ioctl(LIVEUPDATE_SESSION_FINISH)
> * luo_file_finish_one()
> * fh->ops->finish() # driver callback
> * pci_liveupdate_finish(dev) # release this device's pci_dev_ser
> * luo_flb_file_finish()
> * liveupdate_flb_put_incoming() # last incoming file only
> * pci_flb_finish() # free struct pci_ser
> *
>
> And here is an updated commit message that I hope explains everything more
> clearly:
>
> PCI: liveupdate: Set up FLB handler for the PCI core
>
> 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 the
s/the/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.
Beautiful, thanks for your patience :)
next prev parent reply other threads:[~2026-09-18 18:49 UTC|newest]
Thread overview: 61+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-28 22:09 [PATCH v8 00/12] PCI: liveupdate: PCI core support for Live Update David Matlack
2026-07-28 22:09 ` [PATCH v8 01/12] PCI: liveupdate: Set up FLB handler for the PCI core David Matlack
2026-08-17 21:12 ` Samiullah Khawaja
2026-09-10 23:48 ` Bjorn Helgaas
2026-09-11 16:44 ` David Matlack
2026-09-16 23:50 ` Bjorn Helgaas
2026-09-18 0:48 ` David Matlack
2026-09-18 18:49 ` Bjorn Helgaas [this message]
2026-07-28 22:09 ` [PATCH v8 02/12] PCI: liveupdate: Track outgoing preserved PCI devices David Matlack
2026-08-24 20:14 ` Samiullah Khawaja
2026-08-27 21:47 ` Bjorn Helgaas
2026-09-16 3:10 ` Zhu Yanjun
2026-09-16 14:58 ` David Matlack
2026-07-28 22:09 ` [PATCH v8 03/12] PCI: liveupdate: Track incoming " David Matlack
2026-08-24 20:13 ` Samiullah Khawaja
2026-09-10 23:49 ` Bjorn Helgaas
2026-09-11 16:45 ` David Matlack
2026-09-16 3:31 ` Zhu Yanjun
2026-09-16 17:28 ` David Matlack
2026-09-16 18:25 ` Pratyush Yadav
2026-09-16 18:31 ` David Matlack
2026-09-16 18:58 ` Pratyush Yadav
2026-09-16 19:23 ` David Matlack
2026-07-28 22:09 ` [PATCH v8 04/12] PCI: liveupdate: Document driver binding responsibilities David Matlack
2026-09-10 23:50 ` Bjorn Helgaas
2026-07-28 22:09 ` [PATCH v8 05/12] PCI: liveupdate: Preserve bus numbers during Live Update David Matlack
2026-09-10 23:51 ` Bjorn Helgaas
2026-09-11 18:30 ` David Matlack
2026-09-12 17:31 ` David Matlack
2026-09-16 23:54 ` Bjorn Helgaas
2026-07-28 22:10 ` [PATCH v8 06/12] PCI: liveupdate: Auto-preserve upstream bridges across " David Matlack
2026-08-24 13:41 ` Pranjal Shrivastava
2026-09-10 23:51 ` Bjorn Helgaas
2026-09-11 17:00 ` David Matlack
2026-09-17 0:18 ` Bjorn Helgaas
2026-09-17 23:42 ` David Matlack
2026-09-17 0:07 ` Bjorn Helgaas
2026-09-17 23:44 ` David Matlack
2026-07-28 22:10 ` [PATCH v8 07/12] PCI: Refactor matching logic for pci_dev_acs_ops David Matlack
2026-07-28 22:10 ` [PATCH v8 08/12] PCI: liveupdate: Adopt ACS controls in incoming preserved devices David Matlack
2026-08-24 13:42 ` Pranjal Shrivastava
2026-09-10 23:51 ` Bjorn Helgaas
2026-09-11 18:31 ` David Matlack
2026-09-14 16:45 ` David Matlack
2026-09-17 0:23 ` Bjorn Helgaas
2026-07-28 22:10 ` [PATCH v8 09/12] PCI: liveupdate: Adopt ARI Forwarding Enable on preserved bridges David Matlack
2026-08-24 13:43 ` Pranjal Shrivastava
2026-09-17 19:47 ` Bjorn Helgaas
2026-07-28 22:10 ` [PATCH v8 10/12] PCI: liveupdate: Freeze preservation status during shutdown David Matlack
2026-08-24 20:07 ` Samiullah Khawaja
2026-09-17 20:17 ` Bjorn Helgaas
2026-09-17 23:38 ` David Matlack
2026-07-28 22:10 ` [PATCH v8 11/12] PCI: liveupdate: Do not disable bus mastering on preserved devices during kexec David Matlack
2026-08-24 20:02 ` Samiullah Khawaja
2026-09-17 20:19 ` Bjorn Helgaas
2026-07-28 22:10 ` [PATCH v8 12/12] Documentation: PCI: Add documentation for Live Update David Matlack
2026-08-24 20:01 ` Samiullah Khawaja
2026-09-17 21:39 ` Bjorn Helgaas
2026-09-17 23:33 ` David Matlack
2026-08-18 17:01 ` [PATCH v8 00/12] PCI: liveupdate: PCI core support " David Matlack
2026-09-10 21:37 ` Pasha Tatashin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260918184911.GA1172993@bhelgaas \
--to=helgaas@kernel.org \
--cc=ajayachandra@nvidia.com \
--cc=alex@shazbot.org \
--cc=bhelgaas@google.com \
--cc=chrisl@kernel.org \
--cc=corbet@lwn.net \
--cc=dmatlack@google.com \
--cc=graf@amazon.com \
--cc=jacob.pan@linux.microsoft.com \
--cc=jgg@nvidia.com \
--cc=jrhilke@google.com \
--cc=kexec@lists.infradead.org \
--cc=leonro@nvidia.com \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-pci@vger.kernel.org \
--cc=lukas@wunner.de \
--cc=parav@nvidia.com \
--cc=pasha.tatashin@soleen.com \
--cc=praan@google.com \
--cc=pratyush@kernel.org \
--cc=rientjes@google.com \
--cc=rppt@kernel.org \
--cc=saeedm@nvidia.com \
--cc=skhan@linuxfoundation.org \
--cc=skhawaja@google.com \
--cc=vipinsh@google.com \
--cc=witu@nvidia.com \
--cc=yi.l.liu@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®