The patch subject is a bit long.
On 2026/07/27 14:39, Cédric Le Goater wrote:
Add a PF-level "x-vf-migration" boolean property (default off) that,
when enabled, causes each emulated VF to advertise a vendor-specific
PCI capability in its config space. The variant driver igb-vfio-pci
probes for this capability at bind time and uses its presence to
enable migration support.
The capability is a 16-byte vendor-specific capability (PCI_CAP_ID_VNDR)
containing a magic value ("MIGB"), the BAR index where the migration
region will be mapped, and feature flags indicating which migration
features are supported.
Assisted-by: Claude
Suggested-by: Alex Williamson <[email protected]>
Signed-off-by: Cédric Le Goater <[email protected]>
---
MAINTAINERS | 6 +++
docs/system/device-emulation.rst | 1 +
docs/system/devices/igb-migration.rst | 20 ++++++++
docs/system/devices/igb.rst | 6 +++
hw/net/igb_migration.h | 43 ++++++++++++++++
hw/net/igb.c | 12 +++++
hw/net/igb_migration.c | 72 +++++++++++++++++++++++++++
hw/net/igbvf.c | 11 ++++
hw/net/meson.build | 2 +-
hw/net/trace-events | 1 +
10 files changed, 173 insertions(+), 1 deletion(-)
create mode 100644 docs/system/devices/igb-migration.rst
create mode 100644 hw/net/igb_migration.h
create mode 100644 hw/net/igb_migration.c
diff --git a/MAINTAINERS b/MAINTAINERS
index a28935c89866..6d29b905c47c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2765,6 +2765,12 @@ F: tests/functional/x86_64/test_netdev_ethtool.py
F: tests/qtest/igb-test.c
F: tests/qtest/libqos/igb.c
+igb VF migration
+M: Cédric Le Goater <[email protected]>
+S: Maintained
+F: hw/net/igb_migration.*
+F: docs/system/devices/igb-migration.rst
+
eepro100
M: Stefan Weil <[email protected]>
S: Maintained
diff --git a/docs/system/device-emulation.rst b/docs/system/device-emulation.rst
index 40054bb7dfcc..75f423b795cd 100644
--- a/docs/system/device-emulation.rst
+++ b/docs/system/device-emulation.rst
@@ -90,6 +90,7 @@ Emulated Devices
devices/cxl.rst
devices/emmc.rst
devices/igb.rst
+ devices/igb-migration.rst
devices/ivshmem-flat.rst
devices/ivshmem.rst
devices/keyboard.rst
diff --git a/docs/system/devices/igb-migration.rst
b/docs/system/devices/igb-migration.rst
new file mode 100644
index 000000000000..017b47c4544e
--- /dev/null
+++ b/docs/system/devices/igb-migration.rst
@@ -0,0 +1,20 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+.. _igb-migration:
+
+igb VF Migration
+----------------
+
+The igb device supports an experimental VF migration interface that allows
+the ``igb-vfio-pci`` variant driver to migrate VF state during live
+migration. This is enabled with the ``x-vf-migration`` property::
+
+ -device igb,x-vf-migration=on,...
+
+When enabled, each emulated VF advertises a vendor-specific PCI capability
+(cap id 0x09) with a magic signature (``0x4D494742`` / "MIGB") that the
+variant driver probes at bind time. The capability contains an interface
+version number, the BAR index hosting the migration register region, and
+feature flags indicating which migration features are supported.
+
+This feature is experimental and the ``x-`` prefix indicates the interface
+may change.
diff --git a/docs/system/devices/igb.rst b/docs/system/devices/igb.rst
index 50f625fd77e4..00271dbc92c3 100644
--- a/docs/system/devices/igb.rst
+++ b/docs/system/devices/igb.rst
@@ -64,6 +64,12 @@ command:
pyvenv/bin/meson test --suite thorough func-x86_64-netdev_ethtool
+VF Migration (experimental)
+===========================
+
+See :ref:`igb-migration` for details on the experimental VF live migration
+interface.
+
References
==========
diff --git a/hw/net/igb_migration.h b/hw/net/igb_migration.h
new file mode 100644
index 000000000000..e79892436b21
--- /dev/null
+++ b/hw/net/igb_migration.h
@@ -0,0 +1,43 @@
+/*
+ * QEMU Intel 82576 SR/IOV VF Migration Support
+ *
+ * Copyright (c) 2026 Red Hat, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef IGB_MIGRATION_H
+#define IGB_MIGRATION_H
+
+#include "hw/pci/pci_device.h"
+
+/* Migration BAR definitions */
+#define IGB_MIG_BAR_IDX (2)
+#define IGB_MIG_BAR_SIZE (64 * 1024)
+
+/*
+ * Vendor-specific PCI capability for migration discovery.
+ *
+ * The igb-vfio-pci variant driver probes for this at bind time.
+ * If present, the driver knows the emulated VF supports migration.
+ */
+#define IGB_MIG_CAP_MAGIC 0x4D494742 /* "MIGB" */
+#define IGB_MIG_CAP_VERSION 1
+
+#define IGB_MIG_CAP_F_STATE (1u << 0) /* device state serialization */
+#define IGB_MIG_CAP_F_DIRTY (1u << 1) /* dirty page tracking */
+
+#define IGB_MIG_CAP_SIZE 16
+#define IGB_MIG_CAP_OFF_MAGIC 4 /* offset within cap for magic field */
+#define IGB_MIG_CAP_OFF_BARID 8 /* offset within cap for BAR id */
+#define IGB_MIG_CAP_OFF_FLAGS 12 /* offset within cap for feature flags */
+
+typedef struct IgbVfMigState {
+ bool migration_cap;
+ MemoryRegion mig_bar;
+} IgbVfMigState;
+
+void igb_pf_init_migration_bar(PCIDevice *dev);
+bool igbvf_add_migration_cap(PCIDevice *dev, Error **errp);
+
+#endif
diff --git a/hw/net/igb.c b/hw/net/igb.c
index c076807e7110..b43235996db2 100644
--- a/hw/net/igb.c
+++ b/hw/net/igb.c
@@ -57,6 +57,7 @@
#include "igb_common.h"
#include "igb_core.h"
+#include "igb_migration.h"
#include "trace.h"
#include "qapi/error.h"
@@ -69,6 +70,7 @@ struct IGBState {
PCIDevice parent_obj;
NICState *nic;
NICConf conf;
+ bool vf_migration;
MemoryRegion mmio;
MemoryRegion flash;
@@ -459,6 +461,15 @@ static void igb_pci_realize(PCIDevice *pci_dev, Error
**errp)
pcie_sriov_pf_init_vf_bar(pci_dev, IGBVF_MSIX_BAR_IDX,
PCI_BASE_ADDRESS_MEM_TYPE_64 | PCI_BASE_ADDRESS_MEM_PREFETCH,
IGBVF_MSIX_SIZE);
+ /*
+ * When VF migration support is enabled, register an additional VF
+ * BAR for the migration register region. The variant driver
+ * discovers this via a vendor-specific PCI capability that points
+ * to this BAR.
+ */
+ if (s->vf_migration) {
+ igb_pf_init_migration_bar(pci_dev);
+ }
igb_init_net_peer(s, pci_dev, macaddr);
@@ -597,6 +608,7 @@ static const VMStateDescription igb_vmstate = {
static const Property igb_properties[] = {
DEFINE_NIC_PROPERTIES(IGBState, conf),
DEFINE_PROP_BOOL("x-pcie-flr-init", IGBState, has_flr, true),
+ DEFINE_PROP_BOOL("x-vf-migration", IGBState, vf_migration, false),
};
static void igb_class_init(ObjectClass *class, const void *data)
diff --git a/hw/net/igb_migration.c b/hw/net/igb_migration.c
new file mode 100644
index 000000000000..794f1217d3e5
--- /dev/null
+++ b/hw/net/igb_migration.c
@@ -0,0 +1,72 @@
+/*
+ * QEMU Intel 82576 SR/IOV VF Migration Support
+ *
+ * Copyright (c) 2026 Red Hat, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/pci/pci_device.h"
+#include "hw/pci/pcie.h"
+#include "igb_common.h"
+#include "igb_migration.h"
+#include "trace.h"
+
+
+
+/*
+ * 32-bit prefetchable BAR. A 64-bit BAR2 would consume BAR2+BAR3, but
+ * BAR3 is already used for MSI-X (IGBVF_MSIX_BAR_IDX = 3).
+ *
+ * BAR Index Type Size Purpose
+ * BAR0 0+1 64-bit prefetchable 16 KB MMIO registers
+ * BAR2 2 32-bit prefetchable 64 KB Migration
+ * BAR3 3+4 64-bit prefetchable 16 KB MSI-X table + PBA
+ * BAR5 5 - - Unused
+ */
+void igb_pf_init_migration_bar(PCIDevice *dev)
+{
+ pcie_sriov_pf_init_vf_bar(dev, IGB_MIG_BAR_IDX,
+ PCI_BASE_ADDRESS_MEM_PREFETCH,
+ IGB_MIG_BAR_SIZE);
+}
+
+/*
+ * Add vendor-specific PCI capability that the variant driver probes for.
+ *
+ * Layout (16 bytes):
+ * [0] cap_id (PCI_CAP_ID_VNDR = 0x09)
+ * [1] next_cap
+ * [2] cap_len (16)
+ * [3] version (IGB_MIG_CAP_VERSION)
+ * [4-7] magic (IGB_MIG_CAP_MAGIC, little-endian)
+ * [8-11] bar_id (IGB_MIG_BAR_IDX, little-endian)
+ * [12-15] flags (feature flags, little-endian)
+ */
+bool igbvf_add_migration_cap(PCIDevice *dev, Error **errp)
+{
+ int offset;
+
+ offset = pci_add_capability(dev, PCI_CAP_ID_VNDR, 0,
+ IGB_MIG_CAP_SIZE, errp);
+ if (offset < 0) {
+ return false;
+ }
+
+ /* Length and version in the standard cap flags word */
+ pci_set_byte(dev->config + offset + PCI_CAP_FLAGS,
+ IGB_MIG_CAP_SIZE);
+ pci_set_byte(dev->config + offset + PCI_CAP_FLAGS + 1,
+ IGB_MIG_CAP_VERSION);
+
+ pci_set_long(dev->config + offset + IGB_MIG_CAP_OFF_MAGIC,
+ IGB_MIG_CAP_MAGIC);
+ pci_set_long(dev->config + offset + IGB_MIG_CAP_OFF_BARID,
+ IGB_MIG_BAR_IDX);
+ pci_set_long(dev->config + offset + IGB_MIG_CAP_OFF_FLAGS,
+ IGB_MIG_CAP_F_STATE);
It advertises IGB_MIG_CAP_F_STATE before registering BAR2’s
MemoryRegion. The companion driver therefore discovers migration support
and tries to use an unimplemented BAR. Please change the patch series to
publish the capability with the BAR implementation or squash the commits.
Regards,
Akihiko Odaki
+
+ trace_igbvf_mig_cap_add(pcie_sriov_vf_number(dev), offset);
+ return true;
+}
diff --git a/hw/net/igbvf.c b/hw/net/igbvf.c
index 9a165c7063ee..94c9739cd58c 100644
--- a/hw/net/igbvf.c
+++ b/hw/net/igbvf.c
@@ -47,6 +47,7 @@
#include "net/net.h"
#include "igb_common.h"
#include "igb_core.h"
+#include "igb_migration.h"
#include "trace.h"
#include "qapi/error.h"
@@ -57,6 +58,8 @@ struct IgbVfState {
MemoryRegion mmio;
MemoryRegion msix;
+
+ IgbVfMigState mig;
};
static hwaddr vf_to_pf_addr(hwaddr addr, uint16_t vfn, bool write)
@@ -272,6 +275,14 @@ static void igbvf_pci_realize(PCIDevice *dev, Error **errp)
hw_error("Failed to initialize PCIe capability");
}
+ s->mig.migration_cap = object_property_get_bool(OBJECT(pcie_sriov_get_pf(dev)),
+ "x-vf-migration",
&error_abort);
+ if (s->mig.migration_cap) {
+ if (!igbvf_add_migration_cap(dev, errp)) {
+ return;
+ }
+ }
+
if (object_property_get_bool(OBJECT(pcie_sriov_get_pf(dev)),
"x-pcie-flr-init", &error_abort)) {
pcie_cap_flr_init(dev);
diff --git a/hw/net/meson.build b/hw/net/meson.build
index 84f142df222a..bb4b449b25ba 100644
--- a/hw/net/meson.build
+++ b/hw/net/meson.build
@@ -11,7 +11,7 @@ system_ss.add(when: 'CONFIG_E1000_PCI', if_true:
files('e1000.c', 'e1000x_common
system_ss.add(when: 'CONFIG_E1000E_PCI_EXPRESS', if_true:
files('net_tx_pkt.c', 'net_rx_pkt.c'))
system_ss.add(when: 'CONFIG_E1000E_PCI_EXPRESS', if_true: files('e1000e.c',
'e1000e_core.c', 'e1000x_common.c'))
system_ss.add(when: 'CONFIG_IGB_PCI_EXPRESS', if_true: files('net_tx_pkt.c',
'net_rx_pkt.c'))
-system_ss.add(when: 'CONFIG_IGB_PCI_EXPRESS', if_true: files('igb.c',
'igbvf.c', 'igb_core.c'))
+system_ss.add(when: 'CONFIG_IGB_PCI_EXPRESS', if_true: files('igb.c',
'igbvf.c', 'igb_core.c', 'igb_migration.c'))
system_ss.add(when: 'CONFIG_RTL8139_PCI', if_true: files('rtl8139.c'))
system_ss.add(when: 'CONFIG_TULIP', if_true: files('tulip.c'))
system_ss.add(when: 'CONFIG_VMXNET3_PCI', if_true: files('net_tx_pkt.c',
'net_rx_pkt.c'))
diff --git a/hw/net/trace-events b/hw/net/trace-events
index 001a20b0e2ac..06d8848023e5 100644
--- a/hw/net/trace-events
+++ b/hw/net/trace-events
@@ -294,6 +294,7 @@ igb_wrn_rx_desc_modes_not_supp(int desc_type) "Not
supported descriptor type: %d
# igbvf.c
igbvf_wrn_io_addr_unknown(uint64_t addr) "IO unknown register 0x%"PRIx64
+igbvf_mig_cap_add(uint16_t vfn, int offset) "VF%u: added migration vendor cap at
config offset 0x%x"
# spapr_llan.c
spapr_vlan_get_rx_bd_from_pool_found(int pool, int32_t count, uint32_t rx_bufs) "pool=%d
count=%"PRId32" rxbufs=%"PRIu32