Re: [RFC PATCH 00/11] igb: Add experimental VF live migration support

Cédric Le Goater <[email protected]>
Newsgroups gmane.comp.emulators.qemu
Message-ID <[email protected]>
On 7/27/26 22:36, Alex Williamson wrote:
> On Mon, 27 Jul 2026 07:39:24 +0200
> Cédric Le Goater <[email protected]> wrote:
> 
>> Hello,
>>
>> Live migration of VFIO-passthrough devices - SR-IOV VFs, vGPUs - is a
>> growing requirement, but real hardware with migration support is
>> scarce and hard to debug. An emulated device provides a fully
>> controlled testbed for developing and validating the entire software
>> stack - vfio-pci variant drivers, VFIO core migration v2 framework,
>> QEMU, libvirt - and for tuning complex migration policies such as
>> downtime convergence. It also serves as an educational reference for
>> understanding VFIO migration end-to-end, from device state
>> serialization to dirty page tracking.
>>
>> This series adds an experimental VF live migration interface to the
>> emulated igb (82576) device. It enables a vfio-pci variant driver
>> (igb-vfio-pci) to migrate VFs using the standard VFIO migration v2
>> protocol with stop-copy and pre-copy support.
>>
>> The target scenario is nested virtualization:
>>
>>    L0 QEMU (these patches)
>>      igb PF with x-vf-migration=on
>>      └── VFs with migration BAR + vendor cap
>>
>>    L1 kernel
>>      igb-vfio-pci variant driver [1]
>>      translates VFIO migration v2 ioctls → BAR2 MMIO
>>
>>    L1 QEMU (stock, unmodified)
>>      vfio-pci device model, standard migration fd
>>
>>    L2 guest
>>      standard igbvf driver, unaware of migration
>>
>> The L1 QEMU is completely unmodified -- it sees a standard VFIO
>> migratable device and uses the normal migration fd path.
>>
>> * Design
>>
>> The migration interface is exposed through a hidden 64KB PCI BAR
>> (BAR2) on each VF, discovered via a vendor-specific PCI capability
>> ("MIGB", PCI_CAP_ID_VNDR). The BAR exposes a register-based state
>> machine that mirrors VFIO migration states (RUNNING, STOP, STOP_COPY,
>> RESUMING, PRE_COPY).
> 
> I think you're placing the migration BAR on the VF in order to
> implement this in a small footprint, QEMU + vfio-pci variant driver,
> without PF guest driver changes.  

yes.

> A model that better matches real
> world hardware might be to put the migration BAR on the PF, segmented
> per VF, and then have the PF driver vend those segments out to the VF
> drivers.  

True.

On the migration topic, I saw that the SR-IOV specs had "VF Migration
State Array" feature, which was deprecated.

> That would remove the BAR always mapped problem, 

That's the main problem today.

> but expands
> the footprint to include the PF driver.  However, we're not exactly
> clean with respect to the PF driver as implemented here when we're
> going around the PF driver's back to setup DMA mappings.

That's not uncommon today. The PDS vfio-pci variant driver setups DMA
mappings in the PF to migrate the VF. But yes, given that the IGB PF
has no idea that a VF could be migrated, it's a bit of a resource hijack.

> Can we take advantage of the fact that this is a virtual device to
> avoid all these warts?
> 
> For example, do we really need MMIO BAR space for the register set
> exposed or can we prune that down to some key registers and doorbells
> and move the rest to memory?  We can put the vendor capability in
> extended config space to give ourselves more room to work with if
> necessary.  

There is plenty of space in the extended config space. The required
register set is relatively small.

> We also don't really need to play by the physical rules for
> access, the variant driver in the L1 kernel can allocate contiguous
> ranges and write GPAs into config space registers.  

yes.

> L0 QEMU can just
> write migration data and dirty bitmaps directly to those GPAs,
> bypassing any pretense of DMA mapping.

yes that works.

A previous implementation of this proposal was allocating GPAs.
I then preferred a solution that was more PCI friendly. Anyhow,
it's not a problem to change it again, once we agree on the
HW interface.

> There might be some tricks we can steal from virtio as it seems to
> optionally honor things like vIOMMUs as well. 

Yes. That's where the PCI DMAs mapping were interesting. I will
look at it.

> Anyway, if we want to
> confine the implementation to the virtual VF, avoiding dependencies on
> the PF driver, both at the cross-driver API and device DMA state, I
> think we can probably lean harder on QEMU being able to push data into
> an arbitrary GPA regardless of the IO topology we're exposing.  

So, the extra PCI BAR is indeed a problem and we should switch to
extended config space to avoid it. I have been exploring several
ideas and this proposal is an hybrid MMIO/shared buffer solution.


Here are my plans for the next.

Reduce the register set to a minimum and use a shared buffer for
all commands. The driver would allocate a single large enough buffer
for the largest command payload (DIRTY_QUERY with bitmap) and write
its GPA into BUF_ADDR once at init. Each operation is: fill buffer,
kick CTRL, poll STATUS.


Registers in extended config space :

   0x00    Header        Cap ID
   0x04    CAPS          Features, max_ranges, pgsizes
   0x08    CTRL          Doorbell (state transitions, dirty ops)
   0x0C    STATUS        Completion + error code
   0x10    BUF_ADDR_LO   Shared buffer GPA low
   0x14    BUF_ADDR_HI   Shared buffer GPA high

Commands and payload :

   1. SET_STATE
   0x00    target_state    driver      Requested VFIO state

   2. SAVE
   0x00    data_size       device      Bytes written  (32-bit)
   0x04    reserved        -           May be more reserved bytes to align data
                                       on 32bits
   0x08    data[]          device      State blob

   3. LOAD
   0x00    data_size       driver      Bytes to load (32-bit)
   0x04    reserved        -           May be more reserved
   0x08    data[]          driver      State blob

   4. DIRTY_ENABLE
   0x00    iova            driver      Range start (64-bit)
   0x08    size            driver      Range size (64-bit)
   0x10    pgsize          driver      Page granularity
   0x14    reserved        -

   5. DIRTY_DISABLE

   6. DIRTY_QUERY
   Request (driver):
   0x00    iova            driver      Query range start (64-bit)
   0x08    size            driver      Query range size (64-bit)
   0x10    pgsize          driver      Page granularity (for queries)
   0x14    reserved        -

   Response (device):
   0x18    bitmap_size     device      Bytes in bitmap
   0x1C    dirty_pages     device      Set bits count
   0x20    dma_writes      device      DMA writes since enable (64-bit)
   0x28    reserved        -
   0x30    bitmap[]        device      Dirty page bitmap

   7. GET_STATS
   0x00    dma_writes      device      (32-bit)
   0x04    dma_bytes       device      (64-bit)
   0x0C    dirty_pages_set device
   0x10    dirty_pages_clr device
   0x14    dirty_page_count device
   0x18    dirty_query_cnt device


We could add a shared buffer header (not sure this is useful though)

   0x00    command         driver      Operation to perform
   0x04    status          device      Completion + error code
   0x08    payload_size    both        Size of payload following header
   0x0C    reserved        -           Alignment

Do we want 'flags' anywhere ?

Thanks,

C.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.