* [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes
@ 2026-09-11 9:01 Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 01/75] virtio: fix exit(1) on DMA mapping failure during migration restore Michael S. Tsirkin
` (76 more replies)
0 siblings, 77 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:01 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell
The following changes since commit 1df256f5968e9f7c3c4533a1383b071c044a36d6:
Merge tag 'qom-qapi-pr-pr-v1' of https://gitlab.com/marcandre.lureau/qemu into staging (2026-09-08 18:35:31 +0100)
are available in the Git repository at:
https://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git tags/for_upstream
for you to fetch changes up to 2f8991c0b9c400f55897849a538580039b61865a:
MAINTAINERS: add Junjie Cao as CXL reviewer (2026-09-11 04:59:15 -0400)
----------------------------------------------------------------
pci, vhost, virtio, iommu, apci: features, fixes
new vhost-user-media device
virtio-net now supports live-TAP local migration
cxl now supports CFMW restrictions and per-window options
intel_iommu now supports concurrent page fault handling with PRI
pci now batches memory transactions around mapping updates
vhost-user-blk now allows toggling inflight-migration at runtime
virtio-rtc now supports smeared UTC clock type
intel_iommu now exposes SMPWC when SVM is enabled
new reviewer for CXL patches
Fixes, cleanups all over the place
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
----------------------------------------------------------------
Albert Esteve (4):
linux-headers: add VIRTIO_ID_MEDIA
hw/display: add vhost-user-media device
hw/display/vhost-user-media: add shared memory region BAR
linux-headers: Update to Linux v7.3-rc1
Alexandr Moshkov (6):
vhost-user: add skip_drain param to do_vhost_virtqueue_stop
vhost-user: add GET_VRING_BASE_SKIP_DRAIN message
vhost-user: use skip_drain with GET_VRING_BASE_SKIP_DRAIN message
vhost-user-blk: make inflight-migration prop mutable on running vm
vhost-user-blk: move inflight_needed higher
vhost-user-blk: use GET_VRING_BASE_SKIP_DRAIN when inflight-migration is on
Alyssa Ross (1):
vhost-user.rst: fix typo
Bin Guo (2):
libvhost-user: accept the postcopy client base ack in vu_add_mem_reg()
libvhost-user: return the backend mapping address for added regions
Clément MATHIEU--DRIF (4):
intel_iommu: Support concurrent page fault handling with PRI
intel_iommu: Only set dirty bit when PTE exposes write permission
intel_iommu: Always write all the flags passed to vtd_set_flag_in_pte
intel_iommu: Expose SMPWC when SVM is enabled
Davidlohr Bueso (5):
tests/bios-tables-test: Exclude CEDT.cxl for the CFMW restriction change
hw/cxl: Drop Back-Invalidate from default CFMW window restrictions
tests/acpi/cxl: Update CEDT.cxl for the default CFMW restrictions
hw/cxl: Add configurable CXL Fixed Memory Window restriction flags
tests/qtest/cxl: Add CXL Fixed Memory Window restriction flag tests
Denis V. Lunev (2):
pci: batch BAR remapping into one memory transaction
pci: load a device's config inside one memory transaction
GuoHan Zhao (1):
virtio-crypto: clean up every data queue
Hanna Czenczek (6):
hw/virtio-blk: Account discard operations
hw/virtio-blk: Complete zone-append cookies
hw/nvme: Fix block accounting in nvme_copy()
hw/nvme: Fix block accounting for compare
hw/ide: Have ide_dma_cb() complete accounting
hw/scsi-disk: Fix accounting for IGNORE, ret > 0
Jia Jia (2):
virtio: reduce code duplication for split ring
hw/virtio: reject inverted virtio-iommu IOVA ranges
Junjie Cao (3):
hw/cxl: Fix guest-triggerable QEMU exit on reserved interleave ways
hw/cxl: fix the CDAT DOE overlapping the Flex Bus DVSEC when sn= is set
MAINTAINERS: add Junjie Cao as CXL reviewer
Kuan-Wei Chiu (1):
virtio-rtc: Report smeared UTC clock type
Laurent Vivier (2):
hw/net/virtio-net: check packet size before VLAN tag access in receive_filter()
hw/net/virtio-net: strip trailing padding when caching RSC segment
Michael S. Tsirkin (7):
virtio: fix exit(1) on DMA mapping failure during migration restore
virtio: fix config_len DoS in migration restore path
virtio-pci: reject Q_ENABLE write on already-enabled queue
meson: disable "maybe uninitilized" errors with -Og
virtio-balloon: fix free-page BH teardown on unrealize
net/tap-solaris: Fix resource leaks on error paths
virtio-net: validate IHL in virtio_net_rsc_extract_unit4 before use
Philippe Mathieu-Daudé (4):
hw/acpi: Make AcpiGedState const in build_ged_aml()
hw/hotplug: Mark various HotplugHandlerClass variables as const
hw/hotplug: Reduce some HotplugHandler variables scope
hw/hotplug: Constify HotplugHandler
Sairaj Kodilkar (7):
amd_iommu: Return empty efr for stub call
tests/acpi: x86: Allow IVRS acpi table changes
amd_iommu: acpi-build: update PA, GVA and VA size macros
acpi_build: Use IOMMU pci device to build IOMMU DeviceID
acpi_build: Build IVRS feature report using extended feature register
amd_iommu: acpi-build: Remove unsupported PPR and HE feature
tests/acpi: x86: update golden masters for IVRS
Stefan Hajnoczi (1):
virtio-scsi: set dataplane_started to false upon failure
Vladimir Sementsov-Ogievskiy (16):
net/tap: rework tap_parse_script
net/tap: improve script/downscript options documentation
net/tap: deprecate "no" as special value for script/downscript
net/tap: move vhost-net open() calls to tap_parse_vhost_fds()
net/tap: move vhost initialization to tap_setup_vhost()
net/tap: use container_of instead of DO_UPCAST
net/tap: QOMify tap backend
net/tap: add TYPE_VMSTATE_IF interface
qapi: add local migration parameter
migration/fd: fix fd leak when fd is not valid for migration
migration/fd: add errp parameter to migration_fd_valid()
migration: check that transfer is UNIX socket when "local" set
virtio-net: support local migration of backend
net/tap: disable read polling for stopped VM
net/tap: support local migration with virtio-net
tests/functional: add test_tap_migration
Xiong Weimin (1):
hw/virtio: Propagate vhost_virtqueue_mask errors
MAINTAINERS | 7 +
docs/about/deprecated.rst | 18 +
docs/interop/vhost-user.rst | 44 ++-
docs/system/devices/cxl.rst | 25 +-
docs/system/i386/microvm.rst | 4 +-
docs/system/i386/xenpvh.rst | 2 +-
docs/system/ppc/ppce500.rst | 4 +-
docs/system/riscv/microchip-icicle-kit.rst | 2 +-
docs/system/riscv/sifive_u.rst | 2 +-
meson.build | 4 +
qapi/machine.json | 28 ++
qapi/migration.json | 21 +-
qapi/net.json | 45 ++-
hw/i386/amd_iommu.h | 27 +-
hw/i386/intel_iommu_internal.h | 1 +
hw/s390x/ccw-device.h | 2 +-
include/hw/acpi/cpu.h | 4 +-
include/hw/acpi/cpu_hotplug.h | 2 +-
include/hw/acpi/generic_event_device.h | 3 +-
include/hw/acpi/ich9.h | 10 +-
include/hw/acpi/memory_hotplug.h | 4 +-
include/hw/acpi/pcihp.h | 8 +-
include/hw/core/boards.h | 4 +-
include/hw/core/hotplug.h | 13 +-
include/hw/core/qdev.h | 14 +-
include/hw/cxl/cxl.h | 12 +
include/hw/i386/microvm.h | 4 +-
include/hw/i386/x86.h | 10 +-
include/hw/mem/nvdimm.h | 2 +-
include/hw/pci/pci_bridge.h | 6 +-
include/hw/pci/pcie.h | 8 +-
include/hw/pci/shpc.h | 6 +-
include/hw/ppc/spapr_nvdimm.h | 2 +-
include/hw/virtio/vhost-backend.h | 1 +
include/hw/virtio/vhost-user-media.h | 46 +++
include/hw/virtio/vhost-user.h | 2 +-
include/hw/virtio/vhost.h | 16 +-
include/hw/virtio/virtio-balloon.h | 1 +
include/hw/virtio/virtio-net.h | 1 +
include/hw/virtio/virtio.h | 2 +-
include/migration/misc.h | 2 +
include/migration/vmstate.h | 2 +
include/net/net.h | 9 +
include/net/tap.h | 2 +
include/standard-headers/linux/ethtool.h | 6 +
include/standard-headers/linux/virtio_ids.h | 1 +
linux-headers/linux/iommufd.h | 45 ++-
linux-headers/linux/userfaultfd.h | 54 ++-
linux-headers/linux/vduse.h | 28 ++
linux-headers/linux/vfio.h | 21 ++
linux-headers/linux/vfio_zdev.h | 2 +
backends/cryptodev-vhost.c | 2 +-
backends/vhost-user.c | 2 +-
hw/acpi/acpi-cpu-hotplug-stub.c | 4 +-
hw/acpi/acpi-mem-hotplug-stub.c | 4 +-
hw/acpi/acpi-nvdimm-stub.c | 2 +-
hw/acpi/acpi-pci-hotplug-stub.c | 8 +-
hw/acpi/cpu.c | 6 +-
hw/acpi/cxl.c | 2 +-
hw/acpi/generic_event_device.c | 13 +-
hw/acpi/ich9.c | 10 +-
hw/acpi/memory_hotplug.c | 7 +-
hw/acpi/nvdimm.c | 2 +-
hw/acpi/pcihp.c | 11 +-
hw/acpi/piix4.c | 12 +-
hw/arm/virt.c | 23 +-
hw/block/vhost-user-blk.c | 60 +++-
hw/block/virtio-blk.c | 38 ++-
hw/char/virtio-serial-bus.c | 6 +-
hw/core/hotplug.c | 16 +-
hw/core/qdev-hotplug.c | 10 +-
hw/core/qdev.c | 2 +-
hw/cxl/cxl-host.c | 48 ++-
hw/display/vhost-user-media-pci.c | 115 +++++++
hw/display/vhost-user-media.c | 388 ++++++++++++++++++++++
hw/i386/acpi-build.c | 65 ++--
hw/i386/amd_iommu-stub.c | 2 +-
hw/i386/amd_iommu.c | 2 +-
hw/i386/intel_iommu.c | 118 ++++---
hw/i386/intel_iommu_accel.c | 6 +
hw/i386/microvm.c | 12 +-
hw/i386/pc.c | 28 +-
hw/i386/x86-common.c | 8 +-
hw/ide/core.c | 3 +-
hw/intc/loongarch_dintc.c | 8 +-
hw/intc/loongarch_extioi_common.c | 4 +-
hw/intc/loongarch_ipi.c | 4 +-
hw/loongarch/virt.c | 44 +--
hw/mem/cxl_type3.c | 6 +-
hw/net/vhost_net.c | 9 +-
hw/net/virtio-net.c | 131 +++++++-
hw/nvme/ctrl.c | 78 +++--
hw/pci-bridge/pci_bridge_dev.c | 6 +-
hw/pci/pci.c | 8 +
hw/pci/pcie.c | 10 +-
hw/pci/pcie_port.c | 2 +-
hw/pci/shpc.c | 11 +-
hw/ppc/e500plat.c | 4 +-
hw/ppc/spapr.c | 48 +--
hw/ppc/spapr_nvdimm.c | 2 +-
hw/ppc/spapr_pci.c | 12 +-
hw/remote/machine.c | 2 +-
hw/riscv/virt.c | 6 +-
hw/s390x/css-bridge.c | 2 +-
hw/s390x/s390-pci-bus.c | 12 +-
hw/s390x/s390-virtio-ccw.c | 16 +-
hw/s390x/virtio-ccw-md.c | 10 +-
hw/s390x/virtio-ccw.c | 2 +-
hw/scsi/scsi-disk.c | 7 +
hw/scsi/vhost-scsi-common.c | 2 +-
hw/scsi/virtio-scsi-dataplane.c | 2 +-
hw/scsi/virtio-scsi.c | 10 +-
hw/scsi/vmw_pvscsi.c | 4 +-
hw/virtio/vdpa-dev.c | 2 +-
hw/virtio/vhost-user-base.c | 2 +-
hw/virtio/vhost-user-fs.c | 2 +-
hw/virtio/vhost-user-scmi.c | 2 +-
hw/virtio/vhost-user.c | 47 ++-
hw/virtio/vhost-vsock-common.c | 2 +-
hw/virtio/vhost.c | 44 ++-
hw/virtio/virtio-balloon.c | 19 +-
hw/virtio/virtio-crypto.c | 5 +-
hw/virtio/virtio-iommu.c | 17 +-
hw/virtio/virtio-md-pci.c | 10 +-
hw/virtio/virtio-pci.c | 7 +
hw/virtio/virtio-rtc.c | 3 +-
hw/virtio/virtio.c | 85 ++---
hw/xen/xen-bus.c | 2 +-
migration/fd.c | 28 +-
migration/migration.c | 13 +
migration/options.c | 18 +-
net/net.c | 14 +-
net/tap-solaris.c | 69 ++--
net/tap.c | 448 ++++++++++++++++++++-----
stubs/hotplug-stubs.c | 6 +-
subprojects/libvhost-user/libvhost-user.c | 34 +-
system/qdev-monitor.c | 4 +-
tests/qtest/cxl-test.c | 95 ++++++
hw/display/Kconfig | 5 +
hw/display/meson.build | 3 +
qemu-options.hx | 13 +-
tests/data/acpi/x86/q35/CEDT.cxl | Bin 184 -> 184 bytes
tests/data/acpi/x86/q35/IVRS.ivrs | Bin 176 -> 176 bytes
tests/functional/x86_64/meson.build | 1 +
tests/functional/x86_64/test_tap_migration.py | 461 ++++++++++++++++++++++++++
145 files changed, 2884 insertions(+), 663 deletions(-)
create mode 100644 include/hw/virtio/vhost-user-media.h
create mode 100644 hw/display/vhost-user-media-pci.c
create mode 100644 hw/display/vhost-user-media.c
create mode 100755 tests/functional/x86_64/test_tap_migration.py
^ permalink raw reply [flat|nested] 82+ messages in thread
* [PULL v2 01/75] virtio: fix exit(1) on DMA mapping failure during migration restore
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
@ 2026-09-11 9:01 ` Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 02/75] virtio: fix config_len DoS in migration restore path Michael S. Tsirkin
` (75 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:01 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Stefan Hajnoczi, Kevin Wolf, Hanna Reitz,
Laurent Vivier, Amit Shah, Marc-André Lureau, Paolo Bonzini,
Fam Zheng, qemu-block
When QEMU restores pending virtio requests from a migration stream, it
calls qemu_get_virtqueue_element(), which calls virtqueue_map() and
virtqueue_map_iovec() to re-map the saved DMA fragment addresses into
the destination address space. If the addresses in the migration stream
are corrupted, and as a result dma_memory_map() returns NULL or a
shorter-than-expected length, virtqueue_map_iovec() calls exit(1),
terminating the destination QEMU process instead of failing the
migration cleanly.
Convert virtqueue_map_iovec() and virtqueue_map() from void to bool.
On failure, virtqueue_map_iovec() unmaps any entries it has already
mapped and returns false; virtqueue_map() similarly cleans up the in_sg
entries if out_sg mapping fails. qemu_get_virtqueue_element() now
checks the return value, frees the element and returns NULL on failure,
allowing the migration restore path to propagate a clean error. The
callers in virtio-blk, virtio-serial-bus and virtio-scsi that invoke
qemu_get_virtqueue_element() during load are updated to check for NULL
and return an error code.
Fixes: 3b3b062821 ("virtio: slim down allocation of VirtQueueElements")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3888
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
include/hw/virtio/virtio.h | 2 +-
hw/block/virtio-blk.c | 4 +++
hw/char/virtio-serial-bus.c | 4 +++
hw/scsi/virtio-scsi.c | 4 +++
hw/virtio/virtio.c | 49 +++++++++++++++++++++++++++----------
5 files changed, 49 insertions(+), 14 deletions(-)
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index c99cb19d88..27c5fe3a6b 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -320,7 +320,7 @@ bool virtqueue_rewind(VirtQueue *vq, unsigned int num);
void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
unsigned int len, unsigned int idx);
-void virtqueue_map(VirtIODevice *vdev, VirtQueueElement *elem);
+bool virtqueue_map(VirtIODevice *vdev, VirtQueueElement *elem);
void *virtqueue_pop(VirtQueue *vq, size_t sz);
unsigned int virtqueue_drop_all(VirtQueue *vq);
void *qemu_get_virtqueue_element(VirtIODevice *vdev, QEMUFile *f, size_t sz);
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index 6b92066aff..cb6a276a82 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -1384,6 +1384,10 @@ static int virtio_blk_load_device(VirtIODevice *vdev, QEMUFile *f,
}
req = qemu_get_virtqueue_element(vdev, f, sizeof(VirtIOBlockReq));
+ if (!req) {
+ error_report("Failed to restore virtio-blk request");
+ return -EINVAL;
+ }
virtio_blk_init_request(s, virtio_get_queue(vdev, vq_idx), req);
WITH_QEMU_LOCK_GUARD(&s->rq_lock) {
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
index 83a033ce85..81db0bdc91 100644
--- a/hw/char/virtio-serial-bus.c
+++ b/hw/char/virtio-serial-bus.c
@@ -764,6 +764,10 @@ static int fetch_active_ports_list(QEMUFile *f,
port->elem =
qemu_get_virtqueue_element(vdev, f, sizeof(VirtQueueElement));
+ if (!port->elem) {
+ error_report("Failed to restore virtio-serial element");
+ return -EINVAL;
+ }
/*
* Port was throttled on source machine. Let's
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index bf64d1231a..132f833226 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -274,6 +274,10 @@ static void *virtio_scsi_load_request(QEMUFile *f, SCSIRequest *sreq)
assert(n < vs->conf.num_queues);
req = qemu_get_virtqueue_element(vdev, f,
sizeof(VirtIOSCSIReq) + vs->cdb_size);
+ if (!req) {
+ error_report("Failed to restore virtio-scsi request");
+ return NULL;
+ }
virtio_scsi_init_req(s, vs->cmd_vqs[n], req);
if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICmdReq) + vs->cdb_size,
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index daa5607338..34f1df260b 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -1680,36 +1680,56 @@ static void virtqueue_undo_map_desc(AddressSpace *as,
}
}
-static void virtqueue_map_iovec(VirtIODevice *vdev, struct iovec *sg,
+static bool virtqueue_map_iovec(VirtIODevice *vdev, struct iovec *sg,
hwaddr *addr, unsigned int num_sg,
bool is_write)
{
unsigned int i;
hwaddr len;
+ DMADirection dir = is_write ? DMA_DIRECTION_FROM_DEVICE :
+ DMA_DIRECTION_TO_DEVICE;
for (i = 0; i < num_sg; i++) {
len = sg[i].iov_len;
- sg[i].iov_base = dma_memory_map(vdev->dma_as,
- addr[i], &len, is_write ?
- DMA_DIRECTION_FROM_DEVICE :
- DMA_DIRECTION_TO_DEVICE,
- MEMTXATTRS_UNSPECIFIED);
+ sg[i].iov_base = dma_memory_map(vdev->dma_as, addr[i], &len,
+ dir, MEMTXATTRS_UNSPECIFIED);
if (!sg[i].iov_base) {
error_report("virtio: error trying to map MMIO memory");
- exit(1);
+ goto err_undo_map;
}
if (len != sg[i].iov_len) {
error_report("virtio: unexpected memory split");
- exit(1);
+ dma_memory_unmap(vdev->dma_as, sg[i].iov_base, len, dir, 0);
+ goto err_undo_map;
}
}
+ return true;
+
+err_undo_map:
+ while (i-- > 0) {
+ dma_memory_unmap(vdev->dma_as, sg[i].iov_base, sg[i].iov_len,
+ dir, 0);
+ }
+ return false;
}
-void virtqueue_map(VirtIODevice *vdev, VirtQueueElement *elem)
+bool virtqueue_map(VirtIODevice *vdev, VirtQueueElement *elem)
{
- virtqueue_map_iovec(vdev, elem->in_sg, elem->in_addr, elem->in_num, true);
- virtqueue_map_iovec(vdev, elem->out_sg, elem->out_addr, elem->out_num,
- false);
+ if (!virtqueue_map_iovec(vdev, elem->in_sg, elem->in_addr,
+ elem->in_num, true)) {
+ return false;
+ }
+ if (!virtqueue_map_iovec(vdev, elem->out_sg, elem->out_addr,
+ elem->out_num, false)) {
+ unsigned int i;
+ for (i = 0; i < elem->in_num; i++) {
+ dma_memory_unmap(vdev->dma_as, elem->in_sg[i].iov_base,
+ elem->in_sg[i].iov_len,
+ DMA_DIRECTION_FROM_DEVICE, 0);
+ }
+ return false;
+ }
+ return true;
}
static void *virtqueue_alloc_element(size_t sz, unsigned out_num, unsigned in_num)
@@ -2206,7 +2226,10 @@ void *qemu_get_virtqueue_element(VirtIODevice *vdev, QEMUFile *f, size_t sz)
qemu_get_be32s(f, &elem->ndescs);
}
- virtqueue_map(vdev, elem);
+ if (!virtqueue_map(vdev, elem)) {
+ g_free(elem);
+ return NULL;
+ }
return elem;
}
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 02/75] virtio: fix config_len DoS in migration restore path
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 01/75] virtio: fix exit(1) on DMA mapping failure during migration restore Michael S. Tsirkin
@ 2026-09-11 9:01 ` Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 03/75] virtio-pci: reject Q_ENABLE write on already-enabled queue Michael S. Tsirkin
` (74 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:01 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Dr. David Alan Gilbert
virtio_load() reads config_len from the migration stream into a local
int32_t variable and then, if the incoming length exceeds the device's
own config size, skips the surplus one byte at a time in a loop. Two
defects in this loop allow a malicious or truncated migration stream to
cause a prolonged CPU spin on the destination QEMU.
First, the local variable is int32_t while vdev->config_len is size_t.
The C standard converts the signed operand to the unsigned type for the
comparison, so any value with the high bit set becomes a very large
size_t that exceeds the device config length. The loop then counts the
signed counter down through all negative values and back around,
effectively running for up to 2^32 iterations.
Second, once the file stream reaches EOF, qemu_get_byte() returns 0
without advancing the read position. Without a check for file errors,
the loop spins until the counter reaches the device config length. An
attacker who sends a large config_len and then closes the stream can
hold the destination QEMU busy for attacker-controlled time.
Change the local config_len to uint32_t so that the comparison with
size_t is unsigned and values with the high bit set are treated as
large-but-finite skip counts. In addition, check qemu_file_get_error()
after each byte read and return failure immediately when the stream
signals EOF or an I/O error.
Fixes: 2f5732e964 ("Allow mismatched virtio config-len")
Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3891
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
hw/virtio/virtio.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 34f1df260b..848fe8539e 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -3584,6 +3584,9 @@ virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
return -1;
}
qemu_get_byte(f);
+ if (qemu_file_get_error(f)) {
+ return -1;
+ }
config_len--;
}
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 03/75] virtio-pci: reject Q_ENABLE write on already-enabled queue
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 01/75] virtio: fix exit(1) on DMA mapping failure during migration restore Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 02/75] virtio: fix config_len DoS in migration restore path Michael S. Tsirkin
@ 2026-09-11 9:01 ` Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 04/75] hw/cxl: Fix guest-triggerable QEMU exit on reserved interleave ways Michael S. Tsirkin
` (73 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:01 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Kangjie Xu
When the guest writes 1 to the VIRTIO_PCI_COMMON_Q_ENABLE field of a
queue that is already enabled, QEMU re-applies the ring geometry stored
in the PCI proxy shadow registers by calling virtio_queue_set_num() and
virtio_queue_set_rings(). Those functions update the vring descriptor,
available, and used addresses and the region cache, but they do not
touch the host-side progress fields - last_avail_idx, shadow_avail_idx,
used_idx, inuse, and the packed-ring wrap counters - which are only
zeroed by __virtio_queue_reset().
Because the progress indices are stale while the ring layout is new, the
host can treat the new ring as though there are up to 65535 pending
descriptors already waiting, causing virtqueue_pop() to iterate far
beyond what the guest actually posted. On virtio-iommu this translates
into a stream of ATTACH/DETACH/MAP/UNMAP commands, driving the QEMU
process toward OOM from guest-controlled BAR writes.
The virtio specification requires the driver to complete a full queue
reset cycle before re-enabling a queue. Fix this by checking the
proxy's per-queue enabled flag before processing the write. If the
queue is already enabled, log the violation as a guest error and ignore
the write.
Fixes: d1060e3dc5 ("virtio-pci: support queue enable")
Cc: Kangjie Xu <kangjie.xu@linux.alibaba.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
hw/virtio/virtio-pci.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 6f5db5fc42..c73f1f546c 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1692,6 +1692,13 @@ static void virtio_pci_common_write(void *opaque, hwaddr addr,
break;
case VIRTIO_PCI_COMMON_Q_ENABLE:
if (val == 1) {
+ if (proxy->vqs[vdev->queue_sel].enabled) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: queue %d already enabled - "
+ "reset queue before re-enabling\n",
+ __func__, vdev->queue_sel);
+ break;
+ }
virtio_queue_set_num(vdev, vdev->queue_sel,
proxy->vqs[vdev->queue_sel].num);
virtio_queue_set_rings(vdev, vdev->queue_sel,
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 04/75] hw/cxl: Fix guest-triggerable QEMU exit on reserved interleave ways
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (2 preceding siblings ...)
2026-09-11 9:01 ` [PULL v2 03/75] virtio-pci: reject Q_ENABLE write on already-enabled queue Michael S. Tsirkin
@ 2026-09-11 9:01 ` Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 05/75] linux-headers: add VIRTIO_ID_MEDIA Michael S. Tsirkin
` (72 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:01 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Junjie Cao, qemu-stable, Jonathan Cameron,
linux-cxl
From: Junjie Cao <junjie.cao@intel.com>
A buggy or malicious guest can program a committed HDM decoder with a
reserved Interleave Ways encoding (e.g. 0x5-0x7, 0xb-0xf). Two call
sites pass &error_fatal to cxl_interleave_ways_dec(), which calls
exit(1) on the reserved encoding before the subsequent decoded_iw == 0
guards can run:
- cxl-host.c update_non_interleaved(): called at commit time from
hdm_decoder_commit() via cfmws_update_non_interleaved(), so a guest
writing COMMIT with a reserved IW terminates QEMU immediately. This
is the primary trigger on the current tree.
- cxl_type3.c cxl_type3_dpa(): called on memory access while iterating
past committed decoders to accumulate dpa_base. Once the commit-time
exit is removed, the decoder stays committed with the reserved
encoding, so a later guest access outside that decoder's range would
otherwise hit this second &error_fatal; both are fixed here.
Pass NULL instead of &error_fatal at both sites so that the reserved
encoding returns zero and the existing guards handle it gracefully.
This can be reproduced by writing the HDM Decoder 0 Control register
with a reserved IW encoding and the COMMIT bit set (e.g. IW=0x5,
COMMIT=1).
Cc: qemu-stable@nongnu.org
Fixes: 680935c9a6ff ("hw/cxl: Add a performant (and correct) path for the non interleaved cases")
Fixes: 48461825af1b ("hw/mem/cxl_type3: Fix potential divide by zero reported by coverity")
Signed-off-by: Junjie Cao <junjie.cao@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260618104316.557306-1-junjie.cao@intel.com>
---
hw/cxl/cxl-host.c | 2 +-
hw/mem/cxl_type3.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/cxl/cxl-host.c b/hw/cxl/cxl-host.c
index eba13c9e7c..369a985f9b 100644
--- a/hw/cxl/cxl-host.c
+++ b/hw/cxl/cxl-host.c
@@ -442,7 +442,7 @@ static int update_non_interleaved(Object *obj, void *opaque)
}
}
- interleave_ways_dec = cxl_interleave_ways_dec(iw, &error_fatal);
+ interleave_ways_dec = cxl_interleave_ways_dec(iw, NULL);
if (interleave_ways_dec == 0) {
return 0;
}
diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index 28f41fa623..6f44770db6 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.c
@@ -1200,7 +1200,7 @@ static bool cxl_type3_dpa(CXLType3Dev *ct3d, hwaddr host_addr, uint64_t *dpa)
}
if (((uint64_t)host_addr < decoder_base) ||
(hpa_offset >= decoder_size)) {
- int decoded_iw = cxl_interleave_ways_dec(iw, &error_fatal);
+ int decoded_iw = cxl_interleave_ways_dec(iw, NULL);
if (decoded_iw == 0) {
return false;
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 05/75] linux-headers: add VIRTIO_ID_MEDIA
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (3 preceding siblings ...)
2026-09-11 9:01 ` [PULL v2 04/75] hw/cxl: Fix guest-triggerable QEMU exit on reserved interleave ways Michael S. Tsirkin
@ 2026-09-11 9:01 ` Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 06/75] hw/display: add vhost-user-media device Michael S. Tsirkin
` (71 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:01 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Albert Esteve, Dorinda Bassey, Cornelia Huck,
Paolo Bonzini
From: Albert Esteve <aesteve@redhat.com>
The ID was added in Linux commit 2187be212179 ("virtio: Add ID for
virtio media") and is included in v7.3-rc1.
Signed-off-by: Albert Esteve <aesteve@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Tested-by: Dorinda Bassey <dbassey@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260901-virtio-media-v2-1-bd3cc9347ab9@redhat.com>
---
include/standard-headers/linux/virtio_ids.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/standard-headers/linux/virtio_ids.h b/include/standard-headers/linux/virtio_ids.h
index 6c12db16fa..f9056af0c6 100644
--- a/include/standard-headers/linux/virtio_ids.h
+++ b/include/standard-headers/linux/virtio_ids.h
@@ -69,6 +69,7 @@
#define VIRTIO_ID_BT 40 /* virtio bluetooth */
#define VIRTIO_ID_GPIO 41 /* virtio gpio */
#define VIRTIO_ID_SPI 45 /* virtio spi */
+#define VIRTIO_ID_MEDIA 48 /* virtio media */
/*
* Virtio Transitional IDs
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 06/75] hw/display: add vhost-user-media device
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (4 preceding siblings ...)
2026-09-11 9:01 ` [PULL v2 05/75] linux-headers: add VIRTIO_ID_MEDIA Michael S. Tsirkin
@ 2026-09-11 9:01 ` Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 07/75] hw/display/vhost-user-media: add shared memory region BAR Michael S. Tsirkin
` (70 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:01 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Albert Esteve, Dorinda Bassey, Paolo Bonzini,
Stefano Garzarella, Marc-André Lureau
From: Albert Esteve <aesteve@redhat.com>
Add the QEMU side of the vhost-user-media device, which connects to a
virtio-media vhost-user backend daemon implementing the V4L2 API over
the virtio-media protocol.
The virtio-media device is specified in the VirtIO specification v1.4,
section 5.22:
https://docs.oasis-open.org/virtio/virtio/v1.4/cs01/virtio-v1.4-cs01.html
Tested with the rust-vmm vhost-device-media backend [1]:
cargo run -- -s /path/to/media.sock -d /dev/video0 --backend v4l2-proxy
Example invocation:
qemu-system-x86_64 \
-chardev socket,path=/path/to/media.sock,id=media \
-device vhost-user-media-pci,chardev=media,id=media
[1] https://github.com/rust-vmm/vhost-device/tree/main/vhost-device-media
Tested-by: Dorinda Bassey <dbassey@redhat.com>
Signed-off-by: Albert Esteve <aesteve@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260901-virtio-media-v2-2-bd3cc9347ab9@redhat.com>
---
MAINTAINERS | 6 +
include/hw/virtio/vhost-user-media.h | 46 ++++
hw/display/vhost-user-media-pci.c | 80 ++++++
hw/display/vhost-user-media.c | 348 +++++++++++++++++++++++++++
hw/virtio/virtio.c | 3 +-
hw/display/Kconfig | 5 +
hw/display/meson.build | 3 +
7 files changed, 490 insertions(+), 1 deletion(-)
create mode 100644 include/hw/virtio/vhost-user-media.h
create mode 100644 hw/display/vhost-user-media-pci.c
create mode 100644 hw/display/vhost-user-media.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 7183babd6a..ec313c3259 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2690,6 +2690,12 @@ S: Supported
F: include/hw/virtio/vhost-user-rtc.h
F: hw/virtio/vhost-user-rtc*
+vhost-user-media
+M: Albert Esteve <aesteve@redhat.com>
+S: Supported
+F: hw/display/vhost-user-media*
+F: include/hw/virtio/vhost-user-media.h
+
virtio-crypto
M: Gonglei <arei.gonglei@huawei.com>
S: Supported
diff --git a/include/hw/virtio/vhost-user-media.h b/include/hw/virtio/vhost-user-media.h
new file mode 100644
index 0000000000..d040c70f63
--- /dev/null
+++ b/include/hw/virtio/vhost-user-media.h
@@ -0,0 +1,46 @@
+/*
+ * vhost-user-media virtio device
+ *
+ * Copyright Red Hat, Inc. 2026
+ *
+ * Authors:
+ * Albert Esteve <aesteve@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef QEMU_VHOST_USER_MEDIA_H
+#define QEMU_VHOST_USER_MEDIA_H
+
+#include "hw/virtio/virtio.h"
+#include "hw/virtio/vhost.h"
+#include "hw/virtio/vhost-user.h"
+#include "qom/object.h"
+
+#define TYPE_VHOST_USER_MEDIA "vhost-user-media-device"
+OBJECT_DECLARE_SIMPLE_TYPE(VHostUserMEDIA, VHOST_USER_MEDIA)
+
+/* virtio-media config layout, spec 5.22.4 */
+struct virtio_media_config {
+ uint32_t device_caps;
+ uint32_t device_type;
+ uint8_t card[32];
+} QEMU_PACKED;
+
+typedef struct {
+ CharFrontend chardev;
+} VHostUserMEDIAConf;
+
+struct VHostUserMEDIA {
+ /*< private >*/
+ VirtIODevice parent;
+ VHostUserMEDIAConf conf;
+ struct vhost_dev vhost_dev;
+ VhostUserState vhost_user;
+ VirtQueue *command_vq;
+ VirtQueue *event_vq;
+ bool connected;
+ /*< public >*/
+};
+
+#endif /* QEMU_VHOST_USER_MEDIA_H */
diff --git a/hw/display/vhost-user-media-pci.c b/hw/display/vhost-user-media-pci.c
new file mode 100644
index 0000000000..3e09fcfdd0
--- /dev/null
+++ b/hw/display/vhost-user-media-pci.c
@@ -0,0 +1,80 @@
+/*
+ * Vhost-user MEDIA virtio device PCI glue
+ *
+ * Copyright Red Hat, Inc. 2026
+ * Authors: Albert Esteve <aesteve@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/core/qdev-properties.h"
+#include "hw/virtio/vhost-user-media.h"
+#include "hw/virtio/virtio-pci.h"
+
+#define TYPE_VHOST_USER_MEDIA_PCI "vhost-user-media-pci-base"
+OBJECT_DECLARE_SIMPLE_TYPE(VHostUserMEDIAPCI, VHOST_USER_MEDIA_PCI)
+
+struct VHostUserMEDIAPCI {
+ VirtIOPCIProxy parent_obj;
+ VHostUserMEDIA vdev;
+};
+
+static const Property vumedia_pci_properties[] = {
+ DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
+ VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
+ DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
+ DEV_NVECTORS_UNSPECIFIED),
+};
+
+static void vumedia_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
+{
+ VHostUserMEDIAPCI *dev = VHOST_USER_MEDIA_PCI(vpci_dev);
+ DeviceState *dev_state = DEVICE(&dev->vdev);
+
+ if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) {
+ vpci_dev->nvectors = 1;
+ }
+
+ if (!qdev_realize(dev_state, BUS(&vpci_dev->bus), errp)) {
+ return;
+ }
+}
+
+static void vumedia_pci_class_init(ObjectClass *klass, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
+ PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
+ k->realize = vumedia_pci_realize;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ device_class_set_props(dc, vumedia_pci_properties);
+ pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+ pcidev_k->device_id = 0; /* Set by virtio-pci based on virtio id */
+ pcidev_k->revision = 0x00;
+ pcidev_k->class_id = PCI_CLASS_MULTIMEDIA_VIDEO;
+}
+
+static void vumedia_pci_instance_init(Object *obj)
+{
+ VHostUserMEDIAPCI *dev = VHOST_USER_MEDIA_PCI(obj);
+
+ virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
+ TYPE_VHOST_USER_MEDIA);
+}
+
+static const VirtioPCIDeviceTypeInfo vumedia_pci_info = {
+ .base_name = TYPE_VHOST_USER_MEDIA_PCI,
+ .non_transitional_name = "vhost-user-media-pci",
+ .instance_size = sizeof(VHostUserMEDIAPCI),
+ .instance_init = vumedia_pci_instance_init,
+ .class_init = vumedia_pci_class_init,
+};
+
+static void vumedia_pci_register(void)
+{
+ virtio_pci_types_register(&vumedia_pci_info);
+}
+
+type_init(vumedia_pci_register);
diff --git a/hw/display/vhost-user-media.c b/hw/display/vhost-user-media.c
new file mode 100644
index 0000000000..14edc7c668
--- /dev/null
+++ b/hw/display/vhost-user-media.c
@@ -0,0 +1,348 @@
+/*
+ * Vhost-user Media device
+ *
+ * Copyright Red Hat, Inc. 2026
+ *
+ * This is the boilerplate for instantiating a vhost-user device
+ * implementing a virtio-media device.
+ *
+ * Authors:
+ * Albert Esteve <aesteve@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+#include "hw/core/qdev-properties-system.h"
+#include "standard-headers/linux/virtio_ids.h"
+#include "hw/virtio/virtio-bus.h"
+#include "hw/virtio/vhost-user-media.h"
+
+static const int feature_bits[] = {
+ VIRTIO_F_VERSION_1,
+ VIRTIO_F_NOTIFY_ON_EMPTY,
+ VIRTIO_RING_F_INDIRECT_DESC,
+ VIRTIO_RING_F_EVENT_IDX,
+ VIRTIO_F_RING_RESET,
+ VHOST_INVALID_FEATURE_BIT
+};
+
+static void
+vu_media_get_config(VirtIODevice *vdev, uint8_t *config_data)
+{
+ VHostUserMEDIA *media = VHOST_USER_MEDIA(vdev);
+ Error *local_err = NULL;
+ int ret;
+
+ memset(config_data, 0, sizeof(struct virtio_media_config));
+
+ ret = vhost_dev_get_config(&media->vhost_dev,
+ config_data, sizeof(struct virtio_media_config),
+ &local_err);
+ if (ret) {
+ error_report_err(local_err);
+ return;
+ }
+}
+
+static void vu_media_start(VirtIODevice *vdev)
+{
+ VHostUserMEDIA *media = VHOST_USER_MEDIA(vdev);
+ BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
+ VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
+ int ret;
+ int i;
+
+ if (!k->set_guest_notifiers) {
+ error_report("binding does not support guest notifiers");
+ return;
+ }
+
+ ret = vhost_dev_enable_notifiers(&media->vhost_dev, vdev);
+ if (ret < 0) {
+ error_report("Error enabling host notifiers: %d", -ret);
+ return;
+ }
+
+ ret = k->set_guest_notifiers(qbus->parent, media->vhost_dev.nvqs, true);
+ if (ret < 0) {
+ error_report("Error binding guest notifier: %d", -ret);
+ goto err_host_notifiers;
+ }
+
+ media->vhost_dev.acked_features = vdev->guest_features;
+
+ media->vhost_dev.vq_index_end = media->vhost_dev.nvqs;
+ ret = vhost_dev_start(&media->vhost_dev, vdev, true);
+ if (ret < 0) {
+ error_report("Error starting vhost-user-media: %d", -ret);
+ goto err_guest_notifiers;
+ }
+
+ /*
+ * guest_notifier_mask/pending not used yet, so just unmask
+ * everything here. virtio-pci will do the right thing by
+ * enabling/disabling irqfd.
+ */
+ for (i = 0; i < media->vhost_dev.nvqs; i++) {
+ vhost_virtqueue_mask(&media->vhost_dev, vdev, i, false);
+ }
+
+ return;
+
+err_guest_notifiers:
+ k->set_guest_notifiers(qbus->parent, media->vhost_dev.nvqs, false);
+err_host_notifiers:
+ vhost_dev_disable_notifiers(&media->vhost_dev, vdev);
+}
+
+static void vu_media_stop(VirtIODevice *vdev)
+{
+ VHostUserMEDIA *media = VHOST_USER_MEDIA(vdev);
+ BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
+ VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
+ int ret;
+
+ if (!k->set_guest_notifiers) {
+ return;
+ }
+
+ vhost_dev_stop(&media->vhost_dev, vdev, true);
+
+ ret = k->set_guest_notifiers(qbus->parent, media->vhost_dev.nvqs, false);
+ if (ret < 0) {
+ error_report("vhost guest notifier cleanup failed: %d", ret);
+ return;
+ }
+
+ vhost_dev_disable_notifiers(&media->vhost_dev, vdev);
+}
+
+static int vu_media_set_status(VirtIODevice *vdev, uint8_t status)
+{
+ VHostUserMEDIA *media = VHOST_USER_MEDIA(vdev);
+ bool should_start = virtio_device_should_start(vdev, status);
+
+ if (vhost_dev_is_started(&media->vhost_dev) == should_start) {
+ return 0;
+ }
+
+ if (should_start) {
+ vu_media_start(vdev);
+ } else {
+ vu_media_stop(vdev);
+ }
+ return 0;
+}
+
+static uint64_t vu_media_get_features(VirtIODevice *vdev,
+ uint64_t requested_features,
+ Error **errp)
+{
+ VHostUserMEDIA *media = VHOST_USER_MEDIA(vdev);
+
+ return vhost_get_features(&media->vhost_dev, feature_bits,
+ requested_features);
+}
+
+static void vu_media_handle_output(VirtIODevice *vdev, VirtQueue *vq)
+{
+ /*
+ * Not normally called; it's the daemon that handles the queue;
+ * however virtio's cleanup path can call this.
+ */
+}
+
+static void vu_media_guest_notifier_mask(VirtIODevice *vdev, int idx,
+ bool mask)
+{
+ VHostUserMEDIA *media = VHOST_USER_MEDIA(vdev);
+
+ if (idx == VIRTIO_CONFIG_IRQ_IDX) {
+ return;
+ }
+
+ vhost_virtqueue_mask(&media->vhost_dev, vdev, idx, mask);
+}
+
+static bool vu_media_guest_notifier_pending(VirtIODevice *vdev, int idx)
+{
+ VHostUserMEDIA *media = VHOST_USER_MEDIA(vdev);
+
+ if (idx == VIRTIO_CONFIG_IRQ_IDX) {
+ return false;
+ }
+
+ return vhost_virtqueue_pending(&media->vhost_dev, idx);
+}
+
+static int vu_media_handle_config_change(struct vhost_dev *dev)
+{
+ virtio_notify_config(dev->vdev);
+ return 0;
+}
+
+static const VhostDevConfigOps media_ops = {
+ .vhost_dev_config_notifier = vu_media_handle_config_change,
+};
+
+static int vu_media_connect(DeviceState *dev)
+{
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VHostUserMEDIA *media = VHOST_USER_MEDIA(vdev);
+
+ if (media->connected) {
+ return 0;
+ }
+ media->connected = true;
+
+ /* restore vhost state */
+ if (virtio_device_started(vdev, vdev->status)) {
+ vu_media_start(vdev);
+ }
+
+ return 0;
+}
+
+static void vu_media_disconnect(DeviceState *dev)
+{
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VHostUserMEDIA *media = VHOST_USER_MEDIA(vdev);
+
+ if (!media->connected) {
+ return;
+ }
+ media->connected = false;
+
+ if (vhost_dev_is_started(&media->vhost_dev)) {
+ vu_media_stop(vdev);
+ }
+}
+
+static void vu_media_event(void *opaque, QEMUChrEvent event)
+{
+ DeviceState *dev = opaque;
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VHostUserMEDIA *media = VHOST_USER_MEDIA(vdev);
+
+ switch (event) {
+ case CHR_EVENT_OPENED:
+ if (vu_media_connect(dev) < 0) {
+ qemu_chr_fe_disconnect(&media->conf.chardev);
+ return;
+ }
+ break;
+ case CHR_EVENT_CLOSED:
+ vu_media_disconnect(dev);
+ break;
+ case CHR_EVENT_BREAK:
+ case CHR_EVENT_MUX_IN:
+ case CHR_EVENT_MUX_OUT:
+ /* Ignore */
+ break;
+ }
+}
+
+static void do_vhost_user_cleanup(VirtIODevice *vdev, VHostUserMEDIA *media,
+ struct vhost_virtqueue *vhost_vqs)
+{
+ virtio_delete_queue(media->command_vq);
+ virtio_delete_queue(media->event_vq);
+ g_free(vhost_vqs);
+ virtio_cleanup(vdev);
+ vhost_user_cleanup(&media->vhost_user);
+}
+
+static void vu_media_device_realize(DeviceState *dev, Error **errp)
+{
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VHostUserMEDIA *media = VHOST_USER_MEDIA(dev);
+ struct vhost_virtqueue *vhost_vqs;
+ int ret;
+
+ if (!media->conf.chardev.chr) {
+ error_setg(errp, "vhost-user-media: chardev is mandatory");
+ return;
+ }
+
+ if (!vhost_user_init(&media->vhost_user, &media->conf.chardev, errp)) {
+ return;
+ }
+
+ virtio_init(vdev, VIRTIO_ID_MEDIA, sizeof(struct virtio_media_config));
+
+ media->command_vq = virtio_add_queue(vdev, 128, vu_media_handle_output);
+ media->event_vq = virtio_add_queue(vdev, 128, vu_media_handle_output);
+ media->vhost_dev.nvqs = 2;
+ media->vhost_dev.vqs = g_new0(struct vhost_virtqueue,
+ media->vhost_dev.nvqs);
+ vhost_vqs = media->vhost_dev.vqs;
+
+ vhost_dev_set_config_notifier(&media->vhost_dev, &media_ops);
+ media->vhost_user.supports_config = true;
+
+ ret = vhost_dev_init(&media->vhost_dev, &media->vhost_user,
+ VHOST_BACKEND_TYPE_USER, 0, errp);
+ if (ret < 0) {
+ do_vhost_user_cleanup(vdev, media, vhost_vqs);
+ return;
+ }
+
+ qemu_chr_fe_set_handlers(&media->conf.chardev, NULL,
+ NULL, vu_media_event,
+ NULL, (void *)dev, NULL, true);
+}
+
+static void vu_media_device_unrealize(DeviceState *dev)
+{
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VHostUserMEDIA *media = VHOST_USER_MEDIA(dev);
+ struct vhost_virtqueue *vhost_vqs = media->vhost_dev.vqs;
+
+ /* This will stop vhost backend if appropriate. */
+ vu_media_set_status(vdev, 0);
+ vhost_dev_cleanup(&media->vhost_dev);
+ do_vhost_user_cleanup(vdev, media, vhost_vqs);
+}
+
+static const VMStateDescription vu_media_vmstate = {
+ .name = "vhost-user-media",
+ .unmigratable = 1,
+};
+
+static const Property vu_media_properties[] = {
+ DEFINE_PROP_CHR("chardev", VHostUserMEDIA, conf.chardev),
+};
+
+static void vu_media_class_init(ObjectClass *klass, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+
+ device_class_set_props(dc, vu_media_properties);
+ dc->vmsd = &vu_media_vmstate;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ vdc->realize = vu_media_device_realize;
+ vdc->unrealize = vu_media_device_unrealize;
+ vdc->get_features = vu_media_get_features;
+ vdc->get_config = vu_media_get_config;
+ vdc->set_status = vu_media_set_status;
+ vdc->guest_notifier_mask = vu_media_guest_notifier_mask;
+ vdc->guest_notifier_pending = vu_media_guest_notifier_pending;
+}
+
+static const TypeInfo vu_media_info = {
+ .name = TYPE_VHOST_USER_MEDIA,
+ .parent = TYPE_VIRTIO_DEVICE,
+ .instance_size = sizeof(VHostUserMEDIA),
+ .class_init = vu_media_class_init,
+};
+
+static void vu_media_register_types(void)
+{
+ type_register_static(&vu_media_info);
+}
+
+type_init(vu_media_register_types)
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 848fe8539e..0b2fbbed3f 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -198,7 +198,8 @@ const char *virtio_device_names[] = {
[VIRTIO_ID_AUDIO_POLICY] = "virtio-audio-pol",
[VIRTIO_ID_BT] = "virtio-bluetooth",
[VIRTIO_ID_GPIO] = "virtio-gpio",
- [VIRTIO_ID_SPI] = "virtio-spi"
+ [VIRTIO_ID_SPI] = "virtio-spi",
+ [VIRTIO_ID_MEDIA] = "virtio-media",
};
static const char *virtio_id_to_name(uint16_t device_id)
diff --git a/hw/display/Kconfig b/hw/display/Kconfig
index b3593fe981..060274b1e6 100644
--- a/hw/display/Kconfig
+++ b/hw/display/Kconfig
@@ -120,6 +120,11 @@ config VHOST_USER_VGA
default y
depends on VIRTIO_VGA && VHOST_USER_GPU
+config VHOST_USER_MEDIA
+ bool
+ default y
+ depends on VIRTIO && VHOST_USER
+
config DPCD
bool
select AUX
diff --git a/hw/display/meson.build b/hw/display/meson.build
index ffecedbf70..d8b4e121fe 100644
--- a/hw/display/meson.build
+++ b/hw/display/meson.build
@@ -37,6 +37,9 @@ system_ss.add(when: 'CONFIG_NEXTCUBE', if_true: files('next-fb.c'))
system_ss.add(when: 'CONFIG_VGA', if_true: files('vga.c'))
system_ss.add(when: 'CONFIG_VIRTIO', if_true: files('virtio-dmabuf.c'))
system_ss.add(when: 'CONFIG_DM163', if_true: files('dm163.c'))
+system_ss.add(when: 'CONFIG_VHOST_USER_MEDIA', if_true: files('vhost-user-media.c'))
+system_ss.add(when: ['CONFIG_VHOST_USER_MEDIA', 'CONFIG_VIRTIO_PCI'],
+ if_true: files('vhost-user-media-pci.c'))
stub_ss.add([files('acpi-vga-stub.c'), pixman])
if (config_all_devices.has_key('CONFIG_VGA_CIRRUS') or
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 07/75] hw/display/vhost-user-media: add shared memory region BAR
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (5 preceding siblings ...)
2026-09-11 9:01 ` [PULL v2 06/75] hw/display: add vhost-user-media device Michael S. Tsirkin
@ 2026-09-11 9:01 ` Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 08/75] virtio: reduce code duplication for split ring Michael S. Tsirkin
` (69 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:01 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Albert Esteve, Dorinda Bassey,
Marc-André Lureau, Stefano Garzarella
From: Albert Esteve <aesteve@redhat.com>
Expose virtio-media shared memory region 0 (spec 5.22.6.1.6) as a
prefetchable 64-bit PCI BAR (BAR 2) with a VirtIO shm capability.
The size is obtained through GET_SHMEM_CONFIG and requires at least
one shared region. The guest maps host-provisioned MMAP buffers into
this window; QEMU creates a container region on realize, not a
full-sized RAM allocation.
modern-pio-notify is rejected because it claims BAR 2.
vhost-user still needs shareable guest RAM, e.g.:
-object memory-backend-memfd,id=mem,size=4G,share=on \
-numa node,memdev=mem
Tested-by: Dorinda Bassey <dbassey@redhat.com>
Signed-off-by: Albert Esteve <aesteve@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260901-virtio-media-v2-3-bd3cc9347ab9@redhat.com>
---
hw/display/vhost-user-media-pci.c | 35 ++++++++++++++++++++++++++
hw/display/vhost-user-media.c | 42 ++++++++++++++++++++++++++++++-
2 files changed, 76 insertions(+), 1 deletion(-)
diff --git a/hw/display/vhost-user-media-pci.c b/hw/display/vhost-user-media-pci.c
index 3e09fcfdd0..7681f7505d 100644
--- a/hw/display/vhost-user-media-pci.c
+++ b/hw/display/vhost-user-media-pci.c
@@ -13,12 +13,18 @@
#include "hw/virtio/vhost-user-media.h"
#include "hw/virtio/virtio-pci.h"
+/* BAR 2 is used for the shared memory region exposed to the guest */
+#define VIRTIO_MEDIA_PCI_SHM_BAR 2
+
+#define VIRTIO_MEDIA_PCI_SHMCAP_ID_SHM 0
+
#define TYPE_VHOST_USER_MEDIA_PCI "vhost-user-media-pci-base"
OBJECT_DECLARE_SIMPLE_TYPE(VHostUserMEDIAPCI, VHOST_USER_MEDIA_PCI)
struct VHostUserMEDIAPCI {
VirtIOPCIProxy parent_obj;
VHostUserMEDIA vdev;
+ MemoryRegion shmbar;
};
static const Property vumedia_pci_properties[] = {
@@ -32,14 +38,43 @@ static void vumedia_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
{
VHostUserMEDIAPCI *dev = VHOST_USER_MEDIA_PCI(vpci_dev);
DeviceState *dev_state = DEVICE(&dev->vdev);
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev_state);
+ VirtioSharedMemory *shmem;
+ uint64_t shm_size;
if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) {
vpci_dev->nvectors = 1;
}
+ if (vpci_dev->flags & VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY) {
+ error_setg(errp, "modern-pio-notify is not supported due to PCI BAR "
+ "layout limitations");
+ return;
+ }
+
if (!qdev_realize(dev_state, BUS(&vpci_dev->bus), errp)) {
return;
}
+
+ shmem = virtio_find_shmem_region(vdev, VIRTIO_MEDIA_PCI_SHMCAP_ID_SHM);
+ if (!shmem) {
+ error_setg(errp, "vhost-user-media: missing shared memory region");
+ return;
+ }
+ shm_size = memory_region_size(&shmem->mr);
+
+ memory_region_init(&dev->shmbar, OBJECT(vpci_dev),
+ "vhost-media-pci-shmbar", shm_size);
+ memory_region_add_subregion(&dev->shmbar, 0, &shmem->mr);
+ virtio_pci_add_shm_cap(vpci_dev, VIRTIO_MEDIA_PCI_SHM_BAR, 0,
+ shm_size, VIRTIO_MEDIA_PCI_SHMCAP_ID_SHM);
+
+ /* After 'realized' so the memory region exists */
+ pci_register_bar(&vpci_dev->pci_dev, VIRTIO_MEDIA_PCI_SHM_BAR,
+ PCI_BASE_ADDRESS_SPACE_MEMORY |
+ PCI_BASE_ADDRESS_MEM_PREFETCH |
+ PCI_BASE_ADDRESS_MEM_TYPE_64,
+ &dev->shmbar);
}
static void vumedia_pci_class_init(ObjectClass *klass, const void *data)
diff --git a/hw/display/vhost-user-media.c b/hw/display/vhost-user-media.c
index 14edc7c668..eaf99dc6a2 100644
--- a/hw/display/vhost-user-media.c
+++ b/hw/display/vhost-user-media.c
@@ -19,6 +19,7 @@
#include "standard-headers/linux/virtio_ids.h"
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/vhost-user-media.h"
+#include "migration/blocker.h"
static const int feature_bits[] = {
VIRTIO_F_VERSION_1,
@@ -259,8 +260,9 @@ static void vu_media_device_realize(DeviceState *dev, Error **errp)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VHostUserMEDIA *media = VHOST_USER_MEDIA(dev);
+ uint64_t memory_sizes[VIRTIO_MAX_SHMEM_REGIONS];
struct vhost_virtqueue *vhost_vqs;
- int ret;
+ int ret, nregions;
if (!media->conf.chardev.chr) {
error_setg(errp, "vhost-user-media: chardev is mandatory");
@@ -290,9 +292,47 @@ static void vu_media_device_realize(DeviceState *dev, Error **errp)
return;
}
+ ret = media->vhost_dev.vhost_ops->vhost_get_shmem_config(&media->vhost_dev,
+ &nregions,
+ memory_sizes,
+ errp);
+ if (ret < 0) {
+ goto q_fail;
+ }
+
+ if (!nregions || !memory_sizes[0]) {
+ error_setg(errp, "vhost-user-media: backend did not provide "
+ "shared memory region 0");
+ goto q_fail;
+ }
+
+ if (memory_sizes[0] % qemu_real_host_page_size() != 0) {
+ error_setg(errp, "shared memory region 0 size must be a multiple "
+ "of the host page size");
+ goto q_fail;
+ }
+
+ if (media->vhost_dev.migration_blocker == NULL) {
+ error_setg(&media->vhost_dev.migration_blocker,
+ "Migration disabled: devices with VIRTIO Shared Memory "
+ "Regions do not support migration yet.");
+ ret = migrate_add_blocker_normal(&media->vhost_dev.migration_blocker,
+ errp);
+ if (ret < 0) {
+ goto q_fail;
+ }
+ }
+
+ virtio_new_shmem_region(vdev, 0, memory_sizes[0]);
+
qemu_chr_fe_set_handlers(&media->conf.chardev, NULL,
NULL, vu_media_event,
NULL, (void *)dev, NULL, true);
+ return;
+
+q_fail:
+ vhost_dev_cleanup(&media->vhost_dev);
+ do_vhost_user_cleanup(vdev, media, vhost_vqs);
}
static void vu_media_device_unrealize(DeviceState *dev)
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 08/75] virtio: reduce code duplication for split ring
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (6 preceding siblings ...)
2026-09-11 9:01 ` [PULL v2 07/75] hw/display/vhost-user-media: add shared memory region BAR Michael S. Tsirkin
@ 2026-09-11 9:01 ` Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 09/75] net/tap: rework tap_parse_script Michael S. Tsirkin
` (68 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:01 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Jia Jia
From: Jia Jia <physicalmtea@gmail.com>
virtio_queue_empty_rcu duplicates virtqueue_num_heads
for no good reason, let's not do it. As a nice side effect,
we gain better handling for misbehaving guests.
The virtio_device_disabled() check in virtio_queue_empty_rcu
is redundant because virtqueue_split_pop() is only called through
virtqueue_pop(), which already performs the check.
Signed-off-by: Jia Jia <physicalmtea@gmail.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260726012857.1580646-1-physicalmtea@gmail.com>
---
hw/virtio/virtio.c | 30 ++++++------------------------
1 file changed, 6 insertions(+), 24 deletions(-)
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 0b2fbbed3f..c9f9e5b511 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -717,26 +717,6 @@ static inline bool is_desc_avail(uint16_t flags, bool wrap_counter)
return (avail != used) && (avail == wrap_counter);
}
-/* Fetch avail_idx from VQ memory only when we really need to know if
- * guest has added some buffers.
- * Called within rcu_read_lock(). */
-static int virtio_queue_empty_rcu(VirtQueue *vq)
-{
- if (virtio_device_disabled(vq->vdev)) {
- return 1;
- }
-
- if (unlikely(!vq->vring.avail)) {
- return 1;
- }
-
- if (vq->shadow_avail_idx != vq->last_avail_idx) {
- return 0;
- }
-
- return vring_avail_idx(vq) == vq->last_avail_idx;
-}
-
static int virtio_queue_split_empty(VirtQueue *vq)
{
bool empty;
@@ -1773,12 +1753,14 @@ static void *virtqueue_split_pop(VirtQueue *vq, size_t sz)
address_space_cache_init_empty(&indirect_desc_cache);
RCU_READ_LOCK_GUARD();
- if (virtio_queue_empty_rcu(vq)) {
+ if (unlikely(!vq->vring.avail)) {
+ goto done;
+ }
+
+ rc = virtqueue_num_heads(vq, vq->last_avail_idx);
+ if (rc <= 0) {
goto done;
}
- /* Needed after virtio_queue_empty(), see comment in
- * virtqueue_num_heads(). */
- smp_rmb();
/* When we start there are none of either input nor output. */
out_num = in_num = elem_entries = 0;
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 09/75] net/tap: rework tap_parse_script
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (7 preceding siblings ...)
2026-09-11 9:01 ` [PULL v2 08/75] virtio: reduce code duplication for split ring Michael S. Tsirkin
@ 2026-09-11 9:01 ` Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 10/75] net/tap: improve script/downscript options documentation Michael S. Tsirkin
` (67 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:01 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Ben Chaney,
Markus Armbruster, Jason Wang
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Factor out tap_is_explicit_no_script() helper, to simplify
further changes.
Avoid extra copying by simpler code flow: first check for
NULL / empty / "no" cases, then get default or do copying
respectively.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Ben Chaney <bchaney@akamai.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260819180201.1970193-2-vsementsov@yandex-team.ru>
---
net/tap.c | 30 +++++++++++++++++++++++-------
1 file changed, 23 insertions(+), 7 deletions(-)
diff --git a/net/tap.c b/net/tap.c
index 57ffb09885..2076f5b780 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -92,19 +92,35 @@ static void launch_script(const char *setup_script, const char *ifname,
static void tap_send(void *opaque);
static void tap_writable(void *opaque);
-static char *tap_parse_script(const char *script_arg, const char *default_path)
+static bool tap_is_explicit_no_script(const char *script_arg_value)
{
- g_autofree char *res = g_strdup(script_arg);
-
- if (!res) {
- res = get_relocated_path(default_path);
+ if (!script_arg_value) {
+ return false;
}
- if (res[0] == '\0' || strcmp(res, "no") == 0) {
+ if (script_arg_value[0] == '\0') {
+ return true;
+ }
+
+ if (strcmp(script_arg_value, "no") == 0) {
+ return true;
+ }
+
+ return false;
+}
+
+static char *tap_parse_script(const char *script_arg_value,
+ const char *default_path)
+{
+ if (tap_is_explicit_no_script(script_arg_value)) {
return NULL;
}
- return g_steal_pointer(&res);
+ if (!script_arg_value) {
+ return get_relocated_path(default_path);
+ }
+
+ return g_strdup(script_arg_value);
}
static void tap_update_fd_handler(TAPState *s)
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 10/75] net/tap: improve script/downscript options documentation
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (8 preceding siblings ...)
2026-09-11 9:01 ` [PULL v2 09/75] net/tap: rework tap_parse_script Michael S. Tsirkin
@ 2026-09-11 9:01 ` Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 11/75] net/tap: deprecate "no" as special value for script/downscript Michael S. Tsirkin
` (66 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:01 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Markus Armbruster,
Ben Chaney, Jason Wang, Eric Blake
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Properly document defaults and special values of "" and "no".
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Ben Chaney <bchaney@akamai.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260819180201.1970193-3-vsementsov@yandex-team.ru>
---
qapi/net.json | 10 ++++++++--
qemu-options.hx | 9 +++++----
2 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/qapi/net.json b/qapi/net.json
index 85c78710fe..ab8ed9c086 100644
--- a/qapi/net.json
+++ b/qapi/net.json
@@ -399,9 +399,15 @@
# @fds: multiple file descriptors of already opened multiqueue capable
# tap
#
-# @script: script to initialize the interface
+# @script: script to initialize the interface. An empty string or
+# "no" disables script execution. Defaults to
+# ``<sysconfdir>/qemu-ifup``, where ``<sysconfdir>`` is the
+# system configuration directory at build time (typically /etc).
#
-# @downscript: script to shut down the interface
+# @downscript: script to shut down the interface. An empty string or
+# "no" disables script execution. Defaults to
+# ``<sysconfdir>/qemu-ifdown``, where ``<sysconfdir>`` is the
+# system configuration directory at build time (typically /etc).
#
# @br: bridge name (since 2.8)
#
diff --git a/qemu-options.hx b/qemu-options.hx
index 6c1713ed61..16ef7d5455 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3022,7 +3022,7 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
" use network scripts 'file' (default=" DEFAULT_NETWORK_SCRIPT ")\n"
" to configure it and 'dfile' (default=" DEFAULT_NETWORK_DOWN_SCRIPT ")\n"
" to deconfigure it\n"
- " use '[down]script=no' to disable script execution\n"
+ " use '[down]script=no' or '[down]script=' to disable script execution\n"
" use network helper 'helper' (default=" DEFAULT_BRIDGE_HELPER ") to\n"
" configure it\n"
" use 'fd=h' to connect to an already opened TAP interface\n"
@@ -3558,9 +3558,10 @@ SRST
Use the network script file to configure it and the network script
dfile to deconfigure it. If name is not provided, the OS
automatically provides one. The default network configure script is
- ``/etc/qemu-ifup`` and the default network deconfigure script is
- ``/etc/qemu-ifdown``. Use ``script=no`` or ``downscript=no`` to
- disable script execution.
+ ``<sysconfdir>/qemu-ifup`` and the default network deconfigure script is
+ ``<sysconfdir>/qemu-ifdown``, where ``<sysconfdir>`` is the system
+ configuration directory at build time (typically ``/etc``).
+ Use ``[down]script=no`` or ``[down]script=`` to disable script execution.
If running QEMU as an unprivileged user, use the network helper
to configure the TAP interface and attach it to the bridge.
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 11/75] net/tap: deprecate "no" as special value for script/downscript
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (9 preceding siblings ...)
2026-09-11 9:01 ` [PULL v2 10/75] net/tap: improve script/downscript options documentation Michael S. Tsirkin
@ 2026-09-11 9:01 ` Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 12/75] net/tap: move vhost-net open() calls to tap_parse_vhost_fds() Michael S. Tsirkin
` (65 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:01 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Ben Chaney,
Markus Armbruster, Pierrick Bouvier, Sergio Lopez, Paolo Bonzini,
Zhao Liu, Stefano Stabellini, Anthony PERARD, Edgar E. Iglesias,
Bernhard Beschow, Conor Dooley, Sebastian Huber, Alistair Francis,
Palmer Dabbelt, Jason Wang, Eric Blake, devel, xen-devel,
qemu-ppc, qemu-riscv
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
The interface is ambiguous, as "no" is valid file name. So,
using "no" as a special value to disable script is deprecated.
Use an empty string ("script=" / "downscript=") instead.
In a future version, "no" will be treated as a plain file name, just
like any other non-empty value.
Document the deprecation in docs/about/deprecated.rst, qapi/net.json,
and qemu-options.hx. Update other docs to use empty string instead of
"no". Add a warning.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Ben Chaney <bchaney@akamai.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260819180201.1970193-4-vsementsov@yandex-team.ru>
---
docs/about/deprecated.rst | 18 ++++++++++++++++++
docs/system/i386/microvm.rst | 4 ++--
docs/system/i386/xenpvh.rst | 2 +-
docs/system/ppc/ppce500.rst | 4 ++--
docs/system/riscv/microchip-icicle-kit.rst | 2 +-
docs/system/riscv/sifive_u.rst | 2 +-
qapi/net.json | 14 ++++++++++----
net/tap.c | 17 +++++++++++------
qemu-options.hx | 8 ++++++--
9 files changed, 52 insertions(+), 19 deletions(-)
diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index 98c32991c9..61e775373d 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -71,6 +71,15 @@ flexible enough. The monitor objects have been converted to QOM, so
``-mon mode=control`` is replaced by ``-object monitor-qmp``. The
short convenience options are not deprecated, only ``-mon``.
+``script=no`` and ``downscript=no`` for ``-netdev tap`` (since 11.2)
+'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
+
+The special value ``"no"`` for the ``script`` and ``downscript``
+parameters of ``-netdev tap`` disables script execution. This special
+treatment of ``"no"`` is deprecated. Use an empty string (``script=``
+or ``downscript=``) to disable script execution instead. In a future
+version, ``"no"`` will be treated as a plain file name.
+
QEMU Machine Protocol (QMP) commands
------------------------------------
@@ -164,6 +173,15 @@ Use ``job-finalize`` instead.
Use ``query-accelerators`` instead.
+``"no"`` as value of ``script``/``downscript`` for tap in ``netdev_add`` (since 11.2)
+'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
+
+The special value ``"no"`` for the ``script`` and ``downscript``
+parameters of ``netdev_add`` with ``type=tap`` disables script
+execution. This special treatment of ``"no"`` is deprecated. Use an
+empty string instead. In a future version, ``"no"`` will be treated as
+a plain file name.
+
Human Machine Protocol (HMP) commands
-------------------------------------
diff --git a/docs/system/i386/microvm.rst b/docs/system/i386/microvm.rst
index 1675e37d3e..077ea15751 100644
--- a/docs/system/i386/microvm.rst
+++ b/docs/system/i386/microvm.rst
@@ -79,7 +79,7 @@ legacy ``ISA serial`` device as console::
-serial stdio \
-drive id=test,file=test.img,format=raw,if=none \
-device virtio-blk-device,drive=test \
- -netdev tap,id=tap0,script=no,downscript=no \
+ -netdev tap,id=tap0,script=,downscript= \
-device virtio-net-device,netdev=tap0
While the example above works, you might be interested in reducing the
@@ -103,7 +103,7 @@ disabled::
-device virtconsole,chardev=virtiocon0 \
-drive id=test,file=test.img,format=raw,if=none \
-device virtio-blk-device,drive=test \
- -netdev tap,id=tap0,script=no,downscript=no \
+ -netdev tap,id=tap0,script=,downscript= \
-device virtio-net-device,netdev=tap0
diff --git a/docs/system/i386/xenpvh.rst b/docs/system/i386/xenpvh.rst
index 904778e3f5..862f38830b 100644
--- a/docs/system/i386/xenpvh.rst
+++ b/docs/system/i386/xenpvh.rst
@@ -42,7 +42,7 @@ case you need to construct one manually:
-vnc none \
-display none \
-device virtio-net-pci,id=nic0,netdev=net0,mac=00:16:3e:5c:81:78 \
- -netdev type=tap,id=net0,ifname=vif3.0-emu,br=xenbr0,script=no,downscript=no \
+ -netdev type=tap,id=net0,ifname=vif3.0-emu,br=xenbr0,script=,downscript= \
-smp 4,maxcpus=4 \
-nographic \
-machine xenpvh,ram-low-base=0,ram-low-size=2147483648,ram-high-base=4294967296,ram-high-size=2147483648,pci-ecam-base=824633720832,pci-ecam-size=268435456,pci-mmio-base=4026531840,pci-mmio-size=33554432,pci-mmio-high-base=824902156288,pci-mmio-high-size=68719476736 \
diff --git a/docs/system/ppc/ppce500.rst b/docs/system/ppc/ppce500.rst
index c9fe0915dc..ec5aaf14fd 100644
--- a/docs/system/ppc/ppce500.rst
+++ b/docs/system/ppc/ppce500.rst
@@ -158,14 +158,14 @@ interface at PCI address 0.1.0, but we can switch that to an e1000 NIC by:
$ qemu-system-ppc64 -M ppce500 -smp 4 -m 2G \
-display none -serial stdio \
-bios u-boot \
- -nic tap,ifname=tap0,script=no,downscript=no,model=e1000
+ -nic tap,ifname=tap0,script=,downscript=,model=e1000
The QEMU ``ppce500`` machine can also dynamically instantiate an eTSEC device
if “-device eTSEC” is given to QEMU:
.. code-block:: bash
- -netdev tap,ifname=tap0,script=no,downscript=no,id=net0 -device eTSEC,netdev=net0
+ -netdev tap,ifname=tap0,script=,downscript=,id=net0 -device eTSEC,netdev=net0
Root file system on flash drive
-------------------------------
diff --git a/docs/system/riscv/microchip-icicle-kit.rst b/docs/system/riscv/microchip-icicle-kit.rst
index 9809e94b84..7fdb96601a 100644
--- a/docs/system/riscv/microchip-icicle-kit.rst
+++ b/docs/system/riscv/microchip-icicle-kit.rst
@@ -84,7 +84,7 @@ Then we can boot the machine by:
$ qemu-system-riscv64 -M microchip-icicle-kit -smp 5 -m 2G \
-sd path/to/sdcard.img \
-nic user,model=cadence_gem \
- -nic tap,ifname=tap,model=cadence_gem,script=no \
+ -nic tap,ifname=tap,model=cadence_gem,script= \
-display none -serial stdio \
-kernel path/to/u-boot/build/dir/u-boot.bin \
-dtb path/to/u-boot/build/dir/u-boot.dtb
diff --git a/docs/system/riscv/sifive_u.rst b/docs/system/riscv/sifive_u.rst
index 8f55ae8e31..0e4dcf3e70 100644
--- a/docs/system/riscv/sifive_u.rst
+++ b/docs/system/riscv/sifive_u.rst
@@ -199,7 +199,7 @@ To boot the VxWorks kernel in QEMU with the ``sifive_u`` machine, use:
$ qemu-system-riscv64 -M sifive_u -smp 5 -m 2G \
-display none -serial stdio \
- -nic tap,ifname=tap0,script=no,downscript=no \
+ -nic tap,ifname=tap0,script=,downscript= \
-kernel /path/to/vxWorks \
-append "gem(0,0)host:vxWorks h=192.168.200.1 e=192.168.200.2:ffffff00 u=target pw=vxTarget f=0x01"
diff --git a/qapi/net.json b/qapi/net.json
index ab8ed9c086..dccf95bbbc 100644
--- a/qapi/net.json
+++ b/qapi/net.json
@@ -399,15 +399,21 @@
# @fds: multiple file descriptors of already opened multiqueue capable
# tap
#
-# @script: script to initialize the interface. An empty string or
-# "no" disables script execution. Defaults to
+# @script: script to initialize the interface. An empty string
+# disables script execution. Defaults to
# ``<sysconfdir>/qemu-ifup``, where ``<sysconfdir>`` is the
# system configuration directory at build time (typically /etc).
+# Using "no" to disable script execution is deprecated (since
+# 11.2); use an empty string instead. In a future version, "no"
+# will be treated as a plain file name.
#
-# @downscript: script to shut down the interface. An empty string or
-# "no" disables script execution. Defaults to
+# @downscript: script to shut down the interface. An empty string
+# disables script execution. Defaults to
# ``<sysconfdir>/qemu-ifdown``, where ``<sysconfdir>`` is the
# system configuration directory at build time (typically /etc).
+# Using "no" to disable script execution is deprecated (since
+# 11.2); use an empty string instead. In a future version, "no"
+# will be treated as a plain file name.
#
# @br: bridge name (since 2.8)
#
diff --git a/net/tap.c b/net/tap.c
index 2076f5b780..f4051e8d4b 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -92,7 +92,8 @@ static void launch_script(const char *setup_script, const char *ifname,
static void tap_send(void *opaque);
static void tap_writable(void *opaque);
-static bool tap_is_explicit_no_script(const char *script_arg_value)
+static bool tap_is_explicit_no_script(const char *script_arg_name,
+ const char *script_arg_value)
{
if (!script_arg_value) {
return false;
@@ -103,16 +104,19 @@ static bool tap_is_explicit_no_script(const char *script_arg_value)
}
if (strcmp(script_arg_value, "no") == 0) {
+ warn_report("'%s=no' is deprecated; use '%s=' instead",
+ script_arg_name, script_arg_name);
return true;
}
return false;
}
-static char *tap_parse_script(const char *script_arg_value,
+static char *tap_parse_script(const char *script_arg_name,
+ const char *script_arg_value,
const char *default_path)
{
- if (tap_is_explicit_no_script(script_arg_value)) {
+ if (tap_is_explicit_no_script(script_arg_name, script_arg_value)) {
return NULL;
}
@@ -741,7 +745,7 @@ static bool net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
qemu_set_info_str(&s->nc, "helper=%s", tap->helper);
} else {
qemu_set_info_str(&s->nc, "ifname=%s,script=%s,downscript=%s", ifname,
- script ?: "no", downscript ?: "no");
+ script ?: "", downscript ?: "");
if (downscript) {
snprintf(s->down_script, sizeof(s->down_script), "%s", downscript);
@@ -947,9 +951,10 @@ int net_init_tap(const Netdev *netdev, const char *name,
}
} else {
g_autofree char *script =
- tap_parse_script(tap->script, DEFAULT_NETWORK_SCRIPT);
+ tap_parse_script("script", tap->script, DEFAULT_NETWORK_SCRIPT);
g_autofree char *downscript =
- tap_parse_script(tap->downscript, DEFAULT_NETWORK_DOWN_SCRIPT);
+ tap_parse_script("downscript", tap->downscript,
+ DEFAULT_NETWORK_DOWN_SCRIPT);
if (tap->ifname) {
pstrcpy(ifname, sizeof ifname, tap->ifname);
diff --git a/qemu-options.hx b/qemu-options.hx
index 16ef7d5455..2f6863180b 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3022,7 +3022,8 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
" use network scripts 'file' (default=" DEFAULT_NETWORK_SCRIPT ")\n"
" to configure it and 'dfile' (default=" DEFAULT_NETWORK_DOWN_SCRIPT ")\n"
" to deconfigure it\n"
- " use '[down]script=no' or '[down]script=' to disable script execution\n"
+ " use '[down]script=' to disable script execution\n"
+ " ('[down]script=no' is deprecated and will be treated as a file name in future)\n"
" use network helper 'helper' (default=" DEFAULT_BRIDGE_HELPER ") to\n"
" configure it\n"
" use 'fd=h' to connect to an already opened TAP interface\n"
@@ -3561,7 +3562,10 @@ SRST
``<sysconfdir>/qemu-ifup`` and the default network deconfigure script is
``<sysconfdir>/qemu-ifdown``, where ``<sysconfdir>`` is the system
configuration directory at build time (typically ``/etc``).
- Use ``[down]script=no`` or ``[down]script=`` to disable script execution.
+ Use ``[down]script=`` to disable script execution.
+ Using ``[down]script=no`` is deprecated; it disables script
+ execution now, but in a future version it will be treated as a
+ plain file name.
If running QEMU as an unprivileged user, use the network helper
to configure the TAP interface and attach it to the bridge.
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 12/75] net/tap: move vhost-net open() calls to tap_parse_vhost_fds()
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (10 preceding siblings ...)
2026-09-11 9:01 ` [PULL v2 11/75] net/tap: deprecate "no" as special value for script/downscript Michael S. Tsirkin
@ 2026-09-11 9:01 ` Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 13/75] net/tap: move vhost initialization to tap_setup_vhost() Michael S. Tsirkin
` (64 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:01 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Ben Chaney,
Jason Wang
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
1. Simplify code path: get vhostfds for all cases in one function.
2. Prepare for further tap-fd-migraton feature, when we'll need to
postpone vhost initialization up to post-load stage.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Ben Chaney <bchaney@akamai.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Based-on: <20260318113144.15697-1-vsementsov@yandex-team.ru>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260819180201.1970193-5-vsementsov@yandex-team.ru>
---
net/tap.c | 39 ++++++++++++++++++++++-----------------
1 file changed, 22 insertions(+), 17 deletions(-)
diff --git a/net/tap.c b/net/tap.c
index f4051e8d4b..bec2cd48fd 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -756,8 +756,7 @@ static bool net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
}
}
- if (tap->has_vhost ? tap->vhost :
- (vhostfd != -1) || (tap->has_vhostforce && tap->vhostforce)) {
+ if (vhostfd != -1) {
VhostNetOptions options;
options.backend_type = VHOST_BACKEND_TYPE_KERNEL;
@@ -767,17 +766,6 @@ static bool net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
} else {
options.busyloop_timeout = 0;
}
-
- if (vhostfd == -1) {
- vhostfd = open("/dev/vhost-net", O_RDWR);
- if (vhostfd < 0) {
- error_setg_file_open(errp, errno, "/dev/vhost-net");
- goto failed;
- }
- if (!qemu_set_blocking(vhostfd, false, errp)) {
- goto failed;
- }
- }
options.opaque = (void *)(uintptr_t)vhostfd;
options.nvqs = 2;
options.feature_bits = kernel_feature_bits;
@@ -863,14 +851,31 @@ static int tap_parse_fds_and_queues(const NetdevTapOptions *tap, int **fds,
static bool tap_parse_vhost_fds(const NetdevTapOptions *tap, int **vhost_fds,
int queues, Error **errp)
{
- if (!(tap->vhostfd || tap->vhostfds)) {
+ bool need_vhost = tap->has_vhost ? tap->vhost :
+ ((tap->vhostfd || tap->vhostfds) ||
+ (tap->has_vhostforce && tap->vhostforce));
+
+ if (!need_vhost) {
*vhost_fds = NULL;
return true;
}
- if (net_parse_fds(tap->vhostfd ?: tap->vhostfds,
- vhost_fds, queues, errp) < 0) {
- return false;
+ if (tap->vhostfd || tap->vhostfds) {
+ if (net_parse_fds(tap->vhostfd ?: tap->vhostfds,
+ vhost_fds, queues, errp) < 0) {
+ return false;
+ }
+ } else {
+ *vhost_fds = g_new(int, queues);
+ for (int i = 0; i < queues; i++) {
+ int vhostfd = open("/dev/vhost-net", O_RDWR);
+ if (vhostfd < 0) {
+ error_setg_file_open(errp, errno, "/dev/vhost-net");
+ net_free_fds(*vhost_fds, i);
+ return false;
+ }
+ (*vhost_fds)[i] = vhostfd;
+ }
}
if (!unblock_fds(*vhost_fds, queues, errp)) {
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 13/75] net/tap: move vhost initialization to tap_setup_vhost()
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (11 preceding siblings ...)
2026-09-11 9:01 ` [PULL v2 12/75] net/tap: move vhost-net open() calls to tap_parse_vhost_fds() Michael S. Tsirkin
@ 2026-09-11 9:01 ` Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 14/75] net/tap: use container_of instead of DO_UPCAST Michael S. Tsirkin
` (63 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:01 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Ben Chaney,
Jason Wang
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Make a new helper function in a way it can be reused later for
TAP fd-migration feature: we'll need to initialize vhost in a later
point when we doesn't have access to QAPI parameters.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Ben Chaney <bchaney@akamai.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Based-on: <20260318113144.15697-1-vsementsov@yandex-team.ru>
Based-on: <20260218202829.1322088-1-vsementsov@yandex-team.ru>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260819180201.1970193-6-vsementsov@yandex-team.ru>
---
net/tap.c | 62 ++++++++++++++++++++++++++++++++++---------------------
1 file changed, 38 insertions(+), 24 deletions(-)
diff --git a/net/tap.c b/net/tap.c
index bec2cd48fd..f2b571dd11 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -71,6 +71,8 @@ static const int kernel_feature_bits[] = {
typedef struct TAPState {
NetClientState nc;
int fd;
+ int vhostfd;
+ uint32_t vhost_busyloop_timeout;
char down_script[1024];
char down_script_arg[128];
uint8_t buf[NET_BUFSIZE];
@@ -722,6 +724,38 @@ static int net_tap_init(const NetdevTapOptions *tap, int *vnet_hdr,
return fd;
}
+static bool tap_setup_vhost(TAPState *s, Error **errp)
+{
+ VhostNetOptions options;
+
+ if (s->vhostfd == -1) {
+ return true;
+ }
+
+ options.backend_type = VHOST_BACKEND_TYPE_KERNEL;
+ options.net_backend = &s->nc;
+ options.busyloop_timeout = s->vhost_busyloop_timeout;
+ options.opaque = (void *)(uintptr_t)s->vhostfd;
+ options.nvqs = 2;
+ options.feature_bits = kernel_feature_bits;
+ options.get_acked_features = NULL;
+ options.save_acked_features = NULL;
+ options.max_tx_queue_size = 0;
+ options.is_vhost_user = false;
+
+ s->vhost_net = vhost_net_init(&options);
+ if (!s->vhost_net) {
+ error_setg(errp,
+ "vhost-net requested but could not be initialized");
+ return false;
+ }
+
+ /* vhostfd ownership is passed to s->vhost_net */
+ s->vhostfd = -1;
+
+ return true;
+}
+
static bool net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
const char *name,
const char *ifname, const char *script,
@@ -756,30 +790,10 @@ static bool net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
}
}
- if (vhostfd != -1) {
- VhostNetOptions options;
-
- options.backend_type = VHOST_BACKEND_TYPE_KERNEL;
- options.net_backend = &s->nc;
- if (tap->has_poll_us) {
- options.busyloop_timeout = tap->poll_us;
- } else {
- options.busyloop_timeout = 0;
- }
- options.opaque = (void *)(uintptr_t)vhostfd;
- options.nvqs = 2;
- options.feature_bits = kernel_feature_bits;
- options.get_acked_features = NULL;
- options.save_acked_features = NULL;
- options.max_tx_queue_size = 0;
- options.is_vhost_user = false;
-
- s->vhost_net = vhost_net_init(&options);
- if (!s->vhost_net) {
- error_setg(errp,
- "vhost-net requested but could not be initialized");
- goto failed;
- }
+ s->vhostfd = vhostfd;
+ s->vhost_busyloop_timeout = tap->has_poll_us ? tap->poll_us : 0;
+ if (!tap_setup_vhost(s, errp)) {
+ return false;
}
return true;
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 14/75] net/tap: use container_of instead of DO_UPCAST
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (12 preceding siblings ...)
2026-09-11 9:01 ` [PULL v2 13/75] net/tap: move vhost initialization to tap_setup_vhost() Michael S. Tsirkin
@ 2026-09-11 9:01 ` Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 15/75] net/tap: QOMify tap backend Michael S. Tsirkin
` (62 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:01 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Ben Chaney,
Jason Wang
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
We are going to QOMify tap backend, which includes deriving TAPState
from Object. So "NetClientState nc" will not be a first member.
Let's parepare for this change, and use container_of(), which will
work regardless position of "nc" field.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Ben Chaney <bchaney@akamai.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260819180201.1970193-7-vsementsov@yandex-team.ru>
---
net/tap.c | 36 ++++++++++++++++++------------------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/net/tap.c b/net/tap.c
index f2b571dd11..bfed74717e 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -175,7 +175,7 @@ static ssize_t tap_write_packet(TAPState *s, const struct iovec *iov, int iovcnt
static ssize_t tap_receive_iov(NetClientState *nc, const struct iovec *iov,
int iovcnt)
{
- TAPState *s = DO_UPCAST(TAPState, nc, nc);
+ TAPState *s = container_of(nc, TAPState, nc);
const struct iovec *iovp = iov;
g_autofree struct iovec *iov_copy = NULL;
struct virtio_net_hdr hdr = { };
@@ -211,7 +211,7 @@ ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen)
static void tap_send_completed(NetClientState *nc, ssize_t len)
{
- TAPState *s = DO_UPCAST(TAPState, nc, nc);
+ TAPState *s = container_of(nc, TAPState, nc);
tap_read_poll(s, true);
}
@@ -271,7 +271,7 @@ static void tap_send(void *opaque)
static bool tap_has_ufo(NetClientState *nc)
{
- TAPState *s = DO_UPCAST(TAPState, nc, nc);
+ TAPState *s = container_of(nc, TAPState, nc);
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
@@ -280,7 +280,7 @@ static bool tap_has_ufo(NetClientState *nc)
static bool tap_has_uso(NetClientState *nc)
{
- TAPState *s = DO_UPCAST(TAPState, nc, nc);
+ TAPState *s = container_of(nc, TAPState, nc);
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
@@ -289,7 +289,7 @@ static bool tap_has_uso(NetClientState *nc)
static bool tap_has_tunnel(NetClientState *nc)
{
- TAPState *s = DO_UPCAST(TAPState, nc, nc);
+ TAPState *s = container_of(nc, TAPState, nc);
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
return s->has_tunnel;
@@ -297,7 +297,7 @@ static bool tap_has_tunnel(NetClientState *nc)
static bool tap_has_vnet_hdr(NetClientState *nc)
{
- TAPState *s = DO_UPCAST(TAPState, nc, nc);
+ TAPState *s = container_of(nc, TAPState, nc);
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
@@ -311,7 +311,7 @@ static bool tap_has_vnet_hdr_len(NetClientState *nc, int len)
static void tap_set_vnet_hdr_len(NetClientState *nc, int len)
{
- TAPState *s = DO_UPCAST(TAPState, nc, nc);
+ TAPState *s = container_of(nc, TAPState, nc);
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
@@ -322,21 +322,21 @@ static void tap_set_vnet_hdr_len(NetClientState *nc, int len)
static int tap_set_vnet_le(NetClientState *nc, bool is_le)
{
- TAPState *s = DO_UPCAST(TAPState, nc, nc);
+ TAPState *s = container_of(nc, TAPState, nc);
return tap_fd_set_vnet_le(s->fd, is_le);
}
static int tap_set_vnet_be(NetClientState *nc, bool is_be)
{
- TAPState *s = DO_UPCAST(TAPState, nc, nc);
+ TAPState *s = container_of(nc, TAPState, nc);
return tap_fd_set_vnet_be(s->fd, is_be);
}
static void tap_set_offload(NetClientState *nc, const NetOffloads *ol)
{
- TAPState *s = DO_UPCAST(TAPState, nc, nc);
+ TAPState *s = container_of(nc, TAPState, nc);
if (s->fd < 0) {
return;
}
@@ -357,7 +357,7 @@ static void tap_exit_notify(Notifier *notifier, void *data)
static void tap_cleanup(NetClientState *nc)
{
- TAPState *s = DO_UPCAST(TAPState, nc, nc);
+ TAPState *s = container_of(nc, TAPState, nc);
if (s->vhost_net) {
vhost_net_cleanup(s->vhost_net);
@@ -381,14 +381,14 @@ static void tap_cleanup(NetClientState *nc)
static void tap_poll(NetClientState *nc, bool enable)
{
- TAPState *s = DO_UPCAST(TAPState, nc, nc);
+ TAPState *s = container_of(nc, TAPState, nc);
tap_read_poll(s, enable);
tap_write_poll(s, enable);
}
static bool tap_set_steering_ebpf(NetClientState *nc, int prog_fd)
{
- TAPState *s = DO_UPCAST(TAPState, nc, nc);
+ TAPState *s = container_of(nc, TAPState, nc);
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
return tap_fd_set_steering_ebpf(s->fd, prog_fd) == 0;
@@ -396,7 +396,7 @@ static bool tap_set_steering_ebpf(NetClientState *nc, int prog_fd)
int tap_get_fd(NetClientState *nc)
{
- TAPState *s = DO_UPCAST(TAPState, nc, nc);
+ TAPState *s = container_of(nc, TAPState, nc);
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
return s->fd;
}
@@ -408,7 +408,7 @@ int tap_get_fd(NetClientState *nc)
*/
static VHostNetState *tap_get_vhost_net(NetClientState *nc)
{
- TAPState *s = DO_UPCAST(TAPState, nc, nc);
+ TAPState *s = container_of(nc, TAPState, nc);
assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
return s->vhost_net;
}
@@ -447,7 +447,7 @@ static TAPState *net_tap_fd_init(NetClientState *peer,
nc = qemu_new_net_client(&net_tap_info, peer, model, name);
- s = DO_UPCAST(TAPState, nc, nc);
+ s = container_of(nc, TAPState, nc);
s->fd = fd;
s->host_vnet_hdr_len = vnet_hdr ? sizeof(struct virtio_net_hdr) : 0;
@@ -1016,7 +1016,7 @@ fail:
int tap_enable(NetClientState *nc)
{
- TAPState *s = DO_UPCAST(TAPState, nc, nc);
+ TAPState *s = container_of(nc, TAPState, nc);
int ret;
if (s->enabled) {
@@ -1033,7 +1033,7 @@ int tap_enable(NetClientState *nc)
int tap_disable(NetClientState *nc)
{
- TAPState *s = DO_UPCAST(TAPState, nc, nc);
+ TAPState *s = container_of(nc, TAPState, nc);
int ret;
if (s->enabled == 0) {
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 15/75] net/tap: QOMify tap backend
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (13 preceding siblings ...)
2026-09-11 9:01 ` [PULL v2 14/75] net/tap: use container_of instead of DO_UPCAST Michael S. Tsirkin
@ 2026-09-11 9:01 ` Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 16/75] net/tap: add TYPE_VMSTATE_IF interface Michael S. Tsirkin
` (61 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:01 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Ben Chaney,
Jason Wang
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
We prepare for being able to migrate TAP backend. We'll need a
user change-able property for it, which can be set from machine
type. So, let's QOMify it first.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Ben Chaney <bchaney@akamai.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260819180201.1970193-8-vsementsov@yandex-team.ru>
---
include/net/net.h | 7 +++++++
include/net/tap.h | 2 ++
net/net.c | 14 +++++++-------
net/tap.c | 48 +++++++++++++++++++++++++++++++++++++++--------
4 files changed, 56 insertions(+), 15 deletions(-)
diff --git a/include/net/net.h b/include/net/net.h
index 626b997948..ea07760b56 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -161,6 +161,13 @@ char *qemu_mac_strdup_printf(const uint8_t *macaddr);
NetClientState *qemu_find_netdev(const char *id);
int qemu_find_net_clients_except(const char *id, NetClientState **ncs,
NetClientDriver type, int max);
+void qemu_net_client_setup(NetClientState *nc,
+ NetClientInfo *info,
+ NetClientState *peer,
+ const char *model,
+ const char *name,
+ NetClientDestructor *destructor,
+ bool is_datapath);
NetClientState *qemu_new_net_client(NetClientInfo *info,
NetClientState *peer,
const char *model,
diff --git a/include/net/tap.h b/include/net/tap.h
index 6f34f13eae..268570571f 100644
--- a/include/net/tap.h
+++ b/include/net/tap.h
@@ -28,6 +28,8 @@
#include "standard-headers/linux/virtio_net.h"
+#define TYPE_TAP_NETDEV "tap-netdev"
+
int tap_enable(NetClientState *nc);
int tap_disable(NetClientState *nc);
diff --git a/net/net.c b/net/net.c
index 1161183e18..d7fa637ce5 100644
--- a/net/net.c
+++ b/net/net.c
@@ -261,13 +261,13 @@ static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
int iovcnt,
void *opaque);
-static void qemu_net_client_setup(NetClientState *nc,
- NetClientInfo *info,
- NetClientState *peer,
- const char *model,
- const char *name,
- NetClientDestructor *destructor,
- bool is_datapath)
+void qemu_net_client_setup(NetClientState *nc,
+ NetClientInfo *info,
+ NetClientState *peer,
+ const char *model,
+ const char *name,
+ NetClientDestructor *destructor,
+ bool is_datapath)
{
nc->info = info;
nc->model = g_strdup(model);
diff --git a/net/tap.c b/net/tap.c
index bfed74717e..7392344200 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -43,6 +43,7 @@
#include "qemu/main-loop.h"
#include "qemu/sockets.h"
#include "hw/virtio/vhost.h"
+#include "qom/object.h"
#include "net/tap.h"
#include "net/util.h"
@@ -68,7 +69,11 @@ static const int kernel_feature_bits[] = {
VHOST_INVALID_FEATURE_BIT
};
-typedef struct TAPState {
+OBJECT_DECLARE_SIMPLE_TYPE(TAPState, TAP_NETDEV)
+
+struct TAPState {
+ Object parent_obj;
+
NetClientState nc;
int fd;
int vhostfd;
@@ -86,7 +91,7 @@ typedef struct TAPState {
VHostNetState *vhost_net;
unsigned host_vnet_hdr_len;
Notifier exit;
-} TAPState;
+};
static void launch_script(const char *setup_script, const char *ifname,
int fd, Error **errp);
@@ -413,6 +418,19 @@ static VHostNetState *tap_get_vhost_net(NetClientState *nc)
return s->vhost_net;
}
+
+static const TypeInfo tap_netdev_info = {
+ .name = TYPE_TAP_NETDEV,
+ .parent = TYPE_OBJECT,
+ .instance_size = sizeof(TAPState),
+};
+
+static void tap_net_client_destructor(NetClientState *nc)
+{
+ TAPState *s = container_of(nc, TAPState, nc);
+ object_unref(OBJECT(s));
+}
+
/* fd support */
static NetClientInfo net_tap_info = {
@@ -435,6 +453,18 @@ static NetClientInfo net_tap_info = {
.get_vhost_net = tap_get_vhost_net,
};
+static TAPState *new_tap(NetClientState *peer,
+ const char *model,
+ const char *name)
+{
+ TAPState *s = TAP_NETDEV(object_new(TYPE_TAP_NETDEV));
+
+ qemu_net_client_setup(&s->nc, &net_tap_info, peer, model, name,
+ tap_net_client_destructor, true);
+
+ return s;
+}
+
static TAPState *net_tap_fd_init(NetClientState *peer,
const char *model,
const char *name,
@@ -442,12 +472,7 @@ static TAPState *net_tap_fd_init(NetClientState *peer,
int vnet_hdr)
{
NetOffloads ol = {};
- NetClientState *nc;
- TAPState *s;
-
- nc = qemu_new_net_client(&net_tap_info, peer, model, name);
-
- s = container_of(nc, TAPState, nc);
+ TAPState *s = new_tap(peer, model, name);
s->fd = fd;
s->host_vnet_hdr_len = vnet_hdr ? sizeof(struct virtio_net_hdr) : 0;
@@ -1048,3 +1073,10 @@ int tap_disable(NetClientState *nc)
return ret;
}
}
+
+static void tap_register_types(void)
+{
+ type_register_static(&tap_netdev_info);
+}
+
+type_init(tap_register_types)
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 16/75] net/tap: add TYPE_VMSTATE_IF interface
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (14 preceding siblings ...)
2026-09-11 9:01 ` [PULL v2 15/75] net/tap: QOMify tap backend Michael S. Tsirkin
@ 2026-09-11 9:01 ` Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 17/75] qapi: add local migration parameter Michael S. Tsirkin
` (60 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:01 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Ben Chaney,
Jason Wang
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
We'll need it to implement TAP backend live migration.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Ben Chaney <bchaney@akamai.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260819180201.1970193-9-vsementsov@yandex-team.ru>
---
net/tap.c | 43 ++++++++++++++++++++++++++++++++++---------
1 file changed, 34 insertions(+), 9 deletions(-)
diff --git a/net/tap.c b/net/tap.c
index 7392344200..dd0d134875 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -43,7 +43,6 @@
#include "qemu/main-loop.h"
#include "qemu/sockets.h"
#include "hw/virtio/vhost.h"
-#include "qom/object.h"
#include "net/tap.h"
#include "net/util.h"
@@ -91,6 +90,8 @@ struct TAPState {
VHostNetState *vhost_net;
unsigned host_vnet_hdr_len;
Notifier exit;
+
+ int queue_index;
};
static void launch_script(const char *setup_script, const char *ifname,
@@ -419,10 +420,29 @@ static VHostNetState *tap_get_vhost_net(NetClientState *nc)
}
+static char *tap_vmstate_if_get_id(VMStateIf *obj)
+{
+ TAPState *s = TAP_NETDEV(obj);
+ char *res = g_strdup_printf("%s/%d", s->nc.name, s->queue_index);
+ return res;
+}
+
+static void tap_class_init(ObjectClass *klass, const void *data)
+{
+ VMStateIfClass *vc = VMSTATE_IF_CLASS(klass);
+
+ vc->get_id = tap_vmstate_if_get_id;
+}
+
static const TypeInfo tap_netdev_info = {
.name = TYPE_TAP_NETDEV,
.parent = TYPE_OBJECT,
.instance_size = sizeof(TAPState),
+ .class_init = tap_class_init,
+ .interfaces = (const InterfaceInfo[]) {
+ { TYPE_VMSTATE_IF },
+ { }
+ },
};
static void tap_net_client_destructor(NetClientState *nc)
@@ -455,13 +475,16 @@ static NetClientInfo net_tap_info = {
static TAPState *new_tap(NetClientState *peer,
const char *model,
- const char *name)
+ const char *name,
+ int queue_index)
{
TAPState *s = TAP_NETDEV(object_new(TYPE_TAP_NETDEV));
qemu_net_client_setup(&s->nc, &net_tap_info, peer, model, name,
tap_net_client_destructor, true);
+ s->queue_index = queue_index;
+
return s;
}
@@ -469,10 +492,11 @@ static TAPState *net_tap_fd_init(NetClientState *peer,
const char *model,
const char *name,
int fd,
- int vnet_hdr)
+ int vnet_hdr,
+ int queue_index)
{
NetOffloads ol = {};
- TAPState *s = new_tap(peer, model, name);
+ TAPState *s = new_tap(peer, model, name, queue_index);
s->fd = fd;
s->host_vnet_hdr_len = vnet_hdr ? sizeof(struct virtio_net_hdr) : 0;
@@ -709,7 +733,7 @@ int net_init_bridge(const Netdev *netdev, const char *name,
close(fd);
return -1;
}
- s = net_tap_fd_init(peer, "bridge", name, fd, vnet_hdr);
+ s = net_tap_fd_init(peer, "bridge", name, fd, vnet_hdr, 0);
qemu_set_info_str(&s->nc, "helper=%s,br=%s", helper, br);
@@ -785,10 +809,11 @@ static bool net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
const char *name,
const char *ifname, const char *script,
const char *downscript, int vhostfd,
- int vnet_hdr, int fd, Error **errp)
+ int vnet_hdr, int fd, int queue_index,
+ Error **errp)
{
TAPState *s = net_tap_fd_init(peer, tap->helper ? "bridge" : "tap",
- name, fd, vnet_hdr);
+ name, fd, vnet_hdr, queue_index);
bool sndbuf_required = tap->has_sndbuf;
int sndbuf =
(tap->has_sndbuf && tap->sndbuf) ? MIN(tap->sndbuf, INT_MAX) : INT_MAX;
@@ -989,7 +1014,7 @@ int net_init_tap(const Netdev *netdev, const char *name,
if (!net_init_tap_one(tap, peer, name, ifname,
NULL, NULL,
vhost_fds ? vhost_fds[i] : -1,
- vnet_hdr, fds[i], errp)) {
+ vnet_hdr, fds[i], i, errp)) {
goto fail;
}
}
@@ -1024,7 +1049,7 @@ int net_init_tap(const Netdev *netdev, const char *name,
i >= 1 ? NULL : script,
i >= 1 ? NULL : downscript,
vhost_fds ? vhost_fds[i] : -1,
- vnet_hdr, fd, errp)) {
+ vnet_hdr, fd, i, errp)) {
goto fail;
}
}
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 17/75] qapi: add local migration parameter
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (15 preceding siblings ...)
2026-09-11 9:01 ` [PULL v2 16/75] net/tap: add TYPE_VMSTATE_IF interface Michael S. Tsirkin
@ 2026-09-11 9:01 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 18/75] migration/fd: fix fd leak when fd is not valid for migration Michael S. Tsirkin
` (59 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:01 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Markus Armbruster,
Peter Xu, Fabiano Rosas, Eric Blake
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
We are going to implement local-migration feature: some devices will be
able to transfer open file descriptors through migration stream (which
must UNIX domain socket for that purpose). This allows to transfer the
whole backend state without reconnecting and restarting the backend
service. For example, virtio-net will migrate its attached TAP netdev,
together with its connected file descriptors.
In this commit we introduce a migration parameter, which enables
the feature for devices that support it (none at the moment).
We can't simply auto-detect local migration by checking whether the
migration channel is a UNIX domain socket: the UNIX socket may be only
the first part of the transfer channel to a remote target. Hence an
explicit parameter is needed. Moreover, "local" migration parameter
may be useful in cpr-exec mode, when FDs are passed through exec
instead of UNIX socket.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Acked-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260819180201.1970193-10-vsementsov@yandex-team.ru>
---
qapi/migration.json | 21 +++++++++++++++++----
include/migration/misc.h | 2 ++
migration/options.c | 18 +++++++++++++++++-
3 files changed, 36 insertions(+), 5 deletions(-)
diff --git a/qapi/migration.json b/qapi/migration.json
index b1eaf7b054..f7628b55e9 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -830,7 +830,8 @@
'zero-page-detection',
'direct-io',
{ 'name': 'x-rdma-chunk-size', 'features': [ 'unstable' ] },
- 'cpr-exec-command'] }
+ 'cpr-exec-command',
+ 'local'] }
##
# @migrate-set-parameters:
@@ -1012,10 +1013,20 @@
# Must be set to the same value on both source and destination
# before migration starts. (Since 11.1)
#
+# @local: Permit the use of optimizations for local migration. This
+# must only be set when either both the source and destination
+# QEMU processes are directly connected with a UNIX domain socket
+# as the migration channel (to enable use of file descriptor
+# passing) or cpr-exec migration mode is enabled (this way file
+# descriptors are inherited by new process). Individual device
+# backends may need additional configuration flags set to enable
+# local migration optimizations. This will be documented against
+# the device backends where it applies. (Since 11.2)
+#
# Features:
#
-# @unstable: Members @x-checkpoint-delay, @x-rdma-chunk-size, and
-# @x-vcpu-dirty-limit-period are experimental.
+# @unstable: Members @local, @x-checkpoint-delay, @x-rdma-chunk-size,
+# and @x-vcpu-dirty-limit-period are experimental.
#
# Since: 2.4
##
@@ -1053,7 +1064,9 @@
'*direct-io': 'bool',
'*x-rdma-chunk-size': { 'type': 'uint64',
'features': [ 'unstable' ] },
- '*cpr-exec-command': [ 'str' ]} }
+ '*cpr-exec-command': [ 'str' ],
+ '*local': { 'type': 'bool',
+ 'features': [ 'unstable' ] } } }
##
# @query-migrate-parameters:
diff --git a/include/migration/misc.h b/include/migration/misc.h
index 2b2fbb59a4..019717f4cd 100644
--- a/include/migration/misc.h
+++ b/include/migration/misc.h
@@ -161,4 +161,6 @@ bool multifd_join_device_state_save_threads(void);
void migration_request_switchover_ack_legacy(const char *requester);
+bool migrate_local(void);
+
#endif
diff --git a/migration/options.c b/migration/options.c
index d2575edb6c..05b026f4bf 100644
--- a/migration/options.c
+++ b/migration/options.c
@@ -14,6 +14,7 @@
#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include "qemu/units.h"
+#include "qapi/util.h"
#include "exec/target_page.h"
#include "qapi/clone-visitor.h"
#include "qapi/error.h"
@@ -25,6 +26,7 @@
#include "migration/colo.h"
#include "migration/cpr.h"
#include "migration/misc.h"
+#include "migration/options.h"
#include "migration.h"
#include "migration-stats.h"
#include "qemu-file.h"
@@ -350,6 +352,12 @@ bool migrate_mapped_ram(void)
return s->capabilities[MIGRATION_CAPABILITY_MAPPED_RAM];
}
+bool migrate_local(void)
+{
+ MigrationState *s = migrate_get_current();
+ return s->parameters.local;
+}
+
bool migrate_ignore_shared(void)
{
MigrationState *s = migrate_get_current();
@@ -1101,7 +1109,7 @@ static void migrate_mark_all_params_present(MigrationParameters *p)
&p->has_announce_step, &p->has_block_bitmap_mapping,
&p->has_x_vcpu_dirty_limit_period, &p->has_vcpu_dirty_limit,
&p->has_mode, &p->has_zero_page_detection, &p->has_direct_io,
- &p->has_x_rdma_chunk_size, &p->has_cpr_exec_command,
+ &p->has_x_rdma_chunk_size, &p->has_cpr_exec_command, &p->has_local,
};
len = ARRAY_SIZE(has_fields);
@@ -1449,6 +1457,10 @@ static void migrate_params_test_apply(MigrationParameters *params,
qapi_free_strList(dest->cpr_exec_command);
dest->cpr_exec_command = QAPI_CLONE(strList, params->cpr_exec_command);
}
+
+ if (params->has_local) {
+ dest->local = params->local;
+ }
}
static void migrate_params_apply(MigrationParameters *params)
@@ -1581,6 +1593,10 @@ static void migrate_params_apply(MigrationParameters *params)
s->parameters.cpr_exec_command =
QAPI_CLONE(strList, params->cpr_exec_command);
}
+
+ if (params->has_local) {
+ s->parameters.local = params->local;
+ }
}
void qmp_migrate_set_parameters(MigrationParameters *params, Error **errp)
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 18/75] migration/fd: fix fd leak when fd is not valid for migration
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (16 preceding siblings ...)
2026-09-11 9:01 ` [PULL v2 17/75] qapi: add local migration parameter Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 19/75] migration/fd: add errp parameter to migration_fd_valid() Michael S. Tsirkin
` (58 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Peter Xu,
Fabiano Rosas
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Both fd_connect_outgoing() and fd_connect_incoming() own the file
descriptor after resolving it from the monitor, but forget to close
it when migration_fd_valid() check fails.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Peter Xu <peterx@redhat.com>
Fixes: f1fcc1c101 ("migration: Remove fd: support on files")
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260819180201.1970193-11-vsementsov@yandex-team.ru>
---
migration/fd.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/migration/fd.c b/migration/fd.c
index f05f95992f..02b39b150e 100644
--- a/migration/fd.c
+++ b/migration/fd.c
@@ -62,6 +62,7 @@ QIOChannel *fd_connect_outgoing(MigrationState *s, const char *fdname,
if (!migration_fd_valid(fd)) {
error_setg(errp, "fd: migration to a file is not supported."
" Use file: instead.");
+ close(fd);
goto out;
}
@@ -97,6 +98,7 @@ void fd_connect_incoming(const char *fdname, Error **errp)
if (!migration_fd_valid(fd)) {
error_setg(errp, "fd: migration to a file is not supported."
" Use file: instead.");
+ close(fd);
return;
}
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 19/75] migration/fd: add errp parameter to migration_fd_valid()
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (17 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 18/75] migration/fd: fix fd leak when fd is not valid for migration Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 20/75] migration: check that transfer is UNIX socket when "local" set Michael S. Tsirkin
` (57 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Peter Xu,
Fabiano Rosas
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Let migration_fd_valid() report the error itself, instead of
duplicating the error message in both callers. This also prepares
for adding one more check (with a different error message) to the
function.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Peter Xu <peterx@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260819180201.1970193-12-vsementsov@yandex-team.ru>
---
migration/fd.c | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)
diff --git a/migration/fd.c b/migration/fd.c
index 02b39b150e..78a27caca2 100644
--- a/migration/fd.c
+++ b/migration/fd.c
@@ -37,16 +37,14 @@ static bool fd_is_pipe(int fd)
return S_ISFIFO(statbuf.st_mode);
}
-static bool migration_fd_valid(int fd)
+static bool migration_fd_valid(int fd, Error **errp)
{
- if (fd_is_socket(fd)) {
- return true;
- }
-
- if (fd_is_pipe(fd)) {
+ if (fd_is_socket(fd) || fd_is_pipe(fd)) {
return true;
}
+ error_setg(errp, "fd: migration to a file is not supported."
+ " Use file: instead.");
return false;
}
@@ -59,9 +57,7 @@ QIOChannel *fd_connect_outgoing(MigrationState *s, const char *fdname,
goto out;
}
- if (!migration_fd_valid(fd)) {
- error_setg(errp, "fd: migration to a file is not supported."
- " Use file: instead.");
+ if (!migration_fd_valid(fd, errp)) {
close(fd);
goto out;
}
@@ -95,9 +91,7 @@ void fd_connect_incoming(const char *fdname, Error **errp)
return;
}
- if (!migration_fd_valid(fd)) {
- error_setg(errp, "fd: migration to a file is not supported."
- " Use file: instead.");
+ if (!migration_fd_valid(fd, errp)) {
close(fd);
return;
}
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 20/75] migration: check that transfer is UNIX socket when "local" set
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (18 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 19/75] migration/fd: add errp parameter to migration_fd_valid() Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 21/75] virtio-net: support local migration of backend Michael S. Tsirkin
` (56 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Peter Xu,
Fabiano Rosas
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
As documented, for "local", the migration channel must be direct UNIX
socket connection from source to target (except for CPR_EXEC mode). We
can't check for it being "direct", but let's at least check that we deal
with UNIX socket.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Peter Xu <peterx@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260819180201.1970193-13-vsementsov@yandex-team.ru>
---
migration/fd.c | 14 ++++++++++++++
migration/migration.c | 13 +++++++++++++
2 files changed, 27 insertions(+)
diff --git a/migration/fd.c b/migration/fd.c
index 78a27caca2..4a891e814a 100644
--- a/migration/fd.c
+++ b/migration/fd.c
@@ -39,6 +39,20 @@ static bool fd_is_pipe(int fd)
static bool migration_fd_valid(int fd, Error **errp)
{
+ if (migrate_local() && migrate_mode() != MIG_MODE_CPR_EXEC) {
+ struct sockaddr_storage ss;
+ socklen_t sslen = sizeof(ss);
+
+ if (getsockname(fd, (struct sockaddr *)&ss, &sslen) < 0 ||
+ ss.ss_family != AF_UNIX) {
+ error_setg(errp,
+ "local migration requires a UNIX domain socket channel");
+ return false;
+ }
+
+ return true;
+ }
+
if (fd_is_socket(fd) || fd_is_pipe(fd)) {
return true;
}
diff --git a/migration/migration.c b/migration/migration.c
index b413d28622..d8418e4582 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -260,6 +260,19 @@ migration_capabilities_and_transport_compatible(MigrationAddress *addr,
errp);
}
+ if (migrate_local() && migrate_mode() != MIG_MODE_CPR_EXEC &&
+ (addr->transport != MIGRATION_ADDRESS_TYPE_SOCKET ||
+ (addr->u.socket.type != SOCKET_ADDRESS_TYPE_UNIX &&
+ addr->u.socket.type != SOCKET_ADDRESS_TYPE_FD))) {
+ /*
+ * For SOCKET_ADDRESS_TYPE_FD we do check the fd itself later
+ * in migration_fd_valid().
+ */
+ error_setg(errp,
+ "local migration requires a UNIX domain socket channel");
+ return false;
+ }
+
return true;
}
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 21/75] virtio-net: support local migration of backend
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (19 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 20/75] migration: check that transfer is UNIX socket when "local" set Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 22/75] net/tap: disable read polling for stopped VM Michael S. Tsirkin
` (55 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Ben Chaney,
Jason Wang, Peter Xu, Fabiano Rosas
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Next commit will introduce live-migration (with fd-passing) for
TAP net backend. So, now we prepare virtio-net for it
Add virtio-net option local-migration, which is true by default,
but false for older machine types, which doesn't support the feature.
We introduce interface for live-migrating backends:
1. ->is_wait_incoming() handler, so that virtio-net knows, that
backend is not fully intialized, as it waits for incoming migration
stream.
2. MIG_PRI_BACKEND priority: backends should migrate with higher
priority than virtio-net, so that we can do final preparations
here in post-load handlers and be sure, that backends are already
prepared.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Ben Chaney <bchaney@akamai.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260819180201.1970193-14-vsementsov@yandex-team.ru>
---
include/hw/virtio/virtio-net.h | 1 +
include/migration/vmstate.h | 2 +
include/net/net.h | 2 +
hw/net/virtio-net.c | 89 +++++++++++++++++++++++++++++++++-
4 files changed, 93 insertions(+), 1 deletion(-)
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
index 371e376428..8c967760c2 100644
--- a/include/hw/virtio/virtio-net.h
+++ b/include/hw/virtio/virtio-net.h
@@ -230,6 +230,7 @@ struct VirtIONet {
struct EBPFRSSContext ebpf_rss;
uint32_t nr_ebpf_rss_fds;
char **ebpf_rss_fds;
+ bool peers_wait_incoming;
};
size_t virtio_net_handle_ctrl_iov(VirtIODevice *vdev,
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index e72c3fae9a..7d2b786382 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -169,6 +169,8 @@ typedef enum {
MIG_PRI_LOW, /* Must happen after default */
MIG_PRI_DEFAULT,
+ MIG_PRI_BACKEND, /* Must happen before emulated devices, */
+ /* e.g. virtio-net */
MIG_PRI_IOMMU, /* Must happen before PCI devices */
MIG_PRI_PCI_BUS, /* Must happen before IOMMU */
MIG_PRI_VIRTIO_MEM, /* Must happen before IOMMU */
diff --git a/include/net/net.h b/include/net/net.h
index ea07760b56..fdf6a2ddd4 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -82,6 +82,7 @@ typedef void (SocketReadStateFinalize)(SocketReadState *rs);
typedef void (NetAnnounce)(NetClientState *);
typedef bool (SetSteeringEBPF)(NetClientState *, int);
typedef bool (NetCheckPeerType)(NetClientState *, ObjectClass *, Error **);
+typedef bool (IsWaitIncoming)(NetClientState *);
typedef struct vhost_net *(GetVHostNet)(NetClientState *nc);
typedef struct NetClientInfo {
@@ -110,6 +111,7 @@ typedef struct NetClientInfo {
NetAnnounce *announce;
SetSteeringEBPF *set_steering_ebpf;
NetCheckPeerType *check_peer_type;
+ IsWaitIncoming *is_wait_incoming;
GetVHostNet *get_vhost_net;
} NetClientInfo;
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 814b99a43d..274fbcb0d6 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -40,6 +40,7 @@
#include "migration/misc.h"
#include "standard-headers/linux/ethtool.h"
#include "system/system.h"
+#include "system/runstate.h"
#include "system/replay.h"
#include "trace.h"
#include "monitor/qdev.h"
@@ -3079,7 +3080,17 @@ static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue)
n->multiqueue = multiqueue;
virtio_net_change_num_queues(n, max * 2 + 1);
- virtio_net_set_queue_pairs(n);
+ /*
+ * virtio_net_set_multiqueue() called from set_features(0) on early
+ * reset, when peer may wait for incoming (and is not initialized
+ * yet).
+ * Don't worry about it: virtio_net_set_queue_pairs() will be called
+ * later from virtio_net_post_load_device(), and anyway will be
+ * no-op for local incoming migration with live backend passing.
+ */
+ if (!n->peers_wait_incoming) {
+ virtio_net_set_queue_pairs(n);
+ }
}
static int virtio_net_pre_load_queues(VirtIODevice *vdev, uint32_t n)
@@ -3108,6 +3119,17 @@ static void virtio_net_get_features(VirtIODevice *vdev, uint64_t *features,
virtio_add_feature_ex(features, VIRTIO_NET_F_MAC);
+ if (n->peers_wait_incoming) {
+ /*
+ * Excessive feature set is OK for early initialization when
+ * we wait for local incoming migration: actual guest-negotiated
+ * features will come with migration stream anyway. And we are sure
+ * that we support same host-features as source, because the backend
+ * is the same (the same TAP device, for example).
+ */
+ return;
+ }
+
if (!peer_has_vnet_hdr(n)) {
virtio_clear_feature_ex(features, VIRTIO_NET_F_CSUM);
virtio_clear_feature_ex(features, VIRTIO_NET_F_HOST_TSO4);
@@ -3204,6 +3226,7 @@ static int virtio_net_post_load_device(void *opaque, int version_id)
VirtIODevice *vdev = VIRTIO_DEVICE(n);
int i, link_down;
bool has_tunnel_hdr = virtio_has_tunnel_hdr(vdev->guest_features_ex);
+ Error *local_err = NULL;
trace_virtio_net_post_load_device();
virtio_net_set_mrg_rx_bufs(n, n->mergeable_rx_bufs,
@@ -3261,6 +3284,20 @@ static int virtio_net_post_load_device(void *opaque, int version_id)
}
virtio_net_commit_rss_config(n);
+
+ /*
+ * If live-migration is enabled for some backend, than backend
+ * has already been migrated at higher priority (MIG_PRI_BACKEND)
+ * and virtio_net_vnet_post_load() has already called
+ * peer_test_vnet_hdr(). Recompute host_features so that virtio-net
+ * reflects the capabilities of the restored backend.
+ */
+ virtio_net_get_features(vdev, &vdev->host_features, &local_err);
+ if (local_err) {
+ error_report_err(local_err);
+ return -EINVAL;
+ }
+
return 0;
}
@@ -3411,6 +3448,14 @@ static int virtio_net_vnet_post_load(void *opaque, int version_id)
{
struct VirtIONetMigTmp *tmp = opaque;
+ /*
+ * If live-migration is enabled for some backend, than backend
+ * has already been migrated at higher priority (MIG_PRI_BACKEND),
+ * so n->has_vnet_hdr can be refreshed from the live backend right
+ * here.
+ */
+ peer_test_vnet_hdr(tmp->parent);
+
if (tmp->has_vnet_hdr && !peer_has_vnet_hdr(tmp->parent)) {
error_report("virtio-net: saved image requires vnet_hdr=on");
return -EINVAL;
@@ -3890,6 +3935,42 @@ static bool failover_hide_primary_device(DeviceListener *listener,
return qatomic_read(&n->failover_primary_hidden);
}
+static bool virtio_net_check_peers_wait_incoming(VirtIONet *n, bool *waiting,
+ Error **errp)
+{
+ bool has_waiting = false;
+ bool has_not_waiting = false;
+
+ for (int i = 0; i < n->max_queue_pairs; i++) {
+ NetClientState *peer = n->nic->ncs[i].peer;
+ if (!peer) {
+ continue;
+ }
+
+ if (peer->info->is_wait_incoming &&
+ peer->info->is_wait_incoming(peer)) {
+ has_waiting = true;
+ } else {
+ has_not_waiting = true;
+ }
+
+ if (has_waiting && has_not_waiting) {
+ error_setg(errp, "Mixed peer states: some peers wait for incoming "
+ "migration while others don't");
+ return false;
+ }
+ }
+
+ if (has_waiting && !runstate_check(RUN_STATE_INMIGRATE)) {
+ error_setg(errp, "Peers wait for incoming, but it's not an incoming "
+ "migration.");
+ return false;
+ }
+
+ *waiting = has_waiting;
+ return true;
+}
+
static void virtio_net_device_realize(DeviceState *dev, Error **errp)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
@@ -4027,6 +4108,12 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
n->nic->ncs[i].do_not_pad = true;
}
+ if (!virtio_net_check_peers_wait_incoming(n, &n->peers_wait_incoming,
+ errp)) {
+ virtio_cleanup(vdev);
+ return;
+ }
+
peer_test_vnet_hdr(n);
if (peer_has_vnet_hdr(n)) {
n->host_hdr_len = sizeof(struct virtio_net_hdr);
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 22/75] net/tap: disable read polling for stopped VM
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (20 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 21/75] virtio-net: support local migration of backend Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 23/75] net/tap: support local migration with virtio-net Michael S. Tsirkin
` (54 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Jason Wang
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Polling when VM is stopped doesn't make real sense, as stopped VM can't
handle incoming traffic anyway.
And it's critical for introduction of local TAP migration
feature in the next commit: the TAP device will be transferred
to the target (open fd will be passed through migration channel),
and if we continue polling on source, we may get a package, which
we'll never handle on source (already stopped), it will be lost.
Better is save this package for target VM to handle.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260819180201.1970193-15-vsementsov@yandex-team.ru>
---
net/tap.c | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/net/tap.c b/net/tap.c
index dd0d134875..51d028d956 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -36,6 +36,7 @@
#include "net/net.h"
#include "clients.h"
#include "monitor/monitor.h"
+#include "system/runstate.h"
#include "system/system.h"
#include "qapi/error.h"
#include "qemu/cutils.h"
@@ -92,6 +93,8 @@ struct TAPState {
Notifier exit;
int queue_index;
+ bool enable_poll_on_resume;
+ VMChangeStateEntry *vmstate;
};
static void launch_script(const char *setup_script, const char *ifname,
@@ -145,10 +148,31 @@ static void tap_update_fd_handler(TAPState *s)
static void tap_read_poll(TAPState *s, bool enable)
{
+ if (enable && runstate_check(RUN_STATE_FINISH_MIGRATE)) {
+ s->enable_poll_on_resume = true;
+ return;
+ }
s->read_poll = enable;
tap_update_fd_handler(s);
}
+static void tap_vm_state_change(void *opaque, bool running, RunState state)
+{
+ TAPState *s = opaque;
+
+ if (running) {
+ if (s->enable_poll_on_resume) {
+ tap_read_poll(s, true);
+ s->enable_poll_on_resume = false;
+ }
+ } else if (state == RUN_STATE_FINISH_MIGRATE) {
+ if (s->read_poll) {
+ s->enable_poll_on_resume = true;
+ tap_read_poll(s, false);
+ }
+ }
+}
+
static void tap_write_poll(TAPState *s, bool enable)
{
s->write_poll = enable;
@@ -379,6 +403,11 @@ static void tap_cleanup(NetClientState *nc)
s->exit.notify = NULL;
}
+ if (s->vmstate) {
+ qemu_del_vm_change_state_handler(s->vmstate);
+ s->vmstate = NULL;
+ }
+
tap_read_poll(s, false);
tap_write_poll(s, false);
close(s->fd);
@@ -818,6 +847,9 @@ static bool net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
int sndbuf =
(tap->has_sndbuf && tap->sndbuf) ? MIN(tap->sndbuf, INT_MAX) : INT_MAX;
+ s->enable_poll_on_resume = false;
+ s->vmstate = qemu_add_vm_change_state_handler(tap_vm_state_change, s);
+
if (!tap_set_sndbuf(fd, sndbuf, sndbuf_required ? errp : NULL) &&
sndbuf_required) {
goto failed;
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 23/75] net/tap: support local migration with virtio-net
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (21 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 22/75] net/tap: disable read polling for stopped VM Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 24/75] tests/functional: add test_tap_migration Michael S. Tsirkin
` (53 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Ben Chaney,
Markus Armbruster, Jason Wang, Eric Blake
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Support transferring of TAP state (including open fd).
Add new property "x-permit-local-migration", which defines whether
local migration is actually permitted for this TAP device.
Note that local-migration is enabled by global "local" migration
parameter, but individual devices may have additional options to
enable/disable it per device.
The tricky thing is that we need to know whether to call open/connect in
TAP initialization code, i.e. we need to know the value of migration
parameter "local" when creating the TAP device. For incoming migration,
we can know only for TAP devices created with QMP after setting the
migration parameter with QMP.
So the full picture is:
On source, to start outgoing "local" migration you need:
- migration parameter "local" set to true
- "x-permit-local-migration" TAP option set to true
If at least one of these options is not set, TAP backend
doesn't participate in migration.
On target, things are more difficult:
Same, you need both "local" and "x-permit-local-migration"
be set. And same, if one of them is not set, TAP backend
is initialized as usual, and doesn't accept any incoming
state.
Additionally, if you are going to set "local", it must be
set before creating the TAP device. If TAP device created
with "local" unset, it initializes as usual. If you enable
"local" after it and start incoming migration, it will fail
in .pre_load handler of TAP backend.
Moreover, there are interface restrictions: if you create TAP
device when QEMU is in INCOMING state, and both "local"
and "x-permit-local-migration" set, most of TAP options are
not allowed, and script/downscript are required to be explicitly
disabled.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Ben Chaney <bchaney@akamai.com>
Acked-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260819180201.1970193-16-vsementsov@yandex-team.ru>
---
qapi/net.json | 29 ++++++++-
net/tap.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 189 insertions(+), 7 deletions(-)
diff --git a/qapi/net.json b/qapi/net.json
index dccf95bbbc..64c0ef1f6d 100644
--- a/qapi/net.json
+++ b/qapi/net.json
@@ -437,6 +437,31 @@
# @poll-us: maximum number of microseconds that could be spent on busy
# polling for tap (since 2.7)
#
+# @x-permit-local-migration: permit local migration for this TAP
+# backend. When set, local migration is enabled/disabled by
+# migration parameter @local for this TAP backend. When unset,
+# migration parameter @local is ignored for this TAP backend.
+#
+# To be able to do incoming local migration of a TAP backend,
+# migration parameter @local must be set _before_ creating the
+# TAP backend. Otherwise, TAP backend is initialized as usual,
+# opening/creating TAP devices in kernel. In this case further
+# local incoming migration (with migration parameter @local set
+# after creating TAP backend with @x-permit-local-migration
+# parameter set) will simply fail.
+#
+# Moreover, when QEMU is in incoming migration state, migration
+# parameter @local is set and @x-permit-local-migration is set,
+# the following options are not supported and must not be set:
+# @fd, @fds, @helper, @br, @ifname, @sndbuf, @vnet_hdr.
+# Additionally, @script and @downscript must be explicitly
+# disabled then.
+# (default: false, since 11.2)
+#
+# Features:
+#
+# @unstable: Member @x-permit-local-migration is experimental.
+#
# Since: 1.2
##
{ 'struct': 'NetdevTapOptions',
@@ -455,7 +480,9 @@
'*vhostfds': 'str',
'*vhostforce': 'bool',
'*queues': 'uint32',
- '*poll-us': 'uint32'} }
+ '*poll-us': 'uint32',
+ '*x-permit-local-migration': {
+ 'type': 'bool', 'features' : [ 'unstable'] } } }
##
# @NetdevSocketOptions:
diff --git a/net/tap.c b/net/tap.c
index 51d028d956..d71e3dd117 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -38,12 +38,17 @@
#include "monitor/monitor.h"
#include "system/runstate.h"
#include "system/system.h"
+#include "migration/misc.h"
#include "qapi/error.h"
#include "qemu/cutils.h"
#include "qemu/error-report.h"
#include "qemu/main-loop.h"
#include "qemu/sockets.h"
#include "hw/virtio/vhost.h"
+#include "hw/core/vmstate-if.h"
+#include "migration/vmstate.h"
+#include "qom/object.h"
+#include "qom/compat-properties.h"
#include "net/tap.h"
#include "net/util.h"
@@ -71,6 +76,8 @@ static const int kernel_feature_bits[] = {
OBJECT_DECLARE_SIMPLE_TYPE(TAPState, TAP_NETDEV)
+static const VMStateDescription vmstate_tap;
+
struct TAPState {
Object parent_obj;
@@ -95,6 +102,7 @@ struct TAPState {
int queue_index;
bool enable_poll_on_resume;
VMChangeStateEntry *vmstate;
+ bool permit_local_migration;
};
static void launch_script(const char *setup_script, const char *ifname,
@@ -412,6 +420,8 @@ static void tap_cleanup(NetClientState *nc)
tap_write_poll(s, false);
close(s->fd);
s->fd = -1;
+
+ vmstate_unregister(VMSTATE_IF(s), &vmstate_tap, s);
}
static void tap_poll(NetClientState *nc, bool enable)
@@ -448,6 +458,78 @@ static VHostNetState *tap_get_vhost_net(NetClientState *nc)
return s->vhost_net;
}
+static bool tap_is_wait_incoming(NetClientState *nc)
+{
+ TAPState *s = container_of(nc, TAPState, nc);
+ assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
+ return s->fd == -1;
+}
+
+static bool tap_pre_load(void *opaque, Error **errp)
+{
+ ERRP_GUARD();
+ TAPState *s = opaque;
+
+ if (s->fd != -1) {
+ error_setg(errp,
+ "TAP is already initialized and cannot receive "
+ "incoming fd");
+ error_append_hint(errp,
+ "Migration parameter 'local' must be set"
+ " before creating the TAP device.");
+ return false;
+ }
+
+ return true;
+}
+
+static bool tap_setup_vhost(TAPState *s, Error **errp);
+
+static bool tap_post_load(void *opaque, int version_id, Error **errp)
+{
+ ERRP_GUARD();
+ TAPState *s = opaque;
+
+ tap_read_poll(s, true);
+
+ if (s->fd < 0) {
+ error_setg(errp, "FD was not loaded during incoming migration");
+ return false;
+ }
+
+ if (!tap_setup_vhost(s, errp)) {
+ error_prepend(errp,
+ "Failed to setup vhost during TAP post-load: ");
+ return false;
+ }
+
+ return true;
+}
+
+static bool tap_needed(void *opaque)
+{
+ TAPState *s = opaque;
+
+ return s->permit_local_migration && migrate_local();
+}
+
+static const VMStateDescription vmstate_tap = {
+ .name = "net-tap",
+ .priority = MIG_PRI_BACKEND,
+ .pre_load_errp = tap_pre_load,
+ .post_load_errp = tap_post_load,
+ .needed = tap_needed,
+ .fields = (const VMStateField[]) {
+ VMSTATE_FD(fd, TAPState),
+ VMSTATE_BOOL(using_vnet_hdr, TAPState),
+ VMSTATE_BOOL(has_ufo, TAPState),
+ VMSTATE_BOOL(has_uso, TAPState),
+ VMSTATE_BOOL(has_tunnel, TAPState),
+ VMSTATE_BOOL(enabled, TAPState),
+ VMSTATE_UINT32(host_vnet_hdr_len, TAPState),
+ VMSTATE_END_OF_LIST()
+ }
+};
static char *tap_vmstate_if_get_id(VMStateIf *obj)
{
@@ -456,17 +538,42 @@ static char *tap_vmstate_if_get_id(VMStateIf *obj)
return res;
}
+static bool tap_get_permit_local_migration_prop(Object *obj, Error **errp)
+{
+ TAPState *s = TAP_NETDEV(obj);
+ return s->permit_local_migration;
+}
+
+static void tap_set_permit_local_migration_prop(Object *obj, bool value,
+ Error **errp)
+{
+ TAPState *s = TAP_NETDEV(obj);
+ s->permit_local_migration = value;
+}
+
+static void tap_instance_init(Object *obj)
+{
+ TAPState *s = TAP_NETDEV(obj);
+ s->permit_local_migration = false;
+}
+
static void tap_class_init(ObjectClass *klass, const void *data)
{
VMStateIfClass *vc = VMSTATE_IF_CLASS(klass);
vc->get_id = tap_vmstate_if_get_id;
+
+ object_class_property_add_bool(klass, "x-permit-local-migration",
+ tap_get_permit_local_migration_prop,
+ tap_set_permit_local_migration_prop);
}
static const TypeInfo tap_netdev_info = {
.name = TYPE_TAP_NETDEV,
.parent = TYPE_OBJECT,
.instance_size = sizeof(TAPState),
+ .instance_init = tap_instance_init,
+ .instance_post_init = object_apply_compat_props,
.class_init = tap_class_init,
.interfaces = (const InterfaceInfo[]) {
{ TYPE_VMSTATE_IF },
@@ -499,13 +606,16 @@ static NetClientInfo net_tap_info = {
.set_vnet_le = tap_set_vnet_le,
.set_vnet_be = tap_set_vnet_be,
.set_steering_ebpf = tap_set_steering_ebpf,
+ .is_wait_incoming = tap_is_wait_incoming,
.get_vhost_net = tap_get_vhost_net,
};
static TAPState *new_tap(NetClientState *peer,
const char *model,
const char *name,
- int queue_index)
+ int queue_index,
+ bool has_permit_local_migration,
+ bool permit_local_migration)
{
TAPState *s = TAP_NETDEV(object_new(TYPE_TAP_NETDEV));
@@ -514,6 +624,12 @@ static TAPState *new_tap(NetClientState *peer,
s->queue_index = queue_index;
+ if (has_permit_local_migration) {
+ s->permit_local_migration = permit_local_migration;
+ }
+
+ vmstate_register(VMSTATE_IF(s), VMSTATE_INSTANCE_ID_ANY, &vmstate_tap, s);
+
return s;
}
@@ -522,10 +638,14 @@ static TAPState *net_tap_fd_init(NetClientState *peer,
const char *name,
int fd,
int vnet_hdr,
- int queue_index)
+ int queue_index,
+ bool has_permit_local_migration,
+ bool permit_local_migration)
{
NetOffloads ol = {};
- TAPState *s = new_tap(peer, model, name, queue_index);
+ TAPState *s = new_tap(peer, model, name, queue_index,
+ has_permit_local_migration,
+ permit_local_migration);
s->fd = fd;
s->host_vnet_hdr_len = vnet_hdr ? sizeof(struct virtio_net_hdr) : 0;
@@ -762,7 +882,7 @@ int net_init_bridge(const Netdev *netdev, const char *name,
close(fd);
return -1;
}
- s = net_tap_fd_init(peer, "bridge", name, fd, vnet_hdr, 0);
+ s = net_tap_fd_init(peer, "bridge", name, fd, vnet_hdr, 0, true, false);
qemu_set_info_str(&s->nc, "helper=%s,br=%s", helper, br);
@@ -842,7 +962,9 @@ static bool net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
Error **errp)
{
TAPState *s = net_tap_fd_init(peer, tap->helper ? "bridge" : "tap",
- name, fd, vnet_hdr, queue_index);
+ name, fd, vnet_hdr, queue_index,
+ tap->has_x_permit_local_migration,
+ tap->x_permit_local_migration);
bool sndbuf_required = tap->has_sndbuf;
int sndbuf =
(tap->has_sndbuf && tap->sndbuf) ? MIN(tap->sndbuf, INT_MAX) : INT_MAX;
@@ -990,6 +1112,7 @@ int net_init_tap(const Netdev *netdev, const char *name,
/* for the no-fd, no-helper case */
char ifname[128];
int *fds = NULL, *vhost_fds = NULL;
+ bool incoming_fds;
assert(netdev->type == NET_CLIENT_DRIVER_TAP);
tap = &netdev->u.tap;
@@ -1012,6 +1135,23 @@ int net_init_tap(const Netdev *netdev, const char *name,
return -1;
}
+ incoming_fds = tap->x_permit_local_migration && migrate_local() &&
+ runstate_check(RUN_STATE_INMIGRATE);
+
+ if (incoming_fds &&
+ (tap->fd || tap->fds || tap->helper || tap->br || tap->ifname ||
+ tap->has_sndbuf || tap->has_vnet_hdr ||
+ !tap_is_explicit_no_script("script", tap->script) ||
+ !tap_is_explicit_no_script("downscript", tap->downscript))) {
+ error_setg(errp, "Local incoming migration of TAP device (-incoming, "
+ "migration parameter @local is set, "
+ "TAP parameter @x-permit-local-migration is set) "
+ "is incompatible with "
+ "fd=, fds=, helper=, br=, ifname=, sndbuf= and vnet_hdr=, "
+ "and requires explicit empty script= and downscript=");
+ return -1;
+ }
+
queues = tap_parse_fds_and_queues(tap, &fds, errp);
if (queues < 0) {
return -1;
@@ -1030,7 +1170,22 @@ int net_init_tap(const Netdev *netdev, const char *name,
goto fail;
}
- if (fds) {
+ if (incoming_fds) {
+ for (i = 0; i < queues; i++) {
+ TAPState *s = new_tap(peer, "tap", name, i,
+ tap->has_x_permit_local_migration,
+ tap->x_permit_local_migration);
+ qemu_set_info_str(&s->nc, "incoming");
+
+ s->fd = -1;
+ if (vhost_fds) {
+ s->vhostfd = vhost_fds[i];
+ s->vhost_busyloop_timeout = tap->has_poll_us ? tap->poll_us : 0;
+ } else {
+ s->vhostfd = -1;
+ }
+ }
+ } else if (fds) {
for (i = 0; i < queues; i++) {
if (i == 0) {
vnet_hdr = tap_probe_vnet_hdr(fds[i], errp);
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 24/75] tests/functional: add test_tap_migration
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (22 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 23/75] net/tap: support local migration with virtio-net Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 25/75] tests/bios-tables-test: Exclude CEDT.cxl for the CFMW restriction change Michael S. Tsirkin
` (52 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Ben Chaney,
Paolo Bonzini, Zhao Liu, Peter Xu, Fabiano Rosas
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Add test for a new local-migration migration of virtio-net/tap, with fd
passing through UNIX socket.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Ben Chaney <bchaney@akamai.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260819180201.1970193-17-vsementsov@yandex-team.ru>
---
tests/functional/x86_64/meson.build | 1 +
tests/functional/x86_64/test_tap_migration.py | 461 ++++++++++++++++++
2 files changed, 462 insertions(+)
create mode 100755 tests/functional/x86_64/test_tap_migration.py
diff --git a/tests/functional/x86_64/meson.build b/tests/functional/x86_64/meson.build
index 0353b2af8e..6254149239 100644
--- a/tests/functional/x86_64/meson.build
+++ b/tests/functional/x86_64/meson.build
@@ -51,4 +51,5 @@ tests_x86_64_system_thorough = [
'virtio_balloon',
'virtio_gpu',
'rebuild_vmfd',
+ 'tap_migration',
]
diff --git a/tests/functional/x86_64/test_tap_migration.py b/tests/functional/x86_64/test_tap_migration.py
new file mode 100755
index 0000000000..1e0d602518
--- /dev/null
+++ b/tests/functional/x86_64/test_tap_migration.py
@@ -0,0 +1,461 @@
+#!/usr/bin/env python3
+#
+# Functional test that tests TAP local migration
+# with fd passing
+#
+# Copyright (c) Yandex Technologies LLC, 2026
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import os
+import time
+import subprocess
+from subprocess import run
+import signal
+import ctypes
+import ctypes.util
+import unittest
+from contextlib import contextmanager, ExitStack
+from typing import Tuple
+
+from qemu_test import (
+ LinuxKernelTest,
+ Asset,
+ exec_command_and_wait_for_pattern,
+)
+from qemu_test.decorators import skipWithoutSudo
+
+
+GUEST_IP = "192.168.100.2"
+GUEST_IP_MASK = f"{GUEST_IP}/24"
+GUEST_MAC = "d6:0d:75:f8:0f:b7"
+HOST_IP = "192.168.100.1"
+HOST_IP_MASK = f"{HOST_IP}/24"
+TAP_ID = "tap0"
+TAP_ID2 = "tap1"
+TAP_MAC = "e6:1d:44:b5:03:5d"
+NETNS = f"qemu_test_ns_{os.getpid()}"
+
+
+def ip(args, check=True) -> None:
+ """Run ip command with sudo"""
+ run(["sudo", "ip"] + args, check=check)
+
+
+@contextmanager
+def switch_netns(netns_name):
+ libc = ctypes.CDLL(ctypes.util.find_library("c"))
+ netns_path = f"/var/run/netns/{netns_name}"
+
+ def switch_to_fd(fd, check: bool = False):
+ """Switch to netns by file descriptor"""
+ SYS_setns = 308
+ CLONE_NEWNET = 0x40000000
+ ret = libc.syscall(SYS_setns, fd, CLONE_NEWNET)
+ if check and ret != 0:
+ raise RuntimeError("syscall SETNS failed")
+
+ with ExitStack() as stack:
+ original_netns_fd = os.open("/proc/self/ns/net", os.O_RDONLY)
+ stack.callback(os.close, original_netns_fd)
+
+ ip(["netns", "add", netns_name])
+ stack.callback(ip, ["netns", "del", netns_name], check=False)
+
+ new_netns_fd = os.open(netns_path, os.O_RDONLY)
+ stack.callback(os.close, new_netns_fd)
+
+ switch_to_fd(new_netns_fd)
+ stack.callback(switch_to_fd, original_netns_fd, check=False)
+
+ yield
+
+
+def del_tap(tap_name: str = TAP_ID) -> None:
+ ip(["tuntap", "del", tap_name, "mode", "tap", "multi_queue"], check=False)
+
+
+def init_tap(tap_name: str = TAP_ID, with_ip: bool = True) -> None:
+ ip(["tuntap", "add", "dev", tap_name, "mode", "tap", "multi_queue"])
+ if with_ip:
+ ip(["link", "set", "dev", tap_name, "address", TAP_MAC])
+ ip(["addr", "add", HOST_IP_MASK, "dev", tap_name])
+ ip(["link", "set", tap_name, "up"])
+
+
+def switch_network_to_tap2() -> None:
+ ip(["link", "set", TAP_ID2, "down"])
+ ip(["link", "set", TAP_ID, "down"])
+ ip(["addr", "delete", HOST_IP_MASK, "dev", TAP_ID])
+ ip(["link", "set", "dev", TAP_ID2, "address", TAP_MAC])
+ ip(["addr", "add", HOST_IP_MASK, "dev", TAP_ID2])
+ ip(["link", "set", TAP_ID2, "up"])
+
+
+def parse_ping_line(line: str) -> float:
+ # suspect lines like
+ # [1748524876.590509] 64 bytes from 94.245.155.3 \
+ # (94.245.155.3): icmp_seq=1 ttl=250 time=101 ms
+ spl = line.split()
+ return float(spl[0][1:-1])
+
+
+def parse_ping_output(out) -> Tuple[bool, float, float]:
+ lines = [x for x in out.split("\n") if x.startswith("[")]
+
+ try:
+ first_no_ans = next(
+ (ind for ind in range(len(lines)) if lines[ind][20:26] == "no ans")
+ )
+ except StopIteration:
+ return False, parse_ping_line(lines[0]), parse_ping_line(lines[-1])
+
+ last_no_ans = next(
+ ind
+ for ind in range(len(lines) - 1, -1, -1)
+ if lines[ind][20:26] == "no ans"
+ )
+
+ return (
+ True,
+ parse_ping_line(lines[first_no_ans]),
+ parse_ping_line(lines[last_no_ans]),
+ )
+
+
+def wait_migration_finish(source_vm, target_vm):
+ migr_events = (
+ ("MIGRATION", {"data": {"status": "completed"}}),
+ ("MIGRATION", {"data": {"status": "failed"}}),
+ )
+
+ source_e = source_vm.events_wait(migr_events)["data"]
+ target_e = target_vm.events_wait(migr_events)["data"]
+
+ source_s = source_vm.cmd("query-status")["status"]
+ target_s = target_vm.cmd("query-status")["status"]
+
+ assert (
+ source_e["status"] == "completed"
+ and target_e["status"] == "completed"
+ and source_s == "postmigrate"
+ and target_s == "paused"
+ ), f"""Migration failed:
+ SRC status: {source_s}
+ SRC event: {source_e}
+ TGT status: {target_s}
+ TGT event:{target_e}"""
+
+
+@skipWithoutSudo()
+class TAPFdMigration(LinuxKernelTest):
+
+ ASSET_KERNEL = Asset(
+ (
+ "https://archives.fedoraproject.org/pub/archive/fedora/linux/releases"
+ "/31/Server/x86_64/os/images/pxeboot/vmlinuz"
+ ),
+ "d4738d03dbbe083ca610d0821d0a8f1488bebbdccef54ce33e3adb35fda00129",
+ )
+
+ ASSET_INITRD = Asset(
+ (
+ "https://archives.fedoraproject.org/pub/archive/fedora/linux/releases"
+ "/31/Server/x86_64/os/images/pxeboot/initrd.img"
+ ),
+ "277cd6c7adf77c7e63d73bbb2cded8ef9e2d3a2f100000e92ff1f8396513cd8b",
+ )
+
+ ASSET_ALPINE_ISO = Asset(
+ (
+ "https://dl-cdn.alpinelinux.org/"
+ "alpine/v3.22/releases/x86_64/alpine-standard-3.22.1-x86_64.iso"
+ ),
+ "96d1b44ea1b8a5a884f193526d92edb4676054e9fa903ad2f016441a0fe13089",
+ )
+
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+
+ try:
+ cls.netns_context = switch_netns(NETNS)
+ cls.netns_context.__enter__()
+ except (OSError, subprocess.CalledProcessError) as e:
+ raise unittest.SkipTest(f"can't switch network namespace: {e}")
+
+ @classmethod
+ def tearDownClass(cls):
+ if hasattr(cls, "netns_context"):
+ cls.netns_context.__exit__(None, None, None)
+ super().tearDownClass()
+
+ def setUp(self):
+ super().setUp()
+
+ self.require_accelerator("kvm")
+ self.set_machine("q35")
+
+ self.setup_shared_memory()
+
+ init_tap()
+
+ self.outer_ping_proc = None
+ self.shm_path = None
+
+ def tearDown(self):
+ with ExitStack() as stack:
+ stack.callback(super().tearDown)
+
+ if self.shm_path:
+ stack.callback(lambda p: (os.unlink(p) if os.path.exists(p)
+ else None),
+ self.shm_path)
+ self.shm_path = None
+
+ stack.callback(del_tap, TAP_ID2)
+ stack.callback(del_tap, TAP_ID)
+
+ if self.outer_ping_proc:
+ self.stop_outer_ping()
+
+ def start_outer_ping(self) -> None:
+ assert self.outer_ping_proc is None
+ self.outer_ping_log = self.scratch_file("ping.log")
+ with open(self.outer_ping_log, "w") as f:
+ self.outer_ping_proc = subprocess.Popen(
+ ["ping", "-i", "0", "-O", "-D", GUEST_IP],
+ text=True,
+ stdout=f,
+ )
+
+ def stop_outer_ping(self) -> str:
+ assert self.outer_ping_proc
+ self.outer_ping_proc.send_signal(signal.SIGINT)
+
+ self.outer_ping_proc.communicate(timeout=5)
+ self.outer_ping_proc = None
+
+ with open(self.outer_ping_log) as f:
+ return f.read()
+
+ def stop_ping_and_check(self, stop_time, resume_time):
+ ping_res = self.stop_outer_ping()
+
+ discon, a, b = parse_ping_output(ping_res)
+
+ if not discon:
+ text = (
+ f"STOP: {stop_time}, RESUME: {resume_time}," f"PING: {a} - {b}"
+ )
+ if a > stop_time or b < resume_time:
+ self.fail(f"PING failed: {text}")
+ self.log.info(f"PING: no packets lost: {text}")
+ return
+
+ text = (
+ f"STOP: {stop_time}, RESUME: {resume_time},"
+ f"PING: disconnect: {a} - {b}"
+ )
+ self.log.info(text)
+ eps = 0.05
+ if a < stop_time - eps or b > resume_time + eps:
+ self.fail(text)
+
+ def one_ping_from_guest(self, vm) -> None:
+ exec_command_and_wait_for_pattern(
+ self,
+ f"ping -c 1 -W 1 {HOST_IP}",
+ "1 packets transmitted, 1 packets received",
+ "1 packets transmitted, 0 packets received",
+ vm=vm,
+ )
+ self.wait_for_console_pattern("# ", vm=vm)
+
+ def one_ping_from_host(self) -> None:
+ run(
+ ["ping", "-c", "1", "-W", "1", GUEST_IP],
+ stdout=subprocess.DEVNULL,
+ check=True,
+ )
+
+ def setup_shared_memory(self):
+ self.shm_path = f"/dev/shm/qemu_test_{os.getpid()}"
+
+ try:
+ with open(self.shm_path, "wb") as f:
+ f.write(b"\0" * (1024 * 1024 * 1024)) # 1GB
+ except Exception as e:
+ self.fail(f"Failed to create shared memory file: {e}")
+
+ def prepare_vm(
+ self, shm_path, vhost, incoming=False, vm=None, local=True
+ ):
+ if not vm:
+ vm = self.vm
+
+ vm.set_console()
+ vm.add_args("-accel", "kvm")
+ vm.add_args("-device", "pcie-pci-bridge,id=pci.1,bus=pcie.0")
+ vm.add_args("-m", "1G")
+ vm.add_args("-net", "none")
+
+ vm.add_args(
+ "-object",
+ f"memory-backend-file,id=ram0,size=1G,mem-path={shm_path},share=on",
+ )
+ vm.add_args("-machine", "memory-backend=ram0")
+
+ vm.add_args(
+ "-drive",
+ f"file={self.ASSET_ALPINE_ISO.fetch()},media=cdrom,format=raw",
+ )
+
+ vm.add_args("-S")
+
+ if incoming:
+ vm.add_args("-incoming", "defer")
+
+ def add_virtio_net(
+ self, vm, vhost: bool, tap_name: str, local: bool, incoming: bool
+ ):
+ netdev_params = {
+ "id": "netdev.1",
+ "vhost": vhost,
+ "type": "tap",
+ "queues": 4,
+ "script": "no",
+ "downscript": "no",
+ "x-permit-local-migration": local,
+ }
+
+ if not (local and incoming):
+ netdev_params["vnet_hdr"] = True
+ netdev_params["ifname"] = tap_name
+
+ vm.cmd("netdev_add", netdev_params)
+
+ vm.cmd(
+ "device_add",
+ driver="virtio-net-pci",
+ romfile="",
+ id="vnet.1",
+ netdev="netdev.1",
+ mq=True,
+ vectors=18,
+ bus="pci.1",
+ mac=GUEST_MAC,
+ disable_legacy="off",
+ )
+
+ def set_migration_capabilities(self, vm, local):
+ vm.cmd(
+ "migrate-set-capabilities",
+ {
+ "capabilities": [
+ {"capability": "events", "state": True},
+ {"capability": "x-ignore-shared", "state": True},
+ ]
+ },
+ )
+ vm.cmd("migrate-set-parameters", {"local": local})
+
+ def setup_guest_network(self) -> None:
+ exec_command_and_wait_for_pattern(self, "ip addr", "# ")
+ exec_command_and_wait_for_pattern(
+ self,
+ f"ip addr add {GUEST_IP_MASK} dev eth0 && "
+ "ip link set eth0 up && echo OK",
+ "OK",
+ )
+ self.wait_for_console_pattern("# ")
+
+ def migrate(self, vm, mig_sock):
+ vm.cmd("migrate", uri=f"unix:{mig_sock}")
+ def do_test_tap_fd_migration(self, vhost, local=True):
+ socket_dir = self.socket_dir()
+ mig_sock = os.path.join(socket_dir.name, "mig.sock")
+
+ # Setup second TAP if needed
+ if not local:
+ del_tap(TAP_ID2)
+ init_tap(TAP_ID2, with_ip=False)
+
+ self.prepare_vm(self.shm_path, vhost, local=local)
+ self.vm.launch()
+ self.set_migration_capabilities(self.vm, local=local)
+ self.add_virtio_net(self.vm, vhost, TAP_ID, local, incoming=False)
+
+ self.vm.cmd("cont")
+ self.wait_for_console_pattern("login:")
+ exec_command_and_wait_for_pattern(self, "root", "# ")
+
+ self.setup_guest_network()
+
+ self.one_ping_from_guest(self.vm)
+ self.one_ping_from_host()
+ self.start_outer_ping()
+
+ # Get some successful pings before migration
+ time.sleep(0.5)
+
+ target_vm = self.get_vm(name="target")
+ self.prepare_vm(
+ self.shm_path,
+ vhost,
+ incoming=True,
+ vm=target_vm,
+ local=local,
+ )
+
+ target_vm.launch()
+ if not local:
+ tap_name = TAP_ID2
+ else:
+ tap_name = TAP_ID
+ self.set_migration_capabilities(target_vm, local=local)
+ self.add_virtio_net(target_vm, vhost, tap_name, local, incoming=True)
+
+ target_vm.cmd("migrate-incoming", {"uri": f"unix:{mig_sock}"})
+
+ self.log.info("Starting migration")
+ freeze_start = time.time()
+ self.migrate(self.vm, mig_sock)
+
+ self.log.info("Waiting for migration completion")
+ wait_migration_finish(self.vm, target_vm)
+
+ # Switch network to tap1 if not using local-migration
+ if not local:
+ switch_network_to_tap2()
+
+ target_vm.cmd("cont")
+ freeze_end = time.time()
+
+ self.vm.shutdown()
+
+ self.log.info("Verifying PING on target VM after migration")
+ self.one_ping_from_guest(target_vm)
+ self.one_ping_from_host()
+
+ # And a bit more pings after source shutdown
+ time.sleep(0.3)
+ self.stop_ping_and_check(freeze_start, freeze_end)
+
+ target_vm.shutdown()
+
+ def test_tap_fd_migration(self):
+ self.do_test_tap_fd_migration(False)
+
+ def test_tap_fd_migration_vhost(self):
+ self.do_test_tap_fd_migration(True)
+
+ def test_tap_new_tap_migration(self):
+ self.do_test_tap_fd_migration(False, local=False)
+
+ def test_tap_new_tap_migration_vhost(self):
+ self.do_test_tap_fd_migration(True, local=False)
+
+
+if __name__ == "__main__":
+ LinuxKernelTest.main()
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 25/75] tests/bios-tables-test: Exclude CEDT.cxl for the CFMW restriction change
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (23 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 24/75] tests/functional: add test_tap_migration Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 26/75] hw/cxl: Drop Back-Invalidate from default CFMW window restrictions Michael S. Tsirkin
` (51 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Davidlohr Bueso, Igor Mammedov, Ani Sinha
From: Davidlohr Bueso <dave@stgolabs.net>
The next patch changes the default CXL Fixed Memory Window restrictions,
dropping Back-Invalidate. Add CEDT.cxl to the allowed-diff list so the
comparison passes until the expected blob is regenerated.
Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260720233242.901544-2-dave@stgolabs.net>
---
tests/qtest/bios-tables-test-allowed-diff.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523c8b..b4646b5b31 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,2 @@
/* List of comma-separated changed AML files to ignore */
+"tests/data/acpi/x86/q35/CEDT.cxl",
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 26/75] hw/cxl: Drop Back-Invalidate from default CFMW window restrictions
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (24 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 25/75] tests/bios-tables-test: Exclude CEDT.cxl for the CFMW restriction change Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 27/75] tests/acpi/cxl: Update CEDT.cxl for the default CFMW restrictions Michael S. Tsirkin
` (50 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Davidlohr Bueso, Igor Mammedov, Ani Sinha
From: Davidlohr Bueso <dave@stgolabs.net>
The default CXL Fixed Memory Window restrictions advertised host-only
coherent together with Back-Invalidate. A window advertising both
simultaneously is undefined behavior per CXL r4.0 9.18.1.3.
Drop Back-Invalidate from the default, leaving device-coherent +
host-only + volatile + persistent.
Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260720233242.901544-3-dave@stgolabs.net>
---
hw/acpi/cxl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/acpi/cxl.c b/hw/acpi/cxl.c
index f92f7fa3d5..75edb2c0a6 100644
--- a/hw/acpi/cxl.c
+++ b/hw/acpi/cxl.c
@@ -172,7 +172,7 @@ static void cedt_build_cfmws(CXLFixedWindow *fw, Aml *cedt)
build_append_int_noprefix(table_data, fw->enc_int_gran, 4);
/* Window Restrictions */
- build_append_int_noprefix(table_data, 0x2f, 2);
+ build_append_int_noprefix(table_data, 0x0f, 2);
/* QTG ID */
build_append_int_noprefix(table_data, 0, 2);
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 27/75] tests/acpi/cxl: Update CEDT.cxl for the default CFMW restrictions
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (25 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 26/75] hw/cxl: Drop Back-Invalidate from default CFMW window restrictions Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 28/75] hw/cxl: Add configurable CXL Fixed Memory Window restriction flags Michael S. Tsirkin
` (49 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Davidlohr Bueso, Igor Mammedov, Ani Sinha
From: Davidlohr Bueso <dave@stgolabs.net>
With the default CXL Fixed Memory Window restrictions changed to drop
Back-Invalidate (keeping device-coherent and host-only), update the
expected CEDT to advertise 0x0f instead of 0x2f.
[064h 0100 001h] Subtable Type : 01 [CXL Fixed Memory Window Structure]
[065h 0101 001h] Reserved : 00
[066h 0102 002h] Length : 0028
[068h 0104 004h] Reserved : 00000000
[06Ch 0108 008h] Window base address : 0000000110000000
[074h 0116 008h] Window size : 0000000100000000
[07Ch 0124 001h] Interleave Members : 00
[07Dh 0125 001h] Interleave Arithmetic : 00
[07Eh 0126 002h] Reserved : 0000
[080h 0128 004h] Granularity : 00000005
[084h 0132 002h] Restrictions : 000F
[086h 0134 002h] QtgId : 0000
[088h 0136 004h] First Target : 0000000C
Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260720233242.901544-4-dave@stgolabs.net>
---
tests/qtest/bios-tables-test-allowed-diff.h | 1 -
tests/data/acpi/x86/q35/CEDT.cxl | Bin 184 -> 184 bytes
2 files changed, 1 deletion(-)
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
index b4646b5b31..dfb8523c8b 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1,2 +1 @@
/* List of comma-separated changed AML files to ignore */
-"tests/data/acpi/x86/q35/CEDT.cxl",
diff --git a/tests/data/acpi/x86/q35/CEDT.cxl b/tests/data/acpi/x86/q35/CEDT.cxl
index c35f3882eee67aa5613af427234d1ccd196aa249..ff8203af070241bd23dd0eb8a51460692bb7d229 100644
GIT binary patch
delta 36
scmdnNxPy_)+0`Xv2Ll5G<Hw0yRgC--Th)2^85kIN7#JAtF)%Oy0IW3!t^fc4
delta 36
scmdnNxPy_)+0`Xv2Ll5G<Hm_xRgC%*Th)2=85kIN7#JAtF)%Oy0IF37t^fc4
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 28/75] hw/cxl: Add configurable CXL Fixed Memory Window restriction flags
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (26 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 27/75] tests/acpi/cxl: Update CEDT.cxl for the default CFMW restrictions Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 29/75] tests/qtest/cxl: Add CXL Fixed Memory Window restriction flag tests Michael S. Tsirkin
` (48 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Davidlohr Bueso, Pierrick Bouvier, Igor Mammedov,
Ani Sinha, Jonathan Cameron, Junjie Cao, Eric Blake,
Markus Armbruster, Philippe Mathieu-Daudé, Zhao Liu,
linux-cxl
From: Davidlohr Bueso <dave@stgolabs.net>
Expose the CFMWS "Window Restrictions" (CXL r4.0 9.18.1.3) as named
per-window machine properties -- device-coherent, host-only, volatile,
persistent, fixed-config and back-invalidate -- so the advertised
restrictions can be configured per window rather than left at the
default.
No changes in default options. HDM-D and HDM-H are advertised by default;
disabling one (device-coherent=off or host-only=off) narrows the window to
the other. back-invalidate implies device-coherent (HDM-DB) and suppresses
the host-only default. host-only coherent combined with back-invalidate is
rejected as undefined behavior per the spec.
Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260720233242.901544-5-dave@stgolabs.net>
---
docs/system/devices/cxl.rst | 25 ++++++++++++--------
qapi/machine.json | 28 ++++++++++++++++++++++
include/hw/cxl/cxl.h | 12 ++++++++++
hw/acpi/cxl.c | 2 +-
hw/cxl/cxl-host.c | 46 +++++++++++++++++++++++++++++++++++++
5 files changed, 102 insertions(+), 11 deletions(-)
diff --git a/docs/system/devices/cxl.rst b/docs/system/devices/cxl.rst
index 9d0771cdfd..6bee339cea 100644
--- a/docs/system/devices/cxl.rst
+++ b/docs/system/devices/cxl.rst
@@ -384,8 +384,13 @@ An example of 4 devices below a switch suitable for 1, 2 or 4 way interleave::
-device cxl-type3,bus=swport3,persistent-memdev=cxl-mem3,lsa=cxl-lsa3,id=cxl-pmem3,sn=0x4 \
-M cxl-fmw.0.targets.0=cxl.1,cxl-fmw.0.size=4G,cxl-fmw.0.interleave-granularity=4k
-An example of 4 type3 devices with volatile memory below a switch. Two of the devices
-use HDM-DB for coherence, which requires operating in Flit mode::
+An example of a mixed configuration across two host bridges, each with its
+own CXL window. Below cxl.1, two type3 volatile devices behind a switch use
+HDM-DB for coherence, which requires operating in Flit mode and a window
+that permits the device-coherent Back-Invalidate model. Below cxl.2, two
+plain host-only devices are directly attached and use the default window.
+Because a window targets a host bridge, giving each coherency model its own
+bridge keeps the window-to-device mapping explicit::
qemu-system-x86_64 -M q35,cxl=on -m 4G,maxmem=8G,slots=8 -smp 4 \
...
@@ -395,17 +400,17 @@ use HDM-DB for coherence, which requires operating in Flit mode::
-object memory-backend-ram,id=cxl-mem3,share=on,size=256M \
-device pxb-cxl,bus_nr=12,bus=pcie.0,id=cxl.1 \
-device cxl-rp,port=0,bus=cxl.1,id=root_port0,chassis=0,slot=0 \
- -device cxl-rp,port=1,bus=cxl.1,id=root_port1,chassis=0,slot=1 \
-device cxl-upstream,bus=root_port0,id=us0,x-256b-flit=on \
-device cxl-downstream,port=0,bus=us0,id=swport0,chassis=0,slot=4 \
- -device cxl-type3,bus=swport0,volatile-memdev=cxl-mem0,id=cxl-mem0,sn=0x1,x-256b-flit=on,hdm-db=on \
+ -device cxl-type3,bus=swport0,volatile-memdev=cxl-mem0,id=cxl-vmem0,sn=0x1,x-256b-flit=on,hdm-db=on \
-device cxl-downstream,port=1,bus=us0,id=swport1,chassis=0,slot=5 \
- -device cxl-type3,bus=swport1,volatile-memdev=cxl-mem1,id=cxl-mem1,sn=0x2,x-256b-flit=on,hdm-db=on \
- -device cxl-downstream,port=2,bus=us0,id=swport2,chassis=0,slot=6 \
- -device cxl-type3,bus=swport2,volatile-memdev=cxl-mem2,id=cxl-mem2,sn=0x3 \
- -device cxl-downstream,port=3,bus=us0,id=swport3,chassis=0,slot=7 \
- -device cxl-type3,bus=swport3,volatile-memdev=cxl-mem3,id=cxl-mem3,sn=0x4 \
- -M cxl-fmw.0.targets.0=cxl.1,cxl-fmw.0.size=4G,cxl-fmw.0.interleave-granularity=4k
+ -device cxl-type3,bus=swport1,volatile-memdev=cxl-mem1,id=cxl-vmem1,sn=0x2,x-256b-flit=on,hdm-db=on \
+ -device pxb-cxl,bus_nr=222,bus=pcie.0,id=cxl.2 \
+ -device cxl-rp,port=0,bus=cxl.2,id=root_port1,chassis=0,slot=6 \
+ -device cxl-type3,bus=root_port1,volatile-memdev=cxl-mem2,id=cxl-vmem2,sn=0x3 \
+ -device cxl-rp,port=1,bus=cxl.2,id=root_port2,chassis=0,slot=7 \
+ -device cxl-type3,bus=root_port2,volatile-memdev=cxl-mem3,id=cxl-vmem3,sn=0x4 \
+ -M cxl-fmw.0.targets.0=cxl.1,cxl-fmw.0.size=4G,cxl-fmw.0.interleave-granularity=4k,cxl-fmw.0.back-invalidate=on,cxl-fmw.1.targets.0=cxl.2,cxl-fmw.1.size=4G,cxl-fmw.1.interleave-granularity=4k
A simple arm/virt example featuring a single direct connected CXL Type 3
Volatile Memory device::
diff --git a/qapi/machine.json b/qapi/machine.json
index 2d63c1bac3..de6460f091 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -552,15 +552,43 @@
# accesses will go to a given interleave target. Accepted values
# [256, 512, 1k, 2k, 4k, 8k, 16k]
#
+# @device-coherent: Window permits device-coherent (minimally HDM-D)
+# accesses. (since 11.1)
+#
+# @host-only: Window permits host-only coherent (HDM-H) accesses.
+# (since 11.1)
+#
+# @volatile: Window permits volatile memory. (since 11.1)
+#
+# @persistent: Window permits persistent memory. (since 11.1)
+#
+# @fixed-config: Window has a fixed device configuration. Advertised
+# in the CEDT only; not otherwise emulated. (since 11.1)
+#
+# @back-invalidate: Window permits Back-Invalidate (HDM-DB). Implies
+# @device-coherent. (since 11.1)
+#
# @targets: Target root bridge IDs from -device ...,id=<ID> for each
# root bridge.
#
+# Coherency defaults to both device-coherent and host-only; disabling
+# one (host-only=off or device-coherent=off) narrows to the other.
+# @back-invalidate implies device-coherent and is not host-only.
+# @volatile and @persistent default on. host-only coherent combined
+# with @back-invalidate is rejected as undefined behavior.
+#
# Since: 7.1
##
{ 'struct': 'CXLFixedMemoryWindowOptions',
'data': {
'size': 'size',
'*interleave-granularity': 'size',
+ '*device-coherent': 'bool',
+ '*host-only': 'bool',
+ '*volatile': 'bool',
+ '*persistent': 'bool',
+ '*fixed-config': 'bool',
+ '*back-invalidate': 'bool',
'targets': ['str'] }}
##
diff --git a/include/hw/cxl/cxl.h b/include/hw/cxl/cxl.h
index d8cd8359d2..7cf3dc622c 100644
--- a/include/hw/cxl/cxl.h
+++ b/include/hw/cxl/cxl.h
@@ -27,6 +27,17 @@
typedef struct PXBCXLDev PXBCXLDev;
+/*
+ * CEDT CFMWS "Window Restrictions" bits (CXL r4.0 9.18.1.3), advertising
+ * which capabilities the host bridges below this window support.
+ */
+#define CXL_FMW_DEVICE_COHERENT (1 << 0) /* HDM-D */
+#define CXL_FMW_HOST_ONLY (1 << 1) /* HDM-H */
+#define CXL_FMW_VOLATILE (1 << 2)
+#define CXL_FMW_PERSISTENT (1 << 3)
+#define CXL_FMW_FIXED_CONFIG (1 << 4)
+#define CXL_FMW_BI (1 << 5) /* HDM-DB, Back-Invalidate */
+
typedef struct CXLFixedWindow {
SysBusDevice parent_obj;
int index;
@@ -36,6 +47,7 @@ typedef struct CXLFixedWindow {
uint8_t num_targets;
uint8_t enc_int_ways;
uint8_t enc_int_gran;
+ uint16_t restrictions;
/* Todo: XOR based interleaving */
MemoryRegion mr;
hwaddr base;
diff --git a/hw/acpi/cxl.c b/hw/acpi/cxl.c
index 75edb2c0a6..77c1db6561 100644
--- a/hw/acpi/cxl.c
+++ b/hw/acpi/cxl.c
@@ -172,7 +172,7 @@ static void cedt_build_cfmws(CXLFixedWindow *fw, Aml *cedt)
build_append_int_noprefix(table_data, fw->enc_int_gran, 4);
/* Window Restrictions */
- build_append_int_noprefix(table_data, 0x0f, 2);
+ build_append_int_noprefix(table_data, fw->restrictions, 2);
/* QTG ID */
build_append_int_noprefix(table_data, 0, 2);
diff --git a/hw/cxl/cxl-host.c b/hw/cxl/cxl-host.c
index 369a985f9b..e279ce5fe3 100644
--- a/hw/cxl/cxl-host.c
+++ b/hw/cxl/cxl-host.c
@@ -61,6 +61,52 @@ static void cxl_fixed_memory_window_config(CXLFixedMemoryWindowOptions *object,
fw->enc_int_gran = 0;
}
+ /*
+ * HDM-D and HDM-H are advertised by default; disabling one
+ * (host-only=off or device-coherent=off) narrows the window to the
+ * other.
+ */
+ if (!object->has_device_coherent || object->device_coherent) {
+ fw->restrictions |= CXL_FMW_DEVICE_COHERENT;
+ }
+ if (object->has_host_only ? object->host_only : !object->back_invalidate) {
+ fw->restrictions |= CXL_FMW_HOST_ONLY;
+ }
+ if (object->back_invalidate) {
+ fw->restrictions |= CXL_FMW_DEVICE_COHERENT | CXL_FMW_BI;
+ }
+
+ if (!(fw->restrictions & (CXL_FMW_DEVICE_COHERENT | CXL_FMW_HOST_ONLY))) {
+ error_setg(errp, "CFMW coherency model required");
+ return;
+ }
+
+ if (object->fixed_config) {
+ fw->restrictions |= CXL_FMW_FIXED_CONFIG; /* no-op */
+ }
+
+ /* Volatile and persistent are permitted unless explicitly disabled. */
+ if (!object->has_q_volatile || object->q_volatile) {
+ fw->restrictions |= CXL_FMW_VOLATILE;
+ }
+ if (!object->has_persistent || object->persistent) {
+ fw->restrictions |= CXL_FMW_PERSISTENT;
+ }
+ if (!(fw->restrictions & (CXL_FMW_VOLATILE | CXL_FMW_PERSISTENT))) {
+ error_setg(errp, "CFMW volatile and/or persistent memory required");
+ return;
+ }
+
+ /*
+ * Reject the undefined and conflicting coherency combinations,
+ * per CXL r4.0 9.18.1.3.
+ */
+ if ((fw->restrictions & CXL_FMW_HOST_ONLY) &&
+ (fw->restrictions & CXL_FMW_BI)) {
+ error_setg(errp, "CFMW host-only coherency + BI is undefined behavior");
+ return;
+ }
+
fw->targets = g_malloc0_n(fw->num_targets, sizeof(*fw->targets));
for (i = 0, target = object->targets; target; i++, target = target->next) {
/* This link cannot be resolved yet, so stash the name for now */
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 29/75] tests/qtest/cxl: Add CXL Fixed Memory Window restriction flag tests
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (27 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 28/75] hw/cxl: Add configurable CXL Fixed Memory Window restriction flags Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 30/75] hw/net/virtio-net: check packet size before VLAN tag access in receive_filter() Michael S. Tsirkin
` (47 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Davidlohr Bueso, Fabiano Rosas, Laurent Vivier,
Paolo Bonzini
From: Davidlohr Bueso <dave@stgolabs.net>
Add a /pci/cxl/cfmw group exercising the configurable CFMWS Window
Restrictions.
Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260720233242.901544-6-dave@stgolabs.net>
---
tests/qtest/cxl-test.c | 95 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 95 insertions(+)
diff --git a/tests/qtest/cxl-test.c b/tests/qtest/cxl-test.c
index 8fb7e58d4f..49d820cde1 100644
--- a/tests/qtest/cxl-test.c
+++ b/tests/qtest/cxl-test.c
@@ -81,6 +81,13 @@
"-object memory-backend-file,id=lsa3,mem-path=%s,size=256M " \
"-device cxl-type3,bus=rp3,persistent-memdev=cxl-mem3,lsa=lsa3,id=pmem3 "
+/* Single pxb + volatile type3 + one window; base for the CFMW tests. */
+#define QEMU_CFMW \
+ "-machine q35,cxl=on " \
+ "-device pxb-cxl,id=cxl.0,bus=pcie.0,bus_nr=52 " \
+ QEMU_RP QEMU_T3D_VMEM \
+ "-M cxl-fmw.0.targets.0=cxl.0,cxl-fmw.0.size=4G"
+
static void cxl_basic_hb(void)
{
qtest_start("-machine q35,cxl=on");
@@ -117,6 +124,81 @@ static void cxl_2root_port(void)
qtest_end();
}
+/*
+ * CFMWS "Window Restrictions" (CXL r4.0 9.18.1.3) are configurable per
+ * window; check that valid restriction sets are accepted.
+ */
+static void cxl_cfmw_default(void)
+{
+ /* No coherency flag advertises both HDM-D and HDM-H. */
+ qtest_start(QEMU_CFMW);
+ qtest_end();
+}
+
+static void cxl_cfmw_host_only_off(void)
+{
+ /* Disabling host-only leaves device-coherent (HDM-D). */
+ qtest_start(QEMU_CFMW ",cxl-fmw.0.host-only=off");
+ qtest_end();
+}
+
+static void cxl_cfmw_device_coherent_off(void)
+{
+ /* Disabling device-coherent leaves host-only (HDM-H). */
+ qtest_start(QEMU_CFMW ",cxl-fmw.0.device-coherent=off");
+ qtest_end();
+}
+
+static void cxl_cfmw_back_invalidate(void)
+{
+ /* Back-Invalidate implies device-coherent (HDM-DB). */
+ qtest_start(QEMU_CFMW ",cxl-fmw.0.back-invalidate=on");
+ qtest_end();
+}
+
+static void cxl_cfmw_fixed_config(void)
+{
+ qtest_start(QEMU_CFMW ",cxl-fmw.0.fixed-config=on");
+ qtest_end();
+}
+
+static void cxl_cfmw_device_and_host(void)
+{
+ /*
+ * device-coherent and host-only may both be advertised (the spec
+ * permits multiple bits set); this must be accepted -- a regression
+ * guard against reinstating a device/host-only mutual exclusion.
+ */
+ qtest_start(QEMU_CFMW
+ ",cxl-fmw.0.device-coherent=on,cxl-fmw.0.host-only=on");
+ qtest_end();
+}
+
+static void cxl_cfmw_volatile_only(void)
+{
+ qtest_start(QEMU_CFMW ",cxl-fmw.0.persistent=off");
+ qtest_end();
+}
+
+static void cxl_cfmw_persistent_only(void)
+{
+ qtest_start(QEMU_CFMW ",cxl-fmw.0.volatile=off");
+ qtest_end();
+}
+
+/* Two windows in one VM: a Back-Invalidate window and a host-only window. */
+static void cxl_cfmw_two_windows(void)
+{
+ qtest_start("-machine q35,cxl=on "
+ "-device pxb-cxl,id=cxl.0,bus=pcie.0,bus_nr=52 "
+ "-device pxb-cxl,id=cxl.1,bus=pcie.0,bus_nr=53 "
+ QEMU_RP QEMU_T3D_VMEM
+ "-M cxl-fmw.0.targets.0=cxl.0,cxl-fmw.0.size=4G,"
+ "cxl-fmw.0.back-invalidate=on,"
+ "cxl-fmw.1.targets.0=cxl.1,cxl-fmw.1.size=4G");
+ qtest_end();
+}
+
#ifdef CONFIG_POSIX
static void cxl_t3d_deprecated(void)
{
@@ -233,6 +315,19 @@ int main(int argc, char **argv)
qtest_add_func("/pci/cxl/pxb_x2_with_window", cxl_2pxb_with_window);
qtest_add_func("/pci/cxl/rp", cxl_root_port);
qtest_add_func("/pci/cxl/rp_x2", cxl_2root_port);
+ qtest_add_func("/pci/cxl/cfmw/default", cxl_cfmw_default);
+ qtest_add_func("/pci/cxl/cfmw/host_only_off", cxl_cfmw_host_only_off);
+ qtest_add_func("/pci/cxl/cfmw/device_coherent_off",
+ cxl_cfmw_device_coherent_off);
+ qtest_add_func("/pci/cxl/cfmw/back_invalidate",
+ cxl_cfmw_back_invalidate);
+ qtest_add_func("/pci/cxl/cfmw/fixed_config", cxl_cfmw_fixed_config);
+ qtest_add_func("/pci/cxl/cfmw/device_and_host",
+ cxl_cfmw_device_and_host);
+ qtest_add_func("/pci/cxl/cfmw/volatile_only", cxl_cfmw_volatile_only);
+ qtest_add_func("/pci/cxl/cfmw/persistent_only",
+ cxl_cfmw_persistent_only);
+ qtest_add_func("/pci/cxl/cfmw/two_windows", cxl_cfmw_two_windows);
#ifdef CONFIG_POSIX
qtest_add_func("/pci/cxl/type3_device", cxl_t3d_deprecated);
qtest_add_func("/pci/cxl/type3_device_pmem", cxl_t3d_persistent);
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 30/75] hw/net/virtio-net: check packet size before VLAN tag access in receive_filter()
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (28 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 29/75] tests/qtest/cxl: Add CXL Fixed Memory Window restriction flag tests Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 31/75] hw/virtio-blk: Account discard operations Michael S. Tsirkin
` (46 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Laurent Vivier, qemu-stable,
Philippe Mathieu-Daudé, Jason Wang
From: Laurent Vivier <lvivier@redhat.com>
receive_filter() reads ptr[14..15] to extract the VLAN ID without
checking the packet is large enough. A short frame with VLAN TPID
at bytes 12-13 but no VLAN TCI causes a 2-byte out-of-bounds read.
Add size checks before accessing the Ethernet header and the VLAN
tag fields.
Cc: qemu-stable@nongnu.org
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3788
Fixes: f21c0ed97c97 ("qemu:virtio-net: Add VLAN filtering (Alex Williamson)")
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260722115008.1570510-1-lvivier@redhat.com>
---
hw/net/virtio-net.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 274fbcb0d6..f3f375e1b2 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1751,12 +1751,16 @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size)
}
ptr += n->host_hdr_len;
+ size -= n->host_hdr_len;
+
+ if (size < sizeof(struct eth_header)) {
+ return 0;
+ }
if (!memcmp(&ptr[12], vlan, sizeof(vlan))) {
int vid;
- /* Truncated vlan packet */
- if (size < n->host_hdr_len + 16) {
+ if (size < 16) {
return 0;
}
vid = lduw_be_p(ptr + 14) & 0xfff;
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 31/75] hw/virtio-blk: Account discard operations
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (29 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 30/75] hw/net/virtio-net: check packet size before VLAN tag access in receive_filter() Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 32/75] hw/virtio-blk: Complete zone-append cookies Michael S. Tsirkin
` (45 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Hanna Czenczek, Stefan Hajnoczi, Kevin Wolf,
qemu-block
From: Hanna Czenczek <hreitz@redhat.com>
The acct_failed argument to virtio_blk_handle_rw_error() tells whether
there is accounting for this operation or not. The only operation for
which there is none is discarding, which seems to be because at the time
of the introducing commit 37b06f8d46f ("virtio-blk: add DISCARD and
WRITE_ZEROES features"), BlockAcctType did not yet have a
BLOCK_ACCT_UNMAP variant.
It does have that now, though, so we may as well track those discard
operations with it, and can thus remove the acct_failed parameter.
Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260724152315.234183-2-hreitz@redhat.com>
---
hw/block/virtio-blk.c | 26 +++++++++++---------------
1 file changed, 11 insertions(+), 15 deletions(-)
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index cb6a276a82..4110380392 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -69,7 +69,7 @@ void virtio_blk_req_complete(VirtIOBlockReq *req, unsigned char status)
}
static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
- bool is_read, bool acct_failed)
+ bool is_read)
{
VirtIOBlock *s = req->dev;
BlockErrorAction action = blk_get_error_action(s->blk, is_read, error);
@@ -85,9 +85,7 @@ static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
}
} else if (action == BLOCK_ERROR_ACTION_REPORT) {
virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
- if (acct_failed) {
- block_acct_failed(blk_get_stats(s->blk), &req->acct);
- }
+ block_acct_failed(blk_get_stats(s->blk), &req->acct);
g_free(req);
}
@@ -124,7 +122,7 @@ static void virtio_blk_rw_complete(void *opaque, int ret)
* the memory until the request is completed (which will
* happen on the other side of the migration).
*/
- if (virtio_blk_handle_rw_error(req, -ret, is_read, true)) {
+ if (virtio_blk_handle_rw_error(req, -ret, is_read)) {
continue;
}
}
@@ -140,7 +138,7 @@ static void virtio_blk_flush_complete(void *opaque, int ret)
VirtIOBlockReq *req = opaque;
VirtIOBlock *s = req->dev;
- if (ret && virtio_blk_handle_rw_error(req, -ret, 0, true)) {
+ if (ret && virtio_blk_handle_rw_error(req, -ret, 0)) {
return;
}
@@ -153,17 +151,13 @@ static void virtio_blk_discard_write_zeroes_complete(void *opaque, int ret)
{
VirtIOBlockReq *req = opaque;
VirtIOBlock *s = req->dev;
- bool is_write_zeroes = (virtio_ldl_p(VIRTIO_DEVICE(s), &req->out.type) &
- ~VIRTIO_BLK_T_BARRIER) == VIRTIO_BLK_T_WRITE_ZEROES;
- if (ret && virtio_blk_handle_rw_error(req, -ret, false, is_write_zeroes)) {
+ if (ret && virtio_blk_handle_rw_error(req, -ret, false)) {
return;
}
virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
- if (is_write_zeroes) {
- block_acct_done(blk_get_stats(s->blk), &req->acct);
- }
+ block_acct_done(blk_get_stats(s->blk), &req->acct);
g_free(req);
}
@@ -443,6 +437,9 @@ static uint8_t virtio_blk_handle_discard_write_zeroes(VirtIOBlockReq *req,
goto err;
}
+ block_acct_start(blk_get_stats(s->blk), &req->acct, bytes,
+ BLOCK_ACCT_UNMAP);
+
blk_aio_pdiscard(s->blk, sector << BDRV_SECTOR_BITS, bytes,
virtio_blk_discard_write_zeroes_complete, req);
}
@@ -450,9 +447,8 @@ static uint8_t virtio_blk_handle_discard_write_zeroes(VirtIOBlockReq *req,
return VIRTIO_BLK_S_OK;
err:
- if (is_write_zeroes) {
- block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_WRITE);
- }
+ block_acct_invalid(blk_get_stats(s->blk),
+ is_write_zeroes ? BLOCK_ACCT_WRITE : BLOCK_ACCT_UNMAP);
return err_status;
}
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 32/75] hw/virtio-blk: Complete zone-append cookies
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (30 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 31/75] hw/virtio-blk: Account discard operations Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 33/75] hw/nvme: Fix block accounting in nvme_copy() Michael S. Tsirkin
` (44 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Hanna Czenczek, Stefan Hajnoczi, Kevin Wolf,
qemu-block
From: Hanna Czenczek <hreitz@redhat.com>
virtio_blk_handle_zone_append() starts accounting via
block_acct_start(), but this is actually never completed. Do so.
Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260724152315.234183-3-hreitz@redhat.com>
---
hw/block/virtio-blk.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index 4110380392..61c341ce2c 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -755,7 +755,8 @@ static void virtio_blk_zone_append_complete(void *opaque, int ret)
{
ZoneCmdData *data = opaque;
VirtIOBlockReq *req = data->req;
- VirtIODevice *vdev = VIRTIO_DEVICE(req->dev);
+ VirtIOBlock *s = req->dev;
+ VirtIODevice *vdev = VIRTIO_DEVICE(s);
int64_t append_sector, n;
uint8_t err_status = VIRTIO_BLK_S_OK;
@@ -778,6 +779,11 @@ static void virtio_blk_zone_append_complete(void *opaque, int ret)
out:
virtio_blk_req_complete(req, err_status);
+ if (err_status == VIRTIO_BLK_S_OK) {
+ block_acct_done(blk_get_stats(s->blk), &req->acct);
+ } else {
+ block_acct_failed(blk_get_stats(s->blk), &req->acct);
+ }
g_free(req);
g_free(data);
}
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 33/75] hw/nvme: Fix block accounting in nvme_copy()
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (31 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 32/75] hw/virtio-blk: Complete zone-append cookies Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 34/75] hw/nvme: Fix block accounting for compare Michael S. Tsirkin
` (43 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Hanna Czenczek, Klaus Jensen, Stefan Hajnoczi,
Keith Busch, Klaus Jensen, Jesper Devantier, qemu-block
From: Hanna Czenczek <hreitz@redhat.com>
In nvme_copy(), we start accounting for each of the copied ranges, but
only end it once (in nvme_copy_done()). We should end it after each
read/write operation is done instead, so they are properly accounted
for.
We should also actually pass the number of bytes we are reading/writing
(instead of 0), and probably account for the metadata operations also,
as they are block operations we execute.
Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
Reviewed-by: Klaus Jensen <k.jensen@samsung.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260724152315.234183-4-hreitz@redhat.com>
---
hw/nvme/ctrl.c | 53 +++++++++++++++++++++++++++++++-------------------
1 file changed, 33 insertions(+), 20 deletions(-)
diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index c662d968db..c56725947a 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -2802,8 +2802,6 @@ static const AIOCBInfo nvme_copy_aiocb_info = {
static void nvme_copy_done(NvmeCopyAIOCB *iocb)
{
NvmeRequest *req = iocb->req;
- NvmeNamespace *ns = req->ns;
- BlockAcctStats *stats = blk_get_stats(ns->blkconf.blk);
if (iocb->idx != iocb->nr) {
req->cqe.result = cpu_to_le32(iocb->idx);
@@ -2813,14 +2811,6 @@ static void nvme_copy_done(NvmeCopyAIOCB *iocb)
g_free(iocb->bounce);
g_free(iocb->ranges);
- if (iocb->ret < 0) {
- block_acct_failed(stats, &iocb->acct.read);
- block_acct_failed(stats, &iocb->acct.write);
- } else {
- block_acct_done(stats, &iocb->acct.read);
- block_acct_done(stats, &iocb->acct.write);
- }
-
iocb->common.cb(iocb->common.opaque, iocb->ret);
qemu_aio_unref(iocb);
}
@@ -2951,6 +2941,7 @@ static void nvme_copy_out_completed_cb(void *opaque, int ret)
NvmeCopyAIOCB *iocb = opaque;
NvmeRequest *req = iocb->req;
NvmeNamespace *dns = req->ns;
+ BlockAcctStats *stats = blk_get_stats(dns->blkconf.blk);
uint32_t nlb;
nvme_copy_source_range_parse(iocb->ranges, iocb->idx, iocb->format, NULL,
@@ -2959,10 +2950,12 @@ static void nvme_copy_out_completed_cb(void *opaque, int ret)
if (ret < 0) {
iocb->ret = ret;
req->status = NVME_WRITE_FAULT;
- goto out;
- } else if (iocb->ret < 0) {
+ }
+ if (iocb->ret < 0) {
+ block_acct_failed(stats, &iocb->acct.write);
goto out;
}
+ block_acct_done(stats, &iocb->acct.write);
if (dns->params.zoned) {
nvme_advance_zone_wp(dns, iocb->zone, nlb);
@@ -2979,11 +2972,18 @@ static void nvme_copy_out_cb(void *opaque, int ret)
NvmeCopyAIOCB *iocb = opaque;
NvmeRequest *req = iocb->req;
NvmeNamespace *dns = req->ns;
+ BlockAcctStats *stats = blk_get_stats(dns->blkconf.blk);
uint32_t nlb;
size_t mlen;
uint8_t *mbounce;
- if (ret < 0 || iocb->ret < 0 || !dns->lbaf.ms) {
+ if (ret < 0 || iocb->ret < 0) {
+ block_acct_failed(stats, &iocb->acct.write);
+ goto out;
+ }
+ block_acct_done(stats, &iocb->acct.write);
+
+ if (!dns->lbaf.ms) {
goto out;
}
@@ -2996,6 +2996,7 @@ static void nvme_copy_out_cb(void *opaque, int ret)
qemu_iovec_reset(&iocb->iov);
qemu_iovec_add(&iocb->iov, mbounce, mlen);
+ block_acct_start(stats, &iocb->acct.write, mlen, BLOCK_ACCT_WRITE);
iocb->aiocb = blk_aio_pwritev(dns->blkconf.blk, nvme_moff(dns, iocb->slba),
&iocb->iov, 0, nvme_copy_out_completed_cb,
iocb);
@@ -3012,6 +3013,7 @@ static void nvme_copy_in_completed_cb(void *opaque, int ret)
NvmeRequest *req = iocb->req;
NvmeNamespace *sns = iocb->sns;
NvmeNamespace *dns = req->ns;
+ BlockAcctStats *sstats = blk_get_stats(sns->blkconf.blk);
NvmeCopyCmd *copy = NULL;
uint8_t *mbounce = NULL;
uint32_t nlb;
@@ -3024,10 +3026,12 @@ static void nvme_copy_in_completed_cb(void *opaque, int ret)
if (ret < 0) {
iocb->ret = ret;
req->status = NVME_UNRECOVERED_READ;
- goto out;
- } else if (iocb->ret < 0) {
+ }
+ if (iocb->ret < 0) {
+ block_acct_failed(sstats, &iocb->acct.read);
goto out;
}
+ block_acct_done(sstats, &iocb->acct.read);
nvme_copy_source_range_parse(iocb->ranges, iocb->idx, iocb->format, &slba,
&nlb, NULL, &apptag, &appmask, &reftag);
@@ -3102,7 +3106,7 @@ static void nvme_copy_in_completed_cb(void *opaque, int ret)
qemu_iovec_reset(&iocb->iov);
qemu_iovec_add(&iocb->iov, iocb->bounce, len);
- block_acct_start(blk_get_stats(dns->blkconf.blk), &iocb->acct.write, 0,
+ block_acct_start(blk_get_stats(dns->blkconf.blk), &iocb->acct.write, len,
BLOCK_ACCT_WRITE);
iocb->aiocb = blk_aio_pwritev(dns->blkconf.blk, nvme_l2b(dns, iocb->slba),
@@ -3121,20 +3125,29 @@ static void nvme_copy_in_cb(void *opaque, int ret)
{
NvmeCopyAIOCB *iocb = opaque;
NvmeNamespace *sns = iocb->sns;
+ BlockAcctStats *stats = blk_get_stats(sns->blkconf.blk);
uint64_t slba;
uint32_t nlb;
+ size_t mlen;
- if (ret < 0 || iocb->ret < 0 || !sns->lbaf.ms) {
+ if (ret < 0 || iocb->ret < 0) {
+ block_acct_failed(stats, &iocb->acct.read);
+ goto out;
+ }
+ block_acct_done(stats, &iocb->acct.read);
+
+ if (!sns->lbaf.ms) {
goto out;
}
nvme_copy_source_range_parse(iocb->ranges, iocb->idx, iocb->format, &slba,
&nlb, NULL, NULL, NULL, NULL);
+ mlen = nvme_m2b(sns, nlb);
qemu_iovec_reset(&iocb->iov);
- qemu_iovec_add(&iocb->iov, iocb->bounce + nvme_l2b(sns, nlb),
- nvme_m2b(sns, nlb));
+ qemu_iovec_add(&iocb->iov, iocb->bounce + nvme_l2b(sns, nlb), mlen);
+ block_acct_start(stats, &iocb->acct.read, mlen, BLOCK_ACCT_READ);
iocb->aiocb = blk_aio_preadv(sns->blkconf.blk, nvme_moff(sns, slba),
&iocb->iov, 0, nvme_copy_in_completed_cb,
iocb);
@@ -3342,7 +3355,7 @@ static void nvme_do_copy(NvmeCopyAIOCB *iocb)
assert(len <= blen);
qemu_iovec_add(&iocb->iov, iocb->bounce, len);
- block_acct_start(blk_get_stats(sns->blkconf.blk), &iocb->acct.read, 0,
+ block_acct_start(blk_get_stats(sns->blkconf.blk), &iocb->acct.read, len,
BLOCK_ACCT_READ);
iocb->aiocb = blk_aio_preadv(sns->blkconf.blk, nvme_l2b(sns, slba),
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 34/75] hw/nvme: Fix block accounting for compare
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (32 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 33/75] hw/nvme: Fix block accounting in nvme_copy() Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 35/75] hw/ide: Have ide_dma_cb() complete accounting Michael S. Tsirkin
` (42 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Hanna Czenczek, Philippe Mathieu-Daudé,
Klaus Jensen, Stefan Hajnoczi, Keith Busch, Klaus Jensen,
Jesper Devantier, qemu-block
From: Hanna Czenczek <hreitz@redhat.com>
nvme_compare() starts block accounting for the operation, but
nvme_compare_data_cb() (and nvme_compare_mdata_cb()) do not always
finalize the cookie. Specifically, there are a lot of error paths that
do not call block_acct_failed().
Fix this by putting block_acct_done()/block_acct_failed() under the
`out` labels of nvme_compare_data_cb() and nvme_compare_mdata_cb().
Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Klaus Jensen <k.jensen@samsung.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260724152315.234183-5-hreitz@redhat.com>
---
hw/nvme/ctrl.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index c56725947a..7478f0b33a 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -2389,7 +2389,6 @@ static void nvme_compare_mdata_cb(void *opaque, int ret)
trace_pci_nvme_compare_mdata_cb(nvme_cid(req));
if (ret) {
- block_acct_failed(stats, acct);
req->status = NVME_UNRECOVERED_READ;
trace_pci_nvme_err_aio(nvme_cid(req), strerror(-ret), req->status);
@@ -2444,9 +2443,14 @@ static void nvme_compare_mdata_cb(void *opaque, int ret)
goto out;
}
- block_acct_done(stats, acct);
out:
+ if (req->status == NVME_SUCCESS) {
+ block_acct_done(stats, acct);
+ } else {
+ block_acct_failed(stats, acct);
+ }
+
qemu_iovec_destroy(&ctx->data.iov);
g_free(ctx->data.bounce);
@@ -2474,7 +2478,6 @@ static void nvme_compare_data_cb(void *opaque, int ret)
trace_pci_nvme_compare_data_cb(nvme_cid(req));
if (ret) {
- block_acct_failed(stats, acct);
req->status = NVME_UNRECOVERED_READ;
trace_pci_nvme_err_aio(nvme_cid(req), strerror(-ret), req->status);
@@ -2513,9 +2516,13 @@ static void nvme_compare_data_cb(void *opaque, int ret)
return;
}
- block_acct_done(stats, acct);
-
out:
+ if (req->status == NVME_SUCCESS) {
+ block_acct_done(stats, acct);
+ } else {
+ block_acct_failed(stats, acct);
+ }
+
qemu_iovec_destroy(&ctx->data.iov);
g_free(ctx->data.bounce);
g_free(ctx);
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 35/75] hw/ide: Have ide_dma_cb() complete accounting
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (33 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 34/75] hw/nvme: Fix block accounting for compare Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 36/75] hw/scsi-disk: Fix accounting for IGNORE, ret > 0 Michael S. Tsirkin
` (41 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Hanna Czenczek, Stefan Hajnoczi, John Snow,
Denis V. Lunev, qemu-block
From: Hanna Czenczek <hreitz@redhat.com>
ide_sector_start_dma() starts accounting for reading and writing, and
ide_dma_cb() is supposed to complete it, but currently does not always:
In one case, it just forgets it altogether, in the other, it uses
block_acct_invalid(), which should not be used after a cookie has
already been created.
Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260724152315.234183-6-hreitz@redhat.com>
---
hw/ide/core.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/hw/ide/core.c b/hw/ide/core.c
index ef573798d9..06e6bb6067 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -898,6 +898,7 @@ static void ide_dma_cb(void *opaque, int ret)
if (ret == -EINVAL) {
ide_dma_error(s);
+ block_acct_failed(blk_get_stats(s->blk), &s->acct);
return;
}
@@ -968,7 +969,7 @@ static void ide_dma_cb(void *opaque, int ret)
if ((s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) &&
!ide_sect_range_ok(s, sector_num, n)) {
ide_dma_error(s);
- block_acct_invalid(blk_get_stats(s->blk), s->acct.type);
+ block_acct_failed(blk_get_stats(s->blk), &s->acct);
return;
}
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 36/75] hw/scsi-disk: Fix accounting for IGNORE, ret > 0
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (34 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 35/75] hw/ide: Have ide_dma_cb() complete accounting Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 37/75] meson: disable "maybe uninitilized" errors with -Og Michael S. Tsirkin
` (40 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Hanna Czenczek, Stefan Hajnoczi, Paolo Bonzini,
Fam Zheng
From: Hanna Czenczek <hreitz@redhat.com>
When encountering SCSI error status (ret > 0), accounting is left to
scsi_handle_rw_error(), but the BLOCK_ERROR_ACTION_IGNORE path in turn
leaves accounting (block_acct_done()) to the caller, so neither side
does it. Fix this by unconditionally calling block_acct_done() in the
IGNORE path. Yes, this will often result in it being called twice, but
that is a no-op, as block_acct_done() resets the cookie type to
BLOCK_ACCT_NONE, and will only do accounting if the type is not
BLOCK_ACCT_NONE.
(And given that the conditions on who does what accounting are quite
confusing in scsi-disk, for me at least, I prefer this unconditional
call rather than guard it with a condition that has no obvious reason.)
Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260724152315.234183-7-hreitz@redhat.com>
---
hw/scsi/scsi-disk.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index a42f7d8e77..deb33ac1dd 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -318,6 +318,13 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int ret, bool acct_failed)
return true;
case BLOCK_ERROR_ACTION_IGNORE:
+ /*
+ * The caller may have already finalized the accounting cookie
+ * (e.g. scsi_dma_complete() for ret < 0), but calling
+ * block_acct_done() afterwards is fine (just a no-op). Just
+ * make sure all cookies are indeed accounted at some point.
+ */
+ block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
return false;
case BLOCK_ERROR_ACTION_STOP:
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 37/75] meson: disable "maybe uninitilized" errors with -Og
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (35 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 36/75] hw/scsi-disk: Fix accounting for IGNORE, ret > 0 Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 38/75] hw/net/virtio-net: strip trailing padding when caching RSC segment Michael S. Tsirkin
` (39 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Daniel P. Berrangé, Paolo Bonzini,
Marc-André Lureau, Pierrick Bouvier
GCC's "maybe uninitilized" warnings depend on optimizations
for code flow analysis, and produce false positive errors
with -Og. Default build gives us coverage with that,
so let's just disable with -Og.
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <f559b622eb2d1a384b4f30583a8af10531f4b032.1785144729.git.mst@redhat.com>
---
meson.build | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/meson.build b/meson.build
index ec9b05414a..e2da31880b 100644
--- a/meson.build
+++ b/meson.build
@@ -746,6 +746,10 @@ warn_flags = [
'-Wno-typedef-redefinition',
]
+if get_option('optimization') == 'g'
+ warn_flags += ['-Wno-error=maybe-uninitialized']
+endif
+
if host_os != 'darwin'
tsa_has_cleanup = cc.compiles('''
struct __attribute__((capability("mutex"))) mutex {};
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 38/75] hw/net/virtio-net: strip trailing padding when caching RSC segment
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (36 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 37/75] meson: disable "maybe uninitilized" errors with -Og Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 39/75] virtio-crypto: clean up every data queue Michael S. Tsirkin
` (38 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Laurent Vivier, qemu-stable, Yuri Benditovich,
Sven, Jason Wang
From: Laurent Vivier <lvivier@redhat.com>
When an RSC candidate packet has trailing padding bytes beyond the
declared IP payload, virtio_net_rsc_cache_buf() copies the full wire
size into the coalescing buffer and sets seg->size to that value.
The bounds check in virtio_net_rsc_coalesce_data() uses the IP
length field (o_ip_len) which does not include the padding, so the
check can pass while the subsequent memmove() overflows the buffer.
Fix this by computing the actual IP packet size from the IP header
and using it for both the memcpy and seg->size, so that seg->size
stays in sync with the IP length field. virtio_net_rsc_sanity_check4/6()
guarantees that ip_size <= size.
Fixes: CVE-2026-66900
Fixes: 2974e916df87 ("virtio-net: support RSC v4/v6 tcp traffic for Windows HCK")
Cc: qemu-stable@nongnu.org
Cc: Yuri Benditovich <ybendito@redhat.com>
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3879
Reported-by: Sven <bestswngs@gmail.com>
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260728082311.4179910-1-lvivier@redhat.com>
---
hw/net/virtio-net.c | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index f3f375e1b2..23c26aa08c 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -2200,13 +2200,31 @@ static void virtio_net_rsc_cache_buf(VirtioNetRscChain *chain,
{
uint16_t hdr_len;
VirtioNetRscSeg *seg;
+ size_t ip_size;
hdr_len = chain->n->guest_hdr_len;
+
+ /*
+ * Strip any trailing padding beyond the IP payload so that seg->size
+ * stays in sync with the IP length field used by the bounds check in
+ * virtio_net_rsc_coalesce_data(). virtio_net_rsc_sanity_check4/6()
+ * guarantees that ip_size <= size.
+ */
+ ip_size = hdr_len + sizeof(struct eth_header);
+ if (chain->proto == ETH_P_IP) {
+ struct ip_header *ip = (struct ip_header *)(buf + ip_size);
+ ip_size += htons(ip->ip_len);
+ } else {
+ struct ip6_header *ip6 = (struct ip6_header *)(buf + ip_size);
+ ip_size += sizeof(struct ip6_header)
+ + htons(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen);
+ }
+
seg = g_new(VirtioNetRscSeg, 1);
seg->buf = g_malloc(hdr_len + sizeof(struct eth_header)
+ sizeof(struct ip6_header) + VIRTIO_NET_MAX_TCP_PAYLOAD);
- memcpy(seg->buf, buf, size);
- seg->size = size;
+ memcpy(seg->buf, buf, ip_size);
+ seg->size = ip_size;
seg->packets = 1;
seg->dup_ack = 0;
seg->is_coalesced = 0;
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 39/75] virtio-crypto: clean up every data queue
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (37 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 38/75] hw/net/virtio-net: strip trailing padding when caching RSC segment Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 40/75] hw/virtio: reject inverted virtio-iommu IOVA ranges Michael S. Tsirkin
` (37 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, GuoHan Zhao, Gonglei (Arei)
From: GuoHan Zhao <zhaoguohan@kylinos.cn>
realize() creates max_queues data queues and one BH for each of them.
unrealize() decides how many to tear down from multiqueue, but nothing ever
sets that field, so it only deletes the first queue and BH.
It does not matter how many queues the guest used here. unrealize() must
undo all the allocations made by realize(), so loop over max_queues.
Fixes: 20cb2ffd5ff3 ("virtio-crypto: using bh to handle dataq's requests")
Signed-off-by: GuoHan Zhao <zhaoguohan@kylinos.cn>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260728111217.573046-1-zhaoguohan@kylinos.cn>
---
hw/virtio/virtio-crypto.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
index 79e2acb56c..85c7279aae 100644
--- a/hw/virtio/virtio-crypto.c
+++ b/hw/virtio/virtio-crypto.c
@@ -1114,10 +1114,9 @@ static void virtio_crypto_device_unrealize(DeviceState *dev)
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(dev);
VirtIOCryptoQueue *q;
- int i, max_queues;
+ int i;
- max_queues = vcrypto->multiqueue ? vcrypto->max_queues : 1;
- for (i = 0; i < max_queues; i++) {
+ for (i = 0; i < vcrypto->max_queues; i++) {
virtio_delete_queue(vcrypto->vqs[i].dataq);
q = &vcrypto->vqs[i];
qemu_bh_delete(q->dataq_bh);
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 40/75] hw/virtio: reject inverted virtio-iommu IOVA ranges
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (38 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 39/75] virtio-crypto: clean up every data queue Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 41/75] virtio-balloon: fix free-page BH teardown on unrealize Michael S. Tsirkin
` (36 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Jia Jia, Eric Auger
From: Jia Jia <physicalmtea@gmail.com>
Guest MAP and UNMAP requests can set virt_end below virt_start. Since
virt_end is inclusive, this is not a valid interval. MAP nevertheless
stores it in domain->mappings, but interval_cmp() assumes low <= high.
For an inverted key, interval_cmp(key, key) returns -1. A covering UNMAP
can therefore find the key but fail to remove it and repeat forever while
holding s->mutex.
Reject inverted request ranges with VIRTIO_IOMMU_S_INVAL and make the
notifier range decomposition skip invalid ranges. Keep the existing
notifier-before-remove ordering, but return VIRTIO_IOMMU_S_DEVERR if
g_tree_remove() fails.
Fixes: fe2cacae2438 ("virtio-iommu: Implement map/unmap")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4104
Signed-off-by: Jia Jia <physicalmtea@gmail.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260729131953.1720567-1-physicalmtea@gmail.com>
---
hw/virtio/virtio-iommu.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
index 533bd5073f..208815096f 100644
--- a/hw/virtio/virtio-iommu.c
+++ b/hw/virtio/virtio-iommu.c
@@ -212,6 +212,10 @@ static void virtio_iommu_notify_map_unmap(IOMMUMemoryRegion *mr,
{
uint64_t delta = virt_end - virt_start;
+ if (virt_end < virt_start) {
+ return;
+ }
+
event->entry.iova = virt_start;
event->entry.addr_mask = delta;
@@ -807,6 +811,10 @@ static int virtio_iommu_map(VirtIOIOMMU *s,
return VIRTIO_IOMMU_S_INVAL;
}
+ if (virt_end < virt_start) {
+ return VIRTIO_IOMMU_S_INVAL;
+ }
+
domain = g_tree_lookup(s->domains, GUINT_TO_POINTER(domain_id));
if (!domain) {
return VIRTIO_IOMMU_S_NOENT;
@@ -857,6 +865,10 @@ static int virtio_iommu_unmap(VirtIOIOMMU *s,
trace_virtio_iommu_unmap(domain_id, virt_start, virt_end);
+ if (virt_end < virt_start) {
+ return VIRTIO_IOMMU_S_INVAL;
+ }
+
domain = g_tree_lookup(s->domains, GUINT_TO_POINTER(domain_id));
if (!domain) {
return VIRTIO_IOMMU_S_NOENT;
@@ -879,7 +891,10 @@ static int virtio_iommu_unmap(VirtIOIOMMU *s,
virtio_iommu_notify_unmap(ep->iommu_mr, current_low,
current_high);
}
- g_tree_remove(domain->mappings, iter_key);
+ if (!g_tree_remove(domain->mappings, iter_key)) {
+ ret = VIRTIO_IOMMU_S_DEVERR;
+ break;
+ }
trace_virtio_iommu_unmap_done(domain_id, current_low, current_high);
} else {
ret = VIRTIO_IOMMU_S_RANGE;
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 41/75] virtio-balloon: fix free-page BH teardown on unrealize
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (39 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 40/75] hw/virtio: reject inverted virtio-iommu IOVA ranges Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 42/75] vhost-user.rst: fix typo Michael S. Tsirkin
` (35 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, David Hildenbrand, mhun512
When a guest triggers PCIe hot-unplug while the free-page-hint BH
is running on an IOThread, the BH will keep accessing
vq->used_elems array when running it. Note that qemu_bh_delete
merely prevents new BHs from running, it does not wait
for already running ones to finish.
We need to wait for it to finish - do it like virtio scsi and
run a dummy oneshot AIO in the same context, and wait for it.
But there's a twist: BH could be blocked in qemu_cond_wait,
then AIO won't run.
Add a special reporting state FREE_PAGE_HINT_S_UNREALIZE to make BH exit
immediately.
Cc: David Hildenbrand <david@kernel.org>
Fixes: CVE-2026-66899
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4079
Reported-by: mhun512 <mhun512@gmail.com>
Reviewed-by: David Hildenbrand <david@kernel.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <0967d574d9ffe469edf5fc16da86237e54a69c34.1785327742.git.mst@redhat.com>
---
include/hw/virtio/virtio-balloon.h | 1 +
hw/virtio/virtio-balloon.c | 19 ++++++++++++++++++-
2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h
index abbf339718..53bbaa4c9a 100644
--- a/include/hw/virtio/virtio-balloon.h
+++ b/include/hw/virtio/virtio-balloon.h
@@ -39,6 +39,7 @@ enum virtio_balloon_free_page_hint_status {
FREE_PAGE_HINT_S_REQUESTED = 1,
FREE_PAGE_HINT_S_START = 2,
FREE_PAGE_HINT_S_DONE = 3,
+ FREE_PAGE_HINT_S_UNREALIZE = 4,
};
struct VirtIOBalloon {
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index 4c5f486ba2..07d519cf6d 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -35,6 +35,7 @@
#include "system/reset.h"
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h"
+#include "qemu/aio-wait.h"
#define BALLOON_PAGE_SIZE (1 << VIRTIO_BALLOON_PFN_SHIFT)
@@ -519,6 +520,9 @@ static bool get_free_page_hints(VirtIOBalloon *dev)
int i;
while (dev->block_iothread) {
+ if (dev->free_page_hint_status == FREE_PAGE_HINT_S_UNREALIZE) {
+ return false;
+ }
qemu_cond_wait(&dev->free_page_cond, &dev->free_page_lock);
}
@@ -912,6 +916,11 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp)
qemu_register_resettable(OBJECT(dev));
}
+static void dummy_bh(void *opaque)
+{
+ /* Do nothing */
+}
+
static void virtio_balloon_device_unrealize(DeviceState *dev)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
@@ -919,9 +928,17 @@ static void virtio_balloon_device_unrealize(DeviceState *dev)
qemu_unregister_resettable(OBJECT(dev));
if (s->free_page_bh) {
+ AioContext *ctx = iothread_get_aio_context(s->iothread);
+
qemu_bh_delete(s->free_page_bh);
+
+ qemu_mutex_lock(&s->free_page_lock);
+ s->free_page_hint_status = FREE_PAGE_HINT_S_UNREALIZE;
+ qemu_cond_signal(&s->free_page_cond);
+ qemu_mutex_unlock(&s->free_page_lock);
+ aio_wait_bh_oneshot(ctx, dummy_bh, NULL);
+
object_unref(OBJECT(s->iothread));
- virtio_balloon_free_page_stop(s);
precopy_remove_notifier(&s->free_page_hint_notify);
}
balloon_stats_destroy_timer(s);
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 42/75] vhost-user.rst: fix typo
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (40 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 41/75] virtio-balloon: fix free-page BH teardown on unrealize Michael S. Tsirkin
@ 2026-09-11 9:02 ` Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 43/75] hw/virtio: Propagate vhost_virtqueue_mask errors Michael S. Tsirkin
` (34 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:02 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Alyssa Ross, Manos Pitsidianakis, Stefan Hajnoczi,
Stefano Garzarella, Pierrick Bouvier
From: Alyssa Ross <hi@alyssa.is>
The protocol feature is named SHMEM. SHMEM_MAP is one of the
requests.
Fixes: 588acb45c2 ("vhost_user.rst: Add SHMEM_MAP/_UNMAP to spec")
Signed-off-by: Alyssa Ross <hi@alyssa.is>
Reviewed-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260804121000.444745-3-hi@alyssa.is>
---
docs/interop/vhost-user.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst
index ae8c7ed995..fbfb9d01c6 100644
--- a/docs/interop/vhost-user.rst
+++ b/docs/interop/vhost-user.rst
@@ -1158,7 +1158,7 @@ Protocol features
#define VHOST_USER_PROTOCOL_F_DEVICE_STATE 19
#define VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT 20
#define VHOST_USER_PROTOCOL_F_GPA_ADDRESSES 21
- #define VHOST_USER_PROTOCOL_F_SHMEM_MAP 22
+ #define VHOST_USER_PROTOCOL_F_SHMEM 22
Front-end message types
-----------------------
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 43/75] hw/virtio: Propagate vhost_virtqueue_mask errors
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (41 preceding siblings ...)
2026-09-11 9:02 ` [PULL v2 42/75] vhost-user.rst: fix typo Michael S. Tsirkin
@ 2026-09-11 9:03 ` Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 44/75] amd_iommu: Return empty efr for stub call Michael S. Tsirkin
` (33 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:03 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Xiong Weimin, Stefano Garzarella
From: Xiong Weimin <xiongweimin@kylinos.cn>
vhost_virtqueue_mask() currently reports failures from
vhost_set_vring_call() but always returns void, so callers cannot
react. In particular, vhost_virtqueue_start() has a TODO next to the
unmask call when !use_guest_notifier_mask.
Make vhost_virtqueue_mask() return the underlying errno, and on failure
in vhost_virtqueue_start() jump to the existing fail path which unmaps
the vring and propagates the error to the device start caller. Other
call sites keep today's behavior by ignoring the return value.
Signed-off-by: Xiong Weimin <xiongweimin@kylinos.cn>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260807024359.2157914-1-xiongweimin@kylinos.cn>
---
include/hw/virtio/vhost.h | 9 ++++++---
hw/virtio/vhost.c | 10 +++++++---
2 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index 684bafcaad..3db56433b6 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -310,10 +310,13 @@ void vhost_dev_set_config_notifier(struct vhost_dev *dev,
*/
bool vhost_virtqueue_pending(struct vhost_dev *hdev, int n);
-/* Mask/unmask events from this vq.
+/**
+ * vhost_virtqueue_mask(): mask/unmask events from this vq.
+ *
+ * Returns: 0 on success, a negative errno on failure.
*/
-void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n,
- bool mask);
+int vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n,
+ bool mask);
/**
* vhost_get_features_ex() - sanitize the extended features set
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 371dca17dd..52ea142bd4 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1471,8 +1471,10 @@ int vhost_virtqueue_start(struct vhost_dev *dev,
* will do it later.
*/
if (!vdev->use_guest_notifier_mask) {
- /* TODO: check and handle errors. */
- vhost_virtqueue_mask(dev, vdev, idx, false);
+ r = vhost_virtqueue_mask(dev, vdev, idx, false);
+ if (r < 0) {
+ goto fail;
+ }
}
if (k->query_guest_notifiers &&
@@ -1919,7 +1921,7 @@ bool vhost_virtqueue_pending(struct vhost_dev *hdev, int n)
}
/* Mask/unmask events from this vq. */
-void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n,
+int vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n,
bool mask)
{
struct VirtQueue *vvq = virtio_get_queue(vdev, n);
@@ -1940,7 +1942,9 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n,
r = hdev->vhost_ops->vhost_set_vring_call(hdev, &file);
if (r < 0) {
error_report("vhost_set_vring_call failed %d", -r);
+ return r;
}
+ return 0;
}
bool vhost_config_pending(struct vhost_dev *hdev)
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 44/75] amd_iommu: Return empty efr for stub call
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (42 preceding siblings ...)
2026-09-11 9:03 ` [PULL v2 43/75] hw/virtio: Propagate vhost_virtqueue_mask errors Michael S. Tsirkin
@ 2026-09-11 9:03 ` Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 45/75] tests/acpi: x86: Allow IVRS acpi table changes Michael S. Tsirkin
` (32 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:03 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Sairaj Kodilkar, Alejandro Jimenez, Paolo Bonzini,
Richard Henderson
From: Sairaj Kodilkar <sarunkod@amd.com>
The stub call should not return normal EFR as it is used as place holder
when actual AMD IOMMU calls are not available. Hence return 0.
Signed-off-by: Sairaj Kodilkar <sarunkod@amd.com>
Reviewed-by: Alejandro Jimenez <alejandro.j.jimenez@oracle.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260807061250.27739-2-sarunkod@amd.com>
---
hw/i386/amd_iommu-stub.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/i386/amd_iommu-stub.c b/hw/i386/amd_iommu-stub.c
index d62a3732e6..fb36dee903 100644
--- a/hw/i386/amd_iommu-stub.c
+++ b/hw/i386/amd_iommu-stub.c
@@ -22,5 +22,5 @@
uint64_t amdvi_extended_feature_register(AMDVIState *s)
{
- return AMDVI_DEFAULT_EXT_FEATURES;
+ return 0;
}
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 45/75] tests/acpi: x86: Allow IVRS acpi table changes
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (43 preceding siblings ...)
2026-09-11 9:03 ` [PULL v2 44/75] amd_iommu: Return empty efr for stub call Michael S. Tsirkin
@ 2026-09-11 9:03 ` Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 46/75] amd_iommu: acpi-build: update PA, GVA and VA size macros Michael S. Tsirkin
` (31 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:03 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Sairaj Kodilkar, Igor Mammedov, Ani Sinha
From: Sairaj Kodilkar <sarunkod@amd.com>
Signed-off-by: Sairaj Kodilkar <sarunkod@amd.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260807061250.27739-3-sarunkod@amd.com>
---
tests/qtest/bios-tables-test-allowed-diff.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523c8b..33e9981655 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,2 @@
/* List of comma-separated changed AML files to ignore */
+tests/data/acpi/x86/q35/IVRS.ivrs
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 46/75] amd_iommu: acpi-build: update PA, GVA and VA size macros
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (44 preceding siblings ...)
2026-09-11 9:03 ` [PULL v2 45/75] tests/acpi: x86: Allow IVRS acpi table changes Michael S. Tsirkin
@ 2026-09-11 9:03 ` Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 47/75] acpi_build: Use IOMMU pci device to build IOMMU DeviceID Michael S. Tsirkin
` (30 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:03 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Sairaj Kodilkar, Alejandro Jimenez, Igor Mammedov,
Ani Sinha, Paolo Bonzini, Richard Henderson
From: Sairaj Kodilkar <sarunkod@amd.com>
Current implementation supports up to 64 bit IOVA and up to 52 bit PA.
Modify related macros so that guest can see right size.
Also, use these macros to build the IVINFO field in the IVRS.
Signed-off-by: Sairaj Kodilkar <sarunkod@amd.com>
Reviewed-by: Alejandro Jimenez <alejandro.j.jimenez@oracle.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260807061250.27739-4-sarunkod@amd.com>
---
hw/i386/amd_iommu.h | 11 ++++++++---
hw/i386/acpi-build.c | 4 +++-
hw/i386/amd_iommu.c | 2 +-
3 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/hw/i386/amd_iommu.h b/hw/i386/amd_iommu.h
index 687691ec1c..d01f9b41df 100644
--- a/hw/i386/amd_iommu.h
+++ b/hw/i386/amd_iommu.h
@@ -243,9 +243,14 @@
#define AMDVI_PAGE_SHIFT_4K 12
#define AMDVI_PAGE_MASK_4K GENMASK64(63, 12)
-#define AMDVI_MAX_GVA_ADDR (2UL << 5)
-#define AMDVI_MAX_PH_ADDR (40UL << 8)
-#define AMDVI_MAX_VA_ADDR (48UL << 15)
+/*
+ * IOMMU Capability Offset 10h: Miscellaneous Information Register 0.
+ * VAsize[21:15], PAsize[14:8], and GVAsize[7:5].
+ * These fields use the same layout in the IVRS IVinfo Field.
+ */
+#define AMDVI_VA_SIZE_64 (64UL << 15)
+#define AMDVI_PA_SIZE_52 (52UL << 8)
+#define AMDVI_GVA_SIZE_48 (2UL << 5)
/* Completion Wait data size */
#define AMDVI_COMPLETION_DATA_SIZE 8
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 1696821048..05b68d05a8 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1858,7 +1858,9 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id,
*/
build_append_int_noprefix(table_data,
(1UL << 0) | /* EFRSup */
- (40UL << 8), /* PASize */
+ AMDVI_GVA_SIZE_48 | /* GVASize: 010b = 48 bits */
+ AMDVI_PA_SIZE_52 | /* PASize: 011_0100b = 52 bits */
+ AMDVI_VA_SIZE_64, /* VASize: 100_0000b = 64 bits */
4);
/* reserved */
build_append_int_noprefix(table_data, 0, 8);
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
index 578c27ccbe..56e7815412 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -2595,7 +2595,7 @@ static void amdvi_pci_realize(PCIDevice *pdev, Error **errp)
0xff000000);
pci_set_long(pdev->config + s->capab_offset + AMDVI_CAPAB_MISC, 0);
pci_set_long(pdev->config + s->capab_offset + AMDVI_CAPAB_MISC,
- AMDVI_MAX_PH_ADDR | AMDVI_MAX_GVA_ADDR | AMDVI_MAX_VA_ADDR);
+ AMDVI_PA_SIZE_52 | AMDVI_GVA_SIZE_48 | AMDVI_VA_SIZE_64);
}
static void amdvi_sysbus_reset(DeviceState *dev)
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 47/75] acpi_build: Use IOMMU pci device to build IOMMU DeviceID
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (45 preceding siblings ...)
2026-09-11 9:03 ` [PULL v2 46/75] amd_iommu: acpi-build: update PA, GVA and VA size macros Michael S. Tsirkin
@ 2026-09-11 9:03 ` Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 48/75] acpi_build: Build IVRS feature report using extended feature register Michael S. Tsirkin
` (29 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:03 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Sairaj Kodilkar, Alejandro Jimenez, Igor Mammedov,
Ani Sinha, Paolo Bonzini, Richard Henderson
From: Sairaj Kodilkar <sarunkod@amd.com>
Currently, build_amd_iommu() uses "addr" property to build the DeviceID for
IOMMU device and advertise it through IVRS. But this property does not encode
IOMMU bus number, only the device and function number. This creates an
incorrect DeviceID when the IOMMU is attached to a bus other than the
default one with bus number 0.
Signed-off-by: Sairaj Kodilkar <sarunkod@amd.com>
Reviewed-by: Alejandro Jimenez <alejandro.j.jimenez@oracle.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260807061250.27739-5-sarunkod@amd.com>
---
hw/i386/acpi-build.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 05b68d05a8..a28bb2ec63 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1851,6 +1851,7 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id,
AcpiTable table = { .sig = "IVRS", .rev = 1, .oem_id = oem_id,
.oem_table_id = oem_table_id };
uint64_t feature_report;
+ uint16_t iommu_devid = pci_get_bdf(&s->pci->dev);
acpi_table_begin(&table, table_data);
/* IVinfo - IO virtualization information common to all
@@ -1913,9 +1914,7 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id,
/* IVHD length */
build_append_int_noprefix(table_data, ivhd_blob->len + 24, 2);
/* DeviceID */
- build_append_int_noprefix(table_data,
- object_property_get_int(OBJECT(s->pci), "addr",
- &error_abort), 2);
+ build_append_int_noprefix(table_data, iommu_devid, 2);
/* Capability offset */
build_append_int_noprefix(table_data, s->pci->capab_offset, 2);
/* IOMMU base address */
@@ -1947,10 +1946,9 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id,
/* IVHD length */
build_append_int_noprefix(table_data, ivhd_blob->len + 40, 2);
+
/* DeviceID */
- build_append_int_noprefix(table_data,
- object_property_get_int(OBJECT(s->pci), "addr",
- &error_abort), 2);
+ build_append_int_noprefix(table_data, iommu_devid, 2);
/* Capability offset */
build_append_int_noprefix(table_data, s->pci->capab_offset, 2);
/* IOMMU base address */
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 48/75] acpi_build: Build IVRS feature report using extended feature register
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (46 preceding siblings ...)
2026-09-11 9:03 ` [PULL v2 47/75] acpi_build: Use IOMMU pci device to build IOMMU DeviceID Michael S. Tsirkin
@ 2026-09-11 9:03 ` Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 49/75] amd_iommu: acpi-build: Remove unsupported PPR and HE feature Michael S. Tsirkin
` (28 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:03 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Sairaj Kodilkar, Igor Mammedov, Ani Sinha,
Paolo Bonzini, Richard Henderson, Alejandro Jimenez
From: Sairaj Kodilkar <sarunkod@amd.com>
Currently IVRS feature report values are hardcoded, this is difficult to
maintain as any updates to extended feature must be synced. Along with
it, current feature report does not have GATS and HATS set. Hence use
the extended feature registers to build the IVRS feature report.
Signed-off-by: Sairaj Kodilkar <sarunkod@amd.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260807061250.27739-6-sarunkod@amd.com>
---
hw/i386/amd_iommu.h | 11 ++++++++++
hw/i386/acpi-build.c | 48 +++++++++++++++++++++++++++++++++-----------
2 files changed, 47 insertions(+), 12 deletions(-)
diff --git a/hw/i386/amd_iommu.h b/hw/i386/amd_iommu.h
index d01f9b41df..319db18618 100644
--- a/hw/i386/amd_iommu.h
+++ b/hw/i386/amd_iommu.h
@@ -174,7 +174,11 @@
#define AMDVI_DTE_QUAD3_RESERVED (GENMASK64(14, 0) | GENMASK64(53, 48))
/* AMDVI paging mode */
+#define AMDVI_GATS_MODE_SHIFT (12)
+#define AMDVI_GATS_MODE_MASK (3ULL << 12)
#define AMDVI_GATS_MODE (2ULL << 12)
+#define AMDVI_HATS_MODE_SHIFT (10)
+#define AMDVI_HATS_MODE_MASK (3ULL << 10)
#define AMDVI_HATS_MODE (2ULL << 10)
#define AMDVI_HATS_MODE_RESERVED (3ULL << 10)
@@ -296,6 +300,13 @@
#define AMDVI_DEV_LINT0_PASS_MASK (1ULL << 62)
#define AMDVI_DEV_LINT1_PASS_MASK (1ULL << 63)
+#define AMDVI_IVHD_FEATURE_REPORT_HATS_SHIFT (30)
+#define AMDVI_IVHD_FEATURE_REPORT_GATS_SHIFT (28)
+#define AMDVI_IVHD_FEATURE_REPORT_GA_SUP_SHIFT (6)
+#define AMDVI_IVHD_FEATURE_REPORT_IA_SUP_SHIFT (5)
+#define AMDVI_IVHD_FEATURE_REPORT_GT_SUP_SHIFT (2)
+#define AMDVI_IVHD_FEATURE_REPORT_XT_SUP_SHIFT (0)
+
#define TYPE_AMD_IOMMU_DEVICE "amd-iommu"
OBJECT_DECLARE_SIMPLE_TYPE(AMDVIState, AMD_IOMMU_DEVICE)
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index a28bb2ec63..7bf3858b63 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1842,6 +1842,37 @@ ivrs_host_bridges(Object *obj, void *opaque)
return 0;
}
+/*
+ * IVHD type 0x10 reports features using Feature Reporting field, which has
+ * different format than extended feature register (EFR) in the IOMMU MMIO
+ * space.
+ *
+ * Convert the EFR format to feature reporting format.
+ */
+static uint32_t
+get_amd_ivhd_feature_report(uint64_t extended_feature)
+{
+ uint32_t feature_report;
+ uint64_t hats_mode = (extended_feature & AMDVI_HATS_MODE_MASK) >>
+ AMDVI_HATS_MODE_SHIFT;
+ uint64_t gats_mode = (extended_feature & AMDVI_GATS_MODE_MASK) >>
+ AMDVI_GATS_MODE_SHIFT;
+ uint32_t is_ia = !!(extended_feature & AMDVI_FEATURE_IA);
+ uint32_t is_ga = !!(extended_feature & AMDVI_FEATURE_GA);
+ uint32_t is_gt = !!(extended_feature & AMDVI_FEATURE_GT);
+ uint32_t is_xt = !!(extended_feature & AMDVI_FEATURE_XT);
+
+ feature_report =
+ hats_mode << AMDVI_IVHD_FEATURE_REPORT_HATS_SHIFT | /* HATS[31:30] */
+ gats_mode << AMDVI_IVHD_FEATURE_REPORT_GATS_SHIFT | /* GATS[29:28] */
+ is_ia << AMDVI_IVHD_FEATURE_REPORT_IA_SUP_SHIFT | /* IASup[5] */
+ is_ga << AMDVI_IVHD_FEATURE_REPORT_GA_SUP_SHIFT | /* GASup[6] */
+ is_gt << AMDVI_IVHD_FEATURE_REPORT_GT_SUP_SHIFT | /* GTSup[2] */
+ is_xt << AMDVI_IVHD_FEATURE_REPORT_XT_SUP_SHIFT; /* XTSup[0] */
+
+ return feature_report;
+}
+
static void
build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id,
const char *oem_table_id)
@@ -1850,8 +1881,8 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id,
GArray *ivhd_blob = g_array_new(false, true, 1);
AcpiTable table = { .sig = "IVRS", .rev = 1, .oem_id = oem_id,
.oem_table_id = oem_table_id };
- uint64_t feature_report;
uint16_t iommu_devid = pci_get_bdf(&s->pci->dev);
+ uint64_t extended_feature = amdvi_extended_feature_register(s);
acpi_table_begin(&table, table_data);
/* IVinfo - IO virtualization information common to all
@@ -1924,14 +1955,9 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id,
/* IOMMU info */
build_append_int_noprefix(table_data, 0, 2);
/* IOMMU Feature Reporting */
- feature_report = (48UL << 30) | /* HATS */
- (48UL << 28) | /* GATS */
- (1UL << 2) | /* GTSup */
- (1UL << 6); /* GASup */
- if (s->xtsup) {
- feature_report |= (1UL << 0); /* XTSup */
- }
- build_append_int_noprefix(table_data, feature_report, 4);
+ build_append_int_noprefix(table_data,
+ get_amd_ivhd_feature_report(extended_feature),
+ 4);
/* IVHD entries as found above */
g_array_append_vals(table_data, ivhd_blob->data, ivhd_blob->len);
@@ -1964,9 +1990,7 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id,
build_append_int_noprefix(table_data, 0, 4);
}
/* EFR Register Image */
- build_append_int_noprefix(table_data,
- amdvi_extended_feature_register(s),
- 8);
+ build_append_int_noprefix(table_data, extended_feature, 8);
/* EFR Register Image 2 */
build_append_int_noprefix(table_data, 0, 8);
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 49/75] amd_iommu: acpi-build: Remove unsupported PPR and HE feature
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (47 preceding siblings ...)
2026-09-11 9:03 ` [PULL v2 48/75] acpi_build: Build IVRS feature report using extended feature register Michael S. Tsirkin
@ 2026-09-11 9:03 ` Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 50/75] tests/acpi: x86: update golden masters for IVRS Michael S. Tsirkin
` (27 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:03 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Sairaj Kodilkar, Igor Mammedov, Ani Sinha,
Paolo Bonzini, Richard Henderson, Alejandro Jimenez
From: Sairaj Kodilkar <sarunkod@amd.com>
AMD IOMMU does not support ppr and hardware error registers. Hence do not
publish these features to guest through extended feature MMIO register
and IVHD 10h flags field.
Signed-off-by: Sairaj Kodilkar <sarunkod@amd.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260807061250.27739-7-sarunkod@amd.com>
---
hw/i386/amd_iommu.h | 5 ++---
hw/i386/acpi-build.c | 3 +--
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/hw/i386/amd_iommu.h b/hw/i386/amd_iommu.h
index 319db18618..c5b346cc35 100644
--- a/hw/i386/amd_iommu.h
+++ b/hw/i386/amd_iommu.h
@@ -227,9 +227,8 @@
/* default extended feature */
#define AMDVI_DEFAULT_EXT_FEATURES \
- (AMDVI_FEATURE_PREFETCH | AMDVI_FEATURE_PPR | \
- AMDVI_FEATURE_IA | AMDVI_FEATURE_GT | AMDVI_FEATURE_HE | \
- AMDVI_GATS_MODE | AMDVI_HATS_MODE | AMDVI_FEATURE_GA)
+ (AMDVI_FEATURE_PREFETCH | AMDVI_FEATURE_IA | AMDVI_FEATURE_GT | \
+ AMDVI_GATS_MODE | AMDVI_HATS_MODE | AMDVI_FEATURE_GA)
/* capabilities header */
#define AMDVI_CAPAB_FEATURES (AMDVI_CAPAB_FLAT_EXT | \
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 7bf3858b63..6d7308b4e4 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1938,8 +1938,7 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id,
build_append_int_noprefix(table_data,
(1UL << 0) | /* HtTunEn */
(1UL << 4) | /* iotblSup */
- (1UL << 6) | /* PrefSup */
- (1UL << 7), /* PPRSup */
+ (1UL << 6), /* PrefSup */
1);
/* IVHD length */
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 50/75] tests/acpi: x86: update golden masters for IVRS
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (48 preceding siblings ...)
2026-09-11 9:03 ` [PULL v2 49/75] amd_iommu: acpi-build: Remove unsupported PPR and HE feature Michael S. Tsirkin
@ 2026-09-11 9:03 ` Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 51/75] libvhost-user: accept the postcopy client base ack in vu_add_mem_reg() Michael S. Tsirkin
` (26 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:03 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Sairaj Kodilkar, Igor Mammedov, Ani Sinha
From: Sairaj Kodilkar <sarunkod@amd.com>
Differences between disassembled ASL files for IVRS:
/*
* Intel ACPI Component Architecture
* AML/ASL+ Disassembler version 20200925 (64-bit version)
* Copyright (c) 2000 - 2020 Intel Corporation
*
- * Disassembly of tests/data/acpi/x86/q35/IVRS.ivrs, Mon May 11 11:21:47 2026
+ * Disassembly of /tmp/aml-NGQ9O3, Mon May 11 11:21:47 2026
*
* ACPI Data Table [IVRS]
*
* Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue
*/
[000h 0000 4] Signature : "IVRS" [I/O Virtualization Reporting Structure]
[004h 0004 4] Table Length : 000000B0
[008h 0008 1] Revision : 01
-[009h 0009 1] Checksum : 74
+[009h 0009 1] Checksum : CB
[00Ah 0010 6] Oem ID : "BOCHS "
[010h 0016 8] Oem Table ID : "BXPC "
[018h 0024 4] Oem Revision : 00000001
[01Ch 0028 4] Asl Compiler ID : "BXPC"
[020h 0032 4] Asl Compiler Revision : 00000001
-[024h 0036 4] Virtualization Info : 00002801
+[024h 0036 4] Virtualization Info : 00203441
[028h 0040 8] Reserved : 0000000000000000
[030h 0048 1] Subtable Type : 10 [Hardware Definition Block]
-[031h 0049 1] Flags : D1
+[031h 0049 1] Flags : 51
[032h 0050 2] Length : 0038
[034h 0052 2] DeviceId : 0010
[036h 0054 2] Capability Offset : 0040
[038h 0056 8] Base Address : 00000000FED80000
[040h 0064 2] PCI Segment Group : 0000
[042h 0066 2] Virtualization Info : 0000
-[044h 0068 4] Feature Reporting : 00000044
+[044h 0068 4] Feature Reporting : A0000064
[048h 0072 1] Entry Type : 02
[049h 0073 2] Device ID : 0000
[04Bh 0075 1] Data Setting : 00
[04Ch 0076 1] Entry Type : 02
[04Dh 0077 2] Device ID : 0008
[04Fh 0079 1] Data Setting : 00
[050h 0080 1] Entry Type : 02
[051h 0081 2] Device ID : 0010
[053h 0083 1] Data Setting : 00
[054h 0084 1] Entry Type : 02
[055h 0085 2] Device ID : 00F8
[057h 0087 1] Data Setting : 00
@@ -62,33 +62,33 @@
[061h 0097 2] Device ID : 0000
[063h 0099 1] Data Setting : 00
[064h 0100 1] Handle : 00
[065h 0101 2] Source Used Device ID : 00A0
[067h 0103 1] Variety : 01
[068h 0104 1] Subtable Type : 11 [Hardware Definition Block]
[069h 0105 1] Flags : 11
[06Ah 0106 2] Length : 0048
[06Ch 0108 2] DeviceId : 0010
[06Eh 0110 2] Capability Offset : 0040
[070h 0112 8] Base Address : 00000000FED80000
[078h 0120 2] PCI Segment Group : 0000
[07Ah 0122 2] Virtualization Info : 0000
[07Ch 0124 4] Attributes : 00000000
-[080h 0128 8] EFR Image : 00000000000029D3
+[080h 0128 8] EFR Image : 00000000000028D1
[088h 0136 8] Reserved : 0000000000000000
[090h 0144 1] Entry Type : 02
[091h 0145 2] Device ID : 0000
[093h 0147 1] Data Setting : 00
[094h 0148 1] Entry Type : 02
[095h 0149 2] Device ID : 0008
[097h 0151 1] Data Setting : 00
[098h 0152 1] Entry Type : 02
[099h 0153 2] Device ID : 0010
[09Bh 0155 1] Data Setting : 00
[09Ch 0156 1] Entry Type : 02
[09Dh 0157 2] Device ID : 00F8
@@ -98,27 +98,27 @@
[0A1h 0161 2] Device ID : 00FA
[0A3h 0163 1] Data Setting : 00
[0A4h 0164 1] Entry Type : 02
[0A5h 0165 2] Device ID : 00FB
[0A7h 0167 1] Data Setting : 00
[0A8h 0168 1] Entry Type : 48
[0A9h 0169 2] Device ID : 0000
[0ABh 0171 1] Data Setting : 00
[0ACh 0172 1] Handle : 00
[0ADh 0173 2] Source Used Device ID : 00A0
[0AFh 0175 1] Variety : 01
Signed-off-by: Sairaj Kodilkar <sarunkod@amd.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260807061250.27739-8-sarunkod@amd.com>
---
tests/qtest/bios-tables-test-allowed-diff.h | 1 -
tests/data/acpi/x86/q35/IVRS.ivrs | Bin 176 -> 176 bytes
2 files changed, 1 deletion(-)
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
index 33e9981655..dfb8523c8b 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1,2 +1 @@
/* List of comma-separated changed AML files to ignore */
-tests/data/acpi/x86/q35/IVRS.ivrs
diff --git a/tests/data/acpi/x86/q35/IVRS.ivrs b/tests/data/acpi/x86/q35/IVRS.ivrs
index 7f9e91aabc0b7777a7efc9f219587a4f91f0edb1..b3b809c65f026fde0a49a2243a3216e7b8c87502 100644
GIT binary patch
delta 67
zcmdnMxPg(&Gb|{00|NsC<LQZ9QYwxn3JfqH5NN?5z~I2Zz;NRqOe}?gVZp=+3KKIV
Lm@aBeY|;Y&z19uv
delta 64
zcmdnMxPg(&Gb|{00|NsCW64A=DMdyN1~?G7Xu%-B;K0DZaN{3L&}Cw;^27`YrpuZW
GoAdyMuMFt`
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 51/75] libvhost-user: accept the postcopy client base ack in vu_add_mem_reg()
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (49 preceding siblings ...)
2026-09-11 9:03 ` [PULL v2 50/75] tests/acpi: x86: update golden masters for IVRS Michael S. Tsirkin
@ 2026-09-11 9:03 ` Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 52/75] libvhost-user: return the backend mapping address for added regions Michael S. Tsirkin
` (25 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:03 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Bin Guo, Stefano Garzarella
From: Bin Guo <guobin@linux.alibaba.com>
In postcopy mode QEMU signals that it has collected all the postcopy client
bases by sending a VHOST_USER_ADD_MEM_REG message with a u64 payload of 0
and no file descriptor (see vhost_user_add_remove_regions()).
vu_add_mem_reg() has a case for that message, but only reaches it after
validating the fd count of a regular region, so the ack is rejected first:
VHOST_USER_ADD_MEM_REG received 0 fds - only 1 fd should be sent for
this message type
This kills the backend during memory table setup, making postcopy unusable
for any libvhost-user backend that negotiates
VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS.
Recognise the ack before validating the fd count.
Fixes: 9f4e63491b ("libvhost-user: Add vu_add_mem_reg input validation")
Signed-off-by: Bin Guo <guobin@linux.alibaba.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260813095501.20282-2-guobin@linux.alibaba.com>
---
subprojects/libvhost-user/libvhost-user.c | 26 ++++++++++++-----------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/subprojects/libvhost-user/libvhost-user.c b/subprojects/libvhost-user/libvhost-user.c
index a74d814bb4..248550aae1 100644
--- a/subprojects/libvhost-user/libvhost-user.c
+++ b/subprojects/libvhost-user/libvhost-user.c
@@ -948,6 +948,20 @@ static bool
vu_add_mem_reg(VuDev *dev, VhostUserMsg *vmsg) {
VhostUserMemoryRegion m = vmsg->payload.memreg.region, *msg_region = &m;
+ /*
+ * If we are in postcopy mode and we receive a u64 payload with a 0 value
+ * we know all the postcopy client bases have been received, and we
+ * should start generating faults. This message carries no file
+ * descriptor, so it has to be recognised before the fd count of a real
+ * region is validated below.
+ */
+ if (dev->postcopy_listening &&
+ vmsg->size == sizeof(vmsg->payload.u64) &&
+ vmsg->payload.u64 == 0) {
+ (void)generate_faults(dev);
+ return false;
+ }
+
if (vmsg->fd_num != 1) {
vmsg_close_fds(vmsg);
vu_panic(dev, "VHOST_USER_ADD_MEM_REG received %d fds - only 1 fd "
@@ -971,18 +985,6 @@ vu_add_mem_reg(VuDev *dev, VhostUserMsg *vmsg) {
return false;
}
- /*
- * If we are in postcopy mode and we receive a u64 payload with a 0 value
- * we know all the postcopy client bases have been received, and we
- * should start generating faults.
- */
- if (dev->postcopy_listening &&
- vmsg->size == sizeof(vmsg->payload.u64) &&
- vmsg->payload.u64 == 0) {
- (void)generate_faults(dev);
- return false;
- }
-
_vu_add_mem_reg(dev, msg_region, vmsg->fds[0]);
close(vmsg->fds[0]);
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 52/75] libvhost-user: return the backend mapping address for added regions
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (50 preceding siblings ...)
2026-09-11 9:03 ` [PULL v2 51/75] libvhost-user: accept the postcopy client base ack in vu_add_mem_reg() Michael S. Tsirkin
@ 2026-09-11 9:03 ` Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 53/75] linux-headers: Update to Linux v7.3-rc1 Michael S. Tsirkin
` (24 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:03 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Bin Guo, Stefano Garzarella
From: Bin Guo <guobin@linux.alibaba.com>
In postcopy mode the backend must tell QEMU where it mapped a region, so
that QEMU can translate the backend's fault addresses back into a RAMBlock
and offset. vu_add_mem_reg() works on a copy of the region and lets
_vu_add_mem_reg() fill the mapping address into that copy, but never writes
it back into the reply payload. QEMU then stores its own address as the
postcopy client base, so fault resolution fails:
vhost_user_postcopy_fault_handler: Failed to find region for fault ...
The VHOST_USER_SET_MEM_TABLE path is unaffected, it fills the payload
directly. Put the updated region back into the payload before replying; a
pointer into the payload cannot be used instead, as VhostUserMsg is packed.
Fixes: ec94c8e621 ("Support adding individual regions in libvhost-user")
Signed-off-by: Bin Guo <guobin@linux.alibaba.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260813095501.20282-3-guobin@linux.alibaba.com>
---
subprojects/libvhost-user/libvhost-user.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/subprojects/libvhost-user/libvhost-user.c b/subprojects/libvhost-user/libvhost-user.c
index 248550aae1..2fed792e85 100644
--- a/subprojects/libvhost-user/libvhost-user.c
+++ b/subprojects/libvhost-user/libvhost-user.c
@@ -989,7 +989,13 @@ vu_add_mem_reg(VuDev *dev, VhostUserMsg *vmsg) {
close(vmsg->fds[0]);
if (dev->postcopy_listening) {
- /* Send the message back to qemu with the addresses filled in. */
+ /*
+ * Send the message back to qemu with the addresses filled in.
+ * _vu_add_mem_reg() worked on our copy of the region, so it has to be
+ * put back into the message payload. A pointer into the payload
+ * cannot be handed out instead, VhostUserMsg is packed.
+ */
+ vmsg->payload.memreg.region = m;
vmsg->fd_num = 0;
DPRINT("Successfully added new region in postcopy\n");
return true;
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 53/75] linux-headers: Update to Linux v7.3-rc1
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (51 preceding siblings ...)
2026-09-11 9:03 ` [PULL v2 52/75] libvhost-user: return the backend mapping address for added regions Michael S. Tsirkin
@ 2026-09-11 9:03 ` Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 54/75] virtio-scsi: set dataplane_started to false upon failure Michael S. Tsirkin
` (23 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:03 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Albert Esteve, Cornelia Huck, Paolo Bonzini
From: Albert Esteve <aesteve@redhat.com>
VIRTIO_ID_MEDIA was added previously, synchronize the rest
of the headers to the same version.
Signed-off-by: Albert Esteve <aesteve@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260821135038.2676679-1-aesteve@redhat.com>
---
include/standard-headers/linux/ethtool.h | 6 +++
| 45 ++++++++++++++++++--
| 54 ++++++++++++++++++++++--
| 28 ++++++++++++
| 21 +++++++++
| 2 +
6 files changed, 149 insertions(+), 7 deletions(-)
diff --git a/include/standard-headers/linux/ethtool.h b/include/standard-headers/linux/ethtool.h
index 55f608c3a7..622d634d04 100644
--- a/include/standard-headers/linux/ethtool.h
+++ b/include/standard-headers/linux/ethtool.h
@@ -2015,7 +2015,13 @@ enum ethtool_link_mode_bit_indices {
ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT = 39,
ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT = 40,
ETHTOOL_LINK_MODE_1000baseX_Full_BIT = 41,
+
+ /* Despite the "baseCR" in 10000baseCR, this is not an IEEE 802.3 baseCR
+ * It represents SFF-8431 Appendix-E SFP+ Direct Attach (10G-SFI-DA).
+ * The name is kept as-is for uAPI backward compatibility.
+ */
ETHTOOL_LINK_MODE_10000baseCR_Full_BIT = 42,
+
ETHTOOL_LINK_MODE_10000baseSR_Full_BIT = 43,
ETHTOOL_LINK_MODE_10000baseLR_Full_BIT = 44,
ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT = 45,
--git a/linux-headers/linux/iommufd.h b/linux-headers/linux/iommufd.h
index 10c600d71e..3c61caadbf 100644
--- a/linux-headers/linux/iommufd.h
+++ b/linux-headers/linux/iommufd.h
@@ -57,6 +57,7 @@ enum {
IOMMUFD_CMD_IOAS_CHANGE_PROCESS = 0x92,
IOMMUFD_CMD_VEVENTQ_ALLOC = 0x93,
IOMMUFD_CMD_HW_QUEUE_ALLOC = 0x94,
+ IOMMUFD_CMD_IOAS_NOIOMMU_GET_PA = 0x95,
};
/**
@@ -219,6 +220,33 @@ struct iommu_ioas_map {
};
#define IOMMU_IOAS_MAP _IO(IOMMUFD_TYPE, IOMMUFD_CMD_IOAS_MAP)
+/**
+ * struct iommu_ioas_noiommu_get_pa - ioctl(IOMMU_IOAS_NOIOMMU_GET_PA)
+ * @size: sizeof(struct iommu_ioas_noiommu_get_pa)
+ * @flags: Reserved, must be 0 for now
+ * @ioas_id: IOAS ID to query IOVA to PA mapping from
+ * @__reserved: Must be 0
+ * @iova: IOVA to query
+ * @length: On input, non-zero maximum number of bytes to query starting from
+ * @iova. On output, number of physically contiguous bytes starting
+ * from @out_phys, capped by the input length.
+ * @out_phys: Output physical address the IOVA maps to
+ *
+ * Query the physical address backing an IOVA range. The beginning of the
+ * range must be mapped already and length must be non-zero. For noiommu
+ * devices doing unsafe DMA only.
+ */
+struct iommu_ioas_noiommu_get_pa {
+ __u32 size;
+ __u32 flags;
+ __u32 ioas_id;
+ __u32 __reserved;
+ __aligned_u64 iova;
+ __aligned_u64 length;
+ __aligned_u64 out_phys;
+};
+#define IOMMU_IOAS_NOIOMMU_GET_PA _IO(IOMMUFD_TYPE, IOMMUFD_CMD_IOAS_NOIOMMU_GET_PA)
+
/**
* struct iommu_ioas_map_file - ioctl(IOMMU_IOAS_MAP_FILE)
* @size: sizeof(struct iommu_ioas_map_file)
@@ -574,11 +602,22 @@ struct iommu_hw_info_vtd {
__aligned_u64 ecap_reg;
};
+/**
+ * enum iommu_hw_info_arm_smmuv3_flags - Flags for ARM SMMUv3 hw_info
+ * @IOMMU_HW_INFO_ARM_SMMUV3_ERRATA_REPEAT_TLBI_CFGI:
+ * If set, user space must issue TLBI/CFGI+SYNC commands twice due to
+ * hardware erratum T264-SMMU-3. See the description at
+ * arm_smmu_erratum_repeat_tlbi_cfgi_key.
+ */
+enum iommu_hw_info_arm_smmuv3_flags {
+ IOMMU_HW_INFO_ARM_SMMUV3_ERRATA_REPEAT_TLBI_CFGI = 1 << 0,
+};
+
/**
* struct iommu_hw_info_arm_smmuv3 - ARM SMMUv3 hardware information
* (IOMMU_HW_INFO_TYPE_ARM_SMMUV3)
*
- * @flags: Must be set to 0
+ * @flags: Combination of enum iommu_hw_info_arm_smmuv3_flags
* @__reserved: Must be 0
* @idr: Implemented features for ARM SMMU Non-secure programming interface
* @iidr: Information about the implementation and implementer of ARM SMMU,
@@ -594,7 +633,7 @@ struct iommu_hw_info_vtd {
* idr[0]: ST_LEVEL, TERM_MODEL, STALL_MODEL, TTENDIAN , CD2L, ASID16, TTF
* idr[1]: SIDSIZE, SSIDSIZE
* idr[3]: BBML, RIL
- * idr[5]: VAX, GRAN64K, GRAN16K, GRAN4K
+ * idr[5]: VAX, GRAN64K, GRAN16K, GRAN4K, DS
*
* - S1P should be assumed to be true if a NESTED HWPT can be created
* - VFIO/iommufd only support platforms with COHACC, it should be assumed to be
@@ -602,7 +641,7 @@ struct iommu_hw_info_vtd {
* - ATS is a per-device property. If the VMM describes any devices as ATS
* capable in ACPI/DT it should set the corresponding idr.
*
- * This list may expand in future (eg E0PD, AIE, PBHA, D128, DS etc). It is
+ * This list may expand in future (eg E0PD, AIE, PBHA, D128 etc). It is
* important that VMMs do not read bits outside the list to allow for
* compatibility with future kernels. Several features in the SMMUv3
* architecture are not currently supported by the kernel for nesting: HTTU,
--git a/linux-headers/linux/userfaultfd.h b/linux-headers/linux/userfaultfd.h
index 4283de22d5..c8e99df952 100644
--- a/linux-headers/linux/userfaultfd.h
+++ b/linux-headers/linux/userfaultfd.h
@@ -25,7 +25,8 @@
#define UFFD_API ((__u64)0xAA)
#define UFFD_API_REGISTER_MODES (UFFDIO_REGISTER_MODE_MISSING | \
UFFDIO_REGISTER_MODE_WP | \
- UFFDIO_REGISTER_MODE_MINOR)
+ UFFDIO_REGISTER_MODE_MINOR | \
+ UFFDIO_REGISTER_MODE_RWP)
#define UFFD_API_FEATURES (UFFD_FEATURE_PAGEFAULT_FLAG_WP | \
UFFD_FEATURE_EVENT_FORK | \
UFFD_FEATURE_EVENT_REMAP | \
@@ -42,10 +43,13 @@
UFFD_FEATURE_WP_UNPOPULATED | \
UFFD_FEATURE_POISON | \
UFFD_FEATURE_WP_ASYNC | \
- UFFD_FEATURE_MOVE)
+ UFFD_FEATURE_MOVE | \
+ UFFD_FEATURE_RWP | \
+ UFFD_FEATURE_RWP_ASYNC)
#define UFFD_API_IOCTLS \
((__u64)1 << _UFFDIO_REGISTER | \
(__u64)1 << _UFFDIO_UNREGISTER | \
+ (__u64)1 << _UFFDIO_SET_MODE | \
(__u64)1 << _UFFDIO_API)
#define UFFD_API_RANGE_IOCTLS \
((__u64)1 << _UFFDIO_WAKE | \
@@ -54,13 +58,15 @@
(__u64)1 << _UFFDIO_MOVE | \
(__u64)1 << _UFFDIO_WRITEPROTECT | \
(__u64)1 << _UFFDIO_CONTINUE | \
- (__u64)1 << _UFFDIO_POISON)
+ (__u64)1 << _UFFDIO_POISON | \
+ (__u64)1 << _UFFDIO_RWPROTECT)
#define UFFD_API_RANGE_IOCTLS_BASIC \
((__u64)1 << _UFFDIO_WAKE | \
(__u64)1 << _UFFDIO_COPY | \
(__u64)1 << _UFFDIO_WRITEPROTECT | \
(__u64)1 << _UFFDIO_CONTINUE | \
- (__u64)1 << _UFFDIO_POISON)
+ (__u64)1 << _UFFDIO_POISON | \
+ (__u64)1 << _UFFDIO_RWPROTECT)
/*
* Valid ioctl command number range with this API is from 0x00 to
@@ -79,6 +85,8 @@
#define _UFFDIO_WRITEPROTECT (0x06)
#define _UFFDIO_CONTINUE (0x07)
#define _UFFDIO_POISON (0x08)
+#define _UFFDIO_RWPROTECT (0x09)
+#define _UFFDIO_SET_MODE (0x0A)
#define _UFFDIO_API (0x3F)
/* userfaultfd ioctl ids */
@@ -103,6 +111,10 @@
struct uffdio_continue)
#define UFFDIO_POISON _IOWR(UFFDIO, _UFFDIO_POISON, \
struct uffdio_poison)
+#define UFFDIO_RWPROTECT _IOWR(UFFDIO, _UFFDIO_RWPROTECT, \
+ struct uffdio_rwprotect)
+#define UFFDIO_SET_MODE _IOW(UFFDIO, _UFFDIO_SET_MODE, \
+ struct uffdio_set_mode)
/* read() structure */
struct uffd_msg {
@@ -158,6 +170,7 @@ struct uffd_msg {
#define UFFD_PAGEFAULT_FLAG_WRITE (1<<0) /* If this was a write fault */
#define UFFD_PAGEFAULT_FLAG_WP (1<<1) /* If reason is VM_UFFD_WP */
#define UFFD_PAGEFAULT_FLAG_MINOR (1<<2) /* If reason is VM_UFFD_MINOR */
+#define UFFD_PAGEFAULT_FLAG_RWP (1<<3) /* If reason is VM_UFFD_RWP */
struct uffdio_api {
/* userland asks for an API number and the features to enable */
@@ -230,6 +243,18 @@ struct uffdio_api {
*
* UFFD_FEATURE_MOVE indicates that the kernel supports moving an
* existing page contents from userspace.
+ *
+ * UFFD_FEATURE_RWP indicates that the kernel supports
+ * UFFDIO_REGISTER_MODE_RWP for read-write protection tracking.
+ * Pages are made inaccessible via UFFDIO_RWPROTECT and faults
+ * are delivered when the pages are re-accessed.
+ *
+ * UFFD_FEATURE_RWP_ASYNC indicates asynchronous mode for
+ * UFFDIO_REGISTER_MODE_RWP. When set, faults on read-write
+ * protected pages are auto-resolved by the kernel (PTE
+ * permissions restored immediately) without delivering a message
+ * to the userfaultfd handler. Use PAGEMAP_SCAN with inverted
+ * PAGE_IS_ACCESSED to find pages that were not re-accessed.
*/
#define UFFD_FEATURE_PAGEFAULT_FLAG_WP (1<<0)
#define UFFD_FEATURE_EVENT_FORK (1<<1)
@@ -248,6 +273,8 @@ struct uffdio_api {
#define UFFD_FEATURE_POISON (1<<14)
#define UFFD_FEATURE_WP_ASYNC (1<<15)
#define UFFD_FEATURE_MOVE (1<<16)
+#define UFFD_FEATURE_RWP (1<<17)
+#define UFFD_FEATURE_RWP_ASYNC (1<<18)
__u64 features;
__u64 ioctls;
@@ -263,6 +290,7 @@ struct uffdio_register {
#define UFFDIO_REGISTER_MODE_MISSING ((__u64)1<<0)
#define UFFDIO_REGISTER_MODE_WP ((__u64)1<<1)
#define UFFDIO_REGISTER_MODE_MINOR ((__u64)1<<2)
+#define UFFDIO_REGISTER_MODE_RWP ((__u64)1<<3)
__u64 mode;
/*
@@ -356,6 +384,14 @@ struct uffdio_poison {
__s64 updated;
};
+struct uffdio_rwprotect {
+ struct uffdio_range range;
+ /* !RWP means undo RWP-protection */
+#define UFFDIO_RWPROTECT_MODE_RWP ((__u64)1<<0)
+#define UFFDIO_RWPROTECT_MODE_DONTWAKE ((__u64)1<<1)
+ __u64 mode;
+};
+
struct uffdio_move {
__u64 dst;
__u64 src;
@@ -374,6 +410,16 @@ struct uffdio_move {
__s64 move;
};
+struct uffdio_set_mode {
+ /*
+ * Toggle async mode for features at runtime.
+ * Supported: UFFD_FEATURE_RWP_ASYNC.
+ * Setting a bit in both enable and disable is invalid.
+ */
+ __u64 enable;
+ __u64 disable;
+};
+
/*
* Flags for the userfaultfd(2) system call itself.
*/
--git a/linux-headers/linux/vduse.h b/linux-headers/linux/vduse.h
index e19b3c0f51..bab47129db 100644
--- a/linux-headers/linux/vduse.h
+++ b/linux-headers/linux/vduse.h
@@ -14,6 +14,12 @@
#define VDUSE_API_VERSION_1 1
+/* The VDUSE instance expects a request for vq ready */
+#define VDUSE_F_QUEUE_READY 0
+
+/* The VDUSE instance expects a request for suspend */
+#define VDUSE_F_SUSPEND 1
+
/*
* Get the version of VDUSE API that kernel supported (VDUSE_API_VERSION).
* This is used for future extension.
@@ -63,6 +69,12 @@ struct vduse_dev_config {
*/
#define VDUSE_DESTROY_DEV _IOW(VDUSE_BASE, 0x03, char[VDUSE_NAME_MAX])
+/* Get the VDUSE supported features */
+#define VDUSE_GET_FEATURES _IOR(VDUSE_BASE, 0x04, __u64)
+
+/* Set the VDUSE features */
+#define VDUSE_SET_FEATURES _IOW(VDUSE_BASE, 0x05, __u64)
+
/* The ioctls for VDUSE device (/dev/vduse/$NAME) */
/**
@@ -325,6 +337,8 @@ enum vduse_req_type {
VDUSE_SET_STATUS,
VDUSE_UPDATE_IOTLB,
VDUSE_SET_VQ_GROUP_ASID,
+ VDUSE_SET_VQ_READY,
+ VDUSE_SUSPEND,
};
/**
@@ -372,6 +386,15 @@ struct vduse_iova_range_v2 {
__u32 padding;
};
+/**
+ * struct vduse_vq_ready - Virtqueue ready request message
+ * @num: Virtqueue number
+ */
+struct vduse_vq_ready {
+ __u32 num;
+ __u32 ready;
+};
+
/**
* struct vduse_dev_request - control request
* @type: request type
@@ -382,6 +405,7 @@ struct vduse_iova_range_v2 {
* @iova: IOVA range for updating
* @iova_v2: IOVA range for updating if API_VERSION >= 1
* @vq_group_asid: ASID of a virtqueue group
+ * @vq_ready: Virtqueue ready request
* @padding: padding
*
* Structure used by read(2) on /dev/vduse/$NAME.
@@ -399,6 +423,10 @@ struct vduse_dev_request {
*/
struct vduse_iova_range_v2 iova_v2;
struct vduse_vq_group_asid vq_group_asid;
+
+ /* Only if VDUSE_F_QUEUE_READY is negotiated */
+ struct vduse_vq_ready vq_ready;
+
__u32 padding[32];
};
};
--git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h
index f3282b8e86..c85dcbfe30 100644
--- a/linux-headers/linux/vfio.h
+++ b/linux-headers/linux/vfio.h
@@ -1534,6 +1534,27 @@ struct vfio_device_feature_dma_buf {
*/
#define VFIO_DEVICE_FEATURE_MIG_PRECOPY_INFOv2 12
+/**
+ * VFIO_DEVICE_FEATURE_ZPCI_ERROR feature provides PCI error information to
+ * userspace for vfio-pci devices on s390. On s390, PCI error recovery
+ * involves platform firmware and notification to operating systems is done
+ * by architecture specific mechanism. Exposing this information to
+ * userspace allows it to take appropriate actions to handle an
+ * error on the device.
+ *
+ * Userspace provides an opaque buffer of fixed length, and the kernel
+ * fills it with the zpci_ccdf_err data structure. The length of
+ * zpci_ccdf_err is provided to userspace via the
+ * VFIO_DEVICE_INFO_CAP_ZPCI_BASE capability.
+ *
+ * The ioctl returns -ENOMSG if there are no pending PCI errors.
+ */
+struct vfio_device_feature_zpci_err {
+ __aligned_u64 data;
+};
+
+#define VFIO_DEVICE_FEATURE_ZPCI_ERROR 13
+
/* -------- API for Type1 VFIO IOMMU -------- */
/**
--git a/linux-headers/linux/vfio_zdev.h b/linux-headers/linux/vfio_zdev.h
index 77f2aff1f2..d6c1175c88 100644
--- a/linux-headers/linux/vfio_zdev.h
+++ b/linux-headers/linux/vfio_zdev.h
@@ -32,6 +32,8 @@ struct vfio_device_info_cap_zpci_base {
/* End of version 1 */
__u32 fh; /* PCI function handle */
/* End of version 2 */
+ __u32 ccdf_err_length; /* PCI CCDF length */
+ /* End of version 3 */
};
/**
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 54/75] virtio-scsi: set dataplane_started to false upon failure
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (52 preceding siblings ...)
2026-09-11 9:03 ` [PULL v2 53/75] linux-headers: Update to Linux v7.3-rc1 Michael S. Tsirkin
@ 2026-09-11 9:03 ` Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 55/75] hw/cxl: fix the CDAT DOE overlapping the Flex Bus DVSEC when sn= is set Michael S. Tsirkin
` (22 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:03 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Stefan Hajnoczi, Paolo Bonzini,
Philippe Mathieu-Daudé, Fam Zheng
From: Stefan Hajnoczi <stefanha@redhat.com>
Commit e24a47c5b73e ("virtio-scsi: do not use vring in dataplane") set
dataplane_started to true when virtio_scsi_dataplane_start() fails. This
is likely a typo since dataplane is not functional after failure.
The non-ioeventfd fallback is broken because dataplane_started is true
after virtio_scsi_dataplane_start() failure. As a result, the following
assertion failure occurs when a virtio-scsi device exceeds the open file
descriptor ulimit when setting up notifiers (eventfds):
$ ulimit -n 104 # exact number can vary based on QEMU version
$ qemu-system-x86_64 -M q35,accel=kvm -m 1G -cpu host -smp 14 \
--blockdev file,node-name=drive0,filename=test.img,cache.direct=on,aio=native \
--blockdev file,node-name=drive1,filename=data01.img,cache.direct=on,aio=native \
--device virtio-scsi-pci,id=virtio-scsi-pci0 \
--device scsi-hd,drive=drive0,bus=virtio-scsi-pci0.0 \
--device virtio-scsi-pci,id=virtio-scsi-pci1 \
--device scsi-hd,drive=drive1,bus=virtio-scsi-pci1.0
qemu: virtio-scsi: Failed to set guest notifiers (-24), ensure -accel kvm is set.
qemu: virtio_bus_start_ioeventfd: failed. Fallback to userspace (slower).
qemu-system-x86_64: ../hw/scsi/virtio-scsi.c:1017: virtio_scsi_reset: Assertion `!s->dataplane_started' failed.
Aborted (core dumped)
Cc: Paolo Bonzini <pbonzini@redhat.com>
Fixes: e24a47c5b73e ("virtio-scsi: do not use vring in dataplane")
Buglink: https://redhat.atlassian.net/browse/RHEL-193328
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260825154854.263819-1-stefanha@redhat.com>
---
hw/scsi/virtio-scsi-dataplane.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c
index 95f13fb7c2..bcb6e44133 100644
--- a/hw/scsi/virtio-scsi-dataplane.c
+++ b/hw/scsi/virtio-scsi-dataplane.c
@@ -230,7 +230,7 @@ fail_host_notifiers:
fail_guest_notifiers:
s->dataplane_fenced = true;
s->dataplane_starting = false;
- s->dataplane_started = true;
+ s->dataplane_started = false;
return -ENOSYS;
}
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 55/75] hw/cxl: fix the CDAT DOE overlapping the Flex Bus DVSEC when sn= is set
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (53 preceding siblings ...)
2026-09-11 9:03 ` [PULL v2 54/75] virtio-scsi: set dataplane_started to false upon failure Michael S. Tsirkin
@ 2026-09-11 9:03 ` Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 56/75] virtio-rtc: Report smeared UTC clock type Michael S. Tsirkin
` (21 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:03 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Junjie Cao, Jonathan Cameron, linux-cxl
From: Junjie Cao <junjie.cao@intel.com>
ct3_realize() adds the CDAT DOE at a fixed 0x190. Since 8700ee15de the
four DVSECs take 0x90 bytes, which from 0x100 ends exactly at 0x190.
With sn= the Device Serial Number capability pushes the block to
0x10c..0x19c, and the DOE, added later, overwrites the last 12 bytes of
the Flex Bus Port DVSEC: Capability2, Control2 and Status2. Nothing
catches this -- pcie_add_capability() checks bounds, not overlap, and
the chain still walks because the DVSEC's next pointer becomes 0x190,
inside its own body. Most cxl-type3 examples in
docs/system/devices/cxl.rst set sn=.
Derive the offset from the DVSEC block instead, as cxl_upstream.c
already does. Without sn= the layout is unchanged byte for byte; with
sn= the DOE moves to 0x19c, below the AER capability at 0x200. The
type 3 device has no VMStateDescription, so its config space never
reaches the migration stream.
Fixes: 8700ee15de ("hw/cxl: Standardize all references on CXL r3.1 and minor updates")
Signed-off-by: Junjie Cao <junjie.cao@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260831022302.406740-1-junjie.cao@intel.com>
---
hw/mem/cxl_type3.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index 6f44770db6..a04dc74ecc 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.c
@@ -936,8 +936,8 @@ static void ct3_realize(PCIDevice *pci_dev, Error **errp)
}
/* DOE Initialization */
- pcie_doe_init(pci_dev, &ct3d->doe_cdat, 0x190, doe_cdat_prot, true,
- CXL_T3_MSIX_PCIE_DOE_TABLE_ACCESS);
+ pcie_doe_init(pci_dev, &ct3d->doe_cdat, cxl_cstate->dvsec_offset,
+ doe_cdat_prot, true, CXL_T3_MSIX_PCIE_DOE_TABLE_ACCESS);
cxl_cstate->cdat.build_cdat_table = ct3_build_cdat_table;
cxl_cstate->cdat.free_cdat_table = ct3_free_cdat_table;
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 56/75] virtio-rtc: Report smeared UTC clock type
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (54 preceding siblings ...)
2026-09-11 9:03 ` [PULL v2 55/75] hw/cxl: fix the CDAT DOE overlapping the Flex Bus DVSEC when sn= is set Michael S. Tsirkin
@ 2026-09-11 9:03 ` Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 57/75] intel_iommu: Support concurrent page fault handling with PRI Michael S. Tsirkin
` (20 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:03 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Kuan-Wei Chiu
From: Kuan-Wei Chiu <visitorckw@gmail.com>
The Linux virtio_rtc driver only registers an RTC class device when the
clock type is VIRTIO_RTC_CLOCK_UTC_SMEARED to avoid leap second steps on
pure UTC clocks.
Report VIRTIO_RTC_CLOCK_UTC_SMEARED in clock capabilities so the guest
can expose the device as an RTC device.
Signed-off-by: Kuan-Wei Chiu <visitorckw@gmail.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260831190612.369235-1-visitorckw@gmail.com>
---
hw/virtio/virtio-rtc.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/hw/virtio/virtio-rtc.c b/hw/virtio/virtio-rtc.c
index 32de9c1650..0dcbe94758 100644
--- a/hw/virtio/virtio-rtc.c
+++ b/hw/virtio/virtio-rtc.c
@@ -62,7 +62,8 @@ static void virtio_rtc_handle_request(VirtIODevice *vdev, VirtQueue *vq)
resp.head.status = VIRTIO_RTC_S_ENODEV;
} else {
resp.head.status = VIRTIO_RTC_S_OK;
- resp.type = VIRTIO_RTC_CLOCK_UTC;
+ resp.type = VIRTIO_RTC_CLOCK_UTC_SMEARED;
+ resp.leap_second_smearing = VIRTIO_RTC_SMEAR_UNSPECIFIED;
}
written = iov_from_buf(elem->in_sg, elem->in_num, 0, &resp,
sizeof(resp));
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 57/75] intel_iommu: Support concurrent page fault handling with PRI
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (55 preceding siblings ...)
2026-09-11 9:03 ` [PULL v2 56/75] virtio-rtc: Report smeared UTC clock type Michael S. Tsirkin
@ 2026-09-11 9:03 ` Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 58/75] intel_iommu: Only set dirty bit when PTE exposes write permission Michael S. Tsirkin
` (19 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:03 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Clément MATHIEU--DRIF, Jason Wang, Yi Liu,
Paolo Bonzini, Richard Henderson
From: Clément MATHIEU--DRIF <clement.mathieu--drif@bull.com>
PRQ slot allocation must be thread safe to avoid posting multiple
commands in the same slot so we take a lock in vtd_pri_request_page.
This allows multiple devices to call the page request interface
of the same iommu instance.
Signed-off-by: Clement Mathieu--Drif <clement.mathieu--drif@bull.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260903145044.2245609-1-clement.mathieu--drif@bull.com>
---
hw/i386/intel_iommu.c | 103 ++++++++++++++++++++++++++----------------
1 file changed, 63 insertions(+), 40 deletions(-)
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 82c3c3b2c3..7c442a86ca 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -3627,15 +3627,26 @@ static void vtd_handle_iectl_write(IntelIOMMUState *s)
static void vtd_handle_prs_write(IntelIOMMUState *s)
{
- uint32_t prs = vtd_get_long_raw(s, DMAR_PRS_REG);
+ uint32_t prs;
+
+ vtd_iommu_lock(s);
+
+ prs = vtd_get_long_raw(s, DMAR_PRS_REG);
if (!(prs & VTD_PR_STATUS_PPR) && !(prs & VTD_PR_STATUS_PRO)) {
vtd_set_clear_mask_long(s, DMAR_PECTL_REG, VTD_PR_PECTL_IP, 0);
}
+
+ vtd_iommu_unlock(s);
}
static void vtd_handle_pectl_write(IntelIOMMUState *s)
{
- uint32_t pectl = vtd_get_long_raw(s, DMAR_PECTL_REG);
+ uint32_t pectl;
+
+ vtd_iommu_lock(s);
+
+ pectl = vtd_get_long_raw(s, DMAR_PECTL_REG);
+
if ((pectl & VTD_PR_PECTL_IP) && !(pectl & VTD_PR_PECTL_IM)) {
/*
* If IP field was 1 when software clears the IM field,
@@ -3644,6 +3655,8 @@ static void vtd_handle_pectl_write(IntelIOMMUState *s)
vtd_set_clear_mask_long(s, DMAR_PECTL_REG, VTD_PR_PECTL_IP, 0);
vtd_generate_interrupt(s, DMAR_PEADDR_REG, DMAR_PEDATA_REG);
}
+
+ vtd_iommu_unlock(s);
}
static uint64_t vtd_mem_read(void *opaque, hwaddr addr, unsigned size)
@@ -5377,19 +5390,18 @@ static int vtd_pri_request_page(PCIBus *bus, void *opaque, int devfn,
{
IntelIOMMUState *s = opaque;
VTDAddressSpace *vtd_as;
+ uint64_t queue_addr_reg;
+ uint64_t queue_tail_offset_reg;
+ uint64_t new_queue_tail_offset;
+ uint64_t queue_head_offset_reg;
+ hwaddr queue_tail;
+ uint32_t old_pr_status;
+ uint16_t sid;
+ VTDPRDesc desc;
+ int ret = 0;
vtd_as = vtd_find_add_as(s, bus, devfn, pasid);
-
- uint64_t queue_addr_reg = vtd_get_quad(s, DMAR_PQA_REG);
- uint64_t queue_tail_offset_reg = vtd_get_quad(s, DMAR_PQT_REG);
- uint64_t new_queue_tail_offset = (
- (queue_tail_offset_reg + VTD_PQA_ENTRY_SIZE) %
- (vtd_prq_size(s) * VTD_PQA_ENTRY_SIZE));
- uint64_t queue_head_offset_reg = vtd_get_quad(s, DMAR_PQH_REG);
- hwaddr queue_tail = (queue_addr_reg & VTD_PQA_ADDR) + queue_tail_offset_reg;
- uint32_t old_pr_status = vtd_get_long(s, DMAR_PRS_REG);
- uint16_t sid = PCI_BUILD_BDF(pci_bus_num(vtd_as->bus), vtd_as->devfn);
- VTDPRDesc desc;
+ sid = PCI_BUILD_BDF(pci_bus_num(vtd_as->bus), vtd_as->devfn);
if (!(s->ecap & VTD_ECAP_PRS)) {
return -EPERM;
@@ -5413,25 +5425,7 @@ static int vtd_pri_request_page(PCIBus *bus, void *opaque, int devfn,
return -EPERM;
}
- if (old_pr_status & VTD_PR_STATUS_PRO) {
- /*
- * No action is taken by hardware to report a fault
- * or generate an event
- */
- return -ENOSPC;
- }
-
- /* Check for overflow */
- if (new_queue_tail_offset == queue_head_offset_reg) {
- vtd_set_clear_mask_long(s, DMAR_PRS_REG, 0, VTD_PR_STATUS_PRO);
- vtd_generate_page_request_event(s, old_pr_status);
- return -ENOSPC;
- }
-
- if (vtd_pri_perform_implicit_invalidation(vtd_as, addr)) {
- return -EINVAL;
- }
-
+ /* Prepare the descriptor */
desc.lo = VTD_PRD_TYPE | VTD_PRD_PP(true) | VTD_PRD_RID(sid) |
VTD_PRD_PASID(vtd_as->pasid) | VTD_PRD_PMR(priv_req);
desc.hi = VTD_PRD_RDR(is_read) | VTD_PRD_WRR(is_write) |
@@ -5439,26 +5433,55 @@ static int vtd_pri_request_page(PCIBus *bus, void *opaque, int devfn,
desc.lo = cpu_to_le64(desc.lo);
desc.hi = cpu_to_le64(desc.hi);
+
+ if (vtd_pri_perform_implicit_invalidation(vtd_as, addr)) {
+ return -EINVAL;
+ }
+
+ vtd_iommu_lock(s);
+
+ queue_addr_reg = vtd_get_quad(s, DMAR_PQA_REG);
+ queue_tail_offset_reg = vtd_get_quad(s, DMAR_PQT_REG);
+ new_queue_tail_offset = ((queue_tail_offset_reg + VTD_PQA_ENTRY_SIZE) %
+ (vtd_prq_size(s) * VTD_PQA_ENTRY_SIZE));
+ queue_head_offset_reg = vtd_get_quad(s, DMAR_PQH_REG);
+ queue_tail = (queue_addr_reg & VTD_PQA_ADDR) + queue_tail_offset_reg;
+ old_pr_status = vtd_get_long(s, DMAR_PRS_REG);
+
+ if (old_pr_status & VTD_PR_STATUS_PRO) {
+ /*
+ * No action is taken by hardware to report a fault
+ * or generate an event
+ */
+ ret = -ENOSPC;
+ goto out;
+ }
+
+ /* Check for overflow */
+ if (new_queue_tail_offset == queue_head_offset_reg) {
+ vtd_set_clear_mask_long(s, DMAR_PRS_REG, 0, VTD_PR_STATUS_PRO);
+ vtd_generate_page_request_event(s, old_pr_status);
+ ret = -ENOSPC;
+ goto out;
+ }
+
if (dma_memory_write(&address_space_memory, queue_tail, &desc, sizeof(desc),
MEMTXATTRS_UNSPECIFIED)) {
error_report_once("IO error, the PQ tail cannot be updated");
- return -EIO;
+ ret = -EIO;
+ goto out;
}
/* increment the tail register and set the pending request bit */
vtd_set_quad(s, DMAR_PQT_REG, new_queue_tail_offset);
- /*
- * read status again so that the kernel does not miss a request.
- * in some cases, we can trigger an unecessary interrupt but this strategy
- * drastically improves performance as we don't need to take a lock.
- */
- old_pr_status = vtd_get_long(s, DMAR_PRS_REG);
if (!(old_pr_status & VTD_PR_STATUS_PPR)) {
vtd_set_clear_mask_long(s, DMAR_PRS_REG, 0, VTD_PR_STATUS_PPR);
vtd_generate_page_request_event(s, old_pr_status);
}
- return 0;
+out:
+ vtd_iommu_unlock(s);
+ return ret;
}
static void vtd_init_iotlb_notifier(PCIBus *bus, void *opaque, int devfn,
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 58/75] intel_iommu: Only set dirty bit when PTE exposes write permission
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (56 preceding siblings ...)
2026-09-11 9:03 ` [PULL v2 57/75] intel_iommu: Support concurrent page fault handling with PRI Michael S. Tsirkin
@ 2026-09-11 9:03 ` Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 59/75] intel_iommu: Always write all the flags passed to vtd_set_flag_in_pte Michael S. Tsirkin
` (18 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:03 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Clément MATHIEU--DRIF, Yi Liu, Jason Wang,
Paolo Bonzini, Richard Henderson
From: Clément MATHIEU--DRIF <clement.mathieu--drif@bull.com>
Setting the dirty bit without the write bit in vIOMMU creates a spoofed
shadow stack PTE that misleads the guest OS. This results in infinite
PRI requests from the device, as no actual write permission is ever
granted - the guest OS treats the PTE as a legitimate shadow stack entry
and considers the permissions already correct.
Fixes: 65c4f0999991 ("intel_iommu: Set accessed and dirty bits during stage-1 translation")
Signed-off-by: Clement Mathieu--Drif <clement.mathieu--drif@bull.com>
Reviewed-by: Yi Liu <yi.l.liu@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260903150649.2281104-2-clement.mathieu--drif@bull.com>
---
hw/i386/intel_iommu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 7c442a86ca..eccb16346c 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -2039,7 +2039,7 @@ static int vtd_iova_to_fspte(IntelIOMMUState *s, VTDContextEntry *ce,
return -VTD_FR_FS_PAGING_ENTRY_RSVD;
}
- if (vtd_is_last_pte(fspte, *fspte_level) && is_write) {
+ if (vtd_is_last_pte(fspte, *fspte_level) && *writes && is_write) {
flag_ad |= VTD_FS_D;
}
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 59/75] intel_iommu: Always write all the flags passed to vtd_set_flag_in_pte
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (57 preceding siblings ...)
2026-09-11 9:03 ` [PULL v2 58/75] intel_iommu: Only set dirty bit when PTE exposes write permission Michael S. Tsirkin
@ 2026-09-11 9:03 ` Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 60/75] pci: batch BAR remapping into one memory transaction Michael S. Tsirkin
` (17 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:03 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Clément MATHIEU--DRIF, Yi Liu, Zhenzhong Duan,
Jason Wang, Paolo Bonzini, Richard Henderson
From: Clément MATHIEU--DRIF <clement.mathieu--drif@bull.com>
This function was initially designed to write a single flag in a pte.
The current implementation expects it to set several flags.
Fixes: 65c4f0999991 ("intel_iommu: Set accessed and dirty bits during stage-1 translation")
Signed-off-by: Clement Mathieu--Drif <clement.mathieu--drif@bull.com>
Reviewed-by: Yi Liu <yi.l.liu@intel.com>
Reviewed-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260903150649.2281104-3-clement.mathieu--drif@bull.com>
---
hw/i386/intel_iommu.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index eccb16346c..91ab549dbf 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -1964,13 +1964,13 @@ static bool vtd_iova_fs_check_canonical(IntelIOMMUState *s, uint64_t iova,
}
}
-static MemTxResult vtd_set_flag_in_pte(dma_addr_t base_addr, uint32_t index,
- uint64_t pte, uint64_t flag)
+static MemTxResult vtd_set_flags_in_pte(dma_addr_t base_addr, uint32_t index,
+ uint64_t pte, uint64_t flags)
{
- if (pte & flag) {
+ if ((pte & flags) == flags) {
return MEMTX_OK;
}
- pte |= flag;
+ pte |= flags;
pte = cpu_to_le64(pte);
return dma_memory_write(&address_space_memory,
base_addr + index * sizeof(pte),
@@ -2043,7 +2043,7 @@ static int vtd_iova_to_fspte(IntelIOMMUState *s, VTDContextEntry *ce,
flag_ad |= VTD_FS_D;
}
- if (vtd_set_flag_in_pte(addr, offset, fspte, flag_ad) != MEMTX_OK) {
+ if (vtd_set_flags_in_pte(addr, offset, fspte, flag_ad) != MEMTX_OK) {
return -VTD_FR_FS_BIT_UPDATE_FAILED;
}
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 60/75] pci: batch BAR remapping into one memory transaction
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (58 preceding siblings ...)
2026-09-11 9:03 ` [PULL v2 59/75] intel_iommu: Always write all the flags passed to vtd_set_flag_in_pte Michael S. Tsirkin
@ 2026-09-11 9:03 ` Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 61/75] pci: load a device's config inside " Michael S. Tsirkin
` (16 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:03 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Denis V. Lunev, Denis V. Lunev
From: "Denis V. Lunev" <den@openvz.org>
pci_update_mappings() deletes and re-adds a subregion for each BAR
whose address changed, and both of those commit their own transaction,
so one BAR move costs two full flatview rebuilds.
Nothing between the delete and the add touches an address space, so
the walk can run inside a single transaction. pci_bridge_update_mappings()
already does this for the bridge windows.
CC: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Denis V. Lunev <den@virtuozzo.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260903184542.2629976-2-den@openvz.org>
---
hw/pci/pci.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index c15f2b9f08..14c78e3c62 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -1742,6 +1742,8 @@ static void pci_update_mappings(PCIDevice *d)
int i;
pcibus_t new_addr;
+ memory_region_transaction_begin();
+
for(i = 0; i < PCI_NUM_REGIONS; i++) {
r = &d->io_regions[i];
@@ -1778,6 +1780,8 @@ static void pci_update_mappings(PCIDevice *d)
}
pci_update_vga(d);
+
+ memory_region_transaction_commit();
}
int pci_irq_disabled(PCIDevice *d)
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 61/75] pci: load a device's config inside one memory transaction
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (59 preceding siblings ...)
2026-09-11 9:03 ` [PULL v2 60/75] pci: batch BAR remapping into one memory transaction Michael S. Tsirkin
@ 2026-09-11 9:03 ` Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 62/75] hw/acpi: Make AcpiGedState const in build_ged_aml() Michael S. Tsirkin
` (15 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:03 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Denis V. Lunev, Denis V. Lunev
From: "Denis V. Lunev" <den@openvz.org>
Restoring config space remaps the BARs, updates the bridge windows when
the device is a bridge, and toggles the bus master region. Each of those
commits a transaction of its own, so one device costs several flatview
rebuilds where one would do, and the cost of a rebuild grows with the
number of regions in the machine.
Nothing between them touches an address space, so the three can share a
transaction. The saving scales with the number of PCI devices.
CC: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Denis V. Lunev <den@virtuozzo.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260903184542.2629976-3-den@openvz.org>
---
hw/pci/pci.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 14c78e3c62..0efb4eb4bb 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -840,6 +840,8 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size,
}
memcpy(s->config, config, size);
+ memory_region_transaction_begin();
+
pci_update_mappings(s);
if (IS_PCI_BRIDGE(s)) {
pci_bridge_update_mappings(PCI_BRIDGE(s));
@@ -848,6 +850,8 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size,
pci_set_master(s, pci_get_word(s->config + PCI_COMMAND)
& PCI_COMMAND_MASTER);
+ memory_region_transaction_commit();
+
g_free(config);
return 0;
}
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 62/75] hw/acpi: Make AcpiGedState const in build_ged_aml()
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (60 preceding siblings ...)
2026-09-11 9:03 ` [PULL v2 61/75] pci: load a device's config inside " Michael S. Tsirkin
@ 2026-09-11 9:03 ` Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 63/75] hw/hotplug: Mark various HotplugHandlerClass variables as const Michael S. Tsirkin
` (14 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:03 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Philippe Mathieu-Daudé, Igor Mammedov,
Ani Sinha
From: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
build_ged_aml() do not modify the AcpiGedState structure.
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260903230245.65601-2-philmd@oss.qualcomm.com>
---
hw/acpi/generic_event_device.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
index 67c9e9b3e8..5225e32513 100644
--- a/hw/acpi/generic_event_device.c
+++ b/hw/acpi/generic_event_device.c
@@ -48,7 +48,7 @@ static const uint32_t ged_supported_events[] = {
void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev,
uint32_t ged_irq, AmlRegionSpace rs, hwaddr ged_base)
{
- AcpiGedState *s = ACPI_GED(hotplug_dev);
+ const AcpiGedState *s = ACPI_GED(hotplug_dev);
Aml *crs = aml_resource_template();
Aml *evt, *field;
Aml *dev = aml_device("%s", name);
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 63/75] hw/hotplug: Mark various HotplugHandlerClass variables as const
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (61 preceding siblings ...)
2026-09-11 9:03 ` [PULL v2 62/75] hw/acpi: Make AcpiGedState const in build_ged_aml() Michael S. Tsirkin
@ 2026-09-11 9:03 ` Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 64/75] hw/hotplug: Reduce some HotplugHandler variables scope Michael S. Tsirkin
` (13 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:03 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Philippe Mathieu-Daudé, David Hildenbrand,
Cornelia Huck, Halil Pasic, Eric Farman, Christian Borntraeger,
Matthew Rosato, Richard Henderson, Ilya Leoshkevich,
Paolo Bonzini, Daniel P. Berrangé, qemu-s390x
From: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
The HotplugHandlerClass pointers are only dereferenced, not updated.
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260903230245.65601-3-philmd@oss.qualcomm.com>
---
include/hw/core/qdev.h | 2 +-
hw/core/hotplug.c | 8 ++++----
hw/s390x/virtio-ccw-md.c | 2 +-
hw/virtio/virtio-md-pci.c | 2 +-
system/qdev-monitor.c | 2 +-
5 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/include/hw/core/qdev.h b/include/hw/core/qdev.h
index f054a214fc..e4cb027ab3 100644
--- a/include/hw/core/qdev.h
+++ b/include/hw/core/qdev.h
@@ -1069,7 +1069,7 @@ static inline bool qbus_is_hotpluggable(BusState *bus)
bool ret = !!plug_handler;
if (plug_handler) {
- HotplugHandlerClass *hdc;
+ const HotplugHandlerClass *hdc;
hdc = HOTPLUG_HANDLER_GET_CLASS(plug_handler);
if (hdc->is_hotpluggable_bus) {
diff --git a/hw/core/hotplug.c b/hw/core/hotplug.c
index 68aabad8ae..00e80a67c8 100644
--- a/hw/core/hotplug.c
+++ b/hw/core/hotplug.c
@@ -17,7 +17,7 @@ void hotplug_handler_pre_plug(HotplugHandler *plug_handler,
DeviceState *plugged_dev,
Error **errp)
{
- HotplugHandlerClass *hdc = HOTPLUG_HANDLER_GET_CLASS(plug_handler);
+ const HotplugHandlerClass *hdc = HOTPLUG_HANDLER_GET_CLASS(plug_handler);
if (hdc->pre_plug) {
hdc->pre_plug(plug_handler, plugged_dev, errp);
@@ -28,7 +28,7 @@ void hotplug_handler_plug(HotplugHandler *plug_handler,
DeviceState *plugged_dev,
Error **errp)
{
- HotplugHandlerClass *hdc = HOTPLUG_HANDLER_GET_CLASS(plug_handler);
+ const HotplugHandlerClass *hdc = HOTPLUG_HANDLER_GET_CLASS(plug_handler);
if (hdc->plug) {
hdc->plug(plug_handler, plugged_dev, errp);
@@ -39,7 +39,7 @@ void hotplug_handler_unplug_request(HotplugHandler *plug_handler,
DeviceState *plugged_dev,
Error **errp)
{
- HotplugHandlerClass *hdc = HOTPLUG_HANDLER_GET_CLASS(plug_handler);
+ const HotplugHandlerClass *hdc = HOTPLUG_HANDLER_GET_CLASS(plug_handler);
if (hdc->unplug_request) {
hdc->unplug_request(plug_handler, plugged_dev, errp);
@@ -50,7 +50,7 @@ void hotplug_handler_unplug(HotplugHandler *plug_handler,
DeviceState *plugged_dev,
Error **errp)
{
- HotplugHandlerClass *hdc = HOTPLUG_HANDLER_GET_CLASS(plug_handler);
+ const HotplugHandlerClass *hdc = HOTPLUG_HANDLER_GET_CLASS(plug_handler);
if (hdc->unplug) {
hdc->unplug(plug_handler, plugged_dev, errp);
diff --git a/hw/s390x/virtio-ccw-md.c b/hw/s390x/virtio-ccw-md.c
index 0370f58450..0b18b49bc4 100644
--- a/hw/s390x/virtio-ccw-md.c
+++ b/hw/s390x/virtio-ccw-md.c
@@ -73,7 +73,7 @@ void virtio_ccw_md_unplug_request(VirtIOMDCcw *vmd, MachineState *ms,
VirtIOMDCcwClass *vmdc = VIRTIO_MD_CCW_GET_CLASS(vmd);
DeviceState *dev = DEVICE(vmd);
HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
- HotplugHandlerClass *hdc;
+ const HotplugHandlerClass *hdc;
Error *local_err = NULL;
if (!vmdc->unplug_request_check) {
diff --git a/hw/virtio/virtio-md-pci.c b/hw/virtio/virtio-md-pci.c
index 9278b32cf8..aa5b11c0f6 100644
--- a/hw/virtio/virtio-md-pci.c
+++ b/hw/virtio/virtio-md-pci.c
@@ -72,7 +72,7 @@ void virtio_md_pci_unplug_request(VirtIOMDPCI *vmd, MachineState *ms,
VirtIOMDPCIClass *vmdc = VIRTIO_MD_PCI_GET_CLASS(vmd);
DeviceState *dev = DEVICE(vmd);
HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
- HotplugHandlerClass *hdc;
+ const HotplugHandlerClass *hdc;
Error *local_err = NULL;
if (!vmdc->unplug_request_check) {
diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c
index 5c87fda509..0c5502d45b 100644
--- a/system/qdev-monitor.c
+++ b/system/qdev-monitor.c
@@ -918,7 +918,7 @@ static DeviceState *find_device_state(const char *id, bool use_generic_error,
void qdev_unplug(DeviceState *dev, Error **errp)
{
HotplugHandler *hotplug_ctrl;
- HotplugHandlerClass *hdc;
+ const HotplugHandlerClass *hdc;
Error *local_err = NULL;
if (!qdev_hotunplug_allowed(dev, errp)) {
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 64/75] hw/hotplug: Reduce some HotplugHandler variables scope
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (62 preceding siblings ...)
2026-09-11 9:03 ` [PULL v2 63/75] hw/hotplug: Mark various HotplugHandlerClass variables as const Michael S. Tsirkin
@ 2026-09-11 9:03 ` Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 65/75] hw/hotplug: Constify HotplugHandler Michael S. Tsirkin
` (12 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:03 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Philippe Mathieu-Daudé, Igor Mammedov,
Ani Sinha
From: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260903230245.65601-4-philmd@oss.qualcomm.com>
---
hw/acpi/memory_hotplug.c | 3 ++-
hw/acpi/pcihp.c | 3 ++-
hw/pci/shpc.c | 3 ++-
3 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c
index 1ddfdd17b7..f482c835a1 100644
--- a/hw/acpi/memory_hotplug.c
+++ b/hw/acpi/memory_hotplug.c
@@ -119,7 +119,6 @@ static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data,
MemStatus *mdev;
ACPIOSTInfo *info;
DeviceState *dev = NULL;
- HotplugHandler *hotplug_ctrl = NULL;
Error *local_err = NULL;
if (!mem_st->dev_count) {
@@ -167,6 +166,8 @@ static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data,
mdev->is_removing = false;
trace_mhp_acpi_clear_remove_evt(mem_st->selector);
} else if (data & 8) {
+ HotplugHandler *hotplug_ctrl;
+
if (!mdev->is_enabled) {
trace_mhp_acpi_ejecting_invalid_slot(mem_st->selector);
break;
diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
index b26ddf0a26..336ebe1a13 100644
--- a/hw/acpi/pcihp.c
+++ b/hw/acpi/pcihp.c
@@ -173,7 +173,6 @@ static bool acpi_pcihp_pc_no_hotplug(AcpiPciHpState *s, PCIDevice *dev)
static void acpi_pcihp_eject_slot(AcpiPciHpState *s, unsigned bsel, unsigned slots)
{
- HotplugHandler *hotplug_ctrl;
BusChild *kid, *next;
int slot = ctz32(slots);
PCIBus *bus = acpi_pcihp_find_hotplug_bus(s, bsel);
@@ -210,6 +209,8 @@ static void acpi_pcihp_eject_slot(AcpiPciHpState *s, unsigned bsel, unsigned slo
*/
qdev->pending_deleted_event = false;
} else {
+ HotplugHandler *hotplug_ctrl;
+
hotplug_ctrl = qdev_get_hotplug_handler(qdev);
hotplug_handler_unplug(hotplug_ctrl, qdev, &error_abort);
object_unparent(OBJECT(qdev));
diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c
index 938602866d..1198e1ab8c 100644
--- a/hw/pci/shpc.c
+++ b/hw/pci/shpc.c
@@ -271,7 +271,6 @@ static void shpc_invalid_command(SHPCDevice *shpc)
static void shpc_free_devices_in_slot(SHPCDevice *shpc, int slot)
{
- HotplugHandler *hotplug_ctrl;
int devfn;
int pci_slot = SHPC_IDX_TO_PCI(slot);
for (devfn = PCI_DEVFN(pci_slot, 0);
@@ -279,6 +278,8 @@ static void shpc_free_devices_in_slot(SHPCDevice *shpc, int slot)
++devfn) {
PCIDevice *affected_dev = shpc->sec_bus->devices[devfn];
if (affected_dev) {
+ HotplugHandler *hotplug_ctrl;
+
hotplug_ctrl = qdev_get_hotplug_handler(DEVICE(affected_dev));
hotplug_handler_unplug(hotplug_ctrl, DEVICE(affected_dev),
&error_abort);
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 65/75] hw/hotplug: Constify HotplugHandler
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (63 preceding siblings ...)
2026-09-11 9:03 ` [PULL v2 64/75] hw/hotplug: Reduce some HotplugHandler variables scope Michael S. Tsirkin
@ 2026-09-11 9:03 ` Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 66/75] net/tap-solaris: Fix resource leaks on error paths Michael S. Tsirkin
` (11 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:03 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Philippe Mathieu-Daudé, Igor Mammedov,
Ani Sinha, Aurelien Jarno, Laurent Vivier, Amit Shah,
Marc-André Lureau, Paolo Bonzini, Daniel P. Berrangé,
Sergio Lopez, Richard Henderson, Song Gao, Bibo Mao, Xianglai Li,
Jiaxun Yang, Jason Wang, Keith Busch, Klaus Jensen,
Jesper Devantier, Bernhard Beschow, Nicholas Piggin,
Harsh Prateek Bora, Amit Machhiwal, Elena Ufimtseva,
Jagannathan Raman, Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Chao Liu, Halil Pasic,
Christian Borntraeger, Eric Farman, Farhan Ali, Cornelia Huck,
Matthew Rosato, Ilya Leoshkevich, David Hildenbrand, Fam Zheng,
Dmitry Fleytman, Stefano Stabellini, Anthony PERARD,
Edgar E. Iglesias, Zhao Liu, FangSheng Huang, qemu-arm,
qemu-block, qemu-ppc, qemu-riscv, qemu-s390x, xen-devel
From: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
HotplugHandler value returned from qdev_get_hotplug_handler()
points to the handler of and object implementing the
TYPE_HOTPLUG_HANDLER interface. That handler mostly points to
read-only section which shouldn't not be updated. Better
protect it with the const qualifier.
Mechanical change using 'sed' then manually adapted coding style.
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260903230245.65601-5-philmd@oss.qualcomm.com>
---
hw/s390x/ccw-device.h | 2 +-
include/hw/acpi/cpu.h | 4 +--
include/hw/acpi/cpu_hotplug.h | 2 +-
include/hw/acpi/generic_event_device.h | 3 +-
include/hw/acpi/ich9.h | 10 +++---
include/hw/acpi/memory_hotplug.h | 4 +--
include/hw/acpi/pcihp.h | 8 ++---
include/hw/core/boards.h | 4 +--
include/hw/core/hotplug.h | 13 +++----
include/hw/core/qdev.h | 12 +++----
include/hw/i386/microvm.h | 4 +--
include/hw/i386/x86.h | 10 +++---
include/hw/mem/nvdimm.h | 2 +-
include/hw/pci/pci_bridge.h | 6 ++--
include/hw/pci/pcie.h | 8 ++---
include/hw/pci/shpc.h | 6 ++--
include/hw/ppc/spapr_nvdimm.h | 2 +-
hw/acpi/acpi-cpu-hotplug-stub.c | 4 +--
hw/acpi/acpi-mem-hotplug-stub.c | 4 +--
hw/acpi/acpi-nvdimm-stub.c | 2 +-
hw/acpi/acpi-pci-hotplug-stub.c | 8 ++---
hw/acpi/cpu.c | 6 ++--
hw/acpi/generic_event_device.c | 11 +++---
hw/acpi/ich9.c | 10 +++---
hw/acpi/memory_hotplug.c | 6 ++--
hw/acpi/nvdimm.c | 2 +-
hw/acpi/pcihp.c | 10 +++---
hw/acpi/piix4.c | 12 +++----
hw/arm/virt.c | 23 ++++++------
hw/char/virtio-serial-bus.c | 2 +-
hw/core/hotplug.c | 8 ++---
hw/core/qdev-hotplug.c | 10 +++---
hw/core/qdev.c | 2 +-
hw/i386/microvm.c | 12 +++----
hw/i386/pc.c | 28 +++++++--------
hw/i386/x86-common.c | 8 ++---
hw/intc/loongarch_dintc.c | 8 ++---
hw/intc/loongarch_extioi_common.c | 4 +--
hw/intc/loongarch_ipi.c | 4 +--
hw/loongarch/virt.c | 44 +++++++++++------------
hw/net/virtio-net.c | 4 +--
hw/nvme/ctrl.c | 8 ++---
hw/pci-bridge/pci_bridge_dev.c | 6 ++--
hw/pci/pcie.c | 10 +++---
hw/pci/pcie_port.c | 2 +-
hw/pci/shpc.c | 10 +++---
hw/ppc/e500plat.c | 4 +--
hw/ppc/spapr.c | 48 +++++++++++++-------------
hw/ppc/spapr_nvdimm.c | 2 +-
hw/ppc/spapr_pci.c | 12 +++----
hw/remote/machine.c | 2 +-
hw/riscv/virt.c | 6 ++--
hw/s390x/css-bridge.c | 2 +-
hw/s390x/s390-pci-bus.c | 12 +++----
hw/s390x/s390-virtio-ccw.c | 16 ++++-----
hw/s390x/virtio-ccw-md.c | 8 ++---
hw/s390x/virtio-ccw.c | 2 +-
hw/scsi/virtio-scsi.c | 6 ++--
hw/scsi/vmw_pvscsi.c | 4 +--
hw/virtio/virtio-md-pci.c | 8 ++---
hw/xen/xen-bus.c | 2 +-
stubs/hotplug-stubs.c | 6 ++--
system/qdev-monitor.c | 2 +-
63 files changed, 257 insertions(+), 253 deletions(-)
diff --git a/hw/s390x/ccw-device.h b/hw/s390x/ccw-device.h
index 15f64cfb63..c303f1de42 100644
--- a/hw/s390x/ccw-device.h
+++ b/hw/s390x/ccw-device.h
@@ -37,7 +37,7 @@ extern const VMStateDescription vmstate_ccw_dev;
struct CCWDeviceClass {
DeviceClass parent_class;
- void (*unplug)(HotplugHandler *, DeviceState *, Error **);
+ void (*unplug)(const HotplugHandler *, DeviceState *, Error **);
bool (*realize)(CcwDevice *, Error **);
void (*refill_ids)(CcwDevice *);
};
diff --git a/include/hw/acpi/cpu.h b/include/hw/acpi/cpu.h
index 04c821d2b9..3664ac7a52 100644
--- a/include/hw/acpi/cpu.h
+++ b/include/hw/acpi/cpu.h
@@ -39,10 +39,10 @@ typedef struct CPUHotplugState {
AcpiCpuStatus *devs;
} CPUHotplugState;
-void acpi_cpu_plug_cb(HotplugHandler *hotplug_dev,
+void acpi_cpu_plug_cb(const HotplugHandler *hotplug_dev,
CPUHotplugState *cpu_st, DeviceState *dev, Error **errp);
-void acpi_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
+void acpi_cpu_unplug_request_cb(const HotplugHandler *hotplug_dev,
CPUHotplugState *cpu_st,
DeviceState *dev, Error **errp);
diff --git a/include/hw/acpi/cpu_hotplug.h b/include/hw/acpi/cpu_hotplug.h
index 5b670b04eb..bac40ccfa0 100644
--- a/include/hw/acpi/cpu_hotplug.h
+++ b/include/hw/acpi/cpu_hotplug.h
@@ -25,7 +25,7 @@ typedef struct AcpiCpuHotplug {
uint8_t sts[ACPI_GPE_PROC_LEN];
} AcpiCpuHotplug;
-void legacy_acpi_cpu_plug_cb(HotplugHandler *hotplug_dev,
+void legacy_acpi_cpu_plug_cb(const HotplugHandler *hotplug_dev,
AcpiCpuHotplug *g, DeviceState *dev, Error **errp);
void legacy_acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner,
diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h
index 7cbfb5fe7d..42a8033a23 100644
--- a/include/hw/acpi/generic_event_device.h
+++ b/include/hw/acpi/generic_event_device.h
@@ -136,7 +136,8 @@ typedef struct AcpiGedClass {
ResettablePhases parent_phases;
} AcpiGedClass;
-void build_ged_aml(Aml *table, const char* name, HotplugHandler *hotplug_dev,
+void build_ged_aml(Aml *table, const char *name,
+ const HotplugHandler *hotplug_dev,
uint32_t ged_irq, AmlRegionSpace rs, hwaddr ged_base);
void acpi_dsdt_add_power_button(Aml *scope);
diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h
index 6d14544751..6956b2b9c9 100644
--- a/include/hw/acpi/ich9.h
+++ b/include/hw/acpi/ich9.h
@@ -85,15 +85,15 @@ void ich9_pm_reset_properties(ICH9LPCPMRegs *pm);
void ich9_pm_add_class_properties(ObjectClass *oc, ptrdiff_t pm_offset);
-void ich9_pm_device_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+void ich9_pm_device_pre_plug_cb(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp);
-void ich9_pm_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+void ich9_pm_device_plug_cb(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp);
-void ich9_pm_device_unplug_request_cb(HotplugHandler *hotplug_dev,
+void ich9_pm_device_unplug_request_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp);
-void ich9_pm_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+void ich9_pm_device_unplug_cb(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp);
-bool ich9_pm_is_hotpluggable_bus(HotplugHandler *hotplug_dev, BusState *bus);
+bool ich9_pm_is_hotpluggable_bus(const HotplugHandler *hotplug_dev, BusState *bus);
void ich9_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list);
#endif /* HW_ACPI_ICH9_H */
diff --git a/include/hw/acpi/memory_hotplug.h b/include/hw/acpi/memory_hotplug.h
index eb7f460afe..6e4f82bcf9 100644
--- a/include/hw/acpi/memory_hotplug.h
+++ b/include/hw/acpi/memory_hotplug.h
@@ -36,9 +36,9 @@ typedef struct MemHotplugState {
void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner,
MemHotplugState *state, hwaddr io_base);
-void acpi_memory_plug_cb(HotplugHandler *hotplug_dev, MemHotplugState *mem_st,
+void acpi_memory_plug_cb(const HotplugHandler *hotplug_dev, MemHotplugState *mem_st,
DeviceState *dev, Error **errp);
-void acpi_memory_unplug_request_cb(HotplugHandler *hotplug_dev,
+void acpi_memory_unplug_request_cb(const HotplugHandler *hotplug_dev,
MemHotplugState *mem_st,
DeviceState *dev, Error **errp);
void acpi_memory_unplug_cb(MemHotplugState *mem_st,
diff --git a/include/hw/acpi/pcihp.h b/include/hw/acpi/pcihp.h
index efce5fd2e1..21c0b72355 100644
--- a/include/hw/acpi/pcihp.h
+++ b/include/hw/acpi/pcihp.h
@@ -66,13 +66,13 @@ void acpi_pcihp_init(Object *owner, AcpiPciHpState *,
MemoryRegion *io, uint16_t io_base);
bool acpi_pcihp_is_hotpluggable_bus(AcpiPciHpState *s, BusState *bus);
-void acpi_pcihp_device_pre_plug_cb(HotplugHandler *hotplug_dev,
+void acpi_pcihp_device_pre_plug_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp);
-void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
+void acpi_pcihp_device_plug_cb(const HotplugHandler *hotplug_dev, AcpiPciHpState *s,
DeviceState *dev, Error **errp);
-void acpi_pcihp_device_unplug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
+void acpi_pcihp_device_unplug_cb(const HotplugHandler *hotplug_dev, AcpiPciHpState *s,
DeviceState *dev, Error **errp);
-void acpi_pcihp_device_unplug_request_cb(HotplugHandler *hotplug_dev,
+void acpi_pcihp_device_unplug_request_cb(const HotplugHandler *hotplug_dev,
AcpiPciHpState *s, DeviceState *dev,
Error **errp);
diff --git a/include/hw/core/boards.h b/include/hw/core/boards.h
index a436d48c8e..dba465efc2 100644
--- a/include/hw/core/boards.h
+++ b/include/hw/core/boards.h
@@ -322,8 +322,8 @@ struct MachineClass {
SMPCompatProps smp_props;
const char *default_ram_id;
- HotplugHandler *(*get_hotplug_handler)(MachineState *machine,
- DeviceState *dev);
+ const HotplugHandler *(*get_hotplug_handler)(MachineState *machine,
+ DeviceState *dev);
bool (*hotplug_allowed)(MachineState *state, DeviceState *dev,
Error **errp);
CpuInstanceProperties (*cpu_index_to_instance_props)(MachineState *machine,
diff --git a/include/hw/core/hotplug.h b/include/hw/core/hotplug.h
index a9840ed485..0c69be60ee 100644
--- a/include/hw/core/hotplug.h
+++ b/include/hw/core/hotplug.h
@@ -30,7 +30,7 @@ typedef struct HotplugHandler HotplugHandler;
* @plugged_dev: a device that has been (un)plugged
* @errp: returns an error if this function fails
*/
-typedef void (*hotplug_fn)(HotplugHandler *plug_handler,
+typedef void (*hotplug_fn)(const HotplugHandler *plug_handler,
DeviceState *plugged_dev, Error **errp);
/**
@@ -59,7 +59,8 @@ struct HotplugHandlerClass {
hotplug_fn plug;
hotplug_fn unplug_request;
hotplug_fn unplug;
- bool (*is_hotpluggable_bus)(HotplugHandler *plug_handler, BusState *bus);
+ bool (*is_hotpluggable_bus)(const HotplugHandler *plug_handler,
+ BusState *bus);
};
/**
@@ -67,7 +68,7 @@ struct HotplugHandlerClass {
*
* Call #HotplugHandlerClass.plug callback of @plug_handler.
*/
-void hotplug_handler_plug(HotplugHandler *plug_handler,
+void hotplug_handler_plug(const HotplugHandler *plug_handler,
DeviceState *plugged_dev,
Error **errp);
@@ -76,7 +77,7 @@ void hotplug_handler_plug(HotplugHandler *plug_handler,
*
* Call #HotplugHandlerClass.pre_plug callback of @plug_handler.
*/
-void hotplug_handler_pre_plug(HotplugHandler *plug_handler,
+void hotplug_handler_pre_plug(const HotplugHandler *plug_handler,
DeviceState *plugged_dev,
Error **errp);
@@ -85,7 +86,7 @@ void hotplug_handler_pre_plug(HotplugHandler *plug_handler,
*
* Calls #HotplugHandlerClass.unplug_request callback of @plug_handler.
*/
-void hotplug_handler_unplug_request(HotplugHandler *plug_handler,
+void hotplug_handler_unplug_request(const HotplugHandler *plug_handler,
DeviceState *plugged_dev,
Error **errp);
/**
@@ -93,7 +94,7 @@ void hotplug_handler_unplug_request(HotplugHandler *plug_handler,
*
* Calls #HotplugHandlerClass.unplug callback of @plug_handler.
*/
-void hotplug_handler_unplug(HotplugHandler *plug_handler,
+void hotplug_handler_unplug(const HotplugHandler *plug_handler,
DeviceState *plugged_dev,
Error **errp);
#endif
diff --git a/include/hw/core/qdev.h b/include/hw/core/qdev.h
index e4cb027ab3..1f6bf3fc1a 100644
--- a/include/hw/core/qdev.h
+++ b/include/hw/core/qdev.h
@@ -386,7 +386,7 @@ struct BusState {
/* public: */
DeviceState *parent;
char *name;
- HotplugHandler *hotplug_handler;
+ const HotplugHandler *hotplug_handler;
int max_index;
bool realized;
bool full;
@@ -514,8 +514,8 @@ bool qdev_realize_and_unref(DeviceState *dev, BusState *bus, Error **errp);
void qdev_unrealize(DeviceState *dev);
void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
int required_for_version);
-HotplugHandler *qdev_get_bus_hotplug_handler(DeviceState *dev);
-HotplugHandler *qdev_get_machine_hotplug_handler(DeviceState *dev);
+const HotplugHandler *qdev_get_bus_hotplug_handler(DeviceState *dev);
+const HotplugHandler *qdev_get_machine_hotplug_handler(DeviceState *dev);
bool qdev_hotplug_allowed(DeviceState *dev, BusState *bus, Error **errp);
bool qdev_hotunplug_allowed(DeviceState *dev, Error **errp);
@@ -529,10 +529,10 @@ bool qdev_hotunplug_allowed(DeviceState *dev, Error **errp);
* Return: pointer to object that implements TYPE_HOTPLUG_HANDLER interface
* or NULL if there aren't any.
*/
-HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev);
+const HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev);
void qdev_unplug(DeviceState *dev, Error **errp);
int qdev_sync_config(DeviceState *dev, Error **errp);
-void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev,
+void qdev_simple_device_unplug_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp);
void qdev_machine_creation_done(void);
bool qdev_machine_modified(void);
@@ -1065,7 +1065,7 @@ void qbus_set_bus_hotplug_handler(BusState *bus);
static inline bool qbus_is_hotpluggable(BusState *bus)
{
- HotplugHandler *plug_handler = bus->hotplug_handler;
+ const HotplugHandler *plug_handler = bus->hotplug_handler;
bool ret = !!plug_handler;
if (plug_handler) {
diff --git a/include/hw/i386/microvm.h b/include/hw/i386/microvm.h
index 184b7a8c09..5d5eacd1c6 100644
--- a/include/hw/i386/microvm.h
+++ b/include/hw/i386/microvm.h
@@ -76,8 +76,8 @@
struct MicrovmMachineClass {
X86MachineClass parent;
- HotplugHandler *(*orig_hotplug_handler)(MachineState *machine,
- DeviceState *dev);
+ const HotplugHandler *(*orig_hotplug_handler)(MachineState *machine,
+ DeviceState *dev);
void (*x86_load_linux)(X86MachineState *x86ms, FWCfgState *fw_cfg,
int acpi_data_size);
};
diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
index 71fe6b5e12..abb073ca47 100644
--- a/include/hw/i386/x86.h
+++ b/include/hw/i386/x86.h
@@ -46,7 +46,7 @@ struct X86MachineState {
qemu_irq *gsi;
DeviceState *ioapic2;
GMappedFile *initrd_mapped_file;
- HotplugHandler *acpi_dev;
+ const HotplugHandler *acpi_dev;
/*
* Map the whole BIOS just underneath the 4 GiB address boundary. Only used
@@ -112,13 +112,13 @@ uint32_t x86_cpu_apic_id_from_index(X86MachineState *x86ms,
void x86_cpus_init(X86MachineState *pcms, int default_cpu_version);
void x86_rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count);
-void x86_cpu_pre_plug(HotplugHandler *hotplug_dev,
+void x86_cpu_pre_plug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp);
-void x86_cpu_plug(HotplugHandler *hotplug_dev,
+void x86_cpu_plug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp);
-void x86_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
+void x86_cpu_unplug_request_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp);
-void x86_cpu_unplug_cb(HotplugHandler *hotplug_dev,
+void x86_cpu_unplug_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp);
void x86_isa_bios_init(MemoryRegion *isa_bios, MemoryRegion *isa_memory,
diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h
index d3b763453a..169a943e3c 100644
--- a/include/hw/mem/nvdimm.h
+++ b/include/hw/mem/nvdimm.h
@@ -157,5 +157,5 @@ void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
uint32_t ram_slots, const char *oem_id,
const char *oem_table_id);
void nvdimm_plug(NVDIMMState *state);
-void nvdimm_acpi_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev);
+void nvdimm_acpi_plug_cb(const HotplugHandler *hotplug_dev, DeviceState *dev);
#endif
diff --git a/include/hw/pci/pci_bridge.h b/include/hw/pci/pci_bridge.h
index b61360b900..f114f0a651 100644
--- a/include/hw/pci/pci_bridge.h
+++ b/include/hw/pci/pci_bridge.h
@@ -141,11 +141,11 @@ void pci_bridge_reset(DeviceState *qdev);
void pci_bridge_initfn(PCIDevice *pci_dev, const char *typename);
void pci_bridge_exitfn(PCIDevice *pci_dev);
-void pci_bridge_dev_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+void pci_bridge_dev_plug_cb(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp);
-void pci_bridge_dev_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+void pci_bridge_dev_unplug_cb(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp);
-void pci_bridge_dev_unplug_request_cb(HotplugHandler *hotplug_dev,
+void pci_bridge_dev_unplug_request_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp);
/*
diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h
index 71ba94874b..ec25e7a7de 100644
--- a/include/hw/pci/pcie.h
+++ b/include/hw/pci/pcie.h
@@ -146,13 +146,13 @@ void pcie_ats_init(PCIDevice *dev, uint16_t offset, bool aligned);
void pcie_cap_fill_link_ep_usp(PCIDevice *dev, PCIExpLinkWidth width,
PCIExpLinkSpeed speed, bool flitmode);
-void pcie_cap_slot_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+void pcie_cap_slot_pre_plug_cb(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp);
-void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+void pcie_cap_slot_plug_cb(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp);
-void pcie_cap_slot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+void pcie_cap_slot_unplug_cb(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp);
-void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev,
+void pcie_cap_slot_unplug_request_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp);
void pcie_pasid_common_init(PCIDevice *dev, uint16_t offset,
diff --git a/include/hw/pci/shpc.h b/include/hw/pci/shpc.h
index fce5bdd3bc..67becb5c56 100644
--- a/include/hw/pci/shpc.h
+++ b/include/hw/pci/shpc.h
@@ -45,11 +45,11 @@ void shpc_free(PCIDevice *dev);
void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len);
-void shpc_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+void shpc_device_plug_cb(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp);
-void shpc_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+void shpc_device_unplug_cb(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp);
-void shpc_device_unplug_request_cb(HotplugHandler *hotplug_dev,
+void shpc_device_unplug_request_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp);
extern const VMStateInfo shpc_vmstate_info;
diff --git a/include/hw/ppc/spapr_nvdimm.h b/include/hw/ppc/spapr_nvdimm.h
index e9436cb6ef..386da92042 100644
--- a/include/hw/ppc/spapr_nvdimm.h
+++ b/include/hw/ppc/spapr_nvdimm.h
@@ -18,7 +18,7 @@ typedef struct SpaprMachineState SpaprMachineState;
int spapr_pmem_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
void *fdt, int *fdt_start_offset, Error **errp);
void spapr_dt_persistent_memory(SpaprMachineState *spapr, void *fdt);
-bool spapr_nvdimm_validate(HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm,
+bool spapr_nvdimm_validate(const HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm,
uint64_t size, Error **errp);
void spapr_add_nvdimm(DeviceState *dev, uint64_t slot);
void spapr_nvdimm_finish_flushes(void);
diff --git a/hw/acpi/acpi-cpu-hotplug-stub.c b/hw/acpi/acpi-cpu-hotplug-stub.c
index 72c5f05f5c..2e05d7100b 100644
--- a/hw/acpi/acpi-cpu-hotplug-stub.c
+++ b/hw/acpi/acpi-cpu-hotplug-stub.c
@@ -14,7 +14,7 @@ void acpi_cpu_ospm_status(CPUHotplugState *cpu_st, ACPIOSTInfoList ***list)
{
}
-void acpi_cpu_plug_cb(HotplugHandler *hotplug_dev,
+void acpi_cpu_plug_cb(const HotplugHandler *hotplug_dev,
CPUHotplugState *cpu_st, DeviceState *dev, Error **errp)
{
}
@@ -24,7 +24,7 @@ void acpi_cpu_unplug_cb(CPUHotplugState *cpu_st,
{
}
-void acpi_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
+void acpi_cpu_unplug_request_cb(const HotplugHandler *hotplug_dev,
CPUHotplugState *cpu_st,
DeviceState *dev, Error **errp)
{
diff --git a/hw/acpi/acpi-mem-hotplug-stub.c b/hw/acpi/acpi-mem-hotplug-stub.c
index 7ad0fdcdf2..c218813fd1 100644
--- a/hw/acpi/acpi-mem-hotplug-stub.c
+++ b/hw/acpi/acpi-mem-hotplug-stub.c
@@ -13,7 +13,7 @@ void acpi_memory_ospm_status(MemHotplugState *mem_st, ACPIOSTInfoList ***list)
{
}
-void acpi_memory_plug_cb(HotplugHandler *hotplug_dev, MemHotplugState *mem_st,
+void acpi_memory_plug_cb(const HotplugHandler *hotplug_dev, MemHotplugState *mem_st,
DeviceState *dev, Error **errp)
{
}
@@ -23,7 +23,7 @@ void acpi_memory_unplug_cb(MemHotplugState *mem_st,
{
}
-void acpi_memory_unplug_request_cb(HotplugHandler *hotplug_dev,
+void acpi_memory_unplug_request_cb(const HotplugHandler *hotplug_dev,
MemHotplugState *mem_st,
DeviceState *dev, Error **errp)
{
diff --git a/hw/acpi/acpi-nvdimm-stub.c b/hw/acpi/acpi-nvdimm-stub.c
index 22ba17f511..0120bacaac 100644
--- a/hw/acpi/acpi-nvdimm-stub.c
+++ b/hw/acpi/acpi-nvdimm-stub.c
@@ -2,6 +2,6 @@
#include "hw/mem/nvdimm.h"
#include "hw/core/hotplug.h"
-void nvdimm_acpi_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev)
+void nvdimm_acpi_plug_cb(const HotplugHandler *hotplug_dev, DeviceState *dev)
{
}
diff --git a/hw/acpi/acpi-pci-hotplug-stub.c b/hw/acpi/acpi-pci-hotplug-stub.c
index d58ea726a8..20625c7ed7 100644
--- a/hw/acpi/acpi-pci-hotplug-stub.c
+++ b/hw/acpi/acpi-pci-hotplug-stub.c
@@ -9,22 +9,22 @@ void acpi_pcihp_init(Object *owner, AcpiPciHpState *s,
{
}
-void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
+void acpi_pcihp_device_plug_cb(const HotplugHandler *hotplug_dev, AcpiPciHpState *s,
DeviceState *dev, Error **errp)
{
}
-void acpi_pcihp_device_pre_plug_cb(HotplugHandler *hotplug_dev,
+void acpi_pcihp_device_pre_plug_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
}
-void acpi_pcihp_device_unplug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
+void acpi_pcihp_device_unplug_cb(const HotplugHandler *hotplug_dev, AcpiPciHpState *s,
DeviceState *dev, Error **errp)
{
}
-void acpi_pcihp_device_unplug_request_cb(HotplugHandler *hotplug_dev,
+void acpi_pcihp_device_unplug_request_cb(const HotplugHandler *hotplug_dev,
AcpiPciHpState *s, DeviceState *dev,
Error **errp)
{
diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
index d63ca83c1b..ef97ed779a 100644
--- a/hw/acpi/cpu.c
+++ b/hw/acpi/cpu.c
@@ -132,7 +132,7 @@ static void cpu_hotplug_wr(void *opaque, hwaddr addr, uint64_t data,
trace_cpuhp_acpi_clear_remove_evt(cpu_st->selector);
} else if (data & 8) {
DeviceState *dev = NULL;
- HotplugHandler *hotplug_ctrl = NULL;
+ const HotplugHandler *hotplug_ctrl;
if (!cdev->cpu || cdev->cpu == first_cpu) {
trace_cpuhp_acpi_ejecting_invalid_cpu(cpu_st->selector);
@@ -247,7 +247,7 @@ static AcpiCpuStatus *get_cpu_status(CPUHotplugState *cpu_st, DeviceState *dev)
return NULL;
}
-void acpi_cpu_plug_cb(HotplugHandler *hotplug_dev,
+void acpi_cpu_plug_cb(const HotplugHandler *hotplug_dev,
CPUHotplugState *cpu_st, DeviceState *dev, Error **errp)
{
AcpiCpuStatus *cdev;
@@ -264,7 +264,7 @@ void acpi_cpu_plug_cb(HotplugHandler *hotplug_dev,
}
}
-void acpi_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
+void acpi_cpu_unplug_request_cb(const HotplugHandler *hotplug_dev,
CPUHotplugState *cpu_st,
DeviceState *dev, Error **errp)
{
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
index 5225e32513..65a5d1612f 100644
--- a/hw/acpi/generic_event_device.c
+++ b/hw/acpi/generic_event_device.c
@@ -45,7 +45,8 @@ static const uint32_t ged_supported_events[] = {
* affected by the interrupt. This way, we can support up to 32 events
* with a unique interrupt.
*/
-void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev,
+void build_ged_aml(Aml *table, const char *name,
+ const HotplugHandler *hotplug_dev,
uint32_t ged_irq, AmlRegionSpace rs, hwaddr ged_base)
{
const AcpiGedState *s = ACPI_GED(hotplug_dev);
@@ -250,7 +251,7 @@ static const MemoryRegionOps ged_regs_ops = {
},
};
-static void acpi_ged_device_pre_plug_cb(HotplugHandler *hotplug_dev,
+static void acpi_ged_device_pre_plug_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
@@ -258,7 +259,7 @@ static void acpi_ged_device_pre_plug_cb(HotplugHandler *hotplug_dev,
}
}
-static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev,
+static void acpi_ged_device_plug_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
AcpiGedState *s = ACPI_GED(hotplug_dev);
@@ -279,7 +280,7 @@ static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev,
}
}
-static void acpi_ged_unplug_request_cb(HotplugHandler *hotplug_dev,
+static void acpi_ged_unplug_request_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
AcpiGedState *s = ACPI_GED(hotplug_dev);
@@ -298,7 +299,7 @@ static void acpi_ged_unplug_request_cb(HotplugHandler *hotplug_dev,
}
}
-static void acpi_ged_unplug_cb(HotplugHandler *hotplug_dev,
+static void acpi_ged_unplug_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
AcpiGedState *s = ACPI_GED(hotplug_dev);
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index 8082eae428..6d421b990c 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -410,7 +410,7 @@ void ich9_pm_add_class_properties(ObjectClass *oc, ptrdiff_t pm_offset)
#undef PM_REG_FIELD
-void ich9_pm_device_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+void ich9_pm_device_pre_plug_cb(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
@@ -432,7 +432,7 @@ void ich9_pm_device_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
}
}
-void ich9_pm_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+void ich9_pm_device_plug_cb(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
@@ -455,7 +455,7 @@ void ich9_pm_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
}
}
-void ich9_pm_device_unplug_request_cb(HotplugHandler *hotplug_dev,
+void ich9_pm_device_unplug_request_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
@@ -489,7 +489,7 @@ void ich9_pm_device_unplug_request_cb(HotplugHandler *hotplug_dev,
}
}
-void ich9_pm_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+void ich9_pm_device_unplug_cb(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
@@ -507,7 +507,7 @@ void ich9_pm_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
}
}
-bool ich9_pm_is_hotpluggable_bus(HotplugHandler *hotplug_dev, BusState *bus)
+bool ich9_pm_is_hotpluggable_bus(const HotplugHandler *hotplug_dev, BusState *bus)
{
ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
return acpi_pcihp_is_hotpluggable_bus(&lpc->pm.acpi_pci_hotplug, bus);
diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c
index f482c835a1..b5b6d6ada6 100644
--- a/hw/acpi/memory_hotplug.c
+++ b/hw/acpi/memory_hotplug.c
@@ -166,7 +166,7 @@ static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data,
mdev->is_removing = false;
trace_mhp_acpi_clear_remove_evt(mem_st->selector);
} else if (data & 8) {
- HotplugHandler *hotplug_ctrl;
+ const HotplugHandler *hotplug_ctrl;
if (!mdev->is_enabled) {
trace_mhp_acpi_ejecting_invalid_slot(mem_st->selector);
@@ -254,7 +254,7 @@ acpi_memory_slot_status(MemHotplugState *mem_st,
return &mem_st->devs[slot];
}
-void acpi_memory_plug_cb(HotplugHandler *hotplug_dev, MemHotplugState *mem_st,
+void acpi_memory_plug_cb(const HotplugHandler *hotplug_dev, MemHotplugState *mem_st,
DeviceState *dev, Error **errp)
{
MemStatus *mdev;
@@ -277,7 +277,7 @@ void acpi_memory_plug_cb(HotplugHandler *hotplug_dev, MemHotplugState *mem_st,
}
}
-void acpi_memory_unplug_request_cb(HotplugHandler *hotplug_dev,
+void acpi_memory_unplug_request_cb(const HotplugHandler *hotplug_dev,
MemHotplugState *mem_st,
DeviceState *dev, Error **errp)
{
diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 703e854951..5a7ff1ede8 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -887,7 +887,7 @@ static const MemoryRegionOps nvdimm_dsm_ops = {
},
};
-void nvdimm_acpi_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev)
+void nvdimm_acpi_plug_cb(const HotplugHandler *hotplug_dev, DeviceState *dev)
{
if (dev->hotplugged) {
acpi_send_event(DEVICE(hotplug_dev), ACPI_NVDIMM_HOTPLUG_STATUS);
diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
index 336ebe1a13..b69379a18b 100644
--- a/hw/acpi/pcihp.c
+++ b/hw/acpi/pcihp.c
@@ -209,7 +209,7 @@ static void acpi_pcihp_eject_slot(AcpiPciHpState *s, unsigned bsel, unsigned slo
*/
qdev->pending_deleted_event = false;
} else {
- HotplugHandler *hotplug_ctrl;
+ const HotplugHandler *hotplug_ctrl;
hotplug_ctrl = qdev_get_hotplug_handler(qdev);
hotplug_handler_unplug(hotplug_ctrl, qdev, &error_abort);
@@ -261,7 +261,7 @@ void acpi_pcihp_reset(AcpiPciHpState *s)
acpi_pcihp_update(s);
}
-void acpi_pcihp_device_pre_plug_cb(HotplugHandler *hotplug_dev,
+void acpi_pcihp_device_pre_plug_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
PCIDevice *pdev = PCI_DEVICE(dev);
@@ -275,7 +275,7 @@ void acpi_pcihp_device_pre_plug_cb(HotplugHandler *hotplug_dev,
}
}
-void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
+void acpi_pcihp_device_plug_cb(const HotplugHandler *hotplug_dev, AcpiPciHpState *s,
DeviceState *dev, Error **errp)
{
PCIDevice *pdev = PCI_DEVICE(dev);
@@ -317,7 +317,7 @@ void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
acpi_send_event(DEVICE(hotplug_dev), ACPI_PCI_HOTPLUG_STATUS);
}
-void acpi_pcihp_device_unplug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
+void acpi_pcihp_device_unplug_cb(const HotplugHandler *hotplug_dev, AcpiPciHpState *s,
DeviceState *dev, Error **errp)
{
PCIDevice *pdev = PCI_DEVICE(dev);
@@ -328,7 +328,7 @@ void acpi_pcihp_device_unplug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
qdev_unrealize(dev);
}
-void acpi_pcihp_device_unplug_request_cb(HotplugHandler *hotplug_dev,
+void acpi_pcihp_device_unplug_request_cb(const HotplugHandler *hotplug_dev,
AcpiPciHpState *s, DeviceState *dev,
Error **errp)
{
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 52bd61667f..a7d5356340 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -303,8 +303,8 @@ static void piix4_pm_powerdown_req(Notifier *n, void *opaque)
acpi_pm1_evt_power_down(&s->ar);
}
-static void piix4_device_pre_plug_cb(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
+static void piix4_device_pre_plug_cb(const HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
{
PIIX4PMState *s = PIIX4_PM(hotplug_dev);
@@ -323,7 +323,7 @@ static void piix4_device_pre_plug_cb(HotplugHandler *hotplug_dev,
}
}
-static void piix4_device_plug_cb(HotplugHandler *hotplug_dev,
+static void piix4_device_plug_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
PIIX4PMState *s = PIIX4_PM(hotplug_dev);
@@ -344,7 +344,7 @@ static void piix4_device_plug_cb(HotplugHandler *hotplug_dev,
}
}
-static void piix4_device_unplug_request_cb(HotplugHandler *hotplug_dev,
+static void piix4_device_unplug_request_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
PIIX4PMState *s = PIIX4_PM(hotplug_dev);
@@ -364,7 +364,7 @@ static void piix4_device_unplug_request_cb(HotplugHandler *hotplug_dev,
}
}
-static void piix4_device_unplug_cb(HotplugHandler *hotplug_dev,
+static void piix4_device_unplug_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
PIIX4PMState *s = PIIX4_PM(hotplug_dev);
@@ -383,7 +383,7 @@ static void piix4_device_unplug_cb(HotplugHandler *hotplug_dev,
}
}
-static bool piix4_is_hotpluggable_bus(HotplugHandler *hotplug_dev,
+static bool piix4_is_hotpluggable_bus(const HotplugHandler *hotplug_dev,
BusState *bus)
{
PIIX4PMState *s = PIIX4_PM(hotplug_dev);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 0871a35e11..3eecf094bc 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -3753,7 +3753,7 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms)
return ms->possible_cpus;
}
-static void virt_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
+static void virt_memory_pre_plug(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
@@ -3779,7 +3779,7 @@ static void virt_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
pc_dimm_pre_plug(PC_DIMM(dev), MACHINE(hotplug_dev), errp);
}
-static void virt_memory_plug(HotplugHandler *hotplug_dev,
+static void virt_memory_plug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
@@ -3798,7 +3798,7 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev,
}
}
-static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
+static void virt_machine_device_pre_plug_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
@@ -3896,7 +3896,7 @@ static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
}
}
-static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev,
+static void virt_machine_device_plug_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
@@ -3957,7 +3957,7 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev,
}
}
-static void virt_dimm_unplug_request(HotplugHandler *hotplug_dev,
+static void virt_dimm_unplug_request(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
@@ -3977,7 +3977,7 @@ static void virt_dimm_unplug_request(HotplugHandler *hotplug_dev,
errp);
}
-static void virt_dimm_unplug(HotplugHandler *hotplug_dev,
+static void virt_dimm_unplug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
@@ -3995,8 +3995,9 @@ out:
error_propagate(errp, local_err);
}
-static void virt_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
+static void
+virt_machine_device_unplug_request_cb(const HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
{
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
virt_dimm_unplug_request(hotplug_dev, dev, errp);
@@ -4009,7 +4010,7 @@ static void virt_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev,
}
}
-static void virt_machine_device_unplug_cb(HotplugHandler *hotplug_dev,
+static void virt_machine_device_unplug_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
@@ -4022,8 +4023,8 @@ static void virt_machine_device_unplug_cb(HotplugHandler *hotplug_dev,
}
}
-static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
- DeviceState *dev)
+static const HotplugHandler *
+virt_machine_get_hotplug_handler(MachineState *machine, DeviceState *dev)
{
MachineClass *mc = MACHINE_GET_CLASS(machine);
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
index 81db0bdc91..c36e18a4cf 100644
--- a/hw/char/virtio-serial-bus.c
+++ b/hw/char/virtio-serial-bus.c
@@ -979,7 +979,7 @@ static void virtser_port_device_realize(DeviceState *dev, Error **errp)
port->elem = NULL;
}
-static void virtser_port_device_plug(HotplugHandler *hotplug_dev,
+static void virtser_port_device_plug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev);
diff --git a/hw/core/hotplug.c b/hw/core/hotplug.c
index 00e80a67c8..3aca068840 100644
--- a/hw/core/hotplug.c
+++ b/hw/core/hotplug.c
@@ -13,7 +13,7 @@
#include "hw/core/hotplug.h"
#include "qemu/module.h"
-void hotplug_handler_pre_plug(HotplugHandler *plug_handler,
+void hotplug_handler_pre_plug(const HotplugHandler *plug_handler,
DeviceState *plugged_dev,
Error **errp)
{
@@ -24,7 +24,7 @@ void hotplug_handler_pre_plug(HotplugHandler *plug_handler,
}
}
-void hotplug_handler_plug(HotplugHandler *plug_handler,
+void hotplug_handler_plug(const HotplugHandler *plug_handler,
DeviceState *plugged_dev,
Error **errp)
{
@@ -35,7 +35,7 @@ void hotplug_handler_plug(HotplugHandler *plug_handler,
}
}
-void hotplug_handler_unplug_request(HotplugHandler *plug_handler,
+void hotplug_handler_unplug_request(const HotplugHandler *plug_handler,
DeviceState *plugged_dev,
Error **errp)
{
@@ -46,7 +46,7 @@ void hotplug_handler_unplug_request(HotplugHandler *plug_handler,
}
}
-void hotplug_handler_unplug(HotplugHandler *plug_handler,
+void hotplug_handler_unplug(const HotplugHandler *plug_handler,
DeviceState *plugged_dev,
Error **errp)
{
diff --git a/hw/core/qdev-hotplug.c b/hw/core/qdev-hotplug.c
index 1d547e0dbd..d7fa8a5ed2 100644
--- a/hw/core/qdev-hotplug.c
+++ b/hw/core/qdev-hotplug.c
@@ -14,7 +14,7 @@
#include "hw/core/boards.h"
#include "qapi/error.h"
-HotplugHandler *qdev_get_machine_hotplug_handler(DeviceState *dev)
+const HotplugHandler *qdev_get_machine_hotplug_handler(DeviceState *dev)
{
MachineState *machine;
MachineClass *mc;
@@ -90,7 +90,7 @@ bool qdev_hotunplug_allowed(DeviceState *dev, Error **errp)
qdev_hotplug_unplug_allowed_common(dev, dev->parent_bus, errp);
}
-HotplugHandler *qdev_get_bus_hotplug_handler(DeviceState *dev)
+const HotplugHandler *qdev_get_bus_hotplug_handler(DeviceState *dev)
{
if (dev->parent_bus) {
return dev->parent_bus->hotplug_handler;
@@ -98,9 +98,9 @@ HotplugHandler *qdev_get_bus_hotplug_handler(DeviceState *dev)
return NULL;
}
-HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
+const HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
{
- HotplugHandler *hotplug_ctrl = qdev_get_machine_hotplug_handler(dev);
+ const HotplugHandler *hotplug_ctrl = qdev_get_machine_hotplug_handler(dev);
if (hotplug_ctrl == NULL && dev->parent_bus) {
hotplug_ctrl = qdev_get_bus_hotplug_handler(dev);
@@ -109,7 +109,7 @@ HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
}
/* can be used as ->unplug() callback for the simple cases */
-void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev,
+void qdev_simple_device_unplug_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
qdev_unrealize(dev);
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 0b0f2f47fa..c6540bec56 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -501,7 +501,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
{
DeviceState *dev = DEVICE(obj);
DeviceClass *dc = DEVICE_GET_CLASS(dev);
- HotplugHandler *hotplug_ctrl;
+ const HotplugHandler *hotplug_ctrl;
BusState *bus;
NamedClockList *ncl;
Error *local_err = NULL;
diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
index e7adab7d2e..a49de33749 100644
--- a/hw/i386/microvm.c
+++ b/hw/i386/microvm.c
@@ -416,7 +416,7 @@ static void microvm_fix_kernel_cmdline(MachineState *machine)
g_free(cmdline);
}
-static void microvm_device_pre_plug_cb(HotplugHandler *hotplug_dev,
+static void microvm_device_pre_plug_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
X86CPU *cpu = X86_CPU(dev);
@@ -425,26 +425,26 @@ static void microvm_device_pre_plug_cb(HotplugHandler *hotplug_dev,
x86_cpu_pre_plug(hotplug_dev, dev, errp);
}
-static void microvm_device_plug_cb(HotplugHandler *hotplug_dev,
+static void microvm_device_plug_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
x86_cpu_plug(hotplug_dev, dev, errp);
}
-static void microvm_device_unplug_request_cb(HotplugHandler *hotplug_dev,
+static void microvm_device_unplug_request_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
error_setg(errp, "unplug not supported by microvm");
}
-static void microvm_device_unplug_cb(HotplugHandler *hotplug_dev,
+static void microvm_device_unplug_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
error_setg(errp, "unplug not supported by microvm");
}
-static HotplugHandler *microvm_get_hotplug_handler(MachineState *machine,
- DeviceState *dev)
+static const HotplugHandler *microvm_get_hotplug_handler(MachineState *machine,
+ DeviceState *dev)
{
if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
return HOTPLUG_HANDLER(machine);
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index e9e4fc262b..9006e7c29e 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1181,7 +1181,7 @@ void pc_i8259_create(ISABus *isa_bus, qemu_irq *i8259_irqs)
g_free(i8259);
}
-static void pc_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
+static void pc_memory_pre_plug(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
const X86MachineState *x86ms = X86_MACHINE(hotplug_dev);
@@ -1214,7 +1214,7 @@ static void pc_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
pc_dimm_pre_plug(PC_DIMM(dev), MACHINE(hotplug_dev), errp);
}
-static void pc_memory_plug(HotplugHandler *hotplug_dev,
+static void pc_memory_plug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
PCMachineState *pcms = PC_MACHINE(hotplug_dev);
@@ -1231,7 +1231,7 @@ static void pc_memory_plug(HotplugHandler *hotplug_dev,
hotplug_handler_plug(x86ms->acpi_dev, dev, &error_abort);
}
-static void pc_memory_unplug_request(HotplugHandler *hotplug_dev,
+static void pc_memory_unplug_request(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
X86MachineState *x86ms = X86_MACHINE(hotplug_dev);
@@ -1256,7 +1256,7 @@ static void pc_memory_unplug_request(HotplugHandler *hotplug_dev,
errp);
}
-static void pc_memory_unplug(HotplugHandler *hotplug_dev,
+static void pc_memory_unplug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
PCMachineState *pcms = PC_MACHINE(hotplug_dev);
@@ -1274,7 +1274,7 @@ static void pc_memory_unplug(HotplugHandler *hotplug_dev,
error_propagate(errp, local_err);
}
-static void pc_hv_balloon_pre_plug(HotplugHandler *hotplug_dev,
+static void pc_hv_balloon_pre_plug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
/* The vmbus handler has no hotplug handler; we should never end up here. */
@@ -1282,13 +1282,13 @@ static void pc_hv_balloon_pre_plug(HotplugHandler *hotplug_dev,
memory_device_pre_plug(MEMORY_DEVICE(dev), MACHINE(hotplug_dev), errp);
}
-static void pc_hv_balloon_plug(HotplugHandler *hotplug_dev,
+static void pc_hv_balloon_plug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
memory_device_plug(MEMORY_DEVICE(dev), MACHINE(hotplug_dev));
}
-static void pc_sp_mem_pre_plug(HotplugHandler *hotplug_dev,
+static void pc_sp_mem_pre_plug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
MachineState *ms = MACHINE(hotplug_dev);
@@ -1304,7 +1304,7 @@ static void pc_sp_mem_pre_plug(HotplugHandler *hotplug_dev,
memory_device_pre_plug(MEMORY_DEVICE(dev), ms, errp);
}
-static void pc_sp_mem_plug(HotplugHandler *hotplug_dev,
+static void pc_sp_mem_plug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
SpMemDevice *spm = SP_MEM(dev);
@@ -1318,7 +1318,7 @@ static void pc_sp_mem_plug(HotplugHandler *hotplug_dev,
e820_add_entry(addr, size, E820_SOFT_RESERVED);
}
-static void pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
+static void pc_machine_device_pre_plug_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
@@ -1356,7 +1356,7 @@ static void pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
}
}
-static void pc_machine_device_plug_cb(HotplugHandler *hotplug_dev,
+static void pc_machine_device_plug_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
@@ -1372,7 +1372,7 @@ static void pc_machine_device_plug_cb(HotplugHandler *hotplug_dev,
}
}
-static void pc_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev,
+static void pc_machine_device_unplug_request_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
@@ -1388,7 +1388,7 @@ static void pc_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev,
}
}
-static void pc_machine_device_unplug_cb(HotplugHandler *hotplug_dev,
+static void pc_machine_device_unplug_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
@@ -1403,8 +1403,8 @@ static void pc_machine_device_unplug_cb(HotplugHandler *hotplug_dev,
}
}
-static HotplugHandler *pc_get_hotplug_handler(MachineState *machine,
- DeviceState *dev)
+static const HotplugHandler *pc_get_hotplug_handler(MachineState *machine,
+ DeviceState *dev)
{
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) ||
object_dynamic_cast(OBJECT(dev), TYPE_SP_MEM) ||
diff --git a/hw/i386/x86-common.c b/hw/i386/x86-common.c
index 8f9419e7d3..ae58352760 100644
--- a/hw/i386/x86-common.c
+++ b/hw/i386/x86-common.c
@@ -158,7 +158,7 @@ static CPUArchId *x86_find_cpu_slot(MachineState *ms, uint32_t id, int *idx)
return found_cpu;
}
-void x86_cpu_plug(HotplugHandler *hotplug_dev,
+void x86_cpu_plug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
CPUArchId *found_cpu;
@@ -199,7 +199,7 @@ out:
error_propagate(errp, local_err);
}
-void x86_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
+void x86_cpu_unplug_request_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
int idx = -1;
@@ -222,7 +222,7 @@ void x86_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
errp);
}
-void x86_cpu_unplug_cb(HotplugHandler *hotplug_dev,
+void x86_cpu_unplug_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
CPUArchId *found_cpu;
@@ -248,7 +248,7 @@ void x86_cpu_unplug_cb(HotplugHandler *hotplug_dev,
error_propagate(errp, local_err);
}
-void x86_cpu_pre_plug(HotplugHandler *hotplug_dev,
+void x86_cpu_pre_plug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
int idx;
diff --git a/hw/intc/loongarch_dintc.c b/hw/intc/loongarch_dintc.c
index c01f1fe07e..1bedfbce43 100644
--- a/hw/intc/loongarch_dintc.c
+++ b/hw/intc/loongarch_dintc.c
@@ -168,8 +168,8 @@ static DINTCCore *loongarch_dintc_get_cpu(LoongArchDINTCState *s,
return loongarch_dintc_cpu_by_arch_id(s, arch_id);
}
-static void loongarch_dintc_cpu_plug(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
+static void loongarch_dintc_cpu_plug(const HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
{
LoongArchDINTCState *s = LOONGARCH_DINTC(hotplug_dev);
Object *obj = OBJECT(dev);
@@ -194,8 +194,8 @@ static void loongarch_dintc_cpu_plug(HotplugHandler *hotplug_dev,
return;
}
-static void loongarch_dintc_cpu_unplug(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
+static void loongarch_dintc_cpu_unplug(const HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
{
LoongArchDINTCState *s = LOONGARCH_DINTC(hotplug_dev);
Object *obj = OBJECT(dev);
diff --git a/hw/intc/loongarch_extioi_common.c b/hw/intc/loongarch_extioi_common.c
index 5cb0d396c6..22cbb7a097 100644
--- a/hw/intc/loongarch_extioi_common.c
+++ b/hw/intc/loongarch_extioi_common.c
@@ -28,7 +28,7 @@ static ExtIOICore *loongarch_extioi_get_cpu(LoongArchExtIOICommonState *s,
return NULL;
}
-static void loongarch_extioi_cpu_plug(HotplugHandler *hotplug_dev,
+static void loongarch_extioi_cpu_plug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
LoongArchExtIOICommonState *s = LOONGARCH_EXTIOI_COMMON(hotplug_dev);
@@ -60,7 +60,7 @@ static void loongarch_extioi_cpu_plug(HotplugHandler *hotplug_dev,
}
}
-static void loongarch_extioi_cpu_unplug(HotplugHandler *hotplug_dev,
+static void loongarch_extioi_cpu_unplug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
LoongArchExtIOICommonState *s = LOONGARCH_EXTIOI_COMMON(hotplug_dev);
diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c
index 28d816e3f5..c8f775a93e 100644
--- a/hw/intc/loongarch_ipi.c
+++ b/hw/intc/loongarch_ipi.c
@@ -129,7 +129,7 @@ static void loongarch_ipi_reset_hold(Object *obj, ResetType type)
}
}
-static void loongarch_ipi_cpu_plug(HotplugHandler *hotplug_dev,
+static void loongarch_ipi_cpu_plug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
LoongsonIPICommonState *lics = LOONGSON_IPI_COMMON(hotplug_dev);
@@ -155,7 +155,7 @@ static void loongarch_ipi_cpu_plug(HotplugHandler *hotplug_dev,
qdev_connect_gpio_out(DEVICE(lics), index, qdev_get_gpio_in(dev, IRQ_IPI));
}
-static void loongarch_ipi_cpu_unplug(HotplugHandler *hotplug_dev,
+static void loongarch_ipi_cpu_unplug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
LoongsonIPICommonState *lics = LOONGSON_IPI_COMMON(hotplug_dev);
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 9cc79929a8..9c5371af9d 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -1167,7 +1167,7 @@ static CPUArchId *virt_find_empty_cpu_slot(MachineState *ms)
return NULL;
}
-static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev,
+static void virt_cpu_pre_plug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(hotplug_dev);
@@ -1229,7 +1229,7 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev,
numa_cpu_pre_plug(cpu_slot, dev, errp);
}
-static void virt_cpu_unplug_request(HotplugHandler *hotplug_dev,
+static void virt_cpu_unplug_request(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(hotplug_dev);
@@ -1246,7 +1246,7 @@ static void virt_cpu_unplug_request(HotplugHandler *hotplug_dev,
hotplug_handler_unplug_request(HOTPLUG_HANDLER(lvms->acpi_ged), dev, errp);
}
-static void virt_cpu_unplug(HotplugHandler *hotplug_dev,
+static void virt_cpu_unplug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
CPUArchId *cpu_slot;
@@ -1268,7 +1268,7 @@ static void virt_cpu_unplug(HotplugHandler *hotplug_dev,
cpu_slot->cpu = NULL;
}
-static void virt_cpu_plug(HotplugHandler *hotplug_dev,
+static void virt_cpu_plug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
CPUArchId *cpu_slot;
@@ -1304,14 +1304,14 @@ static bool memhp_type_supported(DeviceState *dev)
!object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
}
-static void virt_mem_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
- Error **errp)
+static void virt_mem_pre_plug(const HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
{
pc_dimm_pre_plug(PC_DIMM(dev), MACHINE(hotplug_dev), errp);
}
-static void virt_device_pre_plug(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
+static void virt_device_pre_plug(const HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
{
if (memhp_type_supported(dev)) {
virt_mem_pre_plug(hotplug_dev, dev, errp);
@@ -1320,8 +1320,8 @@ static void virt_device_pre_plug(HotplugHandler *hotplug_dev,
}
}
-static void virt_mem_unplug_request(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
+static void virt_mem_unplug_request(const HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
{
LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(hotplug_dev);
@@ -1330,8 +1330,8 @@ static void virt_mem_unplug_request(HotplugHandler *hotplug_dev,
errp);
}
-static void virt_device_unplug_request(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
+static void virt_device_unplug_request(const HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
{
if (memhp_type_supported(dev)) {
virt_mem_unplug_request(hotplug_dev, dev, errp);
@@ -1340,8 +1340,8 @@ static void virt_device_unplug_request(HotplugHandler *hotplug_dev,
}
}
-static void virt_mem_unplug(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
+static void virt_mem_unplug(const HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
{
LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(hotplug_dev);
@@ -1350,8 +1350,8 @@ static void virt_mem_unplug(HotplugHandler *hotplug_dev,
qdev_unrealize(dev);
}
-static void virt_device_unplug(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
+static void virt_device_unplug(const HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
{
if (memhp_type_supported(dev)) {
virt_mem_unplug(hotplug_dev, dev, errp);
@@ -1360,8 +1360,8 @@ static void virt_device_unplug(HotplugHandler *hotplug_dev,
}
}
-static void virt_mem_plug(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
+static void virt_mem_plug(const HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
{
LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(hotplug_dev);
@@ -1370,8 +1370,8 @@ static void virt_mem_plug(HotplugHandler *hotplug_dev,
dev, &error_abort);
}
-static void virt_device_plug_cb(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
+static void virt_device_plug_cb(const HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
{
LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(hotplug_dev);
MachineClass *mc = MACHINE_GET_CLASS(lvms);
@@ -1389,8 +1389,8 @@ static void virt_device_plug_cb(HotplugHandler *hotplug_dev,
}
}
-static HotplugHandler *virt_get_hotplug_handler(MachineState *machine,
- DeviceState *dev)
+static const HotplugHandler *virt_get_hotplug_handler(MachineState *machine,
+ DeviceState *dev)
{
MachineClass *mc = MACHINE_GET_CLASS(machine);
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 23c26aa08c..986ceff514 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -3816,7 +3816,7 @@ void virtio_net_set_netclient_name(VirtIONet *n, const char *name,
static bool failover_unplug_primary(VirtIONet *n, DeviceState *dev)
{
- HotplugHandler *hotplug_ctrl;
+ const HotplugHandler *hotplug_ctrl;
PCIDevice *pci_dev;
Error *err = NULL;
@@ -3839,7 +3839,7 @@ static bool failover_replug_primary(VirtIONet *n, DeviceState *dev,
Error **errp)
{
Error *err = NULL;
- HotplugHandler *hotplug_ctrl;
+ const HotplugHandler *hotplug_ctrl;
PCIDevice *pdev = PCI_DEVICE(dev);
BusState *primary_bus;
diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index 7478f0b33a..c641226e27 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -10615,8 +10615,8 @@ static const TypeInfo nvme_info = {
},
};
-static void nvme_ns_hot_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
- Error **errp)
+static void nvme_ns_hot_plug(const HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
{
NvmeNamespace *ns = NVME_NS(dev);
NvmeSubsystem *subsys = ns->subsys;
@@ -10647,8 +10647,8 @@ static void nvme_ns_hot_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
}
}
-static void nvme_ns_hot_unplug(HotplugHandler *hotplug_dev, DeviceState *dev,
- Error **errp)
+static void nvme_ns_hot_unplug(const HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
{
NvmeNamespace *ns = NVME_NS(dev);
NvmeSubsystem *subsys = ns->subsys;
diff --git a/hw/pci-bridge/pci_bridge_dev.c b/hw/pci-bridge/pci_bridge_dev.c
index 0c1383562d..bc53bcb69d 100644
--- a/hw/pci-bridge/pci_bridge_dev.c
+++ b/hw/pci-bridge/pci_bridge_dev.c
@@ -205,7 +205,7 @@ static const VMStateDescription pci_bridge_dev_vmstate = {
}
};
-void pci_bridge_dev_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+void pci_bridge_dev_plug_cb(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev);
@@ -218,7 +218,7 @@ void pci_bridge_dev_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
shpc_device_plug_cb(hotplug_dev, dev, errp);
}
-void pci_bridge_dev_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+void pci_bridge_dev_unplug_cb(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev);
@@ -227,7 +227,7 @@ void pci_bridge_dev_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
shpc_device_unplug_cb(hotplug_dev, dev, errp);
}
-void pci_bridge_dev_unplug_request_cb(HotplugHandler *hotplug_dev,
+void pci_bridge_dev_unplug_request_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev);
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index 4622c75e48..42bcb9206d 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -508,7 +508,7 @@ static void pcie_cap_slot_plug_common(PCIDevice *hotplug_dev, DeviceState *dev,
}
}
-void pcie_cap_slot_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+void pcie_cap_slot_pre_plug_cb(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
PCIDevice *hotplug_pdev = PCI_DEVICE(hotplug_dev);
@@ -525,7 +525,7 @@ void pcie_cap_slot_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
pcie_cap_slot_plug_common(PCI_DEVICE(hotplug_dev), dev, errp);
}
-void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+void pcie_cap_slot_plug_cb(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
PCIDevice *hotplug_pdev = PCI_DEVICE(hotplug_dev);
@@ -571,7 +571,7 @@ void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
}
}
-void pcie_cap_slot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+void pcie_cap_slot_unplug_cb(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
qdev_unrealize(dev);
@@ -579,7 +579,7 @@ void pcie_cap_slot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
static void pcie_unplug_device(PCIBus *bus, PCIDevice *dev, void *opaque)
{
- HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(DEVICE(dev));
+ const HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(DEVICE(dev));
if (dev->partially_hotplugged) {
dev->qdev.pending_deleted_event = false;
@@ -608,7 +608,7 @@ static void pcie_cap_slot_do_unplug(PCIDevice *dev)
PCI_EXP_SLTSTA_PDC);
}
-void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev,
+void pcie_cap_slot_unplug_request_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
Error *local_err = NULL;
diff --git a/hw/pci/pcie_port.c b/hw/pci/pcie_port.c
index dbb6032160..57fcc9079a 100644
--- a/hw/pci/pcie_port.c
+++ b/hw/pci/pcie_port.c
@@ -188,7 +188,7 @@ int pcie_count_ds_ports(PCIBus *bus)
return dsp_count;
}
-static bool pcie_slot_is_hotpluggable_bus(HotplugHandler *plug_handler,
+static bool pcie_slot_is_hotpluggable_bus(const HotplugHandler *plug_handler,
BusState *bus)
{
PCIESlot *s = PCIE_SLOT(bus->parent);
diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c
index 1198e1ab8c..3f24ca84f5 100644
--- a/hw/pci/shpc.c
+++ b/hw/pci/shpc.c
@@ -278,7 +278,7 @@ static void shpc_free_devices_in_slot(SHPCDevice *shpc, int slot)
++devfn) {
PCIDevice *affected_dev = shpc->sec_bus->devices[devfn];
if (affected_dev) {
- HotplugHandler *hotplug_ctrl;
+ const HotplugHandler *hotplug_ctrl;
hotplug_ctrl = qdev_get_hotplug_handler(DEVICE(affected_dev));
hotplug_handler_unplug(hotplug_ctrl, DEVICE(affected_dev),
@@ -561,8 +561,8 @@ static bool shpc_device_get_slot(PCIDevice *affected_dev, int *slot,
return true;
}
-void shpc_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
- Error **errp)
+void shpc_device_plug_cb(const HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
{
PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev);
SHPCDevice *shpc = pci_hotplug_dev->shpc;
@@ -601,13 +601,13 @@ void shpc_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
shpc_interrupt_update(pci_hotplug_dev);
}
-void shpc_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+void shpc_device_unplug_cb(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
qdev_unrealize(dev);
}
-void shpc_device_unplug_request_cb(HotplugHandler *hotplug_dev,
+void shpc_device_unplug_request_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev);
diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c
index 85cec810d9..4bc1426dc8 100644
--- a/hw/ppc/e500plat.c
+++ b/hw/ppc/e500plat.c
@@ -42,7 +42,7 @@ static void e500plat_init(MachineState *machine)
ppce500_init(machine);
}
-static void e500plat_machine_device_plug_cb(HotplugHandler *hotplug_dev,
+static void e500plat_machine_device_plug_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
PPCE500MachineState *pms = PPCE500_MACHINE(hotplug_dev);
@@ -53,7 +53,7 @@ static void e500plat_machine_device_plug_cb(HotplugHandler *hotplug_dev,
}
}
-static
+static const
HotplugHandler *e500plat_machine_get_hotpug_handler(MachineState *machine,
DeviceState *dev)
{
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 20e024907b..6d99464486 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -3616,7 +3616,7 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size,
}
}
-static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
+static void spapr_memory_plug(const HotplugHandler *hotplug_dev, DeviceState *dev)
{
SpaprMachineState *ms = SPAPR_MACHINE(hotplug_dev);
PCDIMMDevice *dimm = PC_DIMM(dev);
@@ -3642,7 +3642,7 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
}
}
-static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
+static void spapr_memory_pre_plug(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
@@ -3807,7 +3807,7 @@ void spapr_memory_unplug_rollback(SpaprMachineState *spapr, DeviceState *dev)
/* Callback to be called during DRC release. */
void spapr_lmb_release(DeviceState *dev)
{
- HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev);
+ const HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev);
SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_ctrl);
SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev));
@@ -3832,7 +3832,7 @@ void spapr_lmb_release(DeviceState *dev)
object_unparent(OBJECT(dev));
}
-static void spapr_memory_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
+static void spapr_memory_unplug(const HotplugHandler *hotplug_dev, DeviceState *dev)
{
SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev));
@@ -3845,7 +3845,7 @@ static void spapr_memory_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
spapr_pending_dimm_unplugs_remove(spapr, ds);
}
-static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev,
+static void spapr_memory_unplug_request(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
@@ -3899,14 +3899,14 @@ static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev,
/* Callback to be called during DRC release. */
void spapr_core_release(DeviceState *dev)
{
- HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev);
+ const HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev);
/* Call the unplug handler chain. This can never fail. */
hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort);
object_unparent(OBJECT(dev));
}
-static void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
+static void spapr_core_unplug(const HotplugHandler *hotplug_dev, DeviceState *dev)
{
MachineState *ms = MACHINE(hotplug_dev);
CPUCore *cc = CPU_CORE(dev);
@@ -3918,7 +3918,7 @@ static void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
}
static
-void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev,
+void spapr_core_unplug_request(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
@@ -3988,7 +3988,7 @@ int spapr_core_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
return 0;
}
-static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
+static void spapr_core_plug(const HotplugHandler *hotplug_dev, DeviceState *dev)
{
SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
MachineClass *mc = MACHINE_GET_CLASS(spapr);
@@ -4043,7 +4043,7 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
}
-static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
+static void spapr_core_pre_plug(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
MachineState *machine = MACHINE(OBJECT(hotplug_dev));
@@ -4169,7 +4169,7 @@ static bool spapr_phb_placement(SpaprMachineState *spapr, uint32_t index,
return true;
}
-static bool spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
+static bool spapr_phb_pre_plug(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
@@ -4198,7 +4198,7 @@ static bool spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
windows_supported, sphb->dma_liobn, errp);
}
-static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
+static void spapr_phb_plug(const HotplugHandler *hotplug_dev, DeviceState *dev)
{
SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
SpaprDrc *drc;
@@ -4220,18 +4220,18 @@ static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
void spapr_phb_release(DeviceState *dev)
{
- HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev);
+ const HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev);
hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort);
object_unparent(OBJECT(dev));
}
-static void spapr_phb_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
+static void spapr_phb_unplug(const HotplugHandler *hotplug_dev, DeviceState *dev)
{
qdev_unrealize(dev);
}
-static void spapr_phb_unplug_request(HotplugHandler *hotplug_dev,
+static void spapr_phb_unplug_request(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
@@ -4251,7 +4251,7 @@ static void spapr_phb_unplug_request(HotplugHandler *hotplug_dev,
}
static
-bool spapr_tpm_proxy_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
+bool spapr_tpm_proxy_pre_plug(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
@@ -4264,7 +4264,7 @@ bool spapr_tpm_proxy_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
return true;
}
-static void spapr_tpm_proxy_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
+static void spapr_tpm_proxy_plug(const HotplugHandler *hotplug_dev, DeviceState *dev)
{
SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
SpaprTpmProxy *tpm_proxy = SPAPR_TPM_PROXY(dev);
@@ -4275,7 +4275,7 @@ static void spapr_tpm_proxy_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
spapr->tpm_proxy = tpm_proxy;
}
-static void spapr_tpm_proxy_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
+static void spapr_tpm_proxy_unplug(const HotplugHandler *hotplug_dev, DeviceState *dev)
{
SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
@@ -4284,7 +4284,7 @@ static void spapr_tpm_proxy_unplug(HotplugHandler *hotplug_dev, DeviceState *dev
spapr->tpm_proxy = NULL;
}
-static void spapr_machine_device_plug(HotplugHandler *hotplug_dev,
+static void spapr_machine_device_plug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
@@ -4298,7 +4298,7 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev,
}
}
-static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev,
+static void spapr_machine_device_unplug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
@@ -4324,7 +4324,7 @@ bool spapr_memory_hot_unplug_supported(SpaprMachineState *spapr)
spapr_ovec_empty(spapr->ov5_cas);
}
-static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev,
+static void spapr_machine_device_unplug_request(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
SpaprMachineState *sms = SPAPR_MACHINE(OBJECT(hotplug_dev));
@@ -4349,7 +4349,7 @@ static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev,
}
}
-static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev,
+static void spapr_machine_device_pre_plug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
@@ -4363,8 +4363,8 @@ static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev,
}
}
-static HotplugHandler *spapr_get_hotplug_handler(MachineState *machine,
- DeviceState *dev)
+static const HotplugHandler *spapr_get_hotplug_handler(MachineState *machine,
+ DeviceState *dev)
{
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) ||
object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE) ||
diff --git a/hw/ppc/spapr_nvdimm.c b/hw/ppc/spapr_nvdimm.c
index 6647428391..542ed79497 100644
--- a/hw/ppc/spapr_nvdimm.c
+++ b/hw/ppc/spapr_nvdimm.c
@@ -64,7 +64,7 @@ struct SPAPRNVDIMMClass {
void (*unrealize)(NVDIMMDevice *dimm, Error **errp);
};
-bool spapr_nvdimm_validate(HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm,
+bool spapr_nvdimm_validate(const HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm,
uint64_t size, Error **errp)
{
const MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev);
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index c1d4b7806e..f7fc544d35 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -1445,7 +1445,7 @@ static int spapr_dt_pci_device(SpaprPhbState *sphb, PCIDevice *dev,
/* Callback to be called during DRC release. */
void spapr_phb_remove_pci_device_cb(DeviceState *dev)
{
- HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev);
+ const HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev);
hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort);
object_unparent(OBJECT(dev));
@@ -1454,7 +1454,7 @@ void spapr_phb_remove_pci_device_cb(DeviceState *dev)
int spapr_pci_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
void *fdt, int *fdt_start_offset, Error **errp)
{
- HotplugHandler *plug_handler = qdev_get_hotplug_handler(drc->dev);
+ const HotplugHandler *plug_handler = qdev_get_hotplug_handler(drc->dev);
SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(plug_handler);
PCIDevice *pdev = PCI_DEVICE(drc->dev);
@@ -1521,7 +1521,7 @@ static bool bridge_has_valid_chassis_nr(Object *bridge, Error **errp)
return true;
}
-static void spapr_pci_pre_plug(HotplugHandler *plug_handler,
+static void spapr_pci_pre_plug(const HotplugHandler *plug_handler,
DeviceState *plugged_dev, Error **errp)
{
SpaprPhbState *phb = SPAPR_PCI_HOST_BRIDGE(DEVICE(plug_handler));
@@ -1556,7 +1556,7 @@ static void spapr_pci_pre_plug(HotplugHandler *plug_handler,
}
}
-static void spapr_pci_plug(HotplugHandler *plug_handler,
+static void spapr_pci_plug(const HotplugHandler *plug_handler,
DeviceState *plugged_dev, Error **errp)
{
SpaprPhbState *phb = SPAPR_PCI_HOST_BRIDGE(DEVICE(plug_handler));
@@ -1614,7 +1614,7 @@ static void spapr_pci_bridge_unplug(SpaprPhbState *phb,
remove_drcs(phb, bus);
}
-static void spapr_pci_unplug(HotplugHandler *plug_handler,
+static void spapr_pci_unplug(const HotplugHandler *plug_handler,
DeviceState *plugged_dev, Error **errp)
{
SpaprPhbState *phb = SPAPR_PCI_HOST_BRIDGE(DEVICE(plug_handler));
@@ -1639,7 +1639,7 @@ static void spapr_pci_unplug(HotplugHandler *plug_handler,
qdev_unrealize(plugged_dev);
}
-static void spapr_pci_unplug_request(HotplugHandler *plug_handler,
+static void spapr_pci_unplug_request(const HotplugHandler *plug_handler,
DeviceState *plugged_dev, Error **errp)
{
SpaprPhbState *phb = SPAPR_PCI_HOST_BRIDGE(DEVICE(plug_handler));
diff --git a/hw/remote/machine.c b/hw/remote/machine.c
index ced782f6a9..f79f5a0565 100644
--- a/hw/remote/machine.c
+++ b/hw/remote/machine.c
@@ -111,7 +111,7 @@ static void remote_machine_instance_init(Object *obj)
s->auto_shutdown = true;
}
-static void remote_machine_dev_unplug_cb(HotplugHandler *hotplug_dev,
+static void remote_machine_dev_unplug_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
qdev_unrealize(dev);
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index f3a1cc5ba3..d4b501802f 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -1088,8 +1088,8 @@ static void virt_set_acpi(Object *obj, Visitor *v, const char *name,
visit_type_OnOffAuto(v, name, &s->acpi, errp);
}
-static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
- DeviceState *dev)
+static const HotplugHandler *
+virt_machine_get_hotplug_handler(MachineState *machine, DeviceState *dev)
{
MachineClass *mc = MACHINE_GET_CLASS(machine);
RISCVVirtState *s = RISCV_VIRT_MACHINE(machine);
@@ -1104,7 +1104,7 @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
return NULL;
}
-static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev,
+static void virt_machine_device_plug_cb(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
RISCVVirtState *s = RISCV_VIRT_MACHINE(hotplug_dev);
diff --git a/hw/s390x/css-bridge.c b/hw/s390x/css-bridge.c
index 440fefb7d0..e7cd9ac7b6 100644
--- a/hw/s390x/css-bridge.c
+++ b/hw/s390x/css-bridge.c
@@ -26,7 +26,7 @@
* (including sending a channel report to the guest) and remove the
* device from the virtual css bus.
*/
-static void ccw_device_unplug(HotplugHandler *hotplug_dev,
+static void ccw_device_unplug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
CcwDevice *ccw_dev = CCW_DEVICE(dev);
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index eff980fdfe..2eb4e8cec4 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -158,7 +158,7 @@ static void s390_pci_shutdown_notifier(Notifier *n, void *opaque)
static void s390_pci_perform_unplug(S390PCIBusDevice *pbdev)
{
- HotplugHandler *hotplug_ctrl;
+ const HotplugHandler *hotplug_ctrl;
if (pbdev->pft == ZPCI_PFT_ISM) {
notifier_remove(&pbdev->shutdown_notifier);
@@ -1005,8 +1005,8 @@ static bool s390_pci_alloc_idx(S390pciState *s, S390PCIBusDevice *pbdev)
return true;
}
-static void s390_pcihost_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
- Error **errp)
+static void s390_pcihost_pre_plug(const HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
{
S390pciState *s = S390_PCI_HOST_BRIDGE(hotplug_dev);
@@ -1079,7 +1079,7 @@ static int s390_pci_interp_plug(S390pciState *s, S390PCIBusDevice *pbdev)
return 0;
}
-static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
+static void s390_pcihost_plug(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
S390pciState *s = S390_PCI_HOST_BRIDGE(hotplug_dev);
@@ -1216,7 +1216,7 @@ static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
}
}
-static void s390_pcihost_unplug(HotplugHandler *hotplug_dev, DeviceState *dev,
+static void s390_pcihost_unplug(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
S390pciState *s = S390_PCI_HOST_BRIDGE(hotplug_dev);
@@ -1255,7 +1255,7 @@ static void s390_pcihost_unplug(HotplugHandler *hotplug_dev, DeviceState *dev,
}
}
-static void s390_pcihost_unplug_request(HotplugHandler *hotplug_dev,
+static void s390_pcihost_unplug_request(const HotplugHandler *hotplug_dev,
DeviceState *dev,
Error **errp)
{
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 17266779a6..7fb78d8fa1 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -343,8 +343,8 @@ static void ccw_init(MachineState *machine)
}
-static void s390_cpu_plug(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
+static void s390_cpu_plug(const HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
{
ERRP_GUARD();
MachineState *ms = MACHINE(hotplug_dev);
@@ -608,7 +608,7 @@ out_lock:
bql_lock();
}
-static void s390_machine_device_pre_plug(HotplugHandler *hotplug_dev,
+static void s390_machine_device_pre_plug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_CCW)) {
@@ -618,7 +618,7 @@ static void s390_machine_device_pre_plug(HotplugHandler *hotplug_dev,
}
}
-static void s390_machine_device_plug(HotplugHandler *hotplug_dev,
+static void s390_machine_device_plug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
S390CcwMachineState *s390ms = S390_CCW_MACHINE(hotplug_dev);
@@ -648,7 +648,7 @@ static void s390_machine_device_plug(HotplugHandler *hotplug_dev,
}
}
-static void s390_machine_device_unplug_request(HotplugHandler *hotplug_dev,
+static void s390_machine_device_unplug_request(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
@@ -662,7 +662,7 @@ static void s390_machine_device_unplug_request(HotplugHandler *hotplug_dev,
}
}
-static void s390_machine_device_unplug(HotplugHandler *hotplug_dev,
+static void s390_machine_device_unplug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_CCW)) {
@@ -715,8 +715,8 @@ static const CPUArchIdList *s390_possible_cpu_arch_ids(MachineState *ms)
return ms->possible_cpus;
}
-static HotplugHandler *s390_get_hotplug_handler(MachineState *machine,
- DeviceState *dev)
+static const HotplugHandler *s390_get_hotplug_handler(MachineState *machine,
+ DeviceState *dev)
{
if (object_dynamic_cast(OBJECT(dev), TYPE_CPU) ||
object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_CCW) ||
diff --git a/hw/s390x/virtio-ccw-md.c b/hw/s390x/virtio-ccw-md.c
index 0b18b49bc4..70dbea819a 100644
--- a/hw/s390x/virtio-ccw-md.c
+++ b/hw/s390x/virtio-ccw-md.c
@@ -19,7 +19,7 @@
void virtio_ccw_md_pre_plug(VirtIOMDCcw *vmd, MachineState *ms, Error **errp)
{
DeviceState *dev = DEVICE(vmd);
- HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
+ const HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
MemoryDeviceState *md = MEMORY_DEVICE(vmd);
Error *local_err = NULL;
@@ -48,7 +48,7 @@ void virtio_ccw_md_pre_plug(VirtIOMDCcw *vmd, MachineState *ms, Error **errp)
void virtio_ccw_md_plug(VirtIOMDCcw *vmd, MachineState *ms, Error **errp)
{
DeviceState *dev = DEVICE(vmd);
- HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
+ const HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
MemoryDeviceState *md = MEMORY_DEVICE(vmd);
Error *local_err = NULL;
@@ -72,7 +72,7 @@ void virtio_ccw_md_unplug_request(VirtIOMDCcw *vmd, MachineState *ms,
{
VirtIOMDCcwClass *vmdc = VIRTIO_MD_CCW_GET_CLASS(vmd);
DeviceState *dev = DEVICE(vmd);
- HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
+ const HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
const HotplugHandlerClass *hdc;
Error *local_err = NULL;
@@ -112,7 +112,7 @@ void virtio_ccw_md_unplug_request(VirtIOMDCcw *vmd, MachineState *ms,
void virtio_ccw_md_unplug(VirtIOMDCcw *vmd, MachineState *ms, Error **errp)
{
DeviceState *dev = DEVICE(vmd);
- HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
+ const HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
MemoryDeviceState *md = MEMORY_DEVICE(vmd);
Error *local_err = NULL;
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index d82874ed27..30fb2c0681 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -1235,7 +1235,7 @@ static void virtio_ccw_busdev_unrealize(DeviceState *dev)
virtio_ccw_device_unrealize(_dev);
}
-static void virtio_ccw_busdev_unplug(HotplugHandler *hotplug_dev,
+static void virtio_ccw_busdev_unplug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
VirtioCcwDevice *_dev = to_virtio_ccw_dev_fast(dev);
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 132f833226..d7e2662aa7 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -1144,14 +1144,14 @@ static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense)
}
}
-static void virtio_scsi_pre_hotplug(HotplugHandler *hotplug_dev,
+static void virtio_scsi_pre_hotplug(const HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
SCSIDevice *sd = SCSI_DEVICE(dev);
sd->hba_supports_iothread = true;
}
-static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
+static void virtio_scsi_hotplug(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev);
@@ -1183,7 +1183,7 @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
}
}
-static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev,
+static void virtio_scsi_hotunplug(const HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev);
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index 05f93171cd..77c9b843b4 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -612,7 +612,7 @@ pvscsi_send_msg(PVSCSIState *s, SCSIDevice *dev, uint32_t msg_type)
}
static void
-pvscsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp)
+pvscsi_hotplug(const HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp)
{
PVSCSIState *s = PVSCSI(hotplug_dev);
@@ -620,7 +620,7 @@ pvscsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp)
}
static void
-pvscsi_hot_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp)
+pvscsi_hot_unplug(const HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp)
{
PVSCSIState *s = PVSCSI(hotplug_dev);
diff --git a/hw/virtio/virtio-md-pci.c b/hw/virtio/virtio-md-pci.c
index aa5b11c0f6..97ea0ec7b3 100644
--- a/hw/virtio/virtio-md-pci.c
+++ b/hw/virtio/virtio-md-pci.c
@@ -19,7 +19,7 @@
void virtio_md_pci_pre_plug(VirtIOMDPCI *vmd, MachineState *ms, Error **errp)
{
DeviceState *dev = DEVICE(vmd);
- HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
+ const HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
MemoryDeviceState *md = MEMORY_DEVICE(vmd);
Error *local_err = NULL;
@@ -47,7 +47,7 @@ void virtio_md_pci_pre_plug(VirtIOMDPCI *vmd, MachineState *ms, Error **errp)
void virtio_md_pci_plug(VirtIOMDPCI *vmd, MachineState *ms, Error **errp)
{
DeviceState *dev = DEVICE(vmd);
- HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
+ const HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
MemoryDeviceState *md = MEMORY_DEVICE(vmd);
Error *local_err = NULL;
@@ -71,7 +71,7 @@ void virtio_md_pci_unplug_request(VirtIOMDPCI *vmd, MachineState *ms,
{
VirtIOMDPCIClass *vmdc = VIRTIO_MD_PCI_GET_CLASS(vmd);
DeviceState *dev = DEVICE(vmd);
- HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
+ const HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
const HotplugHandlerClass *hdc;
Error *local_err = NULL;
@@ -110,7 +110,7 @@ void virtio_md_pci_unplug_request(VirtIOMDPCI *vmd, MachineState *ms,
void virtio_md_pci_unplug(VirtIOMDPCI *vmd, MachineState *ms, Error **errp)
{
DeviceState *dev = DEVICE(vmd);
- HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
+ const HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
MemoryDeviceState *md = MEMORY_DEVICE(vmd);
Error *local_err = NULL;
diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c
index 1762816bf4..8def3bb68b 100644
--- a/hw/xen/xen-bus.c
+++ b/hw/xen/xen-bus.c
@@ -374,7 +374,7 @@ fail:
g_free(key);
}
-static void xen_bus_unplug_request(HotplugHandler *hotplug,
+static void xen_bus_unplug_request(const HotplugHandler *hotplug,
DeviceState *dev,
Error **errp)
{
diff --git a/stubs/hotplug-stubs.c b/stubs/hotplug-stubs.c
index 0f592ee139..32b4af7997 100644
--- a/stubs/hotplug-stubs.c
+++ b/stubs/hotplug-stubs.c
@@ -14,19 +14,19 @@
#include "qemu/osdep.h"
#include "hw/core/qdev.h"
-HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
+const HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
{
return NULL;
}
-void hotplug_handler_pre_plug(HotplugHandler *plug_handler,
+void hotplug_handler_pre_plug(const HotplugHandler *plug_handler,
DeviceState *plugged_dev,
Error **errp)
{
g_assert_not_reached();
}
-void hotplug_handler_plug(HotplugHandler *plug_handler,
+void hotplug_handler_plug(const HotplugHandler *plug_handler,
DeviceState *plugged_dev,
Error **errp)
{
diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c
index 0c5502d45b..a62ad23ecf 100644
--- a/system/qdev-monitor.c
+++ b/system/qdev-monitor.c
@@ -917,7 +917,7 @@ static DeviceState *find_device_state(const char *id, bool use_generic_error,
void qdev_unplug(DeviceState *dev, Error **errp)
{
- HotplugHandler *hotplug_ctrl;
+ const HotplugHandler *hotplug_ctrl;
const HotplugHandlerClass *hdc;
Error *local_err = NULL;
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 66/75] net/tap-solaris: Fix resource leaks on error paths
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (64 preceding siblings ...)
2026-09-11 9:03 ` [PULL v2 65/75] hw/hotplug: Constify HotplugHandler Michael S. Tsirkin
@ 2026-09-11 9:03 ` Michael S. Tsirkin
2026-09-11 9:04 ` [PULL v2 67/75] virtio-net: validate IHL in virtio_net_rsc_extract_unit4 before use Michael S. Tsirkin
` (10 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:03 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Weimin Xiong, Jason Wang
Signed-off-by: Weimin Xiong <xiongwm2026@163.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
net/tap-solaris.c | 69 ++++++++++++++++++++++++++++++++---------------
1 file changed, 48 insertions(+), 21 deletions(-)
diff --git a/net/tap-solaris.c b/net/tap-solaris.c
index 8704b1084b..2c6c7af15e 100644
--- a/net/tap-solaris.c
+++ b/net/tap-solaris.c
@@ -60,8 +60,6 @@ ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen)
*/
static int tap_alloc(char *dev, size_t dev_size, Error **errp)
{
- /* FIXME leaks like a sieve on error paths */
- /* FIXME suspicious: many errors are reported, then ignored */
int tap_fd, if_fd, ppa = -1;
static int ip_fd = 0;
char *ptr;
@@ -102,45 +100,61 @@ static int tap_alloc(char *dev, size_t dev_size, Error **errp)
strioc_ppa.ic_timout = 0;
strioc_ppa.ic_len = sizeof(ppa);
strioc_ppa.ic_dp = (char *)&ppa;
- if ((ppa = ioctl (tap_fd, I_STR, &strioc_ppa)) < 0)
+ if ((ppa = ioctl (tap_fd, I_STR, &strioc_ppa)) < 0) {
error_report("Can't assign new interface");
+ goto fail_tap_fd;
+ }
if_fd = RETRY_ON_EINTR(open("/dev/tap", O_RDWR, 0));
if (if_fd < 0) {
error_setg_file_open(errp, errno, "/dev/tap");
- return -1;
+ goto fail_tap_fd;
}
if(ioctl(if_fd, I_PUSH, "ip") < 0){
error_setg(errp, "Can't push IP module");
- return -1;
+ goto fail_if_fd;
}
- if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0)
+ if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0) {
error_report("Can't get flags");
+ goto fail_if_fd;
+ }
- snprintf (actual_name, 32, "tap%d", ppa);
+ snprintf(actual_name, 32, "tap%d", ppa);
pstrcpy(ifr.lifr_name, sizeof(ifr.lifr_name), actual_name);
ifr.lifr_ppa = ppa;
- /* Assign ppa according to the unit number returned by tun device */
-
- if (ioctl (if_fd, SIOCSLIFNAME, &ifr) < 0)
+ if (ioctl(if_fd, SIOCSLIFNAME, &ifr) < 0) {
error_report("Can't set PPA %d", ppa);
- if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) <0)
+ goto fail_if_fd;
+ }
+
+ if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0) {
error_report("Can't get flags");
+ goto fail_if_fd;
+ }
+
/* Push arp module to if_fd */
- if (ioctl (if_fd, I_PUSH, "arp") < 0)
+ if (ioctl(if_fd, I_PUSH, "arp") < 0) {
error_report("Can't push ARP module (2)");
+ goto fail_if_fd;
+ }
/* Push arp module to ip_fd */
- if (ioctl (ip_fd, I_POP, NULL) < 0)
+ if (ioctl(ip_fd, I_POP, NULL) < 0) {
error_report("I_POP failed");
- if (ioctl (ip_fd, I_PUSH, "arp") < 0)
+ goto fail_if_fd;
+ }
+ if (ioctl(ip_fd, I_PUSH, "arp") < 0) {
error_report("Can't push ARP module (3)");
+ goto fail_if_fd;
+ }
/* Open arp_fd */
arp_fd = RETRY_ON_EINTR(open("/dev/tap", O_RDWR, 0));
- if (arp_fd < 0)
+ if (arp_fd < 0) {
error_report("Can't open %s", "/dev/tap");
+ goto fail_if_fd;
+ }
/* Set ifname to arp */
strioc_if.ic_cmd = SIOCSLIFNAME;
@@ -149,32 +163,45 @@ static int tap_alloc(char *dev, size_t dev_size, Error **errp)
strioc_if.ic_dp = (char *)𝔦
if (ioctl(arp_fd, I_STR, &strioc_if) < 0){
error_report("Can't set ifname to arp");
+ goto fail_arp_fd;
}
if((ip_muxid = ioctl(ip_fd, I_LINK, if_fd)) < 0){
error_setg(errp, "Can't link TAP device to IP");
- return -1;
+ goto fail_arp_fd;
}
- if ((arp_muxid = ioctl (ip_fd, link_type, arp_fd)) < 0)
+ if ((arp_muxid = ioctl(ip_fd, link_type, arp_fd)) < 0) {
error_report("Can't link TAP device to ARP");
+ goto fail_ip_muxid;
+ }
- close (if_fd);
+ close(if_fd);
memset(&ifr, 0x0, sizeof(ifr));
pstrcpy(ifr.lifr_name, sizeof(ifr.lifr_name), actual_name);
ifr.lifr_ip_muxid = ip_muxid;
ifr.lifr_arp_muxid = arp_muxid;
- if (ioctl (ip_fd, SIOCSLIFMUXID, &ifr) < 0)
+ if (ioctl(ip_fd, SIOCSLIFMUXID, &ifr) < 0)
{
- ioctl (ip_fd, I_PUNLINK , arp_muxid);
- ioctl (ip_fd, I_PUNLINK, ip_muxid);
+ ioctl(ip_fd, I_PUNLINK, arp_muxid);
+ ioctl(ip_fd, I_PUNLINK, ip_muxid);
error_report("Can't set multiplexor id");
}
snprintf(dev, dev_size, "tap%d", ppa);
return tap_fd;
+
+fail_ip_muxid:
+ ioctl(ip_fd, I_PUNLINK, ip_muxid);
+fail_arp_fd:
+ close(arp_fd);
+fail_if_fd:
+ close(if_fd);
+fail_tap_fd:
+ close(tap_fd);
+ return -1;
}
int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 67/75] virtio-net: validate IHL in virtio_net_rsc_extract_unit4 before use
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (65 preceding siblings ...)
2026-09-11 9:03 ` [PULL v2 66/75] net/tap-solaris: Fix resource leaks on error paths Michael S. Tsirkin
@ 2026-09-11 9:04 ` Michael S. Tsirkin
2026-09-11 9:04 ` [PULL v2 68/75] intel_iommu: Expose SMPWC when SVM is enabled Michael S. Tsirkin
` (9 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Jason Wang, Yuri Benditovich
virtio_net_rsc_extract_unit4() uses the IPv4 IHL nibble from the
wire to compute the TCP header offset, but the caller's length
check only guarantees space for a minimum 20-byte IP header. A
crafted IHL of 15 causes a read 32 bytes past a 66-byte buffer
when the frame was parked in net/queue.c's exact-size allocation.
virtio_net_rsc_sanity_check4() rejects IHL != 5 on the next line,
but runs after the OOB read already happened.
Validate IHL before using it as an offset. Since
virtio_net_rsc_sanity_check4() only accepts IHL == 5 anyway, reject
anything else early and let the caller fall through to the bypass
path.
Fixes: 2974e916df ("virtio-net: support RSC v4/v6 tcp traffic for Windows HCK")
Cc: Jason Wang <jasowangio@gmail.com>
Cc: Yuri Benditovich <yuri.benditovich@daynix.com>
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4166
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
hw/net/virtio-net.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 986ceff514..19f453fb7d 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -2104,6 +2104,14 @@ static void virtio_net_rsc_extract_unit4(VirtioNetRscChain *chain,
unit->ip = (void *)ip;
ip_hdrlen = (ip->ip_ver_len & 0xF) << 2;
unit->ip_plen = &ip->ip_len;
+
+ if (ip_hdrlen != sizeof(struct ip_header)) {
+ unit->tcp = NULL;
+ unit->tcp_hdrlen = 0;
+ unit->payload = 0;
+ return;
+ }
+
unit->tcp = (struct tcp_header *)(((uint8_t *)unit->ip) + ip_hdrlen);
unit->tcp_hdrlen = (htons(unit->tcp->th_offset_flags) & 0xF000) >> 10;
unit->payload = read_unit_ip_len(unit) - ip_hdrlen - unit->tcp_hdrlen;
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 68/75] intel_iommu: Expose SMPWC when SVM is enabled
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (66 preceding siblings ...)
2026-09-11 9:04 ` [PULL v2 67/75] virtio-net: validate IHL in virtio_net_rsc_extract_unit4 before use Michael S. Tsirkin
@ 2026-09-11 9:04 ` Michael S. Tsirkin
2026-09-11 9:04 ` [PULL v2 69/75] vhost-user: add skip_drain param to do_vhost_virtqueue_stop Michael S. Tsirkin
` (8 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:04 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Clément MATHIEU--DRIF, Zhenzhong Duan,
Jason Wang, Yi Liu, Paolo Bonzini, Richard Henderson
From: Clément MATHIEU--DRIF <clement.mathieu--drif@bull.com>
SVM in Linux requires SMPWC. This is free in the current implementation
as it is already in line with the expected behaviour.
Link: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=780dfed68862
Fixes: 952e1a6e90eb ("intel_iommu: Add a CLI option to enable SVM")
Signed-off-by: Clement Mathieu--Drif <clement.mathieu--drif@bull.com>
Reviewed-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260808153626.873965-1-clement.mathieu--drif@bull.com>
---
hw/i386/intel_iommu_internal.h | 1 +
hw/i386/intel_iommu.c | 3 ++-
hw/i386/intel_iommu_accel.c | 6 ++++++
3 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
index 924e91cb8a..df7a0efa6e 100644
--- a/hw/i386/intel_iommu_internal.h
+++ b/hw/i386/intel_iommu_internal.h
@@ -202,6 +202,7 @@
#define VTD_ECAP_SMTS (1ULL << 43)
#define VTD_ECAP_SSTS (1ULL << 46)
#define VTD_ECAP_FSTS (1ULL << 47)
+#define VTD_ECAP_SMPWCS (1ULL << 48)
/* CAP_REG */
/* (offset >> 4) << 24 */
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 91ab549dbf..350d2b7753 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -5121,7 +5121,8 @@ static void vtd_init(IntelIOMMUState *s)
}
if (s->svm) {
- s->ecap |= VTD_ECAP_PRS | VTD_ECAP_PDS | VTD_ECAP_NWFS;
+ s->ecap |= VTD_ECAP_PRS | VTD_ECAP_PDS | VTD_ECAP_NWFS |
+ VTD_ECAP_SMPWCS;
}
vtd_reset_caches(s);
diff --git a/hw/i386/intel_iommu_accel.c b/hw/i386/intel_iommu_accel.c
index c03435f8a2..c3677775e9 100644
--- a/hw/i386/intel_iommu_accel.c
+++ b/hw/i386/intel_iommu_accel.c
@@ -37,6 +37,12 @@ bool vtd_check_hiod_accel(IntelIOMMUState *s, VTDHostIOMMUDevice *vtd_hiod,
return false;
}
+ if ((s->ecap & VTD_ECAP_SMPWCS) && !(vtd->ecap_reg & VTD_ECAP_SMPWCS)) {
+ error_setg(errp,
+ "Scalable-mode coherent walk is unsupported by host IOMMU");
+ return false;
+ }
+
if (s->fs1gp && !(vtd->cap_reg & VTD_CAP_FS1GP)) {
error_setg(errp,
"First stage 1GB large page is unsupported by host IOMMU");
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 69/75] vhost-user: add skip_drain param to do_vhost_virtqueue_stop
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (67 preceding siblings ...)
2026-09-11 9:04 ` [PULL v2 68/75] intel_iommu: Expose SMPWC when SVM is enabled Michael S. Tsirkin
@ 2026-09-11 9:04 ` Michael S. Tsirkin
2026-09-11 9:04 ` [PULL v2 70/75] vhost-user: add GET_VRING_BASE_SKIP_DRAIN message Michael S. Tsirkin
` (7 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:04 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Alexandr Moshkov, Gonglei (Arei), zhenwei pi,
Stefano Garzarella, Raphael Norwitz, Kevin Wolf, Hanna Reitz,
Marc-André Lureau, Albert Esteve, Jason Wang, Paolo Bonzini,
Fam Zheng, Alex Bennée, Stefan Hajnoczi, Milan Zamazal,
qemu-block, virtio-fs
From: Alexandr Moshkov <dtalexundeer@yandex-team.ru>
Currently do_vhost_virtqueue_stop always sends GET_VRING_BASE to the
back-end, which requires the back-end to drain all in-flight I/O before
stopping the vring.
Add a skip_drain parameter to do_vhost_virtqueue_stop and propagate it
up through vhost_virtqueue_stop, vhost_dev_stop and their callers.
The parameter will be used in a follow-up commit to send a new protocol
message that instructs the back-end to suspend in-flight I/O immediately
instead of draining it.
Signed-off-by: Alexandr Moshkov <dtalexundeer@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260803072853.2920007-2-dtalexundeer@yandex-team.ru>
---
include/hw/virtio/vhost.h | 7 +++++--
backends/cryptodev-vhost.c | 2 +-
backends/vhost-user.c | 2 +-
hw/block/vhost-user-blk.c | 2 +-
hw/display/vhost-user-media.c | 2 +-
hw/net/vhost_net.c | 9 +++++----
hw/scsi/vhost-scsi-common.c | 2 +-
hw/virtio/vdpa-dev.c | 2 +-
hw/virtio/vhost-user-base.c | 2 +-
hw/virtio/vhost-user-fs.c | 2 +-
hw/virtio/vhost-user-scmi.c | 2 +-
hw/virtio/vhost-vsock-common.c | 2 +-
hw/virtio/vhost.c | 28 +++++++++++++++++++---------
13 files changed, 39 insertions(+), 25 deletions(-)
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index 3db56433b6..0a322efec1 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -228,6 +228,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings);
* @hdev: common vhost_dev structure
* @vdev: the VirtIODevice structure
* @vrings: true to have vrings disabled in this call
+ * @skip_drain: true to notice back-end to skip draining all in-flight requests
*
* Stop the vhost device. After the device is stopped the notifiers
* can be disabled (@vhost_dev_disable_notifiers) and the device can
@@ -235,7 +236,8 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings);
*
* Return: 0 on success, != 0 on error when stopping dev.
*/
-int vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings);
+int vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings,
+ bool skip_drain);
/**
* vhost_dev_force_stop() - force stop the vhost device
@@ -396,7 +398,8 @@ int vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t iova, int write);
int vhost_virtqueue_start(struct vhost_dev *dev, struct VirtIODevice *vdev,
struct vhost_virtqueue *vq, unsigned idx);
int vhost_virtqueue_stop(struct vhost_dev *dev, struct VirtIODevice *vdev,
- struct vhost_virtqueue *vq, unsigned idx);
+ struct vhost_virtqueue *vq, unsigned idx,
+ bool skip_drain);
void vhost_dev_reset_inflight(struct vhost_inflight *inflight);
void vhost_dev_free_inflight(struct vhost_inflight *inflight);
diff --git a/backends/cryptodev-vhost.c b/backends/cryptodev-vhost.c
index c6069f4e5b..f1ca6bcd4e 100644
--- a/backends/cryptodev-vhost.c
+++ b/backends/cryptodev-vhost.c
@@ -109,7 +109,7 @@ static void
cryptodev_vhost_stop_one(CryptoDevBackendVhost *crypto,
VirtIODevice *dev)
{
- vhost_dev_stop(&crypto->dev, dev, false);
+ vhost_dev_stop(&crypto->dev, dev, false, false);
vhost_dev_disable_notifiers(&crypto->dev, dev);
}
diff --git a/backends/vhost-user.c b/backends/vhost-user.c
index 46dadb7480..de6b1ba267 100644
--- a/backends/vhost-user.c
+++ b/backends/vhost-user.c
@@ -108,7 +108,7 @@ vhost_user_backend_stop(VhostUserBackend *b)
return 0;
}
- ret = vhost_dev_stop(&b->dev, b->vdev, true);
+ ret = vhost_dev_stop(&b->dev, b->vdev, true, false);
if (k->set_guest_notifiers &&
(err = k->set_guest_notifiers(qbus->parent, b->dev.nvqs, false)) < 0) {
diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index 2e5b3ae1b1..c3e3c37f8c 100644
--- a/hw/block/vhost-user-blk.c
+++ b/hw/block/vhost-user-blk.c
@@ -238,7 +238,7 @@ static int vhost_user_blk_stop(VirtIODevice *vdev)
qemu_force_shutdown_requested();
ret = force_stop ? vhost_dev_force_stop(&s->dev, vdev, true) :
- vhost_dev_stop(&s->dev, vdev, true);
+ vhost_dev_stop(&s->dev, vdev, true, false);
err = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, false);
if (err < 0) {
diff --git a/hw/display/vhost-user-media.c b/hw/display/vhost-user-media.c
index eaf99dc6a2..851af8ddc2 100644
--- a/hw/display/vhost-user-media.c
+++ b/hw/display/vhost-user-media.c
@@ -110,7 +110,7 @@ static void vu_media_stop(VirtIODevice *vdev)
return;
}
- vhost_dev_stop(&media->vhost_dev, vdev, true);
+ vhost_dev_stop(&media->vhost_dev, vdev, true, false);
ret = k->set_guest_notifiers(qbus->parent, media->vhost_dev.nvqs, false);
if (ret < 0) {
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 323d117735..6e05c995f1 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -384,7 +384,7 @@ fail:
if (net->nc->info->poll) {
net->nc->info->poll(net->nc, true);
}
- vhost_dev_stop(&net->dev, dev, false);
+ vhost_dev_stop(&net->dev, dev, false, false);
fail_start:
return r;
}
@@ -403,7 +403,7 @@ static void vhost_net_stop_one(struct vhost_net *net,
if (net->nc->info->poll) {
net->nc->info->poll(net->nc, true);
}
- vhost_dev_stop(&net->dev, dev, false);
+ vhost_dev_stop(&net->dev, dev, false, false);
if (net->nc->info->stop) {
net->nc->info->stop(net->nc);
}
@@ -636,7 +636,8 @@ void vhost_net_virtqueue_reset(VirtIODevice *vdev, NetClientState *nc,
vhost_virtqueue_stop(&net->dev,
vdev,
net->dev.vqs + idx,
- net->dev.vq_index + idx);
+ net->dev.vq_index + idx,
+ false);
}
int vhost_net_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc,
@@ -686,7 +687,7 @@ err_start:
assert(ret >= 0);
}
- vhost_dev_stop(&net->dev, vdev, false);
+ vhost_dev_stop(&net->dev, vdev, false, false);
return r;
}
diff --git a/hw/scsi/vhost-scsi-common.c b/hw/scsi/vhost-scsi-common.c
index e19800a0bc..e546a6dc75 100644
--- a/hw/scsi/vhost-scsi-common.c
+++ b/hw/scsi/vhost-scsi-common.c
@@ -108,7 +108,7 @@ int vhost_scsi_common_stop(VHostSCSICommon *vsc)
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
int ret = 0;
- ret = vhost_dev_stop(&vsc->dev, vdev, true);
+ ret = vhost_dev_stop(&vsc->dev, vdev, true, false);
if (k->set_guest_notifiers) {
int r = k->set_guest_notifiers(qbus->parent, vsc->dev.nvqs, false);
diff --git a/hw/virtio/vdpa-dev.c b/hw/virtio/vdpa-dev.c
index 6dc684ab09..7e5cc040e9 100644
--- a/hw/virtio/vdpa-dev.c
+++ b/hw/virtio/vdpa-dev.c
@@ -301,7 +301,7 @@ static void vhost_vdpa_device_stop(VirtIODevice *vdev)
return;
}
- vhost_dev_stop(&s->dev, vdev, false);
+ vhost_dev_stop(&s->dev, vdev, false, false);
ret = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, false);
if (ret < 0) {
diff --git a/hw/virtio/vhost-user-base.c b/hw/virtio/vhost-user-base.c
index 478ec68f09..1a377016e7 100644
--- a/hw/virtio/vhost-user-base.c
+++ b/hw/virtio/vhost-user-base.c
@@ -78,7 +78,7 @@ static int vub_stop(VirtIODevice *vdev)
return 0;
}
- ret = vhost_dev_stop(&vub->vhost_dev, vdev, true);
+ ret = vhost_dev_stop(&vub->vhost_dev, vdev, true, false);
err = k->set_guest_notifiers(qbus->parent, vub->vhost_dev.nvqs, false);
if (err < 0) {
diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c
index 209993918a..0d8842817a 100644
--- a/hw/virtio/vhost-user-fs.c
+++ b/hw/virtio/vhost-user-fs.c
@@ -111,7 +111,7 @@ static int vuf_stop(VirtIODevice *vdev)
return 0;
}
- ret = vhost_dev_stop(&fs->vhost_dev, vdev, true);
+ ret = vhost_dev_stop(&fs->vhost_dev, vdev, true, false);
err = k->set_guest_notifiers(qbus->parent, fs->vhost_dev.nvqs, false);
if (err < 0) {
diff --git a/hw/virtio/vhost-user-scmi.c b/hw/virtio/vhost-user-scmi.c
index 02dc088ea9..c4692bd6aa 100644
--- a/hw/virtio/vhost-user-scmi.c
+++ b/hw/virtio/vhost-user-scmi.c
@@ -101,7 +101,7 @@ static int vu_scmi_stop(VirtIODevice *vdev)
return 0;
}
- ret = vhost_dev_stop(vhost_dev, vdev, true);
+ ret = vhost_dev_stop(vhost_dev, vdev, true, false);
err = k->set_guest_notifiers(qbus->parent, vhost_dev->nvqs, false);
if (err < 0) {
diff --git a/hw/virtio/vhost-vsock-common.c b/hw/virtio/vhost-vsock-common.c
index b79f4c9ce6..4ef037627b 100644
--- a/hw/virtio/vhost-vsock-common.c
+++ b/hw/virtio/vhost-vsock-common.c
@@ -106,7 +106,7 @@ int vhost_vsock_common_stop(VirtIODevice *vdev)
return 0;
}
- ret = vhost_dev_stop(&vvc->vhost_dev, vdev, true);
+ ret = vhost_dev_stop(&vvc->vhost_dev, vdev, true, false);
err = k->set_guest_notifiers(qbus->parent, vvc->vhost_dev.nvqs, false);
if (err < 0) {
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 52ea142bd4..48fe1805bb 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -23,6 +23,7 @@
#include "qemu/log.h"
#include "standard-headers/linux/vhost_types.h"
#include "hw/virtio/virtio-bus.h"
+#include "hw/virtio/vhost-user.h"
#include "hw/mem/memory-device.h"
#include "migration/blocker.h"
#include "migration/qemu-file-types.h"
@@ -1499,8 +1500,13 @@ fail:
static int do_vhost_virtqueue_stop(struct vhost_dev *dev,
struct VirtIODevice *vdev,
struct vhost_virtqueue *vq,
- unsigned idx, bool force)
+ unsigned idx, bool force,
+ bool skip_drain)
{
+ if (skip_drain) {
+ assert(vhost_user_has_protocol_feature(dev,
+ VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT));
+ }
int vhost_vq_index = dev->vhost_ops->vhost_get_vq_index(dev, idx);
struct vhost_vring_state state = {
.index = vhost_vq_index,
@@ -1550,9 +1556,10 @@ static int do_vhost_virtqueue_stop(struct vhost_dev *dev,
int vhost_virtqueue_stop(struct vhost_dev *dev,
struct VirtIODevice *vdev,
struct vhost_virtqueue *vq,
- unsigned idx)
+ unsigned idx,
+ bool skip_drain)
{
- return do_vhost_virtqueue_stop(dev, vdev, vq, idx, false);
+ return do_vhost_virtqueue_stop(dev, vdev, vq, idx, false, skip_drain);
}
static int vhost_virtqueue_set_busyloop_timeout(struct vhost_dev *dev,
@@ -2307,7 +2314,8 @@ fail_vq:
vhost_virtqueue_stop(hdev,
vdev,
hdev->vqs + i,
- hdev->vq_index + i);
+ hdev->vq_index + i,
+ false);
}
fail_mem:
@@ -2322,7 +2330,7 @@ fail_features:
/* Host notifiers must be enabled at this point. */
static int do_vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev,
- bool vrings, bool force)
+ bool vrings, bool force, bool skip_drain)
{
int i;
int rc = 0;
@@ -2349,7 +2357,8 @@ static int do_vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev,
vdev,
hdev->vqs + i,
hdev->vq_index + i,
- force);
+ force,
+ skip_drain);
}
if (hdev->vhost_ops->vhost_reset_status) {
hdev->vhost_ops->vhost_reset_status(hdev);
@@ -2371,15 +2380,16 @@ static int do_vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev,
return rc;
}
-int vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings)
+int vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings,
+ bool skip_drain)
{
- return do_vhost_dev_stop(hdev, vdev, vrings, false);
+ return do_vhost_dev_stop(hdev, vdev, vrings, false, skip_drain);
}
int vhost_dev_force_stop(struct vhost_dev *hdev, VirtIODevice *vdev,
bool vrings)
{
- return do_vhost_dev_stop(hdev, vdev, vrings, true);
+ return do_vhost_dev_stop(hdev, vdev, vrings, true, false);
}
int vhost_net_set_backend(struct vhost_dev *hdev,
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 70/75] vhost-user: add GET_VRING_BASE_SKIP_DRAIN message
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (68 preceding siblings ...)
2026-09-11 9:04 ` [PULL v2 69/75] vhost-user: add skip_drain param to do_vhost_virtqueue_stop Michael S. Tsirkin
@ 2026-09-11 9:04 ` Michael S. Tsirkin
2026-09-11 9:04 ` [PULL v2 71/75] vhost-user: use skip_drain with " Michael S. Tsirkin
` (6 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:04 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Alexandr Moshkov, Stefano Garzarella,
Pierrick Bouvier
From: Alexandr Moshkov <dtalexundeer@yandex-team.ru>
VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT was introduced to allow
the back-end to suspend in-flight I/O during GET_VRING_BASE instead of
draining it, enabling live migration of in-flight requests. However,
this behaviour is tied to the protocol feature itself - once negotiated,
there is no way for the front-end to tell the back-end to fall back to
the normal drain behaviour on a per-stop basis.
Introduce a separate message VHOST_USER_GET_VRING_BASE_SKIP_DRAIN
(id=45) guarded by a new protocol feature
VHOST_USER_PROTOCOL_F_GET_VRING_BASE_SKIP_DRAIN. The message is
identical to GET_VRING_BASE except that the back-end must immediately suspend all
in-flight I/O and record it in the inflight region. This way the
front-end has explicit per-call control: send GET_VRING_BASE for normal drain,
send GET_VRING_BASE_SKIP_DRAIN when immediate suspend is needed.
The new feature requires both
VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT
and VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD to be negotiated.
Signed-off-by: Alexandr Moshkov <dtalexundeer@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260803072853.2920007-3-dtalexundeer@yandex-team.ru>
---
docs/interop/vhost-user.rst | 42 ++++++++++++++++++++---------
include/hw/virtio/vhost-backend.h | 1 +
include/hw/virtio/vhost-user.h | 1 +
hw/virtio/vhost-user.c | 44 +++++++++++++++++++++++++++----
hw/virtio/vhost.c | 2 +-
5 files changed, 72 insertions(+), 18 deletions(-)
diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst
index fbfb9d01c6..c1e02ff7e9 100644
--- a/docs/interop/vhost-user.rst
+++ b/docs/interop/vhost-user.rst
@@ -457,6 +457,7 @@ replies, except for the following requests:
* ``VHOST_USER_GET_FEATURES``
* ``VHOST_USER_GET_PROTOCOL_FEATURES``
* ``VHOST_USER_GET_VRING_BASE``
+* ``VHOST_USER_GET_VRING_BASE_SKIP_DRAIN``
* ``VHOST_USER_SET_LOG_BASE`` (if ``VHOST_USER_PROTOCOL_F_LOG_SHMFD``)
* ``VHOST_USER_GET_INFLIGHT_FD`` (if ``VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD``)
@@ -533,7 +534,7 @@ Rings have two independent states: started/stopped, and enabled/disabled.
Each ring is initialized in a stopped and disabled state. Rings are started
with ``VHOST_USER_SET_VRING_KICK`` (or ``VHOST_USER_VRING_KICK`` if
``VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS`` is negotiated) and stopped with
-``VHOST_USER_GET_VRING_BASE``. A stopped ring enters the started state again
+``VHOST_USER_GET_VRING_BASE`` or ``VHOST_USER_GET_VRING_BASE_SKIP_DRAIN``. A stopped ring enters the started state again
with ``VHOST_USER_SET_VRING_KICK`` (or ``VHOST_USER_VRING_KICK`` if
``VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS`` is negotiated) and the back-end
resumes processing requests.
@@ -1159,6 +1160,7 @@ Protocol features
#define VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT 20
#define VHOST_USER_PROTOCOL_F_GPA_ADDRESSES 21
#define VHOST_USER_PROTOCOL_F_SHMEM 22
+ #define VHOST_USER_PROTOCOL_F_GET_VRING_BASE_SKIP_DRAIN 23
Front-end message types
-----------------------
@@ -1355,17 +1357,11 @@ Front-end message types
set to 0.
By default, the back-end must complete all inflight I/O requests for the
- specified vring before stopping it.
-
- If the ``VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT`` protocol
- feature has been negotiated, the back-end may suspend in-flight I/O
- requests and record them as described in :ref:`Inflight I/O tracking
- <inflight_io_tracking>` instead of completing them before stopping the vring.
- How to suspend an in-flight request depends on the implementation of the back-end
- but it typically can be done by aborting or cancelling the underlying I/O
- request. The ``VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT``
- protocol feature must only be negotiated if
- ``VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD`` is also negotiated.
+ specified vring before stopping it. If the
+ ``VHOST_USER_PROTOCOL_F_GET_VRING_BASE_SKIP_DRAIN`` protocol feature has
+ been negotiated, the front-end may instead use
+ ``VHOST_USER_GET_VRING_BASE_SKIP_DRAIN`` to request the back-end to
+ suspend in-flight I/O immediately.
``VHOST_USER_SET_VRING_KICK``
:id: 12
@@ -1868,6 +1864,28 @@ Front-end message types
* The size may be 0 if the region is unused.
+``VHOST_USER_GET_VRING_BASE_SKIP_DRAIN``
+ :id: 45
+ :equivalent ioctl: N/A
+ :request payload: vring state description
+ :reply payload: vring descriptor index/indices
+
+ This message requires the ``VHOST_USER_PROTOCOL_F_GET_VRING_BASE_SKIP_DRAIN``
+ protocol feature to be negotiated.
+
+ Identical to ``VHOST_USER_GET_VRING_BASE`` except that the back-end
+ must not wait for inflight I/O requests to complete before stopping
+ the vring. Instead, the back-end must immediately suspend all
+ in-flight I/O requests and record them as described in
+ :ref:`Inflight I/O tracking <inflight_io_tracking>`. How to suspend
+ an in-flight request depends on the implementation of the back-end,
+ but it typically can be done by aborting or cancelling the underlying
+ I/O request.
+
+ The ``VHOST_USER_PROTOCOL_F_GET_VRING_BASE_SKIP_DRAIN`` protocol feature
+ must only be negotiated if both ``VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT``
+ and ``VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD`` are also negotiated.
+
Back-end message types
----------------------
diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h
index d878d7b733..daa979a1aa 100644
--- a/include/hw/virtio/vhost-backend.h
+++ b/include/hw/virtio/vhost-backend.h
@@ -190,6 +190,7 @@ typedef struct VhostOps {
vhost_set_vring_num_op vhost_set_vring_num;
vhost_set_vring_base_op vhost_set_vring_base;
vhost_get_vring_base_op vhost_get_vring_base;
+ vhost_get_vring_base_op vhost_get_vring_base_skip_drain;
vhost_set_vring_kick_op vhost_set_vring_kick;
vhost_set_vring_call_op vhost_set_vring_call;
vhost_set_vring_err_op vhost_set_vring_err;
diff --git a/include/hw/virtio/vhost-user.h b/include/hw/virtio/vhost-user.h
index 06c360af18..47c13f8677 100644
--- a/include/hw/virtio/vhost-user.h
+++ b/include/hw/virtio/vhost-user.h
@@ -36,6 +36,7 @@ enum VhostUserProtocolFeature {
VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT = 20,
VHOST_USER_PROTOCOL_F_GPA_ADDRESSES = 21,
VHOST_USER_PROTOCOL_F_SHMEM = 22,
+ VHOST_USER_PROTOCOL_F_GET_VRING_BASE_SKIP_DRAIN = 23,
VHOST_USER_PROTOCOL_F_MAX
};
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 2881cec72d..5fb5d61afb 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -101,6 +101,7 @@ typedef enum VhostUserRequest {
VHOST_USER_SET_DEVICE_STATE_FD = 42,
VHOST_USER_CHECK_DEVICE_STATE = 43,
VHOST_USER_GET_SHMEM_CONFIG = 44,
+ VHOST_USER_GET_VRING_BASE_SKIP_DRAIN = 45,
VHOST_USER_MAX
} VhostUserRequest;
@@ -167,6 +168,7 @@ static const char *vhost_req_name(VhostUserRequest req)
VHOST_USER_CASE(GET_SHARED_OBJECT)
VHOST_USER_CASE(SET_DEVICE_STATE_FD)
VHOST_USER_CASE(CHECK_DEVICE_STATE)
+ VHOST_USER_CASE(GET_VRING_BASE_SKIP_DRAIN)
default:
return "<unknown>";
}
@@ -1402,12 +1404,18 @@ static VhostUserHostNotifier *fetch_notifier(VhostUserState *u,
return g_ptr_array_index(u->notifiers, idx);
}
-static int vhost_user_get_vring_base(struct vhost_dev *dev,
- struct vhost_vring_state *ring)
+static int get_vring_base(struct vhost_dev *dev,
+ struct vhost_vring_state *ring,
+ bool skip_drain)
{
int ret;
+ int request = VHOST_USER_GET_VRING_BASE;
+ if (skip_drain) {
+ request = VHOST_USER_GET_VRING_BASE_SKIP_DRAIN;
+ }
+
VhostUserMsg msg = {
- .hdr.request = VHOST_USER_GET_VRING_BASE,
+ .hdr.request = request,
.hdr.flags = VHOST_USER_VERSION,
.payload.state = *ring,
.hdr.size = sizeof(msg.payload.state),
@@ -1427,9 +1435,9 @@ static int vhost_user_get_vring_base(struct vhost_dev *dev,
return ret;
}
- if (msg.hdr.request != VHOST_USER_GET_VRING_BASE) {
+ if (msg.hdr.request != request) {
error_report("Received unexpected msg type. Expected %d received %d",
- VHOST_USER_GET_VRING_BASE, msg.hdr.request);
+ request, msg.hdr.request);
return -EPROTO;
}
@@ -1443,6 +1451,25 @@ static int vhost_user_get_vring_base(struct vhost_dev *dev,
return 0;
}
+static int vhost_user_get_vring_base(struct vhost_dev *dev,
+ struct vhost_vring_state *ring)
+{
+ return get_vring_base(dev, ring, false);
+}
+
+static int vhost_user_get_vring_base_skip_drain(struct vhost_dev *dev,
+ struct vhost_vring_state *ring)
+{
+ bool skip_drain_supported = vhost_user_has_protocol_feature(dev,
+ VHOST_USER_PROTOCOL_F_GET_VRING_BASE_SKIP_DRAIN);
+
+ if (!skip_drain_supported) {
+ return 0;
+ }
+
+ return get_vring_base(dev, ring, true);
+}
+
static int vhost_set_vring_file(struct vhost_dev *dev,
VhostUserRequest request,
struct vhost_vring_file *file)
@@ -2576,6 +2603,12 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque,
VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT);
}
+ if (!virtio_has_feature(protocol_features,
+ VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT)) {
+ protocol_features &= ~(1ULL <<
+ VHOST_USER_PROTOCOL_F_GET_VRING_BASE_SKIP_DRAIN);
+ }
+
/* final set of protocol features */
u->protocol_features = protocol_features;
err = vhost_user_set_protocol_features(dev, u->protocol_features);
@@ -3434,6 +3467,7 @@ const VhostOps user_ops = {
.vhost_set_vring_num = vhost_user_set_vring_num,
.vhost_set_vring_base = vhost_user_set_vring_base,
.vhost_get_vring_base = vhost_user_get_vring_base,
+ .vhost_get_vring_base_skip_drain = vhost_user_get_vring_base_skip_drain,
.vhost_set_vring_kick = vhost_user_set_vring_kick,
.vhost_set_vring_call = vhost_user_set_vring_call,
.vhost_set_vring_err = vhost_user_set_vring_err,
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 48fe1805bb..7294d3c42a 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1505,7 +1505,7 @@ static int do_vhost_virtqueue_stop(struct vhost_dev *dev,
{
if (skip_drain) {
assert(vhost_user_has_protocol_feature(dev,
- VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT));
+ VHOST_USER_PROTOCOL_F_GET_VRING_BASE_SKIP_DRAIN));
}
int vhost_vq_index = dev->vhost_ops->vhost_get_vq_index(dev, idx);
struct vhost_vring_state state = {
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 71/75] vhost-user: use skip_drain with GET_VRING_BASE_SKIP_DRAIN message
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (69 preceding siblings ...)
2026-09-11 9:04 ` [PULL v2 70/75] vhost-user: add GET_VRING_BASE_SKIP_DRAIN message Michael S. Tsirkin
@ 2026-09-11 9:04 ` Michael S. Tsirkin
2026-09-11 9:04 ` [PULL v2 72/75] vhost-user-blk: make inflight-migration prop mutable on running vm Michael S. Tsirkin
` (5 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Alexandr Moshkov, Stefano Garzarella
From: Alexandr Moshkov <dtalexundeer@yandex-team.ru>
Wire up the skip_drain parameter introduced in the previous commit to
the new GET_VRING_BASE_SKIP_DRAIN message. When skip_drain is set,
send GET_VRING_BASE_SKIP_DRAIN instead of GET_VRING_BASE, instructing
the back-end to suspend in-flight I/O immediately.
Signed-off-by: Alexandr Moshkov <dtalexundeer@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260803072853.2920007-4-dtalexundeer@yandex-team.ru>
---
hw/virtio/vhost.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 7294d3c42a..68a8e40481 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1521,7 +1521,11 @@ static int do_vhost_virtqueue_stop(struct vhost_dev *dev,
}
if (!force) {
- r = dev->vhost_ops->vhost_get_vring_base(dev, &state);
+ if (!skip_drain) {
+ r = dev->vhost_ops->vhost_get_vring_base(dev, &state);
+ } else {
+ r = dev->vhost_ops->vhost_get_vring_base_skip_drain(dev, &state);
+ }
if (r < 0) {
VHOST_OPS_DEBUG(r, "vhost VQ %u ring restore failed: %d", idx, r);
}
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 72/75] vhost-user-blk: make inflight-migration prop mutable on running vm
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (70 preceding siblings ...)
2026-09-11 9:04 ` [PULL v2 71/75] vhost-user: use skip_drain with " Michael S. Tsirkin
@ 2026-09-11 9:04 ` Michael S. Tsirkin
2026-09-11 9:04 ` [PULL v2 73/75] vhost-user-blk: move inflight_needed higher Michael S. Tsirkin
` (4 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:04 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Alexandr Moshkov, Raphael Norwitz,
Stefano Garzarella, Kevin Wolf, Hanna Reitz, qemu-block
From: Alexandr Moshkov <dtalexundeer@yandex-team.ru>
The inflight-migration property currently can only be set before the
device is realized. This makes it impossible to disable inflight
migration at runtime without restarting the VM.
Make the property mutable, but only while the VM is running. Blocking
changes when the VM is not running ensures that the value at stop time
reliably reflects the intent set on a live VM, which allows
vhost_user_blk_stop() to use skip_drain unconditionally based on the
property value without inspecting migration runstate.
Signed-off-by: Alexandr Moshkov <dtalexundeer@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260803072853.2920007-5-dtalexundeer@yandex-team.ru>
---
hw/block/vhost-user-blk.c | 28 ++++++++++++++++++++++++++--
1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index c3e3c37f8c..501de30796 100644
--- a/hw/block/vhost-user-blk.c
+++ b/hw/block/vhost-user-blk.c
@@ -629,6 +629,8 @@ static const VMStateDescription vmstate_vhost_user_blk = {
}
};
+static PropertyInfo vhost_user_blk_inflight_migration_prop;
+
static const Property vhost_user_blk_properties[] = {
DEFINE_PROP_CHR("chardev", VHostUserBlk, chardev),
DEFINE_PROP_UINT16("num-queues", VHostUserBlk, num_queues,
@@ -644,8 +646,9 @@ static const Property vhost_user_blk_properties[] = {
VIRTIO_BLK_F_WRITE_ZEROES, true),
DEFINE_PROP_BOOL("skip-get-vring-base-on-force-shutdown", VHostUserBlk,
skip_get_vring_base_on_force_shutdown, false),
- DEFINE_PROP_BOOL("inflight-migration", VHostUserBlk,
- inflight_migration, false),
+ DEFINE_PROP("inflight-migration", VHostUserBlk, inflight_migration,
+ vhost_user_blk_inflight_migration_prop, bool,
+ .set_default = true, .defval.u = false),
};
static void vhost_user_blk_class_init(ObjectClass *klass, const void *data)
@@ -675,8 +678,29 @@ static const TypeInfo vhost_user_blk_info = {
.class_init = vhost_user_blk_class_init,
};
+static void vhost_user_blk_set_inflight_migration(Object *obj, Visitor *v,
+ const char *name,
+ void *opaque, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+
+ if (dev->realized && !runstate_is_running()) {
+ error_setg(errp, "Property '%s' cannot be changed "
+ "while VM is not running", name);
+ return;
+ }
+
+ qdev_prop_bool.set(obj, v, name, opaque, errp);
+}
+
+
static void virtio_register_types(void)
{
+ vhost_user_blk_inflight_migration_prop = qdev_prop_bool;
+ vhost_user_blk_inflight_migration_prop.realized_set_allowed = true;
+ vhost_user_blk_inflight_migration_prop.set =
+ vhost_user_blk_set_inflight_migration;
+
type_register_static(&vhost_user_blk_info);
}
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 73/75] vhost-user-blk: move inflight_needed higher
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (71 preceding siblings ...)
2026-09-11 9:04 ` [PULL v2 72/75] vhost-user-blk: make inflight-migration prop mutable on running vm Michael S. Tsirkin
@ 2026-09-11 9:04 ` Michael S. Tsirkin
2026-09-11 9:04 ` [PULL v2 74/75] vhost-user-blk: use GET_VRING_BASE_SKIP_DRAIN when inflight-migration is on Michael S. Tsirkin
` (3 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:04 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Alexandr Moshkov, Vladimir Sementsov-Ogievskiy,
Raphael Norwitz, Stefano Garzarella, Kevin Wolf, Hanna Reitz,
qemu-block
From: Alexandr Moshkov <dtalexundeer@yandex-team.ru>
Move vhost_user_blk_inflight_needed() earlier in the file so it can
be called from vhost_user_blk_stop(), which is defined before the
VMState section. No functional change.
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Signed-off-by: Alexandr Moshkov <dtalexundeer@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260803072853.2920007-6-dtalexundeer@yandex-team.ru>
---
hw/block/vhost-user-blk.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index 501de30796..3eaaa19719 100644
--- a/hw/block/vhost-user-blk.c
+++ b/hw/block/vhost-user-blk.c
@@ -137,6 +137,17 @@ const VhostDevConfigOps blk_ops = {
.vhost_dev_config_notifier = vhost_user_blk_handle_config_change,
};
+static bool vhost_user_blk_inflight_needed(void *opaque)
+{
+ struct VHostUserBlk *s = opaque;
+
+ bool inflight_migration = virtio_has_feature(s->dev.protocol_features,
+ VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT);
+
+ return inflight_migration;
+}
+
+
static int vhost_user_blk_start(VirtIODevice *vdev, Error **errp)
{
VHostUserBlk *s = VHOST_USER_BLK(vdev);
@@ -597,14 +608,6 @@ static struct vhost_dev *vhost_user_blk_get_vhost(VirtIODevice *vdev)
return &s->dev;
}
-static bool vhost_user_blk_inflight_needed(void *opaque)
-{
- struct VHostUserBlk *s = opaque;
-
- return vhost_user_has_protocol_feature(
- &s->dev, VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT);
-}
-
static const VMStateDescription vmstate_vhost_user_blk_inflight = {
.name = "vhost-user-blk/inflight",
.version_id = 1,
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 74/75] vhost-user-blk: use GET_VRING_BASE_SKIP_DRAIN when inflight-migration is on
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (72 preceding siblings ...)
2026-09-11 9:04 ` [PULL v2 73/75] vhost-user-blk: move inflight_needed higher Michael S. Tsirkin
@ 2026-09-11 9:04 ` Michael S. Tsirkin
2026-09-11 9:04 ` [PULL v2 75/75] MAINTAINERS: add Junjie Cao as CXL reviewer Michael S. Tsirkin
` (2 subsequent siblings)
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:04 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Alexandr Moshkov, Raphael Norwitz,
Stefano Garzarella, Kevin Wolf, Hanna Reitz, qemu-block
From: Alexandr Moshkov <dtalexundeer@yandex-team.ru>
Currently during live migration vhost-user-blk sends GET_VRING_BASE to
stop vrings, which causes the back-end to drain all in-flight I/O before
returning. This blocks the migration source until all I/O completes,
adding significant downtime proportional to the I/O load.
When inflight-migration is enabled, send GET_VRING_BASE_SKIP_DRAIN
instead. This instructs the back-end to immediately suspend in-flight
I/O and record it in the shared inflight region, which is then migrated
to the destination host along with the rest of the device state.
Since inflight-migration can only be toggled while the VM is running,
i2ts value at stop time reliably reflects the intent set on a live VM.
There is no need to check migration runstate to decide whether to skip
draining. Using GET_VRING_BASE_SKIP_DRAIN on a regular VM stop is
safe - the back-end records any in-flight requests in the shared
inflight region, and they will be resubmitted when the VM starts again
via SET_INFLIGHT_FD.
If the back-end does not support
VHOST_USER_PROTOCOL_F_GET_VRING_BASE_SKIP_DRAIN,
migration is aborted with an error in pre_save rather than hitting an
assert at runtime.
Signed-off-by: Alexandr Moshkov <dtalexundeer@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260803072853.2920007-7-dtalexundeer@yandex-team.ru>
---
include/hw/virtio/vhost-user.h | 1 -
hw/block/vhost-user-blk.c | 29 +++++++++++++++++++++++------
hw/virtio/vhost-user.c | 3 +--
3 files changed, 24 insertions(+), 9 deletions(-)
diff --git a/include/hw/virtio/vhost-user.h b/include/hw/virtio/vhost-user.h
index 47c13f8677..78b4fba27f 100644
--- a/include/hw/virtio/vhost-user.h
+++ b/include/hw/virtio/vhost-user.h
@@ -73,7 +73,6 @@ typedef struct VhostUserState {
GPtrArray *notifiers;
int memory_slots;
bool supports_config;
- bool supports_inflight_migration;
} VhostUserState;
/**
diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index 3eaaa19719..3dade143c9 100644
--- a/hw/block/vhost-user-blk.c
+++ b/hw/block/vhost-user-blk.c
@@ -141,10 +141,7 @@ static bool vhost_user_blk_inflight_needed(void *opaque)
{
struct VHostUserBlk *s = opaque;
- bool inflight_migration = virtio_has_feature(s->dev.protocol_features,
- VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT);
-
- return inflight_migration;
+ return s->inflight_migration;
}
@@ -245,11 +242,13 @@ static int vhost_user_blk_stop(VirtIODevice *vdev)
return 0;
}
+ bool skip_drain = vhost_user_blk_inflight_needed(s);
+
force_stop = s->skip_get_vring_base_on_force_shutdown &&
qemu_force_shutdown_requested();
ret = force_stop ? vhost_dev_force_stop(&s->dev, vdev, true) :
- vhost_dev_stop(&s->dev, vdev, true, false);
+ vhost_dev_stop(&s->dev, vdev, true, skip_drain);
err = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, false);
if (err < 0) {
@@ -381,7 +380,6 @@ static int vhost_user_blk_connect(DeviceState *dev, Error **errp)
vhost_dev_set_config_notifier(&s->dev, &blk_ops);
s->vhost_user.supports_config = true;
- s->vhost_user.supports_inflight_migration = s->inflight_migration;
ret = vhost_dev_init(&s->dev, &s->vhost_user, VHOST_BACKEND_TYPE_USER, 0,
errp);
if (ret < 0) {
@@ -608,10 +606,29 @@ static struct vhost_dev *vhost_user_blk_get_vhost(VirtIODevice *vdev)
return &s->dev;
}
+static bool vhost_user_blk_pre_save(void *opaque, Error **errp)
+{
+ VHostUserBlk *s = VHOST_USER_BLK(opaque);
+
+ bool inflight_migration_enabled = vhost_user_has_protocol_feature(&s->dev,
+ VHOST_USER_PROTOCOL_F_GET_VRING_BASE_SKIP_DRAIN);
+
+ if (vhost_user_blk_inflight_needed(s) && !inflight_migration_enabled) {
+ error_setg(errp, "can't migrate vhost-user-blk device: "
+ "backend doesn't support "
+ "VHOST_USER_PROTOCOL_F_GET_VRING_BASE_SKIP_DRAIN "
+ "protocol feature");
+ return false;
+ }
+
+ return true;
+}
+
static const VMStateDescription vmstate_vhost_user_blk_inflight = {
.name = "vhost-user-blk/inflight",
.version_id = 1,
.needed = vhost_user_blk_inflight_needed,
+ .pre_save_errp = vhost_user_blk_pre_save,
.fields = (const VMStateField[]) {
VMSTATE_VHOST_INFLIGHT_REGION(inflight, VHostUserBlk),
VMSTATE_END_OF_LIST()
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 5fb5d61afb..65889b0776 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -2596,8 +2596,7 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque,
}
}
- if (!u->user->supports_inflight_migration ||
- !virtio_has_feature(protocol_features,
+ if (!virtio_has_feature(protocol_features,
VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)) {
protocol_features &= ~(1ULL <<
VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT);
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* [PULL v2 75/75] MAINTAINERS: add Junjie Cao as CXL reviewer
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (73 preceding siblings ...)
2026-09-11 9:04 ` [PULL v2 74/75] vhost-user-blk: use GET_VRING_BASE_SKIP_DRAIN when inflight-migration is on Michael S. Tsirkin
@ 2026-09-11 9:04 ` Michael S. Tsirkin
2026-09-11 13:41 ` [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Albert Esteve
2026-09-11 19:06 ` Richard Henderson
76 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 9:04 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Junjie Cao, Philippe Mathieu-Daudé,
Markus Armbruster, Pierrick Bouvier, Thomas Huth
From: Junjie Cao <junjie.cao@intel.com>
I have been reviewing, testing and contributing to hw/cxl for the past
few months, and would like to be Cc'd on incoming CXL changes to help
with review.
Suggested-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Junjie Cao <junjie.cao@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260908042310.493882-1-junjie.cao@intel.com>
---
MAINTAINERS | 1 +
1 file changed, 1 insertion(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index ec313c3259..d5eac4b42d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3334,6 +3334,7 @@ F: docs/devel/migration/CPR.rst
Compute Express Link
M: Jonathan Cameron <jic23@kernel.org>
+R: Junjie Cao <junjie.cao@intel.com>
L: linux-cxl@vger.kernel.org
S: Supported
F: hw/cxl/
--
MST
^ permalink raw reply related [flat|nested] 82+ messages in thread
* Re: [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (74 preceding siblings ...)
2026-09-11 9:04 ` [PULL v2 75/75] MAINTAINERS: add Junjie Cao as CXL reviewer Michael S. Tsirkin
@ 2026-09-11 13:41 ` Albert Esteve
2026-09-11 19:40 ` Michael S. Tsirkin
2026-09-11 19:06 ` Richard Henderson
76 siblings, 1 reply; 82+ messages in thread
From: Albert Esteve @ 2026-09-11 13:41 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: qemu-devel, Peter Maydell, Dorinda Bassey, Matej Hrica,
Feifan Qian
On Fri, Sep 11, 2026 at 11:04 AM Michael S. Tsirkin <mst@redhat.com> wrote:
>
> The following changes since commit 1df256f5968e9f7c3c4533a1383b071c044a36d6:
>
> Merge tag 'qom-qapi-pr-pr-v1' of https://gitlab.com/marcandre.lureau/qemu into staging (2026-09-08 18:35:31 +0100)
>
> are available in the Git repository at:
>
> https://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git tags/for_upstream
>
> for you to fetch changes up to 2f8991c0b9c400f55897849a538580039b61865a:
>
> MAINTAINERS: add Junjie Cao as CXL reviewer (2026-09-11 04:59:15 -0400)
>
> ----------------------------------------------------------------
> pci, vhost, virtio, iommu, apci: features, fixes
>
> new vhost-user-media device
> virtio-net now supports live-TAP local migration
> cxl now supports CFMW restrictions and per-window options
> intel_iommu now supports concurrent page fault handling with PRI
> pci now batches memory transactions around mapping updates
> vhost-user-blk now allows toggling inflight-migration at runtime
> virtio-rtc now supports smeared UTC clock type
> intel_iommu now exposes SMPWC when SVM is enabled
> new reviewer for CXL patches
>
> Fixes, cleanups all over the place
>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Hi Michael,
I see you dropped these patches from v1 to v2. Just checking if this
was intended or if there is an issue/CI failure that needs addressing?
[...]
Dorinda Bassey (1):
vhost: Fix SHMEM_MAP transaction ordering and resulting deadlock
Feifan Qian (1):
vhost-user: Reject SHMEM_MAP when no KVM memory slot is left
[...]
Matej Hrica (2):
vhost-user-gpu: Add shared memory region support
vhost-user-gpu: Forward RESOURCE_BLOB and CONTEXT_INIT flags
[...]
Thanks!
Albert
>
> ----------------------------------------------------------------
> Albert Esteve (4):
> linux-headers: add VIRTIO_ID_MEDIA
> hw/display: add vhost-user-media device
> hw/display/vhost-user-media: add shared memory region BAR
> linux-headers: Update to Linux v7.3-rc1
>
> Alexandr Moshkov (6):
> vhost-user: add skip_drain param to do_vhost_virtqueue_stop
> vhost-user: add GET_VRING_BASE_SKIP_DRAIN message
> vhost-user: use skip_drain with GET_VRING_BASE_SKIP_DRAIN message
> vhost-user-blk: make inflight-migration prop mutable on running vm
> vhost-user-blk: move inflight_needed higher
> vhost-user-blk: use GET_VRING_BASE_SKIP_DRAIN when inflight-migration is on
>
> Alyssa Ross (1):
> vhost-user.rst: fix typo
>
> Bin Guo (2):
> libvhost-user: accept the postcopy client base ack in vu_add_mem_reg()
> libvhost-user: return the backend mapping address for added regions
>
> Clément MATHIEU--DRIF (4):
> intel_iommu: Support concurrent page fault handling with PRI
> intel_iommu: Only set dirty bit when PTE exposes write permission
> intel_iommu: Always write all the flags passed to vtd_set_flag_in_pte
> intel_iommu: Expose SMPWC when SVM is enabled
>
> Davidlohr Bueso (5):
> tests/bios-tables-test: Exclude CEDT.cxl for the CFMW restriction change
> hw/cxl: Drop Back-Invalidate from default CFMW window restrictions
> tests/acpi/cxl: Update CEDT.cxl for the default CFMW restrictions
> hw/cxl: Add configurable CXL Fixed Memory Window restriction flags
> tests/qtest/cxl: Add CXL Fixed Memory Window restriction flag tests
>
> Denis V. Lunev (2):
> pci: batch BAR remapping into one memory transaction
> pci: load a device's config inside one memory transaction
>
> GuoHan Zhao (1):
> virtio-crypto: clean up every data queue
>
> Hanna Czenczek (6):
> hw/virtio-blk: Account discard operations
> hw/virtio-blk: Complete zone-append cookies
> hw/nvme: Fix block accounting in nvme_copy()
> hw/nvme: Fix block accounting for compare
> hw/ide: Have ide_dma_cb() complete accounting
> hw/scsi-disk: Fix accounting for IGNORE, ret > 0
>
> Jia Jia (2):
> virtio: reduce code duplication for split ring
> hw/virtio: reject inverted virtio-iommu IOVA ranges
>
> Junjie Cao (3):
> hw/cxl: Fix guest-triggerable QEMU exit on reserved interleave ways
> hw/cxl: fix the CDAT DOE overlapping the Flex Bus DVSEC when sn= is set
> MAINTAINERS: add Junjie Cao as CXL reviewer
>
> Kuan-Wei Chiu (1):
> virtio-rtc: Report smeared UTC clock type
>
> Laurent Vivier (2):
> hw/net/virtio-net: check packet size before VLAN tag access in receive_filter()
> hw/net/virtio-net: strip trailing padding when caching RSC segment
>
> Michael S. Tsirkin (7):
> virtio: fix exit(1) on DMA mapping failure during migration restore
> virtio: fix config_len DoS in migration restore path
> virtio-pci: reject Q_ENABLE write on already-enabled queue
> meson: disable "maybe uninitilized" errors with -Og
> virtio-balloon: fix free-page BH teardown on unrealize
> net/tap-solaris: Fix resource leaks on error paths
> virtio-net: validate IHL in virtio_net_rsc_extract_unit4 before use
>
> Philippe Mathieu-Daudé (4):
> hw/acpi: Make AcpiGedState const in build_ged_aml()
> hw/hotplug: Mark various HotplugHandlerClass variables as const
> hw/hotplug: Reduce some HotplugHandler variables scope
> hw/hotplug: Constify HotplugHandler
>
> Sairaj Kodilkar (7):
> amd_iommu: Return empty efr for stub call
> tests/acpi: x86: Allow IVRS acpi table changes
> amd_iommu: acpi-build: update PA, GVA and VA size macros
> acpi_build: Use IOMMU pci device to build IOMMU DeviceID
> acpi_build: Build IVRS feature report using extended feature register
> amd_iommu: acpi-build: Remove unsupported PPR and HE feature
> tests/acpi: x86: update golden masters for IVRS
>
> Stefan Hajnoczi (1):
> virtio-scsi: set dataplane_started to false upon failure
>
> Vladimir Sementsov-Ogievskiy (16):
> net/tap: rework tap_parse_script
> net/tap: improve script/downscript options documentation
> net/tap: deprecate "no" as special value for script/downscript
> net/tap: move vhost-net open() calls to tap_parse_vhost_fds()
> net/tap: move vhost initialization to tap_setup_vhost()
> net/tap: use container_of instead of DO_UPCAST
> net/tap: QOMify tap backend
> net/tap: add TYPE_VMSTATE_IF interface
> qapi: add local migration parameter
> migration/fd: fix fd leak when fd is not valid for migration
> migration/fd: add errp parameter to migration_fd_valid()
> migration: check that transfer is UNIX socket when "local" set
> virtio-net: support local migration of backend
> net/tap: disable read polling for stopped VM
> net/tap: support local migration with virtio-net
> tests/functional: add test_tap_migration
>
> Xiong Weimin (1):
> hw/virtio: Propagate vhost_virtqueue_mask errors
>
> MAINTAINERS | 7 +
> docs/about/deprecated.rst | 18 +
> docs/interop/vhost-user.rst | 44 ++-
> docs/system/devices/cxl.rst | 25 +-
> docs/system/i386/microvm.rst | 4 +-
> docs/system/i386/xenpvh.rst | 2 +-
> docs/system/ppc/ppce500.rst | 4 +-
> docs/system/riscv/microchip-icicle-kit.rst | 2 +-
> docs/system/riscv/sifive_u.rst | 2 +-
> meson.build | 4 +
> qapi/machine.json | 28 ++
> qapi/migration.json | 21 +-
> qapi/net.json | 45 ++-
> hw/i386/amd_iommu.h | 27 +-
> hw/i386/intel_iommu_internal.h | 1 +
> hw/s390x/ccw-device.h | 2 +-
> include/hw/acpi/cpu.h | 4 +-
> include/hw/acpi/cpu_hotplug.h | 2 +-
> include/hw/acpi/generic_event_device.h | 3 +-
> include/hw/acpi/ich9.h | 10 +-
> include/hw/acpi/memory_hotplug.h | 4 +-
> include/hw/acpi/pcihp.h | 8 +-
> include/hw/core/boards.h | 4 +-
> include/hw/core/hotplug.h | 13 +-
> include/hw/core/qdev.h | 14 +-
> include/hw/cxl/cxl.h | 12 +
> include/hw/i386/microvm.h | 4 +-
> include/hw/i386/x86.h | 10 +-
> include/hw/mem/nvdimm.h | 2 +-
> include/hw/pci/pci_bridge.h | 6 +-
> include/hw/pci/pcie.h | 8 +-
> include/hw/pci/shpc.h | 6 +-
> include/hw/ppc/spapr_nvdimm.h | 2 +-
> include/hw/virtio/vhost-backend.h | 1 +
> include/hw/virtio/vhost-user-media.h | 46 +++
> include/hw/virtio/vhost-user.h | 2 +-
> include/hw/virtio/vhost.h | 16 +-
> include/hw/virtio/virtio-balloon.h | 1 +
> include/hw/virtio/virtio-net.h | 1 +
> include/hw/virtio/virtio.h | 2 +-
> include/migration/misc.h | 2 +
> include/migration/vmstate.h | 2 +
> include/net/net.h | 9 +
> include/net/tap.h | 2 +
> include/standard-headers/linux/ethtool.h | 6 +
> include/standard-headers/linux/virtio_ids.h | 1 +
> linux-headers/linux/iommufd.h | 45 ++-
> linux-headers/linux/userfaultfd.h | 54 ++-
> linux-headers/linux/vduse.h | 28 ++
> linux-headers/linux/vfio.h | 21 ++
> linux-headers/linux/vfio_zdev.h | 2 +
> backends/cryptodev-vhost.c | 2 +-
> backends/vhost-user.c | 2 +-
> hw/acpi/acpi-cpu-hotplug-stub.c | 4 +-
> hw/acpi/acpi-mem-hotplug-stub.c | 4 +-
> hw/acpi/acpi-nvdimm-stub.c | 2 +-
> hw/acpi/acpi-pci-hotplug-stub.c | 8 +-
> hw/acpi/cpu.c | 6 +-
> hw/acpi/cxl.c | 2 +-
> hw/acpi/generic_event_device.c | 13 +-
> hw/acpi/ich9.c | 10 +-
> hw/acpi/memory_hotplug.c | 7 +-
> hw/acpi/nvdimm.c | 2 +-
> hw/acpi/pcihp.c | 11 +-
> hw/acpi/piix4.c | 12 +-
> hw/arm/virt.c | 23 +-
> hw/block/vhost-user-blk.c | 60 +++-
> hw/block/virtio-blk.c | 38 ++-
> hw/char/virtio-serial-bus.c | 6 +-
> hw/core/hotplug.c | 16 +-
> hw/core/qdev-hotplug.c | 10 +-
> hw/core/qdev.c | 2 +-
> hw/cxl/cxl-host.c | 48 ++-
> hw/display/vhost-user-media-pci.c | 115 +++++++
> hw/display/vhost-user-media.c | 388 ++++++++++++++++++++++
> hw/i386/acpi-build.c | 65 ++--
> hw/i386/amd_iommu-stub.c | 2 +-
> hw/i386/amd_iommu.c | 2 +-
> hw/i386/intel_iommu.c | 118 ++++---
> hw/i386/intel_iommu_accel.c | 6 +
> hw/i386/microvm.c | 12 +-
> hw/i386/pc.c | 28 +-
> hw/i386/x86-common.c | 8 +-
> hw/ide/core.c | 3 +-
> hw/intc/loongarch_dintc.c | 8 +-
> hw/intc/loongarch_extioi_common.c | 4 +-
> hw/intc/loongarch_ipi.c | 4 +-
> hw/loongarch/virt.c | 44 +--
> hw/mem/cxl_type3.c | 6 +-
> hw/net/vhost_net.c | 9 +-
> hw/net/virtio-net.c | 131 +++++++-
> hw/nvme/ctrl.c | 78 +++--
> hw/pci-bridge/pci_bridge_dev.c | 6 +-
> hw/pci/pci.c | 8 +
> hw/pci/pcie.c | 10 +-
> hw/pci/pcie_port.c | 2 +-
> hw/pci/shpc.c | 11 +-
> hw/ppc/e500plat.c | 4 +-
> hw/ppc/spapr.c | 48 +--
> hw/ppc/spapr_nvdimm.c | 2 +-
> hw/ppc/spapr_pci.c | 12 +-
> hw/remote/machine.c | 2 +-
> hw/riscv/virt.c | 6 +-
> hw/s390x/css-bridge.c | 2 +-
> hw/s390x/s390-pci-bus.c | 12 +-
> hw/s390x/s390-virtio-ccw.c | 16 +-
> hw/s390x/virtio-ccw-md.c | 10 +-
> hw/s390x/virtio-ccw.c | 2 +-
> hw/scsi/scsi-disk.c | 7 +
> hw/scsi/vhost-scsi-common.c | 2 +-
> hw/scsi/virtio-scsi-dataplane.c | 2 +-
> hw/scsi/virtio-scsi.c | 10 +-
> hw/scsi/vmw_pvscsi.c | 4 +-
> hw/virtio/vdpa-dev.c | 2 +-
> hw/virtio/vhost-user-base.c | 2 +-
> hw/virtio/vhost-user-fs.c | 2 +-
> hw/virtio/vhost-user-scmi.c | 2 +-
> hw/virtio/vhost-user.c | 47 ++-
> hw/virtio/vhost-vsock-common.c | 2 +-
> hw/virtio/vhost.c | 44 ++-
> hw/virtio/virtio-balloon.c | 19 +-
> hw/virtio/virtio-crypto.c | 5 +-
> hw/virtio/virtio-iommu.c | 17 +-
> hw/virtio/virtio-md-pci.c | 10 +-
> hw/virtio/virtio-pci.c | 7 +
> hw/virtio/virtio-rtc.c | 3 +-
> hw/virtio/virtio.c | 85 ++---
> hw/xen/xen-bus.c | 2 +-
> migration/fd.c | 28 +-
> migration/migration.c | 13 +
> migration/options.c | 18 +-
> net/net.c | 14 +-
> net/tap-solaris.c | 69 ++--
> net/tap.c | 448 ++++++++++++++++++++-----
> stubs/hotplug-stubs.c | 6 +-
> subprojects/libvhost-user/libvhost-user.c | 34 +-
> system/qdev-monitor.c | 4 +-
> tests/qtest/cxl-test.c | 95 ++++++
> hw/display/Kconfig | 5 +
> hw/display/meson.build | 3 +
> qemu-options.hx | 13 +-
> tests/data/acpi/x86/q35/CEDT.cxl | Bin 184 -> 184 bytes
> tests/data/acpi/x86/q35/IVRS.ivrs | Bin 176 -> 176 bytes
> tests/functional/x86_64/meson.build | 1 +
> tests/functional/x86_64/test_tap_migration.py | 461 ++++++++++++++++++++++++++
> 145 files changed, 2884 insertions(+), 663 deletions(-)
> create mode 100644 include/hw/virtio/vhost-user-media.h
> create mode 100644 hw/display/vhost-user-media-pci.c
> create mode 100644 hw/display/vhost-user-media.c
> create mode 100755 tests/functional/x86_64/test_tap_migration.py
>
>
^ permalink raw reply [flat|nested] 82+ messages in thread
* Re: [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
` (75 preceding siblings ...)
2026-09-11 13:41 ` [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Albert Esteve
@ 2026-09-11 19:06 ` Richard Henderson
2026-09-11 20:00 ` Michael S. Tsirkin
76 siblings, 1 reply; 82+ messages in thread
From: Richard Henderson @ 2026-09-11 19:06 UTC (permalink / raw)
To: Michael S. Tsirkin, qemu-devel; +Cc: Peter Maydell
On 9/10/26 23:01, Michael S. Tsirkin wrote:
> The following changes since commit 1df256f5968e9f7c3c4533a1383b071c044a36d6:
>
> Merge tag 'qom-qapi-pr-pr-v1' ofhttps://gitlab.com/marcandre.lureau/qemu into staging (2026-09-08 18:35:31 +0100)
>
> are available in the Git repository at:
>
> https://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git tags/for_upstream
>
> for you to fetch changes up to 2f8991c0b9c400f55897849a538580039b61865a:
>
> MAINTAINERS: add Junjie Cao as CXL reviewer (2026-09-11 04:59:15 -0400)
>
> ----------------------------------------------------------------
> pci, vhost, virtio, iommu, apci: features, fixes
>
> new vhost-user-media device
> virtio-net now supports live-TAP local migration
> cxl now supports CFMW restrictions and per-window options
> intel_iommu now supports concurrent page fault handling with PRI
> pci now batches memory transactions around mapping updates
> vhost-user-blk now allows toggling inflight-migration at runtime
> virtio-rtc now supports smeared UTC clock type
> intel_iommu now exposes SMPWC when SVM is enabled
> new reviewer for CXL patches
>
> Fixes, cleanups all over the place
https://gitlab.com/qemu-project/qemu/-/pipelines/2840522620
Between the 6 failing jobs, I think there are 2 failures replicated:
https://gitlab.com/qemu-project/qemu/-/jobs/16454091774#L800
18/34 func-quick+func-x86_64 - qemu:func-x86_64-linters
FAIL 6.00s exit status 1
34/34 func-thorough+func-x86_64-thorough+thorough -
qemu:func-x86_64-tap_migration ERROR 0.19s 0 subtests
passed
r~
^ permalink raw reply [flat|nested] 82+ messages in thread
* Re: [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes
2026-09-11 13:41 ` [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Albert Esteve
@ 2026-09-11 19:40 ` Michael S. Tsirkin
0 siblings, 0 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 19:40 UTC (permalink / raw)
To: Albert Esteve
Cc: qemu-devel, Peter Maydell, Dorinda Bassey, Matej Hrica,
Feifan Qian
On Fri, Sep 11, 2026 at 03:41:31PM +0200, Albert Esteve wrote:
> On Fri, Sep 11, 2026 at 11:04 AM Michael S. Tsirkin <mst@redhat.com> wrote:
> >
> > The following changes since commit 1df256f5968e9f7c3c4533a1383b071c044a36d6:
> >
> > Merge tag 'qom-qapi-pr-pr-v1' of https://gitlab.com/marcandre.lureau/qemu into staging (2026-09-08 18:35:31 +0100)
> >
> > are available in the Git repository at:
> >
> > https://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git tags/for_upstream
> >
> > for you to fetch changes up to 2f8991c0b9c400f55897849a538580039b61865a:
> >
> > MAINTAINERS: add Junjie Cao as CXL reviewer (2026-09-11 04:59:15 -0400)
> >
> > ----------------------------------------------------------------
> > pci, vhost, virtio, iommu, apci: features, fixes
> >
> > new vhost-user-media device
> > virtio-net now supports live-TAP local migration
> > cxl now supports CFMW restrictions and per-window options
> > intel_iommu now supports concurrent page fault handling with PRI
> > pci now batches memory transactions around mapping updates
> > vhost-user-blk now allows toggling inflight-migration at runtime
> > virtio-rtc now supports smeared UTC clock type
> > intel_iommu now exposes SMPWC when SVM is enabled
> > new reviewer for CXL patches
> >
> > Fixes, cleanups all over the place
> >
> > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
>
> Hi Michael,
>
> I see you dropped these patches from v1 to v2. Just checking if this
> was intended or if there is an issue/CI failure that needs addressing?
>
> [...]
> Dorinda Bassey (1):
> vhost: Fix SHMEM_MAP transaction ordering and resulting deadlock
>
> Feifan Qian (1):
> vhost-user: Reject SHMEM_MAP when no KVM memory slot is left
>
> [...]
> Matej Hrica (2):
> vhost-user-gpu: Add shared memory region support
> vhost-user-gpu: Forward RESOURCE_BLOB and CONTEXT_INIT flags
> [...]
>
> Thanks!
> Albert
No issue, I just don't normally merge gpu things. This one
was needed originally to resolve some other issue so I picked it up
but I guess the issue's gone because it now passed without.
So I'm happy to have it go through the usual channels.
> >
> > ----------------------------------------------------------------
> > Albert Esteve (4):
> > linux-headers: add VIRTIO_ID_MEDIA
> > hw/display: add vhost-user-media device
> > hw/display/vhost-user-media: add shared memory region BAR
> > linux-headers: Update to Linux v7.3-rc1
> >
> > Alexandr Moshkov (6):
> > vhost-user: add skip_drain param to do_vhost_virtqueue_stop
> > vhost-user: add GET_VRING_BASE_SKIP_DRAIN message
> > vhost-user: use skip_drain with GET_VRING_BASE_SKIP_DRAIN message
> > vhost-user-blk: make inflight-migration prop mutable on running vm
> > vhost-user-blk: move inflight_needed higher
> > vhost-user-blk: use GET_VRING_BASE_SKIP_DRAIN when inflight-migration is on
> >
> > Alyssa Ross (1):
> > vhost-user.rst: fix typo
> >
> > Bin Guo (2):
> > libvhost-user: accept the postcopy client base ack in vu_add_mem_reg()
> > libvhost-user: return the backend mapping address for added regions
> >
> > Clément MATHIEU--DRIF (4):
> > intel_iommu: Support concurrent page fault handling with PRI
> > intel_iommu: Only set dirty bit when PTE exposes write permission
> > intel_iommu: Always write all the flags passed to vtd_set_flag_in_pte
> > intel_iommu: Expose SMPWC when SVM is enabled
> >
> > Davidlohr Bueso (5):
> > tests/bios-tables-test: Exclude CEDT.cxl for the CFMW restriction change
> > hw/cxl: Drop Back-Invalidate from default CFMW window restrictions
> > tests/acpi/cxl: Update CEDT.cxl for the default CFMW restrictions
> > hw/cxl: Add configurable CXL Fixed Memory Window restriction flags
> > tests/qtest/cxl: Add CXL Fixed Memory Window restriction flag tests
> >
> > Denis V. Lunev (2):
> > pci: batch BAR remapping into one memory transaction
> > pci: load a device's config inside one memory transaction
> >
> > GuoHan Zhao (1):
> > virtio-crypto: clean up every data queue
> >
> > Hanna Czenczek (6):
> > hw/virtio-blk: Account discard operations
> > hw/virtio-blk: Complete zone-append cookies
> > hw/nvme: Fix block accounting in nvme_copy()
> > hw/nvme: Fix block accounting for compare
> > hw/ide: Have ide_dma_cb() complete accounting
> > hw/scsi-disk: Fix accounting for IGNORE, ret > 0
> >
> > Jia Jia (2):
> > virtio: reduce code duplication for split ring
> > hw/virtio: reject inverted virtio-iommu IOVA ranges
> >
> > Junjie Cao (3):
> > hw/cxl: Fix guest-triggerable QEMU exit on reserved interleave ways
> > hw/cxl: fix the CDAT DOE overlapping the Flex Bus DVSEC when sn= is set
> > MAINTAINERS: add Junjie Cao as CXL reviewer
> >
> > Kuan-Wei Chiu (1):
> > virtio-rtc: Report smeared UTC clock type
> >
> > Laurent Vivier (2):
> > hw/net/virtio-net: check packet size before VLAN tag access in receive_filter()
> > hw/net/virtio-net: strip trailing padding when caching RSC segment
> >
> > Michael S. Tsirkin (7):
> > virtio: fix exit(1) on DMA mapping failure during migration restore
> > virtio: fix config_len DoS in migration restore path
> > virtio-pci: reject Q_ENABLE write on already-enabled queue
> > meson: disable "maybe uninitilized" errors with -Og
> > virtio-balloon: fix free-page BH teardown on unrealize
> > net/tap-solaris: Fix resource leaks on error paths
> > virtio-net: validate IHL in virtio_net_rsc_extract_unit4 before use
> >
> > Philippe Mathieu-Daudé (4):
> > hw/acpi: Make AcpiGedState const in build_ged_aml()
> > hw/hotplug: Mark various HotplugHandlerClass variables as const
> > hw/hotplug: Reduce some HotplugHandler variables scope
> > hw/hotplug: Constify HotplugHandler
> >
> > Sairaj Kodilkar (7):
> > amd_iommu: Return empty efr for stub call
> > tests/acpi: x86: Allow IVRS acpi table changes
> > amd_iommu: acpi-build: update PA, GVA and VA size macros
> > acpi_build: Use IOMMU pci device to build IOMMU DeviceID
> > acpi_build: Build IVRS feature report using extended feature register
> > amd_iommu: acpi-build: Remove unsupported PPR and HE feature
> > tests/acpi: x86: update golden masters for IVRS
> >
> > Stefan Hajnoczi (1):
> > virtio-scsi: set dataplane_started to false upon failure
> >
> > Vladimir Sementsov-Ogievskiy (16):
> > net/tap: rework tap_parse_script
> > net/tap: improve script/downscript options documentation
> > net/tap: deprecate "no" as special value for script/downscript
> > net/tap: move vhost-net open() calls to tap_parse_vhost_fds()
> > net/tap: move vhost initialization to tap_setup_vhost()
> > net/tap: use container_of instead of DO_UPCAST
> > net/tap: QOMify tap backend
> > net/tap: add TYPE_VMSTATE_IF interface
> > qapi: add local migration parameter
> > migration/fd: fix fd leak when fd is not valid for migration
> > migration/fd: add errp parameter to migration_fd_valid()
> > migration: check that transfer is UNIX socket when "local" set
> > virtio-net: support local migration of backend
> > net/tap: disable read polling for stopped VM
> > net/tap: support local migration with virtio-net
> > tests/functional: add test_tap_migration
> >
> > Xiong Weimin (1):
> > hw/virtio: Propagate vhost_virtqueue_mask errors
> >
> > MAINTAINERS | 7 +
> > docs/about/deprecated.rst | 18 +
> > docs/interop/vhost-user.rst | 44 ++-
> > docs/system/devices/cxl.rst | 25 +-
> > docs/system/i386/microvm.rst | 4 +-
> > docs/system/i386/xenpvh.rst | 2 +-
> > docs/system/ppc/ppce500.rst | 4 +-
> > docs/system/riscv/microchip-icicle-kit.rst | 2 +-
> > docs/system/riscv/sifive_u.rst | 2 +-
> > meson.build | 4 +
> > qapi/machine.json | 28 ++
> > qapi/migration.json | 21 +-
> > qapi/net.json | 45 ++-
> > hw/i386/amd_iommu.h | 27 +-
> > hw/i386/intel_iommu_internal.h | 1 +
> > hw/s390x/ccw-device.h | 2 +-
> > include/hw/acpi/cpu.h | 4 +-
> > include/hw/acpi/cpu_hotplug.h | 2 +-
> > include/hw/acpi/generic_event_device.h | 3 +-
> > include/hw/acpi/ich9.h | 10 +-
> > include/hw/acpi/memory_hotplug.h | 4 +-
> > include/hw/acpi/pcihp.h | 8 +-
> > include/hw/core/boards.h | 4 +-
> > include/hw/core/hotplug.h | 13 +-
> > include/hw/core/qdev.h | 14 +-
> > include/hw/cxl/cxl.h | 12 +
> > include/hw/i386/microvm.h | 4 +-
> > include/hw/i386/x86.h | 10 +-
> > include/hw/mem/nvdimm.h | 2 +-
> > include/hw/pci/pci_bridge.h | 6 +-
> > include/hw/pci/pcie.h | 8 +-
> > include/hw/pci/shpc.h | 6 +-
> > include/hw/ppc/spapr_nvdimm.h | 2 +-
> > include/hw/virtio/vhost-backend.h | 1 +
> > include/hw/virtio/vhost-user-media.h | 46 +++
> > include/hw/virtio/vhost-user.h | 2 +-
> > include/hw/virtio/vhost.h | 16 +-
> > include/hw/virtio/virtio-balloon.h | 1 +
> > include/hw/virtio/virtio-net.h | 1 +
> > include/hw/virtio/virtio.h | 2 +-
> > include/migration/misc.h | 2 +
> > include/migration/vmstate.h | 2 +
> > include/net/net.h | 9 +
> > include/net/tap.h | 2 +
> > include/standard-headers/linux/ethtool.h | 6 +
> > include/standard-headers/linux/virtio_ids.h | 1 +
> > linux-headers/linux/iommufd.h | 45 ++-
> > linux-headers/linux/userfaultfd.h | 54 ++-
> > linux-headers/linux/vduse.h | 28 ++
> > linux-headers/linux/vfio.h | 21 ++
> > linux-headers/linux/vfio_zdev.h | 2 +
> > backends/cryptodev-vhost.c | 2 +-
> > backends/vhost-user.c | 2 +-
> > hw/acpi/acpi-cpu-hotplug-stub.c | 4 +-
> > hw/acpi/acpi-mem-hotplug-stub.c | 4 +-
> > hw/acpi/acpi-nvdimm-stub.c | 2 +-
> > hw/acpi/acpi-pci-hotplug-stub.c | 8 +-
> > hw/acpi/cpu.c | 6 +-
> > hw/acpi/cxl.c | 2 +-
> > hw/acpi/generic_event_device.c | 13 +-
> > hw/acpi/ich9.c | 10 +-
> > hw/acpi/memory_hotplug.c | 7 +-
> > hw/acpi/nvdimm.c | 2 +-
> > hw/acpi/pcihp.c | 11 +-
> > hw/acpi/piix4.c | 12 +-
> > hw/arm/virt.c | 23 +-
> > hw/block/vhost-user-blk.c | 60 +++-
> > hw/block/virtio-blk.c | 38 ++-
> > hw/char/virtio-serial-bus.c | 6 +-
> > hw/core/hotplug.c | 16 +-
> > hw/core/qdev-hotplug.c | 10 +-
> > hw/core/qdev.c | 2 +-
> > hw/cxl/cxl-host.c | 48 ++-
> > hw/display/vhost-user-media-pci.c | 115 +++++++
> > hw/display/vhost-user-media.c | 388 ++++++++++++++++++++++
> > hw/i386/acpi-build.c | 65 ++--
> > hw/i386/amd_iommu-stub.c | 2 +-
> > hw/i386/amd_iommu.c | 2 +-
> > hw/i386/intel_iommu.c | 118 ++++---
> > hw/i386/intel_iommu_accel.c | 6 +
> > hw/i386/microvm.c | 12 +-
> > hw/i386/pc.c | 28 +-
> > hw/i386/x86-common.c | 8 +-
> > hw/ide/core.c | 3 +-
> > hw/intc/loongarch_dintc.c | 8 +-
> > hw/intc/loongarch_extioi_common.c | 4 +-
> > hw/intc/loongarch_ipi.c | 4 +-
> > hw/loongarch/virt.c | 44 +--
> > hw/mem/cxl_type3.c | 6 +-
> > hw/net/vhost_net.c | 9 +-
> > hw/net/virtio-net.c | 131 +++++++-
> > hw/nvme/ctrl.c | 78 +++--
> > hw/pci-bridge/pci_bridge_dev.c | 6 +-
> > hw/pci/pci.c | 8 +
> > hw/pci/pcie.c | 10 +-
> > hw/pci/pcie_port.c | 2 +-
> > hw/pci/shpc.c | 11 +-
> > hw/ppc/e500plat.c | 4 +-
> > hw/ppc/spapr.c | 48 +--
> > hw/ppc/spapr_nvdimm.c | 2 +-
> > hw/ppc/spapr_pci.c | 12 +-
> > hw/remote/machine.c | 2 +-
> > hw/riscv/virt.c | 6 +-
> > hw/s390x/css-bridge.c | 2 +-
> > hw/s390x/s390-pci-bus.c | 12 +-
> > hw/s390x/s390-virtio-ccw.c | 16 +-
> > hw/s390x/virtio-ccw-md.c | 10 +-
> > hw/s390x/virtio-ccw.c | 2 +-
> > hw/scsi/scsi-disk.c | 7 +
> > hw/scsi/vhost-scsi-common.c | 2 +-
> > hw/scsi/virtio-scsi-dataplane.c | 2 +-
> > hw/scsi/virtio-scsi.c | 10 +-
> > hw/scsi/vmw_pvscsi.c | 4 +-
> > hw/virtio/vdpa-dev.c | 2 +-
> > hw/virtio/vhost-user-base.c | 2 +-
> > hw/virtio/vhost-user-fs.c | 2 +-
> > hw/virtio/vhost-user-scmi.c | 2 +-
> > hw/virtio/vhost-user.c | 47 ++-
> > hw/virtio/vhost-vsock-common.c | 2 +-
> > hw/virtio/vhost.c | 44 ++-
> > hw/virtio/virtio-balloon.c | 19 +-
> > hw/virtio/virtio-crypto.c | 5 +-
> > hw/virtio/virtio-iommu.c | 17 +-
> > hw/virtio/virtio-md-pci.c | 10 +-
> > hw/virtio/virtio-pci.c | 7 +
> > hw/virtio/virtio-rtc.c | 3 +-
> > hw/virtio/virtio.c | 85 ++---
> > hw/xen/xen-bus.c | 2 +-
> > migration/fd.c | 28 +-
> > migration/migration.c | 13 +
> > migration/options.c | 18 +-
> > net/net.c | 14 +-
> > net/tap-solaris.c | 69 ++--
> > net/tap.c | 448 ++++++++++++++++++++-----
> > stubs/hotplug-stubs.c | 6 +-
> > subprojects/libvhost-user/libvhost-user.c | 34 +-
> > system/qdev-monitor.c | 4 +-
> > tests/qtest/cxl-test.c | 95 ++++++
> > hw/display/Kconfig | 5 +
> > hw/display/meson.build | 3 +
> > qemu-options.hx | 13 +-
> > tests/data/acpi/x86/q35/CEDT.cxl | Bin 184 -> 184 bytes
> > tests/data/acpi/x86/q35/IVRS.ivrs | Bin 176 -> 176 bytes
> > tests/functional/x86_64/meson.build | 1 +
> > tests/functional/x86_64/test_tap_migration.py | 461 ++++++++++++++++++++++++++
> > 145 files changed, 2884 insertions(+), 663 deletions(-)
> > create mode 100644 include/hw/virtio/vhost-user-media.h
> > create mode 100644 hw/display/vhost-user-media-pci.c
> > create mode 100644 hw/display/vhost-user-media.c
> > create mode 100755 tests/functional/x86_64/test_tap_migration.py
> >
> >
^ permalink raw reply [flat|nested] 82+ messages in thread
* Re: [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes
2026-09-11 19:06 ` Richard Henderson
@ 2026-09-11 20:00 ` Michael S. Tsirkin
2026-09-11 23:43 ` Richard Henderson
2026-09-12 9:54 ` Vladimir Sementsov-Ogievskiy
0 siblings, 2 replies; 82+ messages in thread
From: Michael S. Tsirkin @ 2026-09-11 20:00 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel, Peter Maydell, Vladimir Sementsov-Ogievskiy
On Fri, Sep 11, 2026 at 09:06:26AM -1000, Richard Henderson wrote:
> On 9/10/26 23:01, Michael S. Tsirkin wrote:
> > The following changes since commit 1df256f5968e9f7c3c4533a1383b071c044a36d6:
> >
> > Merge tag 'qom-qapi-pr-pr-v1' ofhttps://gitlab.com/marcandre.lureau/qemu into staging (2026-09-08 18:35:31 +0100)
> >
> > are available in the Git repository at:
> >
> > https://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git tags/for_upstream
> >
> > for you to fetch changes up to 2f8991c0b9c400f55897849a538580039b61865a:
> >
> > MAINTAINERS: add Junjie Cao as CXL reviewer (2026-09-11 04:59:15 -0400)
> >
> > ----------------------------------------------------------------
> > pci, vhost, virtio, iommu, apci: features, fixes
> >
> > new vhost-user-media device
> > virtio-net now supports live-TAP local migration
> > cxl now supports CFMW restrictions and per-window options
> > intel_iommu now supports concurrent page fault handling with PRI
> > pci now batches memory transactions around mapping updates
> > vhost-user-blk now allows toggling inflight-migration at runtime
> > virtio-rtc now supports smeared UTC clock type
> > intel_iommu now exposes SMPWC when SVM is enabled
> > new reviewer for CXL patches
> >
> > Fixes, cleanups all over the place
>
> https://gitlab.com/qemu-project/qemu/-/pipelines/2840522620
>
> Between the 6 failing jobs, I think there are 2 failures replicated:
>
> https://gitlab.com/qemu-project/qemu/-/jobs/16454091774#L800
>
> 18/34 func-quick+func-x86_64 - qemu:func-x86_64-linters FAIL
> 6.00s exit status 1
> 34/34 func-thorough+func-x86_64-thorough+thorough -
> qemu:func-x86_64-tap_migration ERROR 0.19s 0 subtests
> passed
>
>
> r~
That's the new test. I dropped that.
The func-rx-vnc is due to the test using a fixed port which is
always a bad idea, making the test flaky.
Pushed to same tag, could you try again pls?
Vladimir FYI tests/functional: add test_tap_migration is dropped
due to linter issues and missing iproute2 dependency.
--
MST
^ permalink raw reply [flat|nested] 82+ messages in thread
* Re: [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes
2026-09-11 20:00 ` Michael S. Tsirkin
@ 2026-09-11 23:43 ` Richard Henderson
2026-09-12 9:54 ` Vladimir Sementsov-Ogievskiy
1 sibling, 0 replies; 82+ messages in thread
From: Richard Henderson @ 2026-09-11 23:43 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: qemu-devel, Peter Maydell, Vladimir Sementsov-Ogievskiy
On 9/11/26 10:00, Michael S. Tsirkin wrote:
> On Fri, Sep 11, 2026 at 09:06:26AM -1000, Richard Henderson wrote:
>> On 9/10/26 23:01, Michael S. Tsirkin wrote:
>>> The following changes since commit 1df256f5968e9f7c3c4533a1383b071c044a36d6:
>>>
>>> Merge tag 'qom-qapi-pr-pr-v1' ofhttps://gitlab.com/marcandre.lureau/qemu into staging (2026-09-08 18:35:31 +0100)
>>>
>>> are available in the Git repository at:
>>>
>>> https://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git tags/for_upstream
>>>
>>> for you to fetch changes up to 2f8991c0b9c400f55897849a538580039b61865a:
>>>
>>> MAINTAINERS: add Junjie Cao as CXL reviewer (2026-09-11 04:59:15 -0400)
...
> That's the new test. I dropped that.
>
>
> The func-rx-vnc is due to the test using a fixed port which is
> always a bad idea, making the test flaky.
>
> Pushed to same tag, could you try again pls?
Applied, thanks.
r~
^ permalink raw reply [flat|nested] 82+ messages in thread
* Re: [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes
2026-09-11 20:00 ` Michael S. Tsirkin
2026-09-11 23:43 ` Richard Henderson
@ 2026-09-12 9:54 ` Vladimir Sementsov-Ogievskiy
1 sibling, 0 replies; 82+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2026-09-12 9:54 UTC (permalink / raw)
To: Michael S. Tsirkin, Richard Henderson; +Cc: qemu-devel, Peter Maydell
On 11.09.26 23:00, Michael S. Tsirkin wrote:
> On Fri, Sep 11, 2026 at 09:06:26AM -1000, Richard Henderson wrote:
>> On 9/10/26 23:01, Michael S. Tsirkin wrote:
>>> The following changes since commit 1df256f5968e9f7c3c4533a1383b071c044a36d6:
>>>
>>> Merge tag 'qom-qapi-pr-pr-v1' ofhttps://gitlab.com/marcandre.lureau/qemu into staging (2026-09-08 18:35:31 +0100)
>>>
>>> are available in the Git repository at:
>>>
>>> https://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git tags/for_upstream
>>>
>>> for you to fetch changes up to 2f8991c0b9c400f55897849a538580039b61865a:
>>>
>>> MAINTAINERS: add Junjie Cao as CXL reviewer (2026-09-11 04:59:15 -0400)
>>>
>>> ----------------------------------------------------------------
>>> pci, vhost, virtio, iommu, apci: features, fixes
>>>
>>> new vhost-user-media device
>>> virtio-net now supports live-TAP local migration
>>> cxl now supports CFMW restrictions and per-window options
>>> intel_iommu now supports concurrent page fault handling with PRI
>>> pci now batches memory transactions around mapping updates
>>> vhost-user-blk now allows toggling inflight-migration at runtime
>>> virtio-rtc now supports smeared UTC clock type
>>> intel_iommu now exposes SMPWC when SVM is enabled
>>> new reviewer for CXL patches
>>>
>>> Fixes, cleanups all over the place
>>
>> https://gitlab.com/qemu-project/qemu/-/pipelines/2840522620
>>
>> Between the 6 failing jobs, I think there are 2 failures replicated:
>>
>> https://gitlab.com/qemu-project/qemu/-/jobs/16454091774#L800
>>
>> 18/34 func-quick+func-x86_64 - qemu:func-x86_64-linters FAIL
>> 6.00s exit status 1
>> 34/34 func-thorough+func-x86_64-thorough+thorough -
>> qemu:func-x86_64-tap_migration ERROR 0.19s 0 subtests
>> passed
>>
>>
>> r~
>
> That's the new test. I dropped that.
>
>
> The func-rx-vnc is due to the test using a fixed port which is
> always a bad idea, making the test flaky.
>
> Pushed to same tag, could you try again pls?
>
> Vladimir FYI tests/functional: add test_tap_migration is dropped
> due to linter issues and missing iproute2 dependency.
>
OK, no problem, I'll resend it
--
Best regards,
Vladimir
^ permalink raw reply [flat|nested] 82+ messages in thread
end of thread, other threads:[~2026-09-12 9:55 UTC | newest]
Thread overview: 82+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-11 9:01 [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 01/75] virtio: fix exit(1) on DMA mapping failure during migration restore Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 02/75] virtio: fix config_len DoS in migration restore path Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 03/75] virtio-pci: reject Q_ENABLE write on already-enabled queue Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 04/75] hw/cxl: Fix guest-triggerable QEMU exit on reserved interleave ways Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 05/75] linux-headers: add VIRTIO_ID_MEDIA Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 06/75] hw/display: add vhost-user-media device Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 07/75] hw/display/vhost-user-media: add shared memory region BAR Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 08/75] virtio: reduce code duplication for split ring Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 09/75] net/tap: rework tap_parse_script Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 10/75] net/tap: improve script/downscript options documentation Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 11/75] net/tap: deprecate "no" as special value for script/downscript Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 12/75] net/tap: move vhost-net open() calls to tap_parse_vhost_fds() Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 13/75] net/tap: move vhost initialization to tap_setup_vhost() Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 14/75] net/tap: use container_of instead of DO_UPCAST Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 15/75] net/tap: QOMify tap backend Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 16/75] net/tap: add TYPE_VMSTATE_IF interface Michael S. Tsirkin
2026-09-11 9:01 ` [PULL v2 17/75] qapi: add local migration parameter Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 18/75] migration/fd: fix fd leak when fd is not valid for migration Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 19/75] migration/fd: add errp parameter to migration_fd_valid() Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 20/75] migration: check that transfer is UNIX socket when "local" set Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 21/75] virtio-net: support local migration of backend Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 22/75] net/tap: disable read polling for stopped VM Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 23/75] net/tap: support local migration with virtio-net Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 24/75] tests/functional: add test_tap_migration Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 25/75] tests/bios-tables-test: Exclude CEDT.cxl for the CFMW restriction change Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 26/75] hw/cxl: Drop Back-Invalidate from default CFMW window restrictions Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 27/75] tests/acpi/cxl: Update CEDT.cxl for the default CFMW restrictions Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 28/75] hw/cxl: Add configurable CXL Fixed Memory Window restriction flags Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 29/75] tests/qtest/cxl: Add CXL Fixed Memory Window restriction flag tests Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 30/75] hw/net/virtio-net: check packet size before VLAN tag access in receive_filter() Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 31/75] hw/virtio-blk: Account discard operations Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 32/75] hw/virtio-blk: Complete zone-append cookies Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 33/75] hw/nvme: Fix block accounting in nvme_copy() Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 34/75] hw/nvme: Fix block accounting for compare Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 35/75] hw/ide: Have ide_dma_cb() complete accounting Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 36/75] hw/scsi-disk: Fix accounting for IGNORE, ret > 0 Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 37/75] meson: disable "maybe uninitilized" errors with -Og Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 38/75] hw/net/virtio-net: strip trailing padding when caching RSC segment Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 39/75] virtio-crypto: clean up every data queue Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 40/75] hw/virtio: reject inverted virtio-iommu IOVA ranges Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 41/75] virtio-balloon: fix free-page BH teardown on unrealize Michael S. Tsirkin
2026-09-11 9:02 ` [PULL v2 42/75] vhost-user.rst: fix typo Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 43/75] hw/virtio: Propagate vhost_virtqueue_mask errors Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 44/75] amd_iommu: Return empty efr for stub call Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 45/75] tests/acpi: x86: Allow IVRS acpi table changes Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 46/75] amd_iommu: acpi-build: update PA, GVA and VA size macros Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 47/75] acpi_build: Use IOMMU pci device to build IOMMU DeviceID Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 48/75] acpi_build: Build IVRS feature report using extended feature register Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 49/75] amd_iommu: acpi-build: Remove unsupported PPR and HE feature Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 50/75] tests/acpi: x86: update golden masters for IVRS Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 51/75] libvhost-user: accept the postcopy client base ack in vu_add_mem_reg() Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 52/75] libvhost-user: return the backend mapping address for added regions Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 53/75] linux-headers: Update to Linux v7.3-rc1 Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 54/75] virtio-scsi: set dataplane_started to false upon failure Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 55/75] hw/cxl: fix the CDAT DOE overlapping the Flex Bus DVSEC when sn= is set Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 56/75] virtio-rtc: Report smeared UTC clock type Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 57/75] intel_iommu: Support concurrent page fault handling with PRI Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 58/75] intel_iommu: Only set dirty bit when PTE exposes write permission Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 59/75] intel_iommu: Always write all the flags passed to vtd_set_flag_in_pte Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 60/75] pci: batch BAR remapping into one memory transaction Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 61/75] pci: load a device's config inside " Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 62/75] hw/acpi: Make AcpiGedState const in build_ged_aml() Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 63/75] hw/hotplug: Mark various HotplugHandlerClass variables as const Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 64/75] hw/hotplug: Reduce some HotplugHandler variables scope Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 65/75] hw/hotplug: Constify HotplugHandler Michael S. Tsirkin
2026-09-11 9:03 ` [PULL v2 66/75] net/tap-solaris: Fix resource leaks on error paths Michael S. Tsirkin
2026-09-11 9:04 ` [PULL v2 67/75] virtio-net: validate IHL in virtio_net_rsc_extract_unit4 before use Michael S. Tsirkin
2026-09-11 9:04 ` [PULL v2 68/75] intel_iommu: Expose SMPWC when SVM is enabled Michael S. Tsirkin
2026-09-11 9:04 ` [PULL v2 69/75] vhost-user: add skip_drain param to do_vhost_virtqueue_stop Michael S. Tsirkin
2026-09-11 9:04 ` [PULL v2 70/75] vhost-user: add GET_VRING_BASE_SKIP_DRAIN message Michael S. Tsirkin
2026-09-11 9:04 ` [PULL v2 71/75] vhost-user: use skip_drain with " Michael S. Tsirkin
2026-09-11 9:04 ` [PULL v2 72/75] vhost-user-blk: make inflight-migration prop mutable on running vm Michael S. Tsirkin
2026-09-11 9:04 ` [PULL v2 73/75] vhost-user-blk: move inflight_needed higher Michael S. Tsirkin
2026-09-11 9:04 ` [PULL v2 74/75] vhost-user-blk: use GET_VRING_BASE_SKIP_DRAIN when inflight-migration is on Michael S. Tsirkin
2026-09-11 9:04 ` [PULL v2 75/75] MAINTAINERS: add Junjie Cao as CXL reviewer Michael S. Tsirkin
2026-09-11 13:41 ` [PULL v2 00/75] pci, vhost, virtio, iommu, apci: features, fixes Albert Esteve
2026-09-11 19:40 ` Michael S. Tsirkin
2026-09-11 19:06 ` Richard Henderson
2026-09-11 20:00 ` Michael S. Tsirkin
2026-09-11 23:43 ` Richard Henderson
2026-09-12 9:54 ` Vladimir Sementsov-Ogievskiy
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.