All of lore.kernel.org
 help / color / mirror / Atom feed
* [PULL 001/106] amd_iommu: restrict command buffer head/tail ranges to ring size
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
@ 2026-06-14 19:05 ` Michael S. Tsirkin
  2026-06-14 19:05 ` [PULL 002/106] amd_iommu: Update command buffer head ptr in MMIO region after wraparound Michael S. Tsirkin
                   ` (105 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:05 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Paolo Bonzini, Yunhe Wang, qemu-stable,
	Alejandro Jimenez, Sairaj Kodilkar, Richard Henderson

From: Paolo Bonzini <pbonzini@redhat.com>

The AMD IOMMU command buffer is a ring buffer of cmdbuf_len (a power
of two) entries.  Each entry is 16 bytes and the head pointer cycles
through the set:

  [0, 16, 32, ..., (cmdbuf_len - 1) * AMDVI_COMMAND_SIZE]

The tail pointer is written by the guest through the COMMAND_TAIL MMIO
register (offset 0x2008); the while loop in amdvi_cmdbuf_run() only
terminates when head == tail.  If tail is set to a value higher than
cmdbuf_len * 16, head will cycle through all the elements of the ring
buffer indefinitely, without ever matching tail.  Fix this by further
masking tail (and head, for consistency) against the size of the
ring buffer.

Reported-by: Yunhe Wang <yunhewwww@163.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Alejandro Jimenez <alejandro.j.jimenez@oracle.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260511113923.2478812-1-pbonzini@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/i386/amd_iommu.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
index 789e09d6f2..197e452e3c 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -1578,7 +1578,8 @@ static inline void amdvi_handle_devtab_write(AMDVIState *s)
 static inline void amdvi_handle_cmdhead_write(AMDVIState *s)
 {
     s->cmdbuf_head = amdvi_readq(s, AMDVI_MMIO_COMMAND_HEAD)
-                     & AMDVI_MMIO_CMDBUF_HEAD_MASK;
+                     & AMDVI_MMIO_CMDBUF_HEAD_MASK
+                     & (s->cmdbuf_len * AMDVI_COMMAND_SIZE - 1);
     amdvi_cmdbuf_run(s);
 }
 
@@ -1594,7 +1595,8 @@ static inline void amdvi_handle_cmdbase_write(AMDVIState *s)
 static inline void amdvi_handle_cmdtail_write(AMDVIState *s)
 {
     s->cmdbuf_tail = amdvi_readq(s, AMDVI_MMIO_COMMAND_TAIL)
-                     & AMDVI_MMIO_CMDBUF_TAIL_MASK;
+                     & AMDVI_MMIO_CMDBUF_TAIL_MASK
+                     & (s->cmdbuf_len * AMDVI_COMMAND_SIZE - 1);
     amdvi_cmdbuf_run(s);
 }
 
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 002/106] amd_iommu: Update command buffer head ptr in MMIO region after wraparound
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
  2026-06-14 19:05 ` [PULL 001/106] amd_iommu: restrict command buffer head/tail ranges to ring size Michael S. Tsirkin
@ 2026-06-14 19:05 ` Michael S. Tsirkin
  2026-06-14 19:05 ` [PULL 003/106] tests/qtest: Add amd-iommu command buffer head wrap test Michael S. Tsirkin
                   ` (104 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:05 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Alejandro Jimenez, qemu-stable, Sairaj Kodilkar,
	Paolo Bonzini, Richard Henderson

From: Alejandro Jimenez <alejandro.j.jimenez@oracle.com>

When processing a command, amdvi_cmdbuf_run() increments cmdbuf_head and
writes it to the emulated MMIO register space before checking whether it
has reached the end of the command buffer.

If the incremented value reaches the end of the buffer and the tail pointer
is zero, the loop exits and the COMMAND_HEAD offset still contains an
unwrapped value. There are no errors in command processing since internal
cmdbuf_head state is always correctly updated, but the spec defines the
CmdHeadPtr field in MMIO Offset 2000h Command Buffer Head Pointer Register
as RW i.e. guest-visible, so it should be kept consistent.

Wrap cmdbuf_head before updating COMMAND_HEAD so the MMIO-visible register
always matches the internal command buffer head pointer position.

Cc: qemu-stable@nongnu.org
Signed-off-by: Alejandro Jimenez <alejandro.j.jimenez@oracle.com>
Reviewed-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: <20260512150044.334867-1-alejandro.j.jimenez@oracle.com>
---
 hw/i386/amd_iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
index 197e452e3c..5d6a405263 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -1475,12 +1475,12 @@ static void amdvi_cmdbuf_run(AMDVIState *s)
         trace_amdvi_command_exec(s->cmdbuf_head, s->cmdbuf_tail, s->cmdbuf);
         amdvi_cmdbuf_exec(s);
         s->cmdbuf_head += AMDVI_COMMAND_SIZE;
-        amdvi_writeq_raw(s, AMDVI_MMIO_COMMAND_HEAD, s->cmdbuf_head);
 
         /* wrap head pointer */
         if (s->cmdbuf_head >= s->cmdbuf_len * AMDVI_COMMAND_SIZE) {
             s->cmdbuf_head = 0;
         }
+        amdvi_writeq_raw(s, AMDVI_MMIO_COMMAND_HEAD, s->cmdbuf_head);
     }
 }
 
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 003/106] tests/qtest: Add amd-iommu command buffer head wrap test
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
  2026-06-14 19:05 ` [PULL 001/106] amd_iommu: restrict command buffer head/tail ranges to ring size Michael S. Tsirkin
  2026-06-14 19:05 ` [PULL 002/106] amd_iommu: Update command buffer head ptr in MMIO region after wraparound Michael S. Tsirkin
@ 2026-06-14 19:05 ` Michael S. Tsirkin
  2026-06-14 19:05 ` [PULL 004/106] intel_iommu: Remove 'x-' prefix from 'x-scalable-mode' and 'x-flts' properties Michael S. Tsirkin
                   ` (103 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:05 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Costas Argyris, Alejandro Jimenez, Sairaj Kodilkar,
	Fabiano Rosas, Laurent Vivier, Paolo Bonzini

From: Costas Argyris <costas.argyris@amd.com>

Add a qtest for AMD IOMMU command buffer head pointer wraparound.
The test programs a command buffer, fills it with COMPLETION_WAIT commands,
advances the tail to consume all but the final entry, then wraps the tail
to zero to force the final command to advance CmdHeadPtr past the end of
the buffer. The guest-visible CmdHeadPtr register must then wrap back to zero.

This covers the case fixed by an earlier CmdHeadPtr wraparound patch.

The Linux kernel AMD IOMMU driver is not affected by this bug because it
uses COMPLETION_WAIT with a memory store doorbell to detect command progress.

Signed-off-by: Costas Argyris <costas.argyris@amd.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260530183458.7778-1-costas.argyris@amd.com>
---
 MAINTAINERS                  |  1 +
 tests/qtest/amd-iommu-test.c | 76 ++++++++++++++++++++++++++++++++++++
 tests/qtest/meson.build      |  1 +
 3 files changed, 78 insertions(+)
 create mode 100644 tests/qtest/amd-iommu-test.c

diff --git a/MAINTAINERS b/MAINTAINERS
index a90daf0308..3b768fc080 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4053,6 +4053,7 @@ M: Alejandro Jimenez <alejandro.j.jimenez@oracle.com>
 R: Sairaj Kodilkar <sarunkod@amd.com>
 S: Supported
 F: hw/i386/amd_iommu*
+F: tests/qtest/amd-iommu-test.c
 
 OpenSBI Firmware
 L: qemu-riscv@nongnu.org
diff --git a/tests/qtest/amd-iommu-test.c b/tests/qtest/amd-iommu-test.c
new file mode 100644
index 0000000000..fb28511588
--- /dev/null
+++ b/tests/qtest/amd-iommu-test.c
@@ -0,0 +1,76 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+#include "hw/i386/amd_iommu.h"
+
+#define CMDBUF_ADDR       0x200000
+#define CMDBUF_LEN_FIELD  8
+#define CMDBUF_ENTRIES    (1U << CMDBUF_LEN_FIELD)
+
+static inline uint64_t amdvi_reg_readq(QTestState *s, uint64_t offset)
+{
+    return qtest_readq(s, AMDVI_BASE_ADDR + offset);
+}
+
+static inline void amdvi_reg_writeq(QTestState *s, uint64_t offset,
+                                    uint64_t val)
+{
+    qtest_writeq(s, AMDVI_BASE_ADDR + offset, val);
+}
+
+static void test_cmdbuf_head_wrap(void)
+{
+    QTestState *s;
+    uint64_t head;
+    int i;
+    /* 16 bytes per command */
+    struct {
+        uint64_t qw0;
+        uint64_t qw1;
+    } cmdbuf[CMDBUF_ENTRIES];
+
+    if (!qtest_has_machine("q35")) {
+        g_test_skip("q35 machine not available");
+        return;
+    }
+
+    s = qtest_init("-M q35 -device amd-iommu");
+
+    /* fill the command buffer with COMPLETION_WAIT (no-op) commands */
+    for (i = 0; i < CMDBUF_ENTRIES; i++) {
+        cmdbuf[i].qw0 = (uint64_t)AMDVI_CMD_COMPLETION_WAIT << 60;
+        cmdbuf[i].qw1 = 0;
+    }
+    qtest_memwrite(s, CMDBUF_ADDR, cmdbuf, sizeof(cmdbuf));
+
+    /* point the IOMMU at the command buffer and set its length */
+    amdvi_reg_writeq(s, AMDVI_MMIO_COMMAND_BASE,
+                     CMDBUF_ADDR | ((uint64_t)CMDBUF_LEN_FIELD << 56));
+
+    /* enable the IOMMU and its command buffer processor */
+    amdvi_reg_writeq(s, AMDVI_MMIO_CONTROL,
+                     AMDVI_MMIO_CONTROL_AMDVIEN | AMDVI_MMIO_CONTROL_CMDBUFLEN);
+
+    /* advance tail to the last entry, consuming all but the final entry */
+    amdvi_reg_writeq(s, AMDVI_MMIO_COMMAND_TAIL,
+                     (CMDBUF_ENTRIES - 1) * AMDVI_COMMAND_SIZE);
+
+    /* wrap tail to 0, consuming the final entry and completing the buffer */
+    amdvi_reg_writeq(s, AMDVI_MMIO_COMMAND_TAIL, 0);
+
+    /* after consuming all entries the IOMMU must wrap CmdHeadPtr to 0 */
+    head = amdvi_reg_readq(s, AMDVI_MMIO_COMMAND_HEAD);
+    g_assert((head & AMDVI_MMIO_CMDBUF_HEAD_MASK) == 0);
+
+    qtest_quit(s);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+    qtest_add_func("/q35/amd-iommu/cmdbuf-head-wrap", test_cmdbuf_head_wrap);
+    return g_test_run();
+}
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 728dde54b3..67eea5c71a 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -95,6 +95,7 @@ qtests_i386 = \
   (config_all_devices.has_key('CONFIG_SB16') ? ['fuzz-sb16-test'] : []) +                   \
   (config_all_devices.has_key('CONFIG_SDHCI_PCI') ? ['fuzz-sdcard-test'] : []) +            \
   (config_all_devices.has_key('CONFIG_ESP_PCI') ? ['am53c974-test'] : []) +                 \
+  (config_all_devices.has_key('CONFIG_AMD_IOMMU') ? ['amd-iommu-test'] : []) +             \
   (config_all_devices.has_key('CONFIG_VTD') ? ['intel-iommu-test'] : []) +                 \
   (config_all_devices.has_key('CONFIG_VTD') and
    config_all_devices.has_key('CONFIG_IOMMU_TESTDEV') ? ['iommu-intel-test'] : []) +      \
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 004/106] intel_iommu: Remove 'x-' prefix from 'x-scalable-mode' and 'x-flts' properties
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (2 preceding siblings ...)
  2026-06-14 19:05 ` [PULL 003/106] tests/qtest: Add amd-iommu command buffer head wrap test Michael S. Tsirkin
@ 2026-06-14 19:05 ` Michael S. Tsirkin
  2026-06-14 19:05 ` [PULL 005/106] intel_iommu: Change 'flts' property naming to 'fsts' Michael S. Tsirkin
                   ` (102 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:05 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Zhenzhong Duan, Yi Liu, Eric Auger,
	Pierrick Bouvier, Jason Wang, Clément Mathieu--Drif,
	Paolo Bonzini, Richard Henderson, Fabiano Rosas, Laurent Vivier

From: Zhenzhong Duan <zhenzhong.duan@intel.com>

We had 'x-scalable-mode' for more than 5 years and 'x-flts' for more than 1
year, it's fine to remove 'x-' now.

This is a prerequisite to enable intel_iommu's scalable mode and first stage
translation support in libvirt.

Signed-off-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: <20260513064227.2304854-2-zhenzhong.duan@intel.com>
---
 docs/devel/vfio-iommufd.rst    | 10 +++++-----
 hw/i386/intel_iommu.c          |  8 ++++----
 hw/i386/intel_iommu_accel.c    |  4 ++--
 tests/qtest/intel-iommu-test.c |  2 +-
 tests/qtest/iommu-intel-test.c |  4 ++--
 5 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/docs/devel/vfio-iommufd.rst b/docs/devel/vfio-iommufd.rst
index 78bcdffac7..5755532443 100644
--- a/docs/devel/vfio-iommufd.rst
+++ b/docs/devel/vfio-iommufd.rst
@@ -153,22 +153,22 @@ RAM discarding for mdev.
 ``vfio-ap`` and ``vfio-ccw`` devices don't have same issue as their backend
 devices are always mdev and RAM discarding is force enabled.
 
-Usage with intel_iommu featuring x-flts=on
+Usage with intel_iommu featuring flts=on
 ------------------------------------------
 
 Only IOMMUFD backed VFIO device is supported when intel_iommu is configured
-with x-flts=on, for legacy container backed VFIO device, below error shows:
+with flts=on, for legacy container backed VFIO device, below error shows:
 
 .. code-block:: none
 
-    qemu-system-x86_64: -device vfio-pci,host=0000:02:00.0: vfio 0000:02:00.0: Failed to set vIOMMU: Need IOMMUFD backend when x-flts=on
+    qemu-system-x86_64: -device vfio-pci,host=0000:02:00.0: vfio 0000:02:00.0: Failed to set vIOMMU: Need IOMMUFD backend when flts=on
 
 VFIO device under PCI bridge is unsupported, use PCIE bridge if necessary,
 otherwise below error shows:
 
 .. code-block:: none
 
-    qemu-system-x86_64: -device vfio-pci,host=0000:02:00.0,bus=bridge1,iommufd=iommufd0: vfio 0000:02:00.0: Failed to set vIOMMU: Host device downstream to a PCI bridge is unsupported when x-flts=on
+    qemu-system-x86_64: -device vfio-pci,host=0000:02:00.0,bus=bridge1,iommufd=iommufd0: vfio 0000:02:00.0: Failed to set vIOMMU: Host device downstream to a PCI bridge is unsupported when flts=on
 
 If host IOMMU has ERRATA_772415_SPR17, running guest with "intel_iommu=on,sm_off"
 is unsupported, kexec or reboot guest from "intel_iommu=on,sm_on" to
@@ -177,4 +177,4 @@ below if it's not needed by guest:
 
 .. code-block:: bash
 
-    -device intel-iommu,x-scalable-mode=off
+    -device intel-iommu,scalable-mode=off
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index b784c5f10a..f09a87b50b 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -4200,8 +4200,8 @@ static const Property vtd_properties[] = {
     DEFINE_PROP_UINT8("aw-bits", IntelIOMMUState, aw_bits,
                       VTD_HOST_ADDRESS_WIDTH),
     DEFINE_PROP_BOOL("caching-mode", IntelIOMMUState, caching_mode, FALSE),
-    DEFINE_PROP_BOOL("x-scalable-mode", IntelIOMMUState, scalable_mode, FALSE),
-    DEFINE_PROP_BOOL("x-flts", IntelIOMMUState, fsts, FALSE),
+    DEFINE_PROP_BOOL("scalable-mode", IntelIOMMUState, scalable_mode, FALSE),
+    DEFINE_PROP_BOOL("flts", IntelIOMMUState, fsts, FALSE),
     DEFINE_PROP_BOOL("snoop-control", IntelIOMMUState, snoop_control, false),
     DEFINE_PROP_BOOL("x-pasid-mode", IntelIOMMUState, pasid, false),
     DEFINE_PROP_BOOL("svm", IntelIOMMUState, svm, false),
@@ -5563,7 +5563,7 @@ static bool vtd_decide_config(IntelIOMMUState *s, Error **errp)
     }
 
     if (!s->scalable_mode && s->fsts) {
-        error_setg(errp, "x-flts is only available in scalable mode");
+        error_setg(errp, "flts is only available in scalable mode");
         return false;
     }
 
@@ -5576,7 +5576,7 @@ static bool vtd_decide_config(IntelIOMMUState *s, Error **errp)
     }
 
     if (s->fsts && s->aw_bits != VTD_HOST_AW_48BIT) {
-        error_setg(errp, "Scalable mode(x-flts=on): supported value for "
+        error_setg(errp, "Scalable mode(flts=on): supported value for "
                    "aw-bits is: %d", VTD_HOST_AW_48BIT);
         return false;
     }
diff --git a/hw/i386/intel_iommu_accel.c b/hw/i386/intel_iommu_accel.c
index ed3793602b..36dc5ac020 100644
--- a/hw/i386/intel_iommu_accel.c
+++ b/hw/i386/intel_iommu_accel.c
@@ -26,7 +26,7 @@ bool vtd_check_hiod_accel(IntelIOMMUState *s, VTDHostIOMMUDevice *vtd_hiod,
     PCIDevice *pdev = bus->devices[vtd_hiod->devfn];
 
     if (!object_dynamic_cast(OBJECT(hiod), TYPE_HOST_IOMMU_DEVICE_IOMMUFD)) {
-        error_setg(errp, "Need IOMMUFD backend when x-flts=on");
+        error_setg(errp, "Need IOMMUFD backend when flts=on");
         return false;
     }
 
@@ -44,7 +44,7 @@ bool vtd_check_hiod_accel(IntelIOMMUState *s, VTDHostIOMMUDevice *vtd_hiod,
 
     if (pci_device_get_iommu_bus_devfn(pdev, &bus, NULL, NULL)) {
         error_setg(errp, "Host device downstream to a PCI bridge is "
-                   "unsupported when x-flts=on");
+                   "unsupported when flts=on");
         return false;
     }
 
diff --git a/tests/qtest/intel-iommu-test.c b/tests/qtest/intel-iommu-test.c
index e5cc6acaf0..4f12c56260 100644
--- a/tests/qtest/intel-iommu-test.c
+++ b/tests/qtest/intel-iommu-test.c
@@ -29,7 +29,7 @@ static void test_intel_iommu_stage_1(void)
     uint64_t cap, ecap, tmp;
     QTestState *s;
 
-    s = qtest_init("-M q35 -device intel-iommu,x-scalable-mode=on,x-flts=on");
+    s = qtest_init("-M q35 -device intel-iommu,scalable-mode=on,flts=on");
 
     cap = vtd_reg_readq(s, DMAR_CAP_REG);
     g_assert((cap & CAP_STAGE_1_FIXED1) == CAP_STAGE_1_FIXED1);
diff --git a/tests/qtest/iommu-intel-test.c b/tests/qtest/iommu-intel-test.c
index a52c45e298..8125be9e28 100644
--- a/tests/qtest/iommu-intel-test.c
+++ b/tests/qtest/iommu-intel-test.c
@@ -54,10 +54,10 @@ static const char *qvtd_iommu_args(QVTDTransMode mode)
 {
     switch (mode) {
     case QVTD_TM_SCALABLE_FLT:
-        return "-device intel-iommu,x-scalable-mode=on,x-flts=on ";
+        return "-device intel-iommu,scalable-mode=on,flts=on ";
     case QVTD_TM_SCALABLE_PT:
     case QVTD_TM_SCALABLE_SLT:
-        return "-device intel-iommu,x-scalable-mode=on ";
+        return "-device intel-iommu,scalable-mode=on ";
     default:
         return "-device intel-iommu ";
     }
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 005/106] intel_iommu: Change 'flts' property naming to 'fsts'
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (3 preceding siblings ...)
  2026-06-14 19:05 ` [PULL 004/106] intel_iommu: Remove 'x-' prefix from 'x-scalable-mode' and 'x-flts' properties Michael S. Tsirkin
@ 2026-06-14 19:05 ` Michael S. Tsirkin
  2026-06-14 19:05 ` [PULL 006/106] vfio/iommufd: Extend attach/detach_hwpt callback implementations with pasid Michael S. Tsirkin
                   ` (101 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:05 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Zhenzhong Duan, Yi Liu, Eric Auger,
	Pierrick Bouvier, Jason Wang, Clément Mathieu--Drif,
	Paolo Bonzini, Richard Henderson, Fabiano Rosas, Laurent Vivier

From: Zhenzhong Duan <zhenzhong.duan@intel.com>

Previous patch Removed 'x-' prefix from 'x-flts' property.
Opportunistically, this patch does s/flts/fsts for property name
in order to better align with newer spec since revision 3.4 which
changed terminology from "First-level" to "First-stage".

Signed-off-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: <20260513064227.2304854-3-zhenzhong.duan@intel.com>
---
 docs/devel/vfio-iommufd.rst    |  8 ++++----
 hw/i386/intel_iommu.c          | 10 +++++-----
 hw/i386/intel_iommu_accel.c    |  6 +++---
 tests/qtest/intel-iommu-test.c |  2 +-
 tests/qtest/iommu-intel-test.c |  2 +-
 5 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/docs/devel/vfio-iommufd.rst b/docs/devel/vfio-iommufd.rst
index 5755532443..d5538461ba 100644
--- a/docs/devel/vfio-iommufd.rst
+++ b/docs/devel/vfio-iommufd.rst
@@ -153,22 +153,22 @@ RAM discarding for mdev.
 ``vfio-ap`` and ``vfio-ccw`` devices don't have same issue as their backend
 devices are always mdev and RAM discarding is force enabled.
 
-Usage with intel_iommu featuring flts=on
+Usage with intel_iommu featuring fsts=on
 ------------------------------------------
 
 Only IOMMUFD backed VFIO device is supported when intel_iommu is configured
-with flts=on, for legacy container backed VFIO device, below error shows:
+with fsts=on, for legacy container backed VFIO device, below error shows:
 
 .. code-block:: none
 
-    qemu-system-x86_64: -device vfio-pci,host=0000:02:00.0: vfio 0000:02:00.0: Failed to set vIOMMU: Need IOMMUFD backend when flts=on
+    qemu-system-x86_64: -device vfio-pci,host=0000:02:00.0: vfio 0000:02:00.0: Failed to set vIOMMU: Need IOMMUFD backend when fsts=on
 
 VFIO device under PCI bridge is unsupported, use PCIE bridge if necessary,
 otherwise below error shows:
 
 .. code-block:: none
 
-    qemu-system-x86_64: -device vfio-pci,host=0000:02:00.0,bus=bridge1,iommufd=iommufd0: vfio 0000:02:00.0: Failed to set vIOMMU: Host device downstream to a PCI bridge is unsupported when flts=on
+    qemu-system-x86_64: -device vfio-pci,host=0000:02:00.0,bus=bridge1,iommufd=iommufd0: vfio 0000:02:00.0: Failed to set vIOMMU: Host device downstream to a PCI bridge is unsupported when fsts=on
 
 If host IOMMU has ERRATA_772415_SPR17, running guest with "intel_iommu=on,sm_off"
 is unsupported, kexec or reboot guest from "intel_iommu=on,sm_on" to
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index f09a87b50b..4f8302d200 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -4201,7 +4201,7 @@ static const Property vtd_properties[] = {
                       VTD_HOST_ADDRESS_WIDTH),
     DEFINE_PROP_BOOL("caching-mode", IntelIOMMUState, caching_mode, FALSE),
     DEFINE_PROP_BOOL("scalable-mode", IntelIOMMUState, scalable_mode, FALSE),
-    DEFINE_PROP_BOOL("flts", IntelIOMMUState, fsts, FALSE),
+    DEFINE_PROP_BOOL("fsts", IntelIOMMUState, fsts, FALSE),
     DEFINE_PROP_BOOL("snoop-control", IntelIOMMUState, snoop_control, false),
     DEFINE_PROP_BOOL("x-pasid-mode", IntelIOMMUState, pasid, false),
     DEFINE_PROP_BOOL("svm", IntelIOMMUState, svm, false),
@@ -5563,20 +5563,20 @@ static bool vtd_decide_config(IntelIOMMUState *s, Error **errp)
     }
 
     if (!s->scalable_mode && s->fsts) {
-        error_setg(errp, "flts is only available in scalable mode");
+        error_setg(errp, "fsts is only available in scalable mode");
         return false;
     }
 
     if (!s->fsts && s->aw_bits != VTD_HOST_AW_39BIT &&
         s->aw_bits != VTD_HOST_AW_48BIT) {
         error_setg(errp, "%s: supported values for aw-bits are: %d, %d",
-                   s->scalable_mode ? "Scalable mode(flts=off)" : "Legacy mode",
+                   s->scalable_mode ? "Scalable mode(fsts=off)" : "Legacy mode",
                    VTD_HOST_AW_39BIT, VTD_HOST_AW_48BIT);
         return false;
     }
 
     if (s->fsts && s->aw_bits != VTD_HOST_AW_48BIT) {
-        error_setg(errp, "Scalable mode(flts=on): supported value for "
+        error_setg(errp, "Scalable mode(fsts=on): supported value for "
                    "aw-bits is: %d", VTD_HOST_AW_48BIT);
         return false;
     }
@@ -5593,7 +5593,7 @@ static bool vtd_decide_config(IntelIOMMUState *s, Error **errp)
         }
 
         if (!s->fsts) {
-            error_setg(errp, "Need to set flts for svm");
+            error_setg(errp, "Need to set fsts for svm");
             return false;
         }
 
diff --git a/hw/i386/intel_iommu_accel.c b/hw/i386/intel_iommu_accel.c
index 36dc5ac020..18ca5a801a 100644
--- a/hw/i386/intel_iommu_accel.c
+++ b/hw/i386/intel_iommu_accel.c
@@ -26,7 +26,7 @@ bool vtd_check_hiod_accel(IntelIOMMUState *s, VTDHostIOMMUDevice *vtd_hiod,
     PCIDevice *pdev = bus->devices[vtd_hiod->devfn];
 
     if (!object_dynamic_cast(OBJECT(hiod), TYPE_HOST_IOMMU_DEVICE_IOMMUFD)) {
-        error_setg(errp, "Need IOMMUFD backend when flts=on");
+        error_setg(errp, "Need IOMMUFD backend when fsts=on");
         return false;
     }
 
@@ -44,7 +44,7 @@ bool vtd_check_hiod_accel(IntelIOMMUState *s, VTDHostIOMMUDevice *vtd_hiod,
 
     if (pci_device_get_iommu_bus_devfn(pdev, &bus, NULL, NULL)) {
         error_setg(errp, "Host device downstream to a PCI bridge is "
-                   "unsupported when flts=on");
+                   "unsupported when fsts=on");
         return false;
     }
 
@@ -105,7 +105,7 @@ static bool vtd_device_attach_iommufd(VTDHostIOMMUDevice *vtd_hiod,
     bool ret;
 
     /*
-     * We can get here only if flts=on, the supported PGTT is FST or PT.
+     * We can get here only if fsts=on, the supported PGTT is FST or PT.
      * Catch invalid PGTT when processing invalidation request to avoid
      * attaching to wrong hwpt.
      */
diff --git a/tests/qtest/intel-iommu-test.c b/tests/qtest/intel-iommu-test.c
index 4f12c56260..30ee6524df 100644
--- a/tests/qtest/intel-iommu-test.c
+++ b/tests/qtest/intel-iommu-test.c
@@ -29,7 +29,7 @@ static void test_intel_iommu_stage_1(void)
     uint64_t cap, ecap, tmp;
     QTestState *s;
 
-    s = qtest_init("-M q35 -device intel-iommu,scalable-mode=on,flts=on");
+    s = qtest_init("-M q35 -device intel-iommu,scalable-mode=on,fsts=on");
 
     cap = vtd_reg_readq(s, DMAR_CAP_REG);
     g_assert((cap & CAP_STAGE_1_FIXED1) == CAP_STAGE_1_FIXED1);
diff --git a/tests/qtest/iommu-intel-test.c b/tests/qtest/iommu-intel-test.c
index 8125be9e28..703bbfef73 100644
--- a/tests/qtest/iommu-intel-test.c
+++ b/tests/qtest/iommu-intel-test.c
@@ -54,7 +54,7 @@ static const char *qvtd_iommu_args(QVTDTransMode mode)
 {
     switch (mode) {
     case QVTD_TM_SCALABLE_FLT:
-        return "-device intel-iommu,scalable-mode=on,flts=on ";
+        return "-device intel-iommu,scalable-mode=on,fsts=on ";
     case QVTD_TM_SCALABLE_PT:
     case QVTD_TM_SCALABLE_SLT:
         return "-device intel-iommu,scalable-mode=on ";
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 006/106] vfio/iommufd: Extend attach/detach_hwpt callback implementations with pasid
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (4 preceding siblings ...)
  2026-06-14 19:05 ` [PULL 005/106] intel_iommu: Change 'flts' property naming to 'fsts' Michael S. Tsirkin
@ 2026-06-14 19:05 ` Michael S. Tsirkin
  2026-06-14 19:05 ` [PULL 007/106] iommufd: Extend attach/detach_hwpt callbacks to support pasid Michael S. Tsirkin
                   ` (100 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:05 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Zhenzhong Duan, Shameer Kolothum Thodi,
	Nicolin Chen, Yi Liu, Cédric Le Goater, Xudong Hao,
	Alex Williamson, Eric Auger

From: Zhenzhong Duan <zhenzhong.duan@intel.com>

For attachment with pasid, pasid together with flag VFIO_DEVICE_ATTACH_PASID
should be passed in.

Define IOMMU_NO_PASID to represent device attachment without pasid same as
in kernel.

The implementation is similar for detachment.

Suggested-by: Shameer Kolothum Thodi <skolothumtho@nvidia.com>
Suggested-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Reviewed-by: Yi Liu <yi.l.liu@intel.com>
Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Reviewed-by: Shameer Kolothum <skolothumtho@nvidia.com>
Tested-by: Xudong Hao <xudong.hao@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260527054658.1021096-2-zhenzhong.duan@intel.com>
---
 hw/vfio/iommufd.c       | 44 +++++++++++++++++++++++++----------------
 hw/vfio/trace-events    |  4 ++--
 include/hw/core/iommu.h |  3 +++
 3 files changed, 32 insertions(+), 19 deletions(-)

diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c
index df148a49a7..f86f6f0d7b 100644
--- a/hw/vfio/iommufd.c
+++ b/hw/vfio/iommufd.c
@@ -20,6 +20,7 @@
 #include "trace.h"
 #include "qapi/error.h"
 #include "system/iommufd.h"
+#include "hw/core/iommu.h"
 #include "hw/core/qdev.h"
 #include "hw/vfio/vfio-cpr.h"
 #include "system/reset.h"
@@ -305,43 +306,48 @@ out:
     return ret;
 }
 
-static int iommufd_cdev_attach_ioas_hwpt(VFIODevice *vbasedev, uint32_t id,
-                                         Error **errp)
+static int iommufd_cdev_pasid_attach_ioas_hwpt(VFIODevice *vbasedev,
+                                               uint32_t pasid, uint32_t id,
+                                               Error **errp)
 {
     int iommufd = vbasedev->iommufd->fd;
     struct vfio_device_attach_iommufd_pt attach_data = {
         .argsz = sizeof(attach_data),
-        .flags = 0,
+        .flags = pasid == IOMMU_NO_PASID ? 0 : VFIO_DEVICE_ATTACH_PASID,
+        .pasid = pasid,
         .pt_id = id,
     };
 
     /* Attach device to an IOAS or hwpt within iommufd */
     if (ioctl(vbasedev->fd, VFIO_DEVICE_ATTACH_IOMMUFD_PT, &attach_data)) {
         error_setg_errno(errp, errno,
-                         "[iommufd=%d] error attach %s (%d) to id=%d",
-                         iommufd, vbasedev->name, vbasedev->fd, id);
+                         "[iommufd=%d] error attach %s (%d) pasid %d to id=%d",
+                         iommufd, vbasedev->name, vbasedev->fd, pasid, id);
         return -errno;
     }
 
-    trace_iommufd_cdev_attach_ioas_hwpt(iommufd, vbasedev->name,
-                                        vbasedev->fd, id);
+    trace_iommufd_cdev_pasid_attach_ioas_hwpt(iommufd, vbasedev->name,
+                                              vbasedev->fd, pasid, id);
     return 0;
 }
 
-static bool iommufd_cdev_detach_ioas_hwpt(VFIODevice *vbasedev, Error **errp)
+static bool iommufd_cdev_pasid_detach_ioas_hwpt(VFIODevice *vbasedev,
+                                                uint32_t pasid, Error **errp)
 {
     int iommufd = vbasedev->iommufd->fd;
     struct vfio_device_detach_iommufd_pt detach_data = {
         .argsz = sizeof(detach_data),
-        .flags = 0,
+        .flags = pasid == IOMMU_NO_PASID ? 0 : VFIO_DEVICE_DETACH_PASID,
+        .pasid = pasid,
     };
 
     if (ioctl(vbasedev->fd, VFIO_DEVICE_DETACH_IOMMUFD_PT, &detach_data)) {
-        error_setg_errno(errp, errno, "detach %s failed", vbasedev->name);
+        error_setg_errno(errp, errno, "detach %s pasid %d failed",
+                         vbasedev->name, pasid);
         return false;
     }
 
-    trace_iommufd_cdev_detach_ioas_hwpt(iommufd, vbasedev->name);
+    trace_iommufd_cdev_pasid_detach_ioas_hwpt(iommufd, vbasedev->name, pasid);
     return true;
 }
 
@@ -363,7 +369,8 @@ static bool iommufd_cdev_autodomains_get(VFIODevice *vbasedev,
     /* Try to find a domain */
     QLIST_FOREACH(hwpt, &container->hwpt_list, next) {
         if (!cpr_is_incoming()) {
-            ret = iommufd_cdev_attach_ioas_hwpt(vbasedev, hwpt->hwpt_id, errp);
+            ret = iommufd_cdev_pasid_attach_ioas_hwpt(vbasedev, IOMMU_NO_PASID,
+                                                      hwpt->hwpt_id, errp);
         } else if (vbasedev->cpr.hwpt_id == hwpt->hwpt_id) {
             ret = 0;
         } else {
@@ -442,7 +449,8 @@ static bool iommufd_cdev_autodomains_get(VFIODevice *vbasedev,
         return false;
     }
 
-    ret = iommufd_cdev_attach_ioas_hwpt(vbasedev, hwpt_id, errp);
+    ret = iommufd_cdev_pasid_attach_ioas_hwpt(vbasedev, IOMMU_NO_PASID, hwpt_id,
+                                              errp);
     if (ret) {
         iommufd_backend_free_id(container->be, hwpt_id);
         return false;
@@ -495,7 +503,8 @@ static bool iommufd_cdev_attach_container(VFIODevice *vbasedev,
 
     /* If CPR, we are already attached to ioas_id. */
     return cpr_is_incoming() ||
-           !iommufd_cdev_attach_ioas_hwpt(vbasedev, container->ioas_id, errp);
+           !iommufd_cdev_pasid_attach_ioas_hwpt(vbasedev, IOMMU_NO_PASID,
+                                                container->ioas_id, errp);
 }
 
 static void iommufd_cdev_detach_container(VFIODevice *vbasedev,
@@ -503,7 +512,7 @@ static void iommufd_cdev_detach_container(VFIODevice *vbasedev,
 {
     Error *err = NULL;
 
-    if (!iommufd_cdev_detach_ioas_hwpt(vbasedev, &err)) {
+    if (!iommufd_cdev_pasid_detach_ioas_hwpt(vbasedev, IOMMU_NO_PASID, &err)) {
         error_report_err(err);
     }
 
@@ -929,7 +938,8 @@ host_iommu_device_iommufd_vfio_attach_hwpt(HostIOMMUDeviceIOMMUFD *hiodi,
 {
     VFIODevice *vbasedev = HOST_IOMMU_DEVICE(hiodi)->agent;
 
-    return !iommufd_cdev_attach_ioas_hwpt(vbasedev, hwpt_id, errp);
+    return !iommufd_cdev_pasid_attach_ioas_hwpt(vbasedev, IOMMU_NO_PASID,
+                                                hwpt_id, errp);
 }
 
 static bool
@@ -938,7 +948,7 @@ host_iommu_device_iommufd_vfio_detach_hwpt(HostIOMMUDeviceIOMMUFD *hiodi,
 {
     VFIODevice *vbasedev = HOST_IOMMU_DEVICE(hiodi)->agent;
 
-    return iommufd_cdev_detach_ioas_hwpt(vbasedev, errp);
+    return iommufd_cdev_pasid_detach_ioas_hwpt(vbasedev, IOMMU_NO_PASID, errp);
 }
 
 static bool hiod_iommufd_vfio_realize(HostIOMMUDevice *hiod, void *opaque,
diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events
index 2049159015..8dbb477298 100644
--- a/hw/vfio/trace-events
+++ b/hw/vfio/trace-events
@@ -183,8 +183,8 @@ vfio_vmstate_change_prepare(const char *name, int running, const char *reason, c
 
 iommufd_cdev_connect_and_bind(int iommufd, const char *name, int devfd, int devid) " [iommufd=%d] Successfully bound device %s (fd=%d): output devid=%d"
 iommufd_cdev_getfd(const char *dev, int devfd) " %s (fd=%d)"
-iommufd_cdev_attach_ioas_hwpt(int iommufd, const char *name, int devfd, int id) " [iommufd=%d] Successfully attached device %s (%d) to id=%d"
-iommufd_cdev_detach_ioas_hwpt(int iommufd, const char *name) " [iommufd=%d] Successfully detached %s"
+iommufd_cdev_pasid_attach_ioas_hwpt(int iommufd, const char *name, int devfd, uint32_t pasid, int id) " [iommufd=%d] Successfully attached device %s (%d) pasid %u to id=%d"
+iommufd_cdev_pasid_detach_ioas_hwpt(int iommufd, const char *name, uint32_t pasid) " [iommufd=%d] Successfully detached %s pasid %u"
 iommufd_cdev_fail_attach_existing_container(const char *msg) " %s"
 iommufd_cdev_alloc_ioas(int iommufd, int ioas_id) " [iommufd=%d] new IOMMUFD container with ioasid=%d"
 iommufd_cdev_device_info(char *name, int devfd, int num_irqs, int num_regions, int flags) " %s (%d) num_irqs=%d num_regions=%d flags=%d"
diff --git a/include/hw/core/iommu.h b/include/hw/core/iommu.h
index cd59a367ce..7fb5c81c9f 100644
--- a/include/hw/core/iommu.h
+++ b/include/hw/core/iommu.h
@@ -30,4 +30,7 @@ enum host_iommu_quirks {
     HOST_IOMMU_QUIRK_NESTING_PARENT_BYPASS_RO = BIT_ULL(0),
 };
 
+/* ABI constant: IOMMU_NO_PASID must always be 0 (keep in sync with kernel) */
+#define IOMMU_NO_PASID 0
+
 #endif /* HW_IOMMU_H */
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 007/106] iommufd: Extend attach/detach_hwpt callbacks to support pasid
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (5 preceding siblings ...)
  2026-06-14 19:05 ` [PULL 006/106] vfio/iommufd: Extend attach/detach_hwpt callback implementations with pasid Michael S. Tsirkin
@ 2026-06-14 19:05 ` Michael S. Tsirkin
  2026-06-14 19:06 ` [PULL 008/106] vfio/iommufd: Create nesting parent hwpt with IOMMU_HWPT_ALLOC_PASID flag Michael S. Tsirkin
                   ` (99 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:05 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Zhenzhong Duan, Shameer Kolothum Thodi,
	Nicolin Chen, Yi Liu, Cédric Le Goater, Xudong Hao,
	Eric Auger, Jason Wang, Clément Mathieu--Drif, Paolo Bonzini,
	Richard Henderson, Alex Williamson, qemu-arm

From: Zhenzhong Duan <zhenzhong.duan@intel.com>

Same for the two wrappers and their call sites.

Suggested-by: Shameer Kolothum Thodi <skolothumtho@nvidia.com>
Suggested-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Reviewed-by: Yi Liu <yi.l.liu@intel.com>
Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Reviewed-by: Shameer Kolothum <skolothumtho@nvidia.com>
Tested-by: Xudong Hao <xudong.hao@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260527054658.1021096-3-zhenzhong.duan@intel.com>
---
 backends/iommufd.c          | 23 ++++++++++++-----------
 hw/arm/smmuv3-accel.c       | 12 ++++++++----
 hw/i386/intel_iommu_accel.c | 19 ++++++++++---------
 hw/vfio/iommufd.c           | 22 +++++++++++-----------
 include/system/iommufd.h    | 18 ++++++++++++------
 5 files changed, 53 insertions(+), 41 deletions(-)

diff --git a/backends/iommufd.c b/backends/iommufd.c
index 410b044370..cfde6f2b2c 100644
--- a/backends/iommufd.c
+++ b/backends/iommufd.c
@@ -539,23 +539,24 @@ bool iommufd_backend_alloc_veventq(IOMMUFDBackend *be, uint32_t viommu_id,
 }
 
 bool host_iommu_device_iommufd_attach_hwpt(HostIOMMUDeviceIOMMUFD *hiodi,
-                                           uint32_t hwpt_id, Error **errp)
-{
-    HostIOMMUDeviceIOMMUFDClass *hiodic =
-        HOST_IOMMU_DEVICE_IOMMUFD_GET_CLASS(hiodi);
-
-    g_assert(hiodic->attach_hwpt);
-    return hiodic->attach_hwpt(hiodi, hwpt_id, errp);
-}
-
-bool host_iommu_device_iommufd_detach_hwpt(HostIOMMUDeviceIOMMUFD *hiodi,
+                                           uint32_t pasid, uint32_t hwpt_id,
                                            Error **errp)
 {
     HostIOMMUDeviceIOMMUFDClass *hiodic =
         HOST_IOMMU_DEVICE_IOMMUFD_GET_CLASS(hiodi);
 
+    g_assert(hiodic->attach_hwpt);
+    return hiodic->attach_hwpt(hiodi, pasid, hwpt_id, errp);
+}
+
+bool host_iommu_device_iommufd_detach_hwpt(HostIOMMUDeviceIOMMUFD *hiodi,
+                                           uint32_t pasid, Error **errp)
+{
+    HostIOMMUDeviceIOMMUFDClass *hiodic =
+        HOST_IOMMU_DEVICE_IOMMUFD_GET_CLASS(hiodi);
+
     g_assert(hiodic->detach_hwpt);
-    return hiodic->detach_hwpt(hiodi, errp);
+    return hiodic->detach_hwpt(hiodi, pasid, errp);
 }
 
 static int hiod_iommufd_get_cap(HostIOMMUDevice *hiod, int cap, Error **errp)
diff --git a/hw/arm/smmuv3-accel.c b/hw/arm/smmuv3-accel.c
index 862be814a0..2947e2e5dc 100644
--- a/hw/arm/smmuv3-accel.c
+++ b/hw/arm/smmuv3-accel.c
@@ -300,7 +300,8 @@ bool smmuv3_accel_install_ste(SMMUv3State *s, SMMUDevice *sdev, int sid,
         return false;
     }
 
-    if (!host_iommu_device_iommufd_attach_hwpt(hiodi, hwpt_id, errp)) {
+    if (!host_iommu_device_iommufd_attach_hwpt(hiodi, IOMMU_NO_PASID, hwpt_id,
+                                               errp)) {
         if (s1_hwpt) {
             iommufd_backend_free_id(hiodi->iommufd, s1_hwpt->hwpt_id);
             g_free(s1_hwpt);
@@ -575,7 +576,8 @@ smmuv3_accel_alloc_viommu(SMMUv3State *s, HostIOMMUDeviceIOMMUFD *hiodi,
 
     /* Attach a HWPT based on SMMUv3 GBPA.ABORT value */
     hwpt_id = smmuv3_accel_gbpa_hwpt(s, accel);
-    if (!host_iommu_device_iommufd_attach_hwpt(hiodi, hwpt_id, errp)) {
+    if (!host_iommu_device_iommufd_attach_hwpt(hiodi, IOMMU_NO_PASID, hwpt_id,
+                                               errp)) {
         goto free_veventq;
     }
     return true;
@@ -665,7 +667,8 @@ static void smmuv3_accel_unset_iommu_device(PCIBus *bus, void *opaque,
     hiodi = accel_dev->hiodi;
     accel = accel_dev->s_accel;
     /* Re-attach the default s2 hwpt id */
-    if (!host_iommu_device_iommufd_attach_hwpt(hiodi, hiodi->hwpt_id, NULL)) {
+    if (!host_iommu_device_iommufd_attach_hwpt(hiodi, IOMMU_NO_PASID,
+                                               hiodi->hwpt_id, NULL)) {
         error_report("Unable to attach the default HW pagetable: hiodi devid "
                      "0x%x", hiodi->devid);
     }
@@ -879,7 +882,8 @@ bool smmuv3_accel_attach_gbpa_hwpt(SMMUv3State *s, Error **errp)
 
     hwpt_id = smmuv3_accel_gbpa_hwpt(s, accel);
     QLIST_FOREACH(accel_dev, &accel->device_list, next) {
-        if (!host_iommu_device_iommufd_attach_hwpt(accel_dev->hiodi, hwpt_id,
+        if (!host_iommu_device_iommufd_attach_hwpt(accel_dev->hiodi,
+                                                   IOMMU_NO_PASID, hwpt_id,
                                                    &local_err)) {
             error_append_hint(&local_err, "Failed to attach GBPA hwpt %u for "
                               "hiodi devid %u", hwpt_id,
diff --git a/hw/i386/intel_iommu_accel.c b/hw/i386/intel_iommu_accel.c
index 18ca5a801a..3beadab035 100644
--- a/hw/i386/intel_iommu_accel.c
+++ b/hw/i386/intel_iommu_accel.c
@@ -121,8 +121,9 @@ static bool vtd_device_attach_iommufd(VTDHostIOMMUDevice *vtd_hiod,
         }
     }
 
-    ret = host_iommu_device_iommufd_attach_hwpt(hiodi, hwpt_id, errp);
-    trace_vtd_device_attach_hwpt(hiodi->devid, vtd_as->pasid, hwpt_id, ret);
+    ret = host_iommu_device_iommufd_attach_hwpt(hiodi, IOMMU_NO_PASID, hwpt_id,
+                                                errp);
+    trace_vtd_device_attach_hwpt(hiodi->devid, IOMMU_NO_PASID, hwpt_id, ret);
     if (ret) {
         /* Destroy old fs_hwpt if it's a replacement */
         vtd_destroy_old_fs_hwpt(hiodi, vtd_as);
@@ -141,22 +142,22 @@ static bool vtd_device_detach_iommufd(VTDHostIOMMUDevice *vtd_hiod,
 {
     HostIOMMUDeviceIOMMUFD *hiodi = HOST_IOMMU_DEVICE_IOMMUFD(vtd_hiod->hiod);
     IntelIOMMUState *s = vtd_as->iommu_state;
-    uint32_t pasid = vtd_as->pasid;
     bool ret;
 
     if (s->dmar_enabled && s->root_scalable) {
-        ret = host_iommu_device_iommufd_detach_hwpt(hiodi, errp);
-        trace_vtd_device_detach_hwpt(hiodi->devid, pasid, ret);
+        ret = host_iommu_device_iommufd_detach_hwpt(hiodi, IOMMU_NO_PASID,
+                                                    errp);
+        trace_vtd_device_detach_hwpt(hiodi->devid, IOMMU_NO_PASID, ret);
     } else {
         /*
          * If DMAR remapping is disabled or guest switches to legacy mode,
          * we fallback to the default HWPT which contains shadow page table.
          * So guest DMA could still work.
          */
-        ret = host_iommu_device_iommufd_attach_hwpt(hiodi, hiodi->hwpt_id,
-                                                    errp);
-        trace_vtd_device_reattach_def_hwpt(hiodi->devid, pasid, hiodi->hwpt_id,
-                                           ret);
+        ret = host_iommu_device_iommufd_attach_hwpt(hiodi, IOMMU_NO_PASID,
+                                                    hiodi->hwpt_id, errp);
+        trace_vtd_device_reattach_def_hwpt(hiodi->devid, IOMMU_NO_PASID,
+                                           hiodi->hwpt_id, ret);
     }
 
     if (ret) {
diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c
index f86f6f0d7b..78e7b6a045 100644
--- a/hw/vfio/iommufd.c
+++ b/hw/vfio/iommufd.c
@@ -934,21 +934,21 @@ static void vfio_iommu_iommufd_class_init(ObjectClass *klass, const void *data)
 
 static bool
 host_iommu_device_iommufd_vfio_attach_hwpt(HostIOMMUDeviceIOMMUFD *hiodi,
-                                           uint32_t hwpt_id, Error **errp)
-{
-    VFIODevice *vbasedev = HOST_IOMMU_DEVICE(hiodi)->agent;
-
-    return !iommufd_cdev_pasid_attach_ioas_hwpt(vbasedev, IOMMU_NO_PASID,
-                                                hwpt_id, errp);
-}
-
-static bool
-host_iommu_device_iommufd_vfio_detach_hwpt(HostIOMMUDeviceIOMMUFD *hiodi,
+                                           uint32_t pasid, uint32_t hwpt_id,
                                            Error **errp)
 {
     VFIODevice *vbasedev = HOST_IOMMU_DEVICE(hiodi)->agent;
 
-    return iommufd_cdev_pasid_detach_ioas_hwpt(vbasedev, IOMMU_NO_PASID, errp);
+    return !iommufd_cdev_pasid_attach_ioas_hwpt(vbasedev, pasid, hwpt_id, errp);
+}
+
+static bool
+host_iommu_device_iommufd_vfio_detach_hwpt(HostIOMMUDeviceIOMMUFD *hiodi,
+                                           uint32_t pasid, Error **errp)
+{
+    VFIODevice *vbasedev = HOST_IOMMU_DEVICE(hiodi)->agent;
+
+    return iommufd_cdev_pasid_detach_ioas_hwpt(vbasedev, pasid, errp);
 }
 
 static bool hiod_iommufd_vfio_realize(HostIOMMUDevice *hiod, void *opaque,
diff --git a/include/system/iommufd.h b/include/system/iommufd.h
index 2925d116ac..4257e50f62 100644
--- a/include/system/iommufd.h
+++ b/include/system/iommufd.h
@@ -138,14 +138,16 @@ struct HostIOMMUDeviceIOMMUFDClass {
      *
      * @hiodi: host IOMMU device backed by IOMMUFD backend.
      *
+     * @pasid: target pasid of the device to be attached.
+     *
      * @hwpt_id: ID of IOMMUFD hardware page table.
      *
      * @errp: pass an Error out when attachment fails.
      *
      * Returns: true on success, false on failure.
      */
-    bool (*attach_hwpt)(HostIOMMUDeviceIOMMUFD *hiodi, uint32_t hwpt_id,
-                        Error **errp);
+    bool (*attach_hwpt)(HostIOMMUDeviceIOMMUFD *hiodi, uint32_t pasid,
+                        uint32_t hwpt_id, Error **errp);
     /**
      * @detach_hwpt: detach host IOMMU device from IOMMUFD hardware page table.
      * VFIO and VDPA device can have different implementation.
@@ -154,15 +156,19 @@ struct HostIOMMUDeviceIOMMUFDClass {
      *
      * @hiodi: host IOMMU device backed by IOMMUFD backend.
      *
-     * @errp: pass an Error out when attachment fails.
+     * @pasid: target pasid of the device to be detached.
+     *
+     * @errp: pass an Error out when detachment fails.
      *
      * Returns: true on success, false on failure.
      */
-    bool (*detach_hwpt)(HostIOMMUDeviceIOMMUFD *hiodi, Error **errp);
+    bool (*detach_hwpt)(HostIOMMUDeviceIOMMUFD *hiodi, uint32_t pasid,
+                        Error **errp);
 };
 
 bool host_iommu_device_iommufd_attach_hwpt(HostIOMMUDeviceIOMMUFD *hiodi,
-                                           uint32_t hwpt_id, Error **errp);
-bool host_iommu_device_iommufd_detach_hwpt(HostIOMMUDeviceIOMMUFD *hiodi,
+                                           uint32_t pasid, uint32_t hwpt_id,
                                            Error **errp);
+bool host_iommu_device_iommufd_detach_hwpt(HostIOMMUDeviceIOMMUFD *hiodi,
+                                           uint32_t pasid, Error **errp);
 #endif
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 008/106] vfio/iommufd: Create nesting parent hwpt with IOMMU_HWPT_ALLOC_PASID flag
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (6 preceding siblings ...)
  2026-06-14 19:05 ` [PULL 007/106] iommufd: Extend attach/detach_hwpt callbacks to support pasid Michael S. Tsirkin
@ 2026-06-14 19:06 ` Michael S. Tsirkin
  2026-06-14 19:06 ` [PULL 009/106] intel_iommu: Create the nested " Michael S. Tsirkin
                   ` (98 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Zhenzhong Duan, Yi Liu, Xudong Hao,
	Shameer Kolothum, Alex Williamson, Cédric Le Goater,
	Eric Auger

From: Zhenzhong Duan <zhenzhong.duan@intel.com>

When both device and vIOMMU have PASID enabled, then guest may setup
pasid usages such as SVM.

VFIO needs to be aware of potential pasid usage and should attach the
non-pasid part of pasid-capable device to hwpt flagged with
IOMMU_HWPT_ALLOC_PASID.

ARM SMMU doesn't support IOMMU_HWPT_ALLOC_PASID, only VTD need it. So
we can't check the existing vIOMMU flag VIOMMU_FLAG_PASID_SUPPORTED to
determine if set flag IOMMU_HWPT_ALLOC_PASID. Instead, introduce a new
flag VIOMMU_FLAG_WANT_PASID_ATTACH which will only be exposed by VTD.

Opportunistically add documentation for VIOMMU_FLAG_PASID_SUPPORTED
and explain the difference with VIOMMU_FLAG_WANT_PASID_ATTACH.

Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Reviewed-by: Yi Liu <yi.l.liu@intel.com>
Tested-by: Xudong Hao <xudong.hao@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260527054658.1021096-4-zhenzhong.duan@intel.com>
Reviewed-by: Shameer Kolothum <skolothumtho@nvidia.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/vfio/device.c              | 11 +++++++++++
 hw/vfio/iommufd.c             |  8 +++++++-
 include/hw/core/iommu.h       | 11 +++++++++++
 include/hw/vfio/vfio-device.h |  1 +
 4 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/hw/vfio/device.c b/hw/vfio/device.c
index ccf14743e9..1a7f8088aa 100644
--- a/hw/vfio/device.c
+++ b/hw/vfio/device.c
@@ -543,6 +543,17 @@ bool vfio_device_get_viommu_flags_want_nesting(VFIODevice *vbasedev)
     return false;
 }
 
+bool vfio_device_get_viommu_flags_want_pasid_attach(VFIODevice *vbasedev)
+{
+    VFIOPCIDevice *vdev = vfio_pci_from_vfio_device(vbasedev);
+
+    if (vdev) {
+        return !!(pci_device_get_viommu_flags(PCI_DEVICE(vdev)) &
+                  VIOMMU_FLAG_WANT_PASID_ATTACH);
+    }
+    return false;
+}
+
 bool vfio_device_get_host_iommu_quirk_bypass_ro(VFIODevice *vbasedev,
                                                 uint32_t type, void *caps,
                                                 uint32_t size)
diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c
index 78e7b6a045..0718f029ca 100644
--- a/hw/vfio/iommufd.c
+++ b/hw/vfio/iommufd.c
@@ -364,6 +364,7 @@ static bool iommufd_cdev_autodomains_get(VFIODevice *vbasedev,
     VendorCaps caps;
     VFIOIOASHwpt *hwpt;
     uint32_t hwpt_id;
+    uint8_t max_pasid_log2 = 0;
     int ret;
 
     /* Try to find a domain */
@@ -409,7 +410,7 @@ static bool iommufd_cdev_autodomains_get(VFIODevice *vbasedev,
      */
     if (!iommufd_backend_get_device_info(vbasedev->iommufd, vbasedev->devid,
                                          &type, &caps, sizeof(caps), &hw_caps,
-                                         NULL, errp)) {
+                                         &max_pasid_log2, errp)) {
         return false;
     }
 
@@ -437,6 +438,11 @@ static bool iommufd_cdev_autodomains_get(VFIODevice *vbasedev,
         }
     }
 
+    if (max_pasid_log2 &&
+        vfio_device_get_viommu_flags_want_pasid_attach(vbasedev)) {
+        flags |= IOMMU_HWPT_ALLOC_PASID;
+    }
+
     if (cpr_is_incoming()) {
         hwpt_id = vbasedev->cpr.hwpt_id;
         goto skip_alloc;
diff --git a/include/hw/core/iommu.h b/include/hw/core/iommu.h
index 7fb5c81c9f..fd513d6472 100644
--- a/include/hw/core/iommu.h
+++ b/include/hw/core/iommu.h
@@ -20,9 +20,20 @@
 enum viommu_flags {
     /* vIOMMU needs nesting parent HWPT to create nested HWPT */
     VIOMMU_FLAG_WANT_NESTING_PARENT = BIT_ULL(0),
+    /*
+     * vIOMMU supports PASID capability, VFIO checks this flag and synthesize
+     * a PASID capability.
+     */
     VIOMMU_FLAG_PASID_SUPPORTED = BIT_ULL(1),
     /* vIOMMU needs dirty tracking on the nesting parent HWPT for nested use */
     VIOMMU_FLAG_WANT_NESTING_DIRTY_TRACKING = BIT_ULL(2),
+    /*
+     * vIOMMU requests other sub-system like VFIO to create a HWPT that can be
+     * used with PASID attachment. VIOMMU_FLAG_PASID_SUPPORTED can't be used
+     * for this purpose as PASID attachment is needed by VTD IOMMU but not ARM
+     * SMMU.
+     */
+    VIOMMU_FLAG_WANT_PASID_ATTACH = BIT_ULL(3),
 };
 
 /* Host IOMMU quirks. Extracted from host IOMMU capabilities */
diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-device.h
index 380a55d6e5..8472420d3f 100644
--- a/include/hw/vfio/vfio-device.h
+++ b/include/hw/vfio/vfio-device.h
@@ -282,6 +282,7 @@ void vfio_device_unprepare(VFIODevice *vbasedev);
 
 bool vfio_device_get_viommu_flags_want_nesting(VFIODevice *vbasedev);
 bool vfio_device_get_viommu_flags_want_nesting_dirty(VFIODevice *vbasedev);
+bool vfio_device_get_viommu_flags_want_pasid_attach(VFIODevice *vbasedev);
 bool vfio_device_get_host_iommu_quirk_bypass_ro(VFIODevice *vbasedev,
                                                 uint32_t type, void *caps,
                                                 uint32_t size);
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 009/106] intel_iommu: Create the nested hwpt with IOMMU_HWPT_ALLOC_PASID flag
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (7 preceding siblings ...)
  2026-06-14 19:06 ` [PULL 008/106] vfio/iommufd: Create nesting parent hwpt with IOMMU_HWPT_ALLOC_PASID flag Michael S. Tsirkin
@ 2026-06-14 19:06 ` Michael S. Tsirkin
  2026-06-14 19:06 ` [PULL 010/106] intel_iommu: Rename pasid property to "pasid-bits" and define it as type uint8 Michael S. Tsirkin
                   ` (97 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Zhenzhong Duan, Clement Mathieu--Drif, Yi Liu,
	Xudong Hao, Jason Wang, Paolo Bonzini, Richard Henderson

From: Zhenzhong Duan <zhenzhong.duan@intel.com>

When pasid is enabled, any hwpt attached to non-PASID or PASID should be
IOMMU_HWPT_ALLOC_PASID flagged, or else attachment fails.

Change vtd_destroy_old_fs_hwpt() to pass in 'VTDHostIOMMUDevice *' for
naming consistency.

Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Reviewed-by: Clement Mathieu--Drif <clement.mathieu--drif@bull.com>
Reviewed-by: Yi Liu <yi.l.liu@intel.com>
Tested-by: Xudong Hao <xudong.hao@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260527054658.1021096-5-zhenzhong.duan@intel.com>
---
 hw/i386/intel_iommu_accel.c | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/hw/i386/intel_iommu_accel.c b/hw/i386/intel_iommu_accel.c
index 3beadab035..6a12cdac10 100644
--- a/hw/i386/intel_iommu_accel.c
+++ b/hw/i386/intel_iommu_accel.c
@@ -69,11 +69,13 @@ VTDHostIOMMUDevice *vtd_find_hiod_iommufd(VTDAddressSpace *as)
     return NULL;
 }
 
-static bool vtd_create_fs_hwpt(HostIOMMUDeviceIOMMUFD *hiodi,
+static bool vtd_create_fs_hwpt(VTDHostIOMMUDevice *vtd_hiod,
                                VTDPASIDEntry *pe, uint32_t *fs_hwpt_id,
                                Error **errp)
 {
+    HostIOMMUDeviceIOMMUFD *hiodi = HOST_IOMMU_DEVICE_IOMMUFD(vtd_hiod->hiod);
     struct iommu_hwpt_vtd_s1 vtd = {};
+    uint32_t flags = vtd_hiod->iommu_state->pasid ? IOMMU_HWPT_ALLOC_PASID : 0;
 
     vtd.flags = (VTD_SM_PASID_ENTRY_SRE(pe) ? IOMMU_VTD_S1_SRE : 0) |
                 (VTD_SM_PASID_ENTRY_WPE(pe) ? IOMMU_VTD_S1_WPE : 0) |
@@ -82,13 +84,16 @@ static bool vtd_create_fs_hwpt(HostIOMMUDeviceIOMMUFD *hiodi,
     vtd.pgtbl_addr = (uint64_t)vtd_pe_get_fspt_base(pe);
 
     return iommufd_backend_alloc_hwpt(hiodi->iommufd, hiodi->devid,
-                                      hiodi->hwpt_id, 0, IOMMU_HWPT_DATA_VTD_S1,
-                                      sizeof(vtd), &vtd, fs_hwpt_id, errp);
+                                      hiodi->hwpt_id, flags,
+                                      IOMMU_HWPT_DATA_VTD_S1, sizeof(vtd), &vtd,
+                                      fs_hwpt_id, errp);
 }
 
-static void vtd_destroy_old_fs_hwpt(HostIOMMUDeviceIOMMUFD *hiodi,
+static void vtd_destroy_old_fs_hwpt(VTDHostIOMMUDevice *vtd_hiod,
                                     VTDAddressSpace *vtd_as)
 {
+    HostIOMMUDeviceIOMMUFD *hiodi = HOST_IOMMU_DEVICE_IOMMUFD(vtd_hiod->hiod);
+
     if (!vtd_as->fs_hwpt_id) {
         return;
     }
@@ -116,7 +121,7 @@ static bool vtd_device_attach_iommufd(VTDHostIOMMUDevice *vtd_hiod,
     }
 
     if (vtd_pe_pgtt_is_fst(pe)) {
-        if (!vtd_create_fs_hwpt(hiodi, pe, &hwpt_id, errp)) {
+        if (!vtd_create_fs_hwpt(vtd_hiod, pe, &hwpt_id, errp)) {
             return false;
         }
     }
@@ -126,7 +131,7 @@ static bool vtd_device_attach_iommufd(VTDHostIOMMUDevice *vtd_hiod,
     trace_vtd_device_attach_hwpt(hiodi->devid, IOMMU_NO_PASID, hwpt_id, ret);
     if (ret) {
         /* Destroy old fs_hwpt if it's a replacement */
-        vtd_destroy_old_fs_hwpt(hiodi, vtd_as);
+        vtd_destroy_old_fs_hwpt(vtd_hiod, vtd_as);
         if (vtd_pe_pgtt_is_fst(pe)) {
             vtd_as->fs_hwpt_id = hwpt_id;
         }
@@ -161,7 +166,7 @@ static bool vtd_device_detach_iommufd(VTDHostIOMMUDevice *vtd_hiod,
     }
 
     if (ret) {
-        vtd_destroy_old_fs_hwpt(hiodi, vtd_as);
+        vtd_destroy_old_fs_hwpt(vtd_hiod, vtd_as);
     }
 
     return ret;
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 010/106] intel_iommu: Rename pasid property to "pasid-bits" and define it as type uint8
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (8 preceding siblings ...)
  2026-06-14 19:06 ` [PULL 009/106] intel_iommu: Create the nested " Michael S. Tsirkin
@ 2026-06-14 19:06 ` Michael S. Tsirkin
  2026-06-14 19:06 ` [PULL 011/106] intel_iommu: make vtd_dev_get_pe_from_pasid() more generic Michael S. Tsirkin
                   ` (96 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Zhenzhong Duan, Clement Mathieu--Drif, Yi Liu,
	Xudong Hao, Jason Wang, Paolo Bonzini, Richard Henderson

From: Zhenzhong Duan <zhenzhong.duan@intel.com>

'x-pasid-mode' is a bool property, we need an extra 'pss' property to
represent PASID size supported. Because there is no any device in QEMU
supporting pasid capability yet, no guest could use the pasid feature
until now, 'x-pasid-mode' takes no effect.

So instead of an extra 'pss' property we can use a single property of
uint8 type and named 'pasid-bits' to represent if pasid is supported
and the PASID bits size. A value of N > 0 means pasid is supported and
N - 1 is the value in PSS field in ECAP register.

PASID bits size should also be no more than 20 bits according to PCI spec.

Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Reviewed-by: Clement Mathieu--Drif <clement.mathieu--drif@bull.com>
Reviewed-by: Yi Liu <yi.l.liu@intel.com>
Tested-by: Xudong Hao <xudong.hao@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260527054658.1021096-6-zhenzhong.duan@intel.com>
---
 hw/i386/intel_iommu.c          | 11 +++++++++--
 hw/i386/intel_iommu_internal.h |  2 +-
 include/hw/i386/intel_iommu.h  |  2 +-
 3 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 4f8302d200..b22feb0301 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -4203,7 +4203,7 @@ static const Property vtd_properties[] = {
     DEFINE_PROP_BOOL("scalable-mode", IntelIOMMUState, scalable_mode, FALSE),
     DEFINE_PROP_BOOL("fsts", IntelIOMMUState, fsts, FALSE),
     DEFINE_PROP_BOOL("snoop-control", IntelIOMMUState, snoop_control, false),
-    DEFINE_PROP_BOOL("x-pasid-mode", IntelIOMMUState, pasid, false),
+    DEFINE_PROP_UINT8("pasid-bits", IntelIOMMUState, pasid, 0),
     DEFINE_PROP_BOOL("svm", IntelIOMMUState, svm, false),
     DEFINE_PROP_BOOL("stale-tm", IntelIOMMUState, stale_tm, false),
     DEFINE_PROP_BOOL("fs1gp", IntelIOMMUState, fs1gp, true),
@@ -5045,7 +5045,8 @@ static void vtd_cap_init(IntelIOMMUState *s)
     }
 
     if (s->pasid) {
-        s->ecap |= VTD_ECAP_PASID | VTD_ECAP_PSS;
+        VTD_ECAP_SET_PSS(s, s->pasid - 1);
+        s->ecap |= VTD_ECAP_PASID;
     }
 }
 
@@ -5586,6 +5587,12 @@ static bool vtd_decide_config(IntelIOMMUState *s, Error **errp)
         return false;
     }
 
+    if (s->pasid > PCI_EXT_CAP_PASID_MAX_WIDTH) {
+        error_setg(errp, "PASID width %d exceeds Max PASID Width %d allowed "
+                   "in PCI spec", s->pasid, PCI_EXT_CAP_PASID_MAX_WIDTH);
+        return false;
+    }
+
     if (s->svm) {
         if (!x86_iommu->dt_supported) {
             error_setg(errp, "Need to set device IOTLB for svm");
diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
index 11a53aa369..db4f186a3e 100644
--- a/hw/i386/intel_iommu_internal.h
+++ b/hw/i386/intel_iommu_internal.h
@@ -195,7 +195,7 @@
 #define VTD_ECAP_MHMV               (15ULL << 20)
 #define VTD_ECAP_SRS                (1ULL << 31)
 #define VTD_ECAP_NWFS               (1ULL << 33)
-#define VTD_ECAP_PSS                (7ULL << 35) /* limit: MemTxAttrs::pid */
+#define VTD_ECAP_SET_PSS(x, v)      ((x)->ecap = deposit64((x)->ecap, 35, 5, v))
 #define VTD_ECAP_PASID              (1ULL << 40)
 #define VTD_ECAP_PDS                (1ULL << 42)
 #define VTD_ECAP_SMTS               (1ULL << 43)
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index e44ce31841..95c76015e4 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -314,7 +314,7 @@ struct IntelIOMMUState {
     bool intr_eime;                 /* Extended interrupt mode enabled */
     OnOffAuto intr_eim;             /* Toggle for EIM cabability */
     uint8_t aw_bits;                /* Host/IOVA address width (in bits) */
-    bool pasid;                     /* Whether to support PASID */
+    uint8_t pasid;                  /* PASID supported in bits, 0 if not */
     bool fs1gp;                     /* First Stage 1-GByte Page Support */
 
     /* Transient Mapping, Reserved(0) since VTD spec revision 3.2 */
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 011/106] intel_iommu: make vtd_dev_get_pe_from_pasid() more generic
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (9 preceding siblings ...)
  2026-06-14 19:06 ` [PULL 010/106] intel_iommu: Rename pasid property to "pasid-bits" and define it as type uint8 Michael S. Tsirkin
@ 2026-06-14 19:06 ` Michael S. Tsirkin
  2026-06-14 19:06 ` [PULL 012/106] intel_iommu: Export some functions Michael S. Tsirkin
                   ` (95 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Zhenzhong Duan, Yi Liu, Clement Mathieu--Drif,
	Jason Wang, Paolo Bonzini, Richard Henderson

From: Zhenzhong Duan <zhenzhong.duan@intel.com>

Refactor vtd_dev_get_pe_from_pasid() to take individual parameters
(IntelIOMMUState, PCIBus, devfn, pasid) instead of VTDAddressSpace.

This makes the function more reusable and prepares it for export to be
used in the acceleration path. Remove inline qualifier as the function
will be exported in a subsequent patch.

No functional changes intended.

Suggested-by: Yi Liu <yi.l.liu@intel.com>
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260527054658.1021096-7-zhenzhong.duan@intel.com>
Reviewed-by: Clement Mathieu--Drif <clement.mathieu--drif@bull.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/i386/intel_iommu.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index b22feb0301..632df21034 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -3113,10 +3113,10 @@ static bool vtd_process_piotlb_desc(IntelIOMMUState *s,
     return true;
 }
 
-static inline int vtd_dev_get_pe_from_pasid(VTDAddressSpace *vtd_as,
-                                            VTDPASIDEntry *pe)
+static int vtd_dev_get_pe_from_pasid(IntelIOMMUState *s, PCIBus *bus,
+                                     uint8_t devfn, uint32_t pasid,
+                                     VTDPASIDEntry *pe)
 {
-    IntelIOMMUState *s = vtd_as->iommu_state;
     VTDContextEntry ce;
     int ret;
 
@@ -3124,13 +3124,12 @@ static inline int vtd_dev_get_pe_from_pasid(VTDAddressSpace *vtd_as,
         return -VTD_FR_RTADDR_INV_TTM;
     }
 
-    ret = vtd_dev_to_context_entry(s, pci_bus_num(vtd_as->bus), vtd_as->devfn,
-                                   &ce);
+    ret = vtd_dev_to_context_entry(s, pci_bus_num(bus), devfn, &ce);
     if (ret) {
         return ret;
     }
 
-    return vtd_ce_get_pasid_entry(s, &ce, pe, vtd_as->pasid);
+    return vtd_ce_get_pasid_entry(s, &ce, pe, pasid);
 }
 
 static int vtd_pasid_entry_compare(VTDPASIDEntry *p1, VTDPASIDEntry *p2)
@@ -3151,7 +3150,8 @@ static void vtd_pasid_cache_sync_locked(gpointer key, gpointer value,
     const char *err_prefix = "Attaching to HWPT failed: ";
     Error *local_err = NULL;
 
-    if (vtd_dev_get_pe_from_pasid(vtd_as, &pe)) {
+    if (vtd_dev_get_pe_from_pasid(vtd_as->iommu_state, vtd_as->bus,
+                                  vtd_as->devfn, vtd_as->pasid, &pe)) {
         if (!pc_entry->valid) {
             return;
         }
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 012/106] intel_iommu: Export some functions
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (10 preceding siblings ...)
  2026-06-14 19:06 ` [PULL 011/106] intel_iommu: make vtd_dev_get_pe_from_pasid() more generic Michael S. Tsirkin
@ 2026-06-14 19:06 ` Michael S. Tsirkin
  2026-06-14 19:06 ` [PULL 013/106] intel_iommu: Fix PASID validity check in fault reporting Michael S. Tsirkin
                   ` (94 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Zhenzhong Duan, Clement Mathieu--Drif, Yi Liu,
	Xudong Hao, Jason Wang, Clément Mathieu--Drif, Paolo Bonzini,
	Richard Henderson

From: Zhenzhong Duan <zhenzhong.duan@intel.com>

Export some functions for accel code usages. Inline functions and MACROs
are moved to internal header files. Then accel code in following patches
could access them.

Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Reviewed-by: Clement Mathieu--Drif <clement.mathieu--drif@eviden.com>
Reviewed-by: Yi Liu <yi.l.liu@intel.com>
Tested-by: Xudong Hao <xudong.hao@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260527054658.1021096-8-zhenzhong.duan@intel.com>
---
 hw/i386/intel_iommu.c          | 43 +++++++---------------------------
 hw/i386/intel_iommu_internal.h | 31 ++++++++++++++++++++++++
 2 files changed, 40 insertions(+), 34 deletions(-)

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 632df21034..e15aecf5f9 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -42,12 +42,6 @@
 #include "migration/vmstate.h"
 #include "trace.h"
 
-/* context entry operations */
-#define VTD_CE_GET_PASID_DIR_TABLE(ce) \
-    ((ce)->val[0] & VTD_PASID_DIR_BASE_ADDR_MASK)
-#define VTD_CE_GET_PRE(ce) \
-    ((ce)->val[0] & VTD_SM_CONTEXT_ENTRY_PRE)
-
 /*
  * Paging mode for first-stage translation (VTD spec Figure 9-6)
  * 00: 4-level paging, 01: 5-level paging
@@ -831,18 +825,12 @@ static inline bool vtd_pe_type_check(IntelIOMMUState *s, VTDPASIDEntry *pe)
     }
 }
 
-static inline bool vtd_pdire_present(VTDPASIDDirEntry *pdire)
-{
-    return pdire->val & 1;
-}
-
 /**
  * Caller of this function should check present bit if wants
  * to use pdir entry for further usage except for fpd bit check.
  */
-static int vtd_get_pdire_from_pdir_table(dma_addr_t pasid_dir_base,
-                                         uint32_t pasid,
-                                         VTDPASIDDirEntry *pdire)
+int vtd_get_pdire_from_pdir_table(dma_addr_t pasid_dir_base, uint32_t pasid,
+                                  VTDPASIDDirEntry *pdire)
 {
     uint32_t index;
     dma_addr_t addr, entry_size;
@@ -860,15 +848,8 @@ static int vtd_get_pdire_from_pdir_table(dma_addr_t pasid_dir_base,
     return 0;
 }
 
-static inline bool vtd_pe_present(VTDPASIDEntry *pe)
-{
-    return pe->val[0] & VTD_PASID_ENTRY_P;
-}
-
-static int vtd_get_pe_in_pasid_leaf_table(IntelIOMMUState *s,
-                                          uint32_t pasid,
-                                          dma_addr_t addr,
-                                          VTDPASIDEntry *pe)
+int vtd_get_pe_in_pasid_leaf_table(IntelIOMMUState *s, uint32_t pasid,
+                                   dma_addr_t addr, VTDPASIDEntry *pe)
 {
     uint8_t pgtt;
     uint32_t index;
@@ -1526,8 +1507,8 @@ static int vtd_ce_pasid_0_check(IntelIOMMUState *s, VTDContextEntry *ce)
 }
 
 /* Map a device to its corresponding domain (context-entry) */
-static int vtd_dev_to_context_entry(IntelIOMMUState *s, uint8_t bus_num,
-                                    uint8_t devfn, VTDContextEntry *ce)
+int vtd_dev_to_context_entry(IntelIOMMUState *s, uint8_t bus_num,
+                             uint8_t devfn, VTDContextEntry *ce)
 {
     VTDRootEntry re;
     int ret_fr;
@@ -1909,7 +1890,7 @@ static VTDAddressSpace *vtd_get_as_by_sid_and_pasid(IntelIOMMUState *s,
                              vtd_find_as_by_sid_and_pasid, &key);
 }
 
-static VTDAddressSpace *vtd_get_as_by_sid(IntelIOMMUState *s, uint16_t sid)
+VTDAddressSpace *vtd_get_as_by_sid(IntelIOMMUState *s, uint16_t sid)
 {
     return vtd_get_as_by_sid_and_pasid(s, sid, PCI_NO_PASID);
 }
@@ -3113,9 +3094,8 @@ static bool vtd_process_piotlb_desc(IntelIOMMUState *s,
     return true;
 }
 
-static int vtd_dev_get_pe_from_pasid(IntelIOMMUState *s, PCIBus *bus,
-                                     uint8_t devfn, uint32_t pasid,
-                                     VTDPASIDEntry *pe)
+int vtd_dev_get_pe_from_pasid(IntelIOMMUState *s, PCIBus *bus, uint8_t devfn,
+                              uint32_t pasid, VTDPASIDEntry *pe)
 {
     VTDContextEntry ce;
     int ret;
@@ -3132,11 +3112,6 @@ static int vtd_dev_get_pe_from_pasid(IntelIOMMUState *s, PCIBus *bus,
     return vtd_ce_get_pasid_entry(s, &ce, pe, pasid);
 }
 
-static int vtd_pasid_entry_compare(VTDPASIDEntry *p1, VTDPASIDEntry *p2)
-{
-    return memcmp(p1, p2, sizeof(*p1));
-}
-
 /* Update or invalidate pasid cache based on the pasid entry in guest memory. */
 static void vtd_pasid_cache_sync_locked(gpointer key, gpointer value,
                                         gpointer user_data)
diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
index db4f186a3e..d738ef1803 100644
--- a/hw/i386/intel_iommu_internal.h
+++ b/hw/i386/intel_iommu_internal.h
@@ -620,6 +620,12 @@ typedef struct VTDRootEntry VTDRootEntry;
 #define VTD_SM_CONTEXT_ENTRY_RSVD_VAL1      0xffffffffffe00000ULL
 #define VTD_SM_CONTEXT_ENTRY_PRE            0x10ULL
 
+/* context entry operations */
+#define VTD_CE_GET_PASID_DIR_TABLE(ce) \
+    ((ce)->val[0] & VTD_PASID_DIR_BASE_ADDR_MASK)
+#define VTD_CE_GET_PRE(ce) \
+    ((ce)->val[0] & VTD_SM_CONTEXT_ENTRY_PRE)
+
 typedef struct VTDPASIDCacheInfo {
     uint8_t type;
     uint16_t did;
@@ -746,4 +752,29 @@ static inline bool vtd_pe_pgtt_is_fst(VTDPASIDEntry *pe)
 {
     return (VTD_SM_PASID_ENTRY_PGTT(pe) == VTD_SM_PASID_ENTRY_FST);
 }
+
+static inline bool vtd_pdire_present(VTDPASIDDirEntry *pdire)
+{
+    return pdire->val & 1;
+}
+
+static inline bool vtd_pe_present(VTDPASIDEntry *pe)
+{
+    return pe->val[0] & VTD_PASID_ENTRY_P;
+}
+
+static inline int vtd_pasid_entry_compare(VTDPASIDEntry *p1, VTDPASIDEntry *p2)
+{
+    return memcmp(p1, p2, sizeof(*p1));
+}
+
+int vtd_get_pdire_from_pdir_table(dma_addr_t pasid_dir_base, uint32_t pasid,
+                                  VTDPASIDDirEntry *pdire);
+int vtd_get_pe_in_pasid_leaf_table(IntelIOMMUState *s, uint32_t pasid,
+                                   dma_addr_t addr, VTDPASIDEntry *pe);
+int vtd_dev_to_context_entry(IntelIOMMUState *s, uint8_t bus_num,
+                             uint8_t devfn, VTDContextEntry *ce);
+VTDAddressSpace *vtd_get_as_by_sid(IntelIOMMUState *s, uint16_t sid);
+int vtd_dev_get_pe_from_pasid(IntelIOMMUState *s, PCIBus *bus, uint8_t devfn,
+                              uint32_t pasid, VTDPASIDEntry *pe);
 #endif
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 013/106] intel_iommu: Fix PASID validity check in fault reporting
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (11 preceding siblings ...)
  2026-06-14 19:06 ` [PULL 012/106] intel_iommu: Export some functions Michael S. Tsirkin
@ 2026-06-14 19:06 ` Michael S. Tsirkin
  2026-06-14 19:06 ` [PULL 014/106] intel_iommu: Use IOMMU_NO_PASID and delete PASID_0 Michael S. Tsirkin
                   ` (93 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Zhenzhong Duan, Yi Liu, Clement Mathieu--Drif,
	Jason Wang, Paolo Bonzini, Richard Henderson

From: Zhenzhong Duan <zhenzhong.duan@intel.com>

The current code incorrectly uses "pasid != PCI_NO_PASID" to determine if
PASID should be reported in fault records. However, this check happens
after the code converts PCI_NO_PASID to PASID_0 in scalable mode.

This means that for requests that originally had PCI_NO_PASID, the check
"pasid != PCI_NO_PASID" will incorrectly return true (since pasid is now
PASID_0), causing fault records to incorrectly indicate PASID validity.
According to the VT-d specification, the PASID field in fault records is
only valid for Requests-with-PASID:

  "When Set, indicates the faulted request has a PASID TLP Prefix."

Fix this by capturing the original PASID state before the PCI_NO_PASID to
PASID_0 conversion, ensuring fault records correctly reflect whether the
original request had a PASID.

Fixes: 1b2b12376c8a ("intel_iommu: process PASID-based iotlb invalidation")
Suggested-by: Yi Liu <yi.l.liu@intel.com>
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260527054658.1021096-9-zhenzhong.duan@intel.com>
Reviewed-by: Clement Mathieu--Drif <clement.mathieu--drif@bull.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/i386/intel_iommu.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index e15aecf5f9..539e8f5763 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -2109,6 +2109,7 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus,
     bool is_fpd_set = false;
     bool reads = true;
     bool writes = true;
+    bool is_pasid = pasid != PCI_NO_PASID;
     uint8_t access_flags, pgtt;
     VTDIOTLBEntry *iotlb_entry;
     uint64_t xlat, size;
@@ -2235,7 +2236,7 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus,
     if (ret_fr) {
         if (!vtd_is_recoverable_fault(-ret_fr, iommu_idx)) {
             vtd_report_fault(s, -ret_fr, is_fpd_set, source_id,
-                            addr, is_write, pasid != PCI_NO_PASID, pasid);
+                            addr, is_write, is_pasid, pasid);
         }
         goto error;
     }
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 014/106] intel_iommu: Use IOMMU_NO_PASID and delete PASID_0
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (12 preceding siblings ...)
  2026-06-14 19:06 ` [PULL 013/106] intel_iommu: Fix PASID validity check in fault reporting Michael S. Tsirkin
@ 2026-06-14 19:06 ` Michael S. Tsirkin
  2026-06-14 19:06 ` [PULL 015/106] intel_iommu: Refactor PASID processing to use IOMMU_NO_PASID internally Michael S. Tsirkin
                   ` (92 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Zhenzhong Duan, Yi Liu, Clement Mathieu--Drif,
	Xudong Hao, Jason Wang, Paolo Bonzini, Richard Henderson

From: Zhenzhong Duan <zhenzhong.duan@intel.com>

In previous patch we introduced a global macro IOMMU_NO_PASID(0) for
the RID attachment, this makes the local macro PASID_0 redundant.
Delete it and use IOMMU_NO_PASID instead.

No functional changes intended.

Suggested-by: Yi Liu <yi.l.liu@intel.com>
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Reviewed-by: Yi Liu <yi.l.liu@intel.com>
Reviewed-by: Clement Mathieu--Drif <clement.mathieu--drif@bull.com>
Tested-by: Xudong Hao <xudong.hao@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260527054658.1021096-10-zhenzhong.duan@intel.com>
---
 hw/i386/intel_iommu.c          | 22 +++++++++++-----------
 hw/i386/intel_iommu_accel.c    |  2 +-
 hw/i386/intel_iommu_internal.h |  1 -
 3 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 539e8f5763..3784910ce0 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -941,7 +941,7 @@ static int vtd_ce_get_pasid_entry(IntelIOMMUState *s, VTDContextEntry *ce,
     dma_addr_t pasid_dir_base;
 
     if (pasid == PCI_NO_PASID) {
-        pasid = PASID_0;
+        pasid = IOMMU_NO_PASID;
     }
     pasid_dir_base = VTD_CE_GET_PASID_DIR_TABLE(ce);
     return vtd_get_pe_from_pasid_table(s, pasid_dir_base, pasid, pe);
@@ -958,7 +958,7 @@ static int vtd_ce_get_pasid_fpd(IntelIOMMUState *s,
     VTDPASIDEntry pe;
 
     if (pasid == PCI_NO_PASID) {
-        pasid = PASID_0;
+        pasid = IOMMU_NO_PASID;
     }
     pasid_dir_base = VTD_CE_GET_PASID_DIR_TABLE(ce);
 
@@ -1501,9 +1501,9 @@ static int vtd_ce_pasid_0_check(IntelIOMMUState *s, VTDContextEntry *ce)
 
     /*
      * Make sure in Scalable Mode, a present context entry
-     * has valid pasid entry setting at PASID_0.
+     * has valid pasid entry setting at IOMMU_NO_PASID.
      */
-    return vtd_ce_get_pasid_entry(s, ce, &pe, PASID_0);
+    return vtd_ce_get_pasid_entry(s, ce, &pe, IOMMU_NO_PASID);
 }
 
 /* Map a device to its corresponding domain (context-entry) */
@@ -1564,7 +1564,7 @@ int vtd_dev_to_context_entry(IntelIOMMUState *s, uint8_t bus_num,
         }
     } else {
         /*
-         * Check if the programming of pasid setting of PASID_0
+         * Check if the programming of pasid setting of IOMMU_NO_PASID
          * is valid, and thus avoids to check pasid entry fetching
          * result in future helper function calling.
          */
@@ -2123,7 +2123,7 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus,
     vtd_iommu_lock(s);
 
     if (pasid == PCI_NO_PASID && s->root_scalable) {
-        pasid = PASID_0;
+        pasid = IOMMU_NO_PASID;
     }
 
     /* Try to fetch pte from IOTLB */
@@ -2488,7 +2488,7 @@ static void vtd_iotlb_domain_invalidate(IntelIOMMUState *s, uint16_t domain_id)
 }
 
 /*
- * There is no pasid field in iotlb invalidation descriptor, so PCI_NO_PASID
+ * There is no pasid field in iotlb invalidation descriptor, so IOMMU_NO_PASID
  * is passed as parameter. Piotlb invalidation supports pasid, pasid in its
  * descriptor is passed which should not be PCI_NO_PASID.
  */
@@ -2509,10 +2509,10 @@ static void vtd_iotlb_page_invalidate_notify(IntelIOMMUState *s,
              * In legacy mode, vtd_as->pasid == pasid is always true.
              * In scalable mode, for vtd address space backing a PCI
              * device without pasid, needs to compare pasid with
-             * PASID_0 of this device.
+             * IOMMU_NO_PASID of this device.
              */
             if (!(vtd_as->pasid == pasid ||
-                  (vtd_as->pasid == PCI_NO_PASID && pasid == PASID_0))) {
+                  (vtd_as->pasid == PCI_NO_PASID && pasid == IOMMU_NO_PASID))) {
                 continue;
             }
 
@@ -2564,7 +2564,7 @@ static void vtd_iotlb_page_invalidate(IntelIOMMUState *s, uint16_t domain_id,
     vtd_iommu_lock(s);
     g_hash_table_foreach_remove(s->iotlb, vtd_hash_remove_by_page, &info);
     vtd_iommu_unlock(s);
-    vtd_iotlb_page_invalidate_notify(s, domain_id, addr, am, PCI_NO_PASID);
+    vtd_iotlb_page_invalidate_notify(s, domain_id, addr, am, IOMMU_NO_PASID);
 }
 
 /* Flush IOTLB
@@ -3023,7 +3023,7 @@ static void vtd_piotlb_pasid_invalidate(IntelIOMMUState *s,
         if (!vtd_dev_to_context_entry(s, pci_bus_num(vtd_as->bus),
                                       vtd_as->devfn, &ce) &&
             domain_id == vtd_get_domain_id(s, &ce, vtd_as->pasid)) {
-            if ((vtd_as->pasid != PCI_NO_PASID || pasid != PASID_0) &&
+            if ((vtd_as->pasid != PCI_NO_PASID || pasid != IOMMU_NO_PASID) &&
                 vtd_as->pasid != pasid) {
                 continue;
             }
diff --git a/hw/i386/intel_iommu_accel.c b/hw/i386/intel_iommu_accel.c
index 6a12cdac10..14180f61cd 100644
--- a/hw/i386/intel_iommu_accel.c
+++ b/hw/i386/intel_iommu_accel.c
@@ -217,7 +217,7 @@ static void vtd_flush_host_piotlb_locked(gpointer key, gpointer value,
 
     did = VTD_SM_PASID_ENTRY_DID(&pc_entry->pasid_entry);
 
-    if (piotlb_info->domain_id == did && piotlb_info->pasid == PASID_0) {
+    if (piotlb_info->domain_id == did && piotlb_info->pasid == IOMMU_NO_PASID) {
         HostIOMMUDeviceIOMMUFD *hiodi =
             HOST_IOMMU_DEVICE_IOMMUFD(vtd_hiod->hiod);
         uint32_t entry_num = 1; /* Only implement one request for simplicity */
diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
index d738ef1803..ee59df09f8 100644
--- a/hw/i386/intel_iommu_internal.h
+++ b/hw/i386/intel_iommu_internal.h
@@ -615,7 +615,6 @@ typedef struct VTDRootEntry VTDRootEntry;
 #define VTD_CTX_ENTRY_LEGACY_SIZE     16
 #define VTD_CTX_ENTRY_SCALABLE_SIZE   32
 
-#define PASID_0                             0
 #define VTD_SM_CONTEXT_ENTRY_RSVD_VAL0(aw)  (0x1e0ULL | ~VTD_HAW_MASK(aw))
 #define VTD_SM_CONTEXT_ENTRY_RSVD_VAL1      0xffffffffffe00000ULL
 #define VTD_SM_CONTEXT_ENTRY_PRE            0x10ULL
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 015/106] intel_iommu: Refactor PASID processing to use IOMMU_NO_PASID internally
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (13 preceding siblings ...)
  2026-06-14 19:06 ` [PULL 014/106] intel_iommu: Use IOMMU_NO_PASID and delete PASID_0 Michael S. Tsirkin
@ 2026-06-14 19:06 ` Michael S. Tsirkin
  2026-06-14 19:06 ` [PULL 016/106] intel_iommu_accel: Handle PASID entry addition for pc_inv_dsc request Michael S. Tsirkin
                   ` (91 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Zhenzhong Duan, Clement Mathieu--Drif, Jason Wang,
	Yi Liu, Paolo Bonzini, Richard Henderson, Peter Xu,
	Philippe Mathieu-Daudé

From: Zhenzhong Duan <zhenzhong.duan@intel.com>

The PCI subsystem uses PCI_NO_PASID for requests-without-PASID, but VT-d
emulation uses IOMMU_NO_PASID internally (ecap.RPS==0). This leads to
conversion and checking code between PCI_NO_PASID and IOMMU_NO_PASID
throughout the implementation.

Refactor to use IOMMU PASID consistently within Intel IOMMU by storing
IOMMU PASID value in vtd_as->pasid. After this change, PCI_NO_PASID is
only used at three boundary points:

1. PCI_NO_PASID -> IOMMU_NO_PASID: Convert PCI PASID to IOMMU PASID in
   vtd_find_add_as() and cache in vtd_as->pasid.
2. IOMMU_NO_PASID -> PCI_NO_PASID: Convert when notifying UNMAP events
   via memory_region_notify_iommu() and returning IOMMUTLBEntry in
   vtd_iommu_translate().

This eliminates conversion/checks in PASID table lookups, simplifies
invalidation logic with consistent PASID values, and improves code
readability. The PCI subsystem interface remains unchanged to maintain
compatibility with other IOMMU implementations that may not use PASID 0
for requests-without-PASID.

Suggested-by: Clement Mathieu--Drif <clement.mathieu--drif@bull.com>
Signed-off-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: <20260527054658.1021096-11-zhenzhong.duan@intel.com>
---
 hw/i386/intel_iommu.c       | 166 +++++++++++++++++-------------------
 hw/i386/intel_iommu_accel.c |   2 +-
 include/system/memory.h     |   2 +-
 3 files changed, 81 insertions(+), 89 deletions(-)

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 3784910ce0..88e0c58c08 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -938,12 +938,8 @@ static int vtd_get_pe_from_pasid_table(IntelIOMMUState *s,
 static int vtd_ce_get_pasid_entry(IntelIOMMUState *s, VTDContextEntry *ce,
                                   VTDPASIDEntry *pe, uint32_t pasid)
 {
-    dma_addr_t pasid_dir_base;
+    dma_addr_t pasid_dir_base = VTD_CE_GET_PASID_DIR_TABLE(ce);
 
-    if (pasid == PCI_NO_PASID) {
-        pasid = IOMMU_NO_PASID;
-    }
-    pasid_dir_base = VTD_CE_GET_PASID_DIR_TABLE(ce);
     return vtd_get_pe_from_pasid_table(s, pasid_dir_base, pasid, pe);
 }
 
@@ -953,15 +949,10 @@ static int vtd_ce_get_pasid_fpd(IntelIOMMUState *s,
                                 uint32_t pasid)
 {
     int ret;
-    dma_addr_t pasid_dir_base;
+    dma_addr_t pasid_dir_base = VTD_CE_GET_PASID_DIR_TABLE(ce);
     VTDPASIDDirEntry pdire;
     VTDPASIDEntry pe;
 
-    if (pasid == PCI_NO_PASID) {
-        pasid = IOMMU_NO_PASID;
-    }
-    pasid_dir_base = VTD_CE_GET_PASID_DIR_TABLE(ce);
-
     /*
      * No present bit check since fpd is meaningful even
      * if the present bit is clear.
@@ -1750,7 +1741,7 @@ static bool vtd_switch_address_space(VTDAddressSpace *as)
          *
          * Need to disable ir for as with PASID.
          */
-        if (as->pasid != PCI_NO_PASID) {
+        if (as->pasid != IOMMU_NO_PASID) {
             memory_region_set_enabled(&as->iommu_ir, false);
         } else {
             memory_region_set_enabled(&as->iommu_ir, true);
@@ -1780,7 +1771,7 @@ static bool vtd_switch_address_space(VTDAddressSpace *as)
      * We enable per as memory region (iommu_ir_fault) for catching
      * the translation for interrupt range through PASID + PT.
      */
-    if (pt && as->pasid != PCI_NO_PASID) {
+    if (pt && as->pasid != IOMMU_NO_PASID) {
         memory_region_set_enabled(&as->iommu_ir_fault, true);
     } else {
         memory_region_set_enabled(&as->iommu_ir_fault, false);
@@ -1892,7 +1883,7 @@ static VTDAddressSpace *vtd_get_as_by_sid_and_pasid(IntelIOMMUState *s,
 
 VTDAddressSpace *vtd_get_as_by_sid(IntelIOMMUState *s, uint16_t sid)
 {
-    return vtd_get_as_by_sid_and_pasid(s, sid, PCI_NO_PASID);
+    return vtd_get_as_by_sid_and_pasid(s, sid, IOMMU_NO_PASID);
 }
 
 static void vtd_pt_enable_fast_path(IntelIOMMUState *s, uint16_t source_id)
@@ -2109,7 +2100,7 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus,
     bool is_fpd_set = false;
     bool reads = true;
     bool writes = true;
-    bool is_pasid = pasid != PCI_NO_PASID;
+    bool is_pasid = pasid != IOMMU_NO_PASID;
     uint8_t access_flags, pgtt;
     VTDIOTLBEntry *iotlb_entry;
     uint64_t xlat, size;
@@ -2122,10 +2113,6 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus,
 
     vtd_iommu_lock(s);
 
-    if (pasid == PCI_NO_PASID && s->root_scalable) {
-        pasid = IOMMU_NO_PASID;
-    }
-
     /* Try to fetch pte from IOTLB */
     iotlb_entry = vtd_lookup_iotlb(s, source_id, pasid, addr);
     if (iotlb_entry) {
@@ -2490,7 +2477,7 @@ static void vtd_iotlb_domain_invalidate(IntelIOMMUState *s, uint16_t domain_id)
 /*
  * There is no pasid field in iotlb invalidation descriptor, so IOMMU_NO_PASID
  * is passed as parameter. Piotlb invalidation supports pasid, pasid in its
- * descriptor is passed which should not be PCI_NO_PASID.
+ * descriptor is passed.
  */
 static void vtd_iotlb_page_invalidate_notify(IntelIOMMUState *s,
                                              uint16_t domain_id, hwaddr addr,
@@ -2504,48 +2491,41 @@ static void vtd_iotlb_page_invalidate_notify(IntelIOMMUState *s,
     QLIST_FOREACH(vtd_as, &(s->vtd_as_with_notifiers), next) {
         ret = vtd_dev_to_context_entry(s, pci_bus_num(vtd_as->bus),
                                        vtd_as->devfn, &ce);
-        if (!ret && domain_id == vtd_get_domain_id(s, &ce, vtd_as->pasid)) {
-            /*
-             * In legacy mode, vtd_as->pasid == pasid is always true.
-             * In scalable mode, for vtd address space backing a PCI
-             * device without pasid, needs to compare pasid with
-             * IOMMU_NO_PASID of this device.
-             */
-            if (!(vtd_as->pasid == pasid ||
-                  (vtd_as->pasid == PCI_NO_PASID && pasid == IOMMU_NO_PASID))) {
-                continue;
-            }
+        if (ret || vtd_as->pasid != pasid ||
+            domain_id != vtd_get_domain_id(s, &ce, pasid)) {
+            continue;
+        }
 
-            if (vtd_as_has_map_notifier(vtd_as)) {
-                /*
-                 * When first stage translation is off, as long as we have MAP
-                 * notifications registered in any of our IOMMU notifiers,
-                 * we need to sync the shadow page table. Otherwise VFIO
-                 * device attaches to nested page table instead of shadow
-                 * page table, so no need to sync.
-                 */
-                if (!s->fsts || !s->root_scalable) {
-                    vtd_sync_shadow_page_table_range(vtd_as, &ce, addr, size);
-                }
-            } else {
-                /*
-                 * For UNMAP-only notifiers, we don't need to walk the
-                 * page tables.  We just deliver the PSI down to
-                 * invalidate caches.
-                 */
-                const IOMMUTLBEvent event = {
-                    .type = IOMMU_NOTIFIER_UNMAP,
-                    .entry = {
-                        .target_as = &address_space_memory,
-                        .iova = addr,
-                        .translated_addr = 0,
-                        .addr_mask = size - 1,
-                        .perm = IOMMU_NONE,
-                        .pasid = vtd_as->pasid,
-                    },
-                };
-                memory_region_notify_iommu(&vtd_as->iommu, 0, event);
+        if (vtd_as_has_map_notifier(vtd_as)) {
+            /*
+             * When first stage translation is off, as long as we have MAP
+             * notifications registered in any of our IOMMU notifiers,
+             * we need to sync the shadow page table. Otherwise VFIO
+             * device attaches to nested page table instead of shadow
+             * page table, so no need to sync.
+             */
+            if (!s->fsts || !s->root_scalable) {
+                vtd_sync_shadow_page_table_range(vtd_as, &ce, addr, size);
             }
+        } else {
+            /*
+             * For UNMAP-only notifiers, we don't need to walk the
+             * page tables.  We just deliver the PSI down to
+             * invalidate caches.
+             */
+            const IOMMUTLBEvent event = {
+                .type = IOMMU_NOTIFIER_UNMAP,
+                .entry = {
+                    .target_as = &address_space_memory,
+                    .iova = addr,
+                    .translated_addr = 0,
+                    .addr_mask = size - 1,
+                    .perm = IOMMU_NONE,
+                     /* Other sub-systems use PCI pasid */
+                    .pasid = pasid == IOMMU_NO_PASID ? PCI_NO_PASID : pasid,
+                },
+            };
+            memory_region_notify_iommu(&vtd_as->iommu, 0, event);
         }
     }
 }
@@ -3008,6 +2988,7 @@ static void vtd_piotlb_pasid_invalidate(IntelIOMMUState *s,
     VTDIOTLBPageInvInfo info;
     VTDAddressSpace *vtd_as;
     VTDContextEntry ce;
+    int ret;
 
     info.domain_id = domain_id;
     info.pasid = pasid;
@@ -3020,17 +3001,15 @@ static void vtd_piotlb_pasid_invalidate(IntelIOMMUState *s,
     vtd_iommu_unlock(s);
 
     QLIST_FOREACH(vtd_as, &s->vtd_as_with_notifiers, next) {
-        if (!vtd_dev_to_context_entry(s, pci_bus_num(vtd_as->bus),
-                                      vtd_as->devfn, &ce) &&
-            domain_id == vtd_get_domain_id(s, &ce, vtd_as->pasid)) {
-            if ((vtd_as->pasid != PCI_NO_PASID || pasid != IOMMU_NO_PASID) &&
-                vtd_as->pasid != pasid) {
-                continue;
-            }
+        ret = vtd_dev_to_context_entry(s, pci_bus_num(vtd_as->bus),
+                                       vtd_as->devfn, &ce);
+        if (ret || vtd_as->pasid != pasid ||
+            domain_id != vtd_get_domain_id(s, &ce, pasid)) {
+            continue;
+        }
 
-            if (!s->fsts || !vtd_as_has_map_notifier(vtd_as)) {
-                vtd_address_space_sync(vtd_as);
-            }
+        if (!s->fsts || !vtd_as_has_map_notifier(vtd_as)) {
+            vtd_address_space_sync(vtd_as);
         }
     }
 }
@@ -3239,7 +3218,7 @@ static bool vtd_process_pasid_desc(IntelIOMMUState *s,
         /* PASID selective implies a DID selective */
         trace_vtd_inv_desc_pasid_cache_psi(did, pasid);
         pc_info.did = did;
-        pc_info.pasid = pasid ?: PCI_NO_PASID;
+        pc_info.pasid = pasid;
         break;
 
     case VTD_INV_DESC_PASIDC_G_GLOBAL:
@@ -3291,6 +3270,7 @@ static void do_invalidate_device_tlb(VTDAddressSpace *vtd_dev_as,
      * ...
      */
 
+    uint32_t pasid = vtd_dev_as->pasid;
     IOMMUTLBEvent event;
     uint64_t sz;
 
@@ -3307,7 +3287,8 @@ static void do_invalidate_device_tlb(VTDAddressSpace *vtd_dev_as,
     event.entry.iova = addr;
     event.entry.perm = IOMMU_NONE;
     event.entry.translated_addr = 0;
-    event.entry.pasid = vtd_dev_as->pasid;
+    /* Other sub-systems use PCI pasid */
+    event.entry.pasid = pasid == IOMMU_NO_PASID ? PCI_NO_PASID : pasid;
     memory_region_notify_iommu(&vtd_dev_as->iommu, 0, event);
 }
 
@@ -3335,7 +3316,7 @@ static bool vtd_process_device_piotlb_desc(IntelIOMMUState *s,
     sid = VTD_INV_DESC_PASID_DEVICE_IOTLB_SID(inv_desc->lo);
     if (global) {
         QLIST_FOREACH(vtd_dev_as, &s->vtd_as_with_notifiers, next) {
-            if ((vtd_dev_as->pasid != PCI_NO_PASID) &&
+            if ((vtd_dev_as->pasid != IOMMU_NO_PASID) &&
                 (PCI_BUILD_BDF(pci_bus_num(vtd_dev_as->bus),
                                            vtd_dev_as->devfn) == sid)) {
                 do_invalidate_device_tlb(vtd_dev_as, size, addr);
@@ -3983,13 +3964,12 @@ static void vtd_mem_write(void *opaque, hwaddr addr,
 }
 
 static void vtd_prepare_identity_entry(hwaddr addr, IOMMUAccessFlags perm,
-                                         uint32_t pasid, IOMMUTLBEntry *iotlb)
+                                       IOMMUTLBEntry *iotlb)
 {
     iotlb->iova = addr & VTD_PAGE_MASK_4K;
     iotlb->translated_addr = addr & VTD_PAGE_MASK_4K;
     iotlb->addr_mask = ~VTD_PAGE_MASK_4K;
     iotlb->perm = perm;
-    iotlb->pasid = pasid;
 }
 
 static inline void vtd_prepare_error_entry(IOMMUTLBEntry *entry)
@@ -4001,6 +3981,10 @@ static inline void vtd_prepare_error_entry(IOMMUTLBEntry *entry)
     entry->pasid = PCI_NO_PASID;
 }
 
+/*
+ * This function returns translation result to other sub-system such as PCI,
+ * so iommu pasid is converted to PCI pasid and returned in IOMMUTLBEntry.
+ */
 static IOMMUTLBEntry vtd_iommu_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
                                          IOMMUAccessFlags flag, int iommu_idx)
 {
@@ -4009,7 +3993,7 @@ static IOMMUTLBEntry vtd_iommu_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
     IOMMUTLBEntry iotlb = {
         /* We'll fill in the rest later. */
         .target_as = &address_space_memory,
-        .pasid = vtd_as->pasid,
+        .pasid = vtd_as->pasid == IOMMU_NO_PASID ? PCI_NO_PASID : vtd_as->pasid,
     };
     bool success;
     bool is_write = flag & IOMMU_WO;
@@ -4017,9 +4001,8 @@ static IOMMUTLBEntry vtd_iommu_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
     if (likely(s->dmar_enabled)) {
         /* Only support translated requests in scalable mode */
         if (iommu_idx == VTD_IDX_TRANSLATED && s->root_scalable) {
-            if (vtd_as->pasid == PCI_NO_PASID) {
-                vtd_prepare_identity_entry(addr, IOMMU_RW, PCI_NO_PASID,
-                                           &iotlb);
+            if (vtd_as->pasid == IOMMU_NO_PASID) {
+                vtd_prepare_identity_entry(addr, IOMMU_RW, &iotlb);
                 success = true;
             } else {
                 vtd_prepare_error_entry(&iotlb);
@@ -4034,7 +4017,7 @@ static IOMMUTLBEntry vtd_iommu_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
         }
     } else {
         /* DMAR disabled, passthrough, use 4k-page*/
-        vtd_prepare_identity_entry(addr, IOMMU_RW, vtd_as->pasid, &iotlb);
+        vtd_prepare_identity_entry(addr, IOMMU_RW, &iotlb);
         success = true;
     }
 
@@ -4460,7 +4443,7 @@ static void vtd_report_sid_ir_illegal_access(IntelIOMMUState *s, uint16_t sid,
     }
 
     vtd_report_fault(s, VTD_FR_SM_INTERRUPT_ADDR, is_fpd_set, sid, addr,
-                     is_write, pasid != PCI_NO_PASID, pasid);
+                     is_write, pasid != IOMMU_NO_PASID, pasid);
 }
 
 static void vtd_report_ir_illegal_access(VTDAddressSpace *vtd_as,
@@ -4488,7 +4471,6 @@ static MemTxResult vtd_mem_ir_write(void *opaque, hwaddr addr,
     int ret = 0;
     MSIMessage from = {}, to = {};
     uint16_t sid = X86_IOMMU_SID_INVALID;
-    uint32_t pasid;
 
     from.address = (uint64_t) addr + VTD_INTERRUPT_ADDR_FIRST;
     from.data = (uint32_t) value;
@@ -4496,11 +4478,11 @@ static MemTxResult vtd_mem_ir_write(void *opaque, hwaddr addr,
     if (!attrs.unspecified) {
         /* We have explicit Source ID */
         sid = attrs.requester_id;
-        pasid = attrs.pid != 0 ? attrs.pid : PCI_NO_PASID;
 
         if (attrs.address_type == PCI_AT_TRANSLATED &&
             sid != X86_IOMMU_SID_INVALID) {
-            vtd_report_sid_ir_illegal_access(s, sid, pasid, from.address, true);
+            vtd_report_sid_ir_illegal_access(s, sid, attrs.pid, from.address,
+                                             true);
             return MEMTX_ERROR;
         }
     }
@@ -4562,9 +4544,19 @@ static const MemoryRegionOps vtd_mem_ir_fault_ops = {
     },
 };
 
+/*
+ * This function is called by many PCIIOMMUOps callbacks to get
+ * VTDAddressSpace or create one if non-exist. Those callbacks are
+ * used by PCI sub-system and are passed in a PCI pasid value.
+ *
+ * VTD honors iommu pasid, so the first thing is to convert PCI
+ * pasid to iommu pasid.
+ */
 VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus,
                                  int devfn, unsigned int pasid)
 {
+    pasid = pasid == PCI_NO_PASID ? IOMMU_NO_PASID : pasid;
+
     /*
      * We can't simply use sid here since the bus number might not be
      * initialized by the guest.
@@ -4606,7 +4598,7 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus,
         new_key->devfn = devfn;
         new_key->pasid = pasid;
 
-        if (pasid == PCI_NO_PASID) {
+        if (pasid == IOMMU_NO_PASID) {
             snprintf(name, sizeof(name), "vtd-%02x.%x", PCI_SLOT(devfn),
                      PCI_FUNC(devfn));
         } else {
@@ -5290,7 +5282,7 @@ error_get_fpd_and_report:
     vtd_ce_get_pasid_fpd(s, &ce, &is_fpd_set, vtd_as->pasid);
 error_report:
     vtd_report_fault(s, -ret, is_fpd_set, sid, addr, is_write,
-                     vtd_as->pasid != PCI_NO_PASID, vtd_as->pasid);
+                     vtd_as->pasid != IOMMU_NO_PASID, vtd_as->pasid);
     return false;
 }
 
@@ -5381,7 +5373,7 @@ static int vtd_pri_request_page(PCIBus *bus, void *opaque, int devfn,
      */
 
     /* We do not support PRI without PASID */
-    if (vtd_as->pasid == PCI_NO_PASID) {
+    if (vtd_as->pasid == IOMMU_NO_PASID) {
         return -EPERM;
     }
     if (exec_req && !is_read) {
diff --git a/hw/i386/intel_iommu_accel.c b/hw/i386/intel_iommu_accel.c
index 14180f61cd..05b927f303 100644
--- a/hw/i386/intel_iommu_accel.c
+++ b/hw/i386/intel_iommu_accel.c
@@ -207,7 +207,7 @@ static void vtd_flush_host_piotlb_locked(gpointer key, gpointer value,
         return;
     }
 
-    assert(vtd_as->pasid == PCI_NO_PASID);
+    assert(vtd_as->pasid == IOMMU_NO_PASID);
 
     /* Nothing to do if there is no first stage HWPT attached */
     if (!pc_entry->valid ||
diff --git a/include/system/memory.h b/include/system/memory.h
index 1417132f6d..1edb38b07d 100644
--- a/include/system/memory.h
+++ b/include/system/memory.h
@@ -150,7 +150,7 @@ struct IOMMUTLBEntry {
     hwaddr           translated_addr;
     hwaddr           addr_mask;  /* 0xfff = 4k translation */
     IOMMUAccessFlags perm;
-    uint32_t         pasid;
+    uint32_t         pasid; /* PCI pasid */
 };
 
 /*
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 016/106] intel_iommu_accel: Handle PASID entry addition for pc_inv_dsc request
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (14 preceding siblings ...)
  2026-06-14 19:06 ` [PULL 015/106] intel_iommu: Refactor PASID processing to use IOMMU_NO_PASID internally Michael S. Tsirkin
@ 2026-06-14 19:06 ` Michael S. Tsirkin
  2026-06-14 19:06 ` [PULL 017/106] intel_iommu_accel: Handle PASID entry removal " Michael S. Tsirkin
                   ` (90 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Zhenzhong Duan, Yi Liu, Xudong Hao, Jason Wang,
	Clément Mathieu--Drif, Paolo Bonzini, Richard Henderson

From: Zhenzhong Duan <zhenzhong.duan@intel.com>

Structure VTDAddressSpace includes some elements suitable for emulated
device and passthrough device without PASID, e.g., address space,
different memory regions, etc, it is also protected by vtd iommu lock,
all these are useless and become a burden for passthrough device with
PASID.

When there are lots of PASIDs used in one device, the AS and MRs are
all registered to memory core and impact the whole system performance.

So instead of using VTDAddressSpace to cache pasid entry for each pasid
of a passthrough device, we define a light weight structure
VTDAccelPASIDCacheEntry with only necessary elements for each pasid. We
will use this struct as a parameter to conduct binding/unbinding to
nested hwpt and to record the current bound nested hwpt. It's also
designed to support IOMMU_NO_PASID.

VTDAccelPASIDCacheEntry is designed to only be used in intel_iommu_accel.c,
similarly VTDPASIDCacheEntry should only be used in hw/i386/intel_iommu.c

When guest creates new PASID entries, QEMU will capture the pc_inv_dsc
(pasid cache invalidation) request, walk through each pasid in each
passthrough device for valid pasid entries, create a new
VTDAccelPASIDCacheEntry if not existing yet.

IOMMU_NO_PASID of passthrough device still need to register MRs in case
guest does not operate in scalable mode. So for IOMMU_NO_PASID, we have
both VTDPASIDCacheEntry and VTDAccelPASIDCacheEntry.

Co-developed-by: Yi Liu <yi.l.liu@intel.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Tested-by: Xudong Hao <xudong.hao@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260527054658.1021096-12-zhenzhong.duan@intel.com>
---
 hw/i386/intel_iommu.c          |   3 +
 hw/i386/intel_iommu_accel.c    | 156 +++++++++++++++++++++++++++++++++
 hw/i386/intel_iommu_accel.h    |  13 +++
 hw/i386/intel_iommu_internal.h |   8 ++
 4 files changed, 180 insertions(+)

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 88e0c58c08..8e034efdfc 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -3181,6 +3181,8 @@ static void vtd_pasid_cache_sync(IntelIOMMUState *s, VTDPASIDCacheInfo *pc_info)
     g_hash_table_foreach(s->vtd_address_spaces, vtd_pasid_cache_sync_locked,
                          pc_info);
     vtd_iommu_unlock(s);
+
+    vtd_accel_pasid_cache_sync(s, pc_info);
 }
 
 static void vtd_replay_pasid_bindings_all(IntelIOMMUState *s)
@@ -4751,6 +4753,7 @@ static bool vtd_dev_set_iommu_device(PCIBus *bus, void *opaque, int devfn,
     vtd_hiod->devfn = (uint8_t)devfn;
     vtd_hiod->iommu_state = s;
     vtd_hiod->hiod = hiod;
+    QLIST_INIT(&vtd_hiod->pasid_cache_list);
 
     if (!vtd_check_hiod(s, vtd_hiod, errp)) {
         g_free(vtd_hiod);
diff --git a/hw/i386/intel_iommu_accel.c b/hw/i386/intel_iommu_accel.c
index 05b927f303..d2653f22ee 100644
--- a/hw/i386/intel_iommu_accel.c
+++ b/hw/i386/intel_iommu_accel.c
@@ -259,6 +259,162 @@ void vtd_flush_host_piotlb_all_locked(IntelIOMMUState *s, uint16_t domain_id,
                          vtd_flush_host_piotlb_locked, &piotlb_info);
 }
 
+static void vtd_accel_fill_pc(VTDHostIOMMUDevice *vtd_hiod, uint32_t pasid,
+                              VTDPASIDEntry *pe)
+{
+    VTDAccelPASIDCacheEntry *vtd_pce;
+
+    QLIST_FOREACH(vtd_pce, &vtd_hiod->pasid_cache_list, next) {
+        if (vtd_pce->pasid == pasid) {
+            if (vtd_pasid_entry_compare(pe, &vtd_pce->pasid_entry)) {
+                vtd_pce->pasid_entry = *pe;
+            }
+            return;
+        }
+    }
+
+    vtd_pce = g_malloc0(sizeof(VTDAccelPASIDCacheEntry));
+    vtd_pce->vtd_hiod = vtd_hiod;
+    vtd_pce->pasid = pasid;
+    vtd_pce->pasid_entry = *pe;
+    QLIST_INSERT_HEAD(&vtd_hiod->pasid_cache_list, vtd_pce, next);
+}
+
+/*
+ * This function walks over PASID range within [start, end) in a single
+ * PASID table for entries matching @info type/did, then create
+ * VTDAccelPASIDCacheEntry if not exist yet.
+ */
+static void vtd_sm_pasid_table_walk_one(VTDHostIOMMUDevice *vtd_hiod,
+                                        dma_addr_t pt_base, int start, int end,
+                                        VTDPASIDCacheInfo *info)
+{
+    IntelIOMMUState *s = vtd_hiod->iommu_state;
+    VTDPASIDEntry pe;
+    int pasid;
+
+    for (pasid = start; pasid < end; pasid++) {
+        if (vtd_get_pe_in_pasid_leaf_table(s, pasid, pt_base, &pe) ||
+            !vtd_pe_present(&pe)) {
+            continue;
+        }
+
+        if ((info->type == VTD_INV_DESC_PASIDC_G_DSI ||
+             info->type == VTD_INV_DESC_PASIDC_G_PASID_SI) &&
+            (info->did != VTD_SM_PASID_ENTRY_DID(&pe))) {
+            /*
+             * VTD_PASID_CACHE_DOMSI and VTD_PASID_CACHE_PASIDSI
+             * requires domain id check. If domain id check fail,
+             * go to next pasid.
+             */
+            continue;
+        }
+
+        vtd_accel_fill_pc(vtd_hiod, pasid, &pe);
+    }
+}
+
+/*
+ * In VT-d scalable mode translation, PASID dir + PASID table is used.
+ * This function aims at looping over a range of PASIDs in the given
+ * two level table to identify the pasid config in guest.
+ */
+static void vtd_sm_pasid_table_walk(VTDHostIOMMUDevice *vtd_hiod,
+                                    dma_addr_t pdt_base, int start, int end,
+                                    VTDPASIDCacheInfo *info)
+{
+    VTDPASIDDirEntry pdire;
+    int pasid = start;
+    int pasid_next;
+    dma_addr_t pt_base;
+
+    while (pasid < end) {
+        pasid_next = (pasid + VTD_PASID_TABLE_ENTRY_NUM) &
+                     ~(VTD_PASID_TABLE_ENTRY_NUM - 1);
+        pasid_next = pasid_next < end ? pasid_next : end;
+
+        if (!vtd_get_pdire_from_pdir_table(pdt_base, pasid, &pdire)
+            && vtd_pdire_present(&pdire)) {
+            pt_base = pdire.val & VTD_PASID_TABLE_BASE_ADDR_MASK;
+            vtd_sm_pasid_table_walk_one(vtd_hiod, pt_base, pasid, pasid_next,
+                                        info);
+        }
+        pasid = pasid_next;
+    }
+}
+
+static void vtd_accel_replay_pasid_bind_for_dev(VTDHostIOMMUDevice *vtd_hiod,
+                                                int start, int end,
+                                                VTDPASIDCacheInfo *pc_info)
+{
+    IntelIOMMUState *s = vtd_hiod->iommu_state;
+    VTDContextEntry ce;
+    int dev_max_pasid = 1 << vtd_hiod->hiod->caps.max_pasid_log2;
+
+    if (!vtd_dev_to_context_entry(s, pci_bus_num(vtd_hiod->bus),
+                                  vtd_hiod->devfn, &ce)) {
+        VTDPASIDCacheInfo walk_info = *pc_info;
+        uint32_t ce_max_pasid = vtd_sm_ce_get_pdt_entry_num(&ce) *
+                                VTD_PASID_TABLE_ENTRY_NUM;
+
+        end = MIN(end, MIN(dev_max_pasid, ce_max_pasid));
+
+        vtd_sm_pasid_table_walk(vtd_hiod, VTD_CE_GET_PASID_DIR_TABLE(&ce),
+                                start, end, &walk_info);
+    }
+}
+
+/*
+ * This function replays the guest pasid bindings by walking the two level
+ * guest PASID table. For each valid pasid entry, it creates an entry
+ * VTDAccelPASIDCacheEntry dynamically if not exist yet. This entry holds
+ * info specific to a pasid
+ */
+void vtd_accel_pasid_cache_sync(IntelIOMMUState *s, VTDPASIDCacheInfo *pc_info)
+{
+    int start = IOMMU_NO_PASID, end = 1 << s->pasid;
+    VTDHostIOMMUDevice *vtd_hiod;
+    GHashTableIter hiod_it;
+
+    if (!s->fsts) {
+        return;
+    }
+
+    switch (pc_info->type) {
+    case VTD_INV_DESC_PASIDC_G_PASID_SI:
+        start = pc_info->pasid;
+        end = pc_info->pasid + 1;
+        /* fall through */
+    case VTD_INV_DESC_PASIDC_G_DSI:
+        /*
+         * loop all assigned devices, do domain id check in
+         * vtd_sm_pasid_table_walk_one() after get pasid entry.
+         */
+        break;
+    case VTD_INV_DESC_PASIDC_G_GLOBAL:
+        /* loop all assigned devices */
+        break;
+    default:
+        g_assert_not_reached();
+    }
+
+    /*
+     * Loop all the vtd_hiod instances to sync the "pasid cache" per the
+     * guest pasid configuration.
+     *
+     * VTD translation callback never accesses vtd_hiod and its corresponding
+     * cached pasid entry, so no iommu lock needed here.
+     */
+    g_hash_table_iter_init(&hiod_it, s->vtd_host_iommu_dev);
+    while (g_hash_table_iter_next(&hiod_it, NULL, (void **)&vtd_hiod)) {
+        if (!object_dynamic_cast(OBJECT(vtd_hiod->hiod),
+                                 TYPE_HOST_IOMMU_DEVICE_IOMMUFD)) {
+            continue;
+        }
+        vtd_accel_replay_pasid_bind_for_dev(vtd_hiod, start, end, pc_info);
+    }
+}
+
 static uint64_t vtd_get_host_iommu_quirks(uint32_t type,
                                           void *caps, uint32_t size)
 {
diff --git a/hw/i386/intel_iommu_accel.h b/hw/i386/intel_iommu_accel.h
index e5f0b077b4..c9b1823745 100644
--- a/hw/i386/intel_iommu_accel.h
+++ b/hw/i386/intel_iommu_accel.h
@@ -12,6 +12,13 @@
 #define HW_I386_INTEL_IOMMU_ACCEL_H
 #include CONFIG_DEVICES
 
+typedef struct VTDAccelPASIDCacheEntry {
+    VTDHostIOMMUDevice *vtd_hiod;
+    VTDPASIDEntry pasid_entry;
+    uint32_t pasid;
+    QLIST_ENTRY(VTDAccelPASIDCacheEntry) next;
+} VTDAccelPASIDCacheEntry;
+
 #ifdef CONFIG_VTD_ACCEL
 bool vtd_check_hiod_accel(IntelIOMMUState *s, VTDHostIOMMUDevice *vtd_hiod,
                           Error **errp);
@@ -20,6 +27,7 @@ bool vtd_propagate_guest_pasid(VTDAddressSpace *vtd_as, Error **errp);
 void vtd_flush_host_piotlb_all_locked(IntelIOMMUState *s, uint16_t domain_id,
                                       uint32_t pasid, hwaddr addr,
                                       uint64_t npages, bool ih);
+void vtd_accel_pasid_cache_sync(IntelIOMMUState *s, VTDPASIDCacheInfo *pc_info);
 void vtd_iommu_ops_update_accel(PCIIOMMUOps *ops);
 #else
 static inline bool vtd_check_hiod_accel(IntelIOMMUState *s,
@@ -49,6 +57,11 @@ static inline void vtd_flush_host_piotlb_all_locked(IntelIOMMUState *s,
 {
 }
 
+static inline void vtd_accel_pasid_cache_sync(IntelIOMMUState *s,
+                                              VTDPASIDCacheInfo *pc_info)
+{
+}
+
 static inline void vtd_iommu_ops_update_accel(PCIIOMMUOps *ops)
 {
 }
diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
index ee59df09f8..9307825017 100644
--- a/hw/i386/intel_iommu_internal.h
+++ b/hw/i386/intel_iommu_internal.h
@@ -615,6 +615,7 @@ typedef struct VTDRootEntry VTDRootEntry;
 #define VTD_CTX_ENTRY_LEGACY_SIZE     16
 #define VTD_CTX_ENTRY_SCALABLE_SIZE   32
 
+#define VTD_SM_CONTEXT_ENTRY_PDTS(x)        extract64((x)->val[0], 9, 3)
 #define VTD_SM_CONTEXT_ENTRY_RSVD_VAL0(aw)  (0x1e0ULL | ~VTD_HAW_MASK(aw))
 #define VTD_SM_CONTEXT_ENTRY_RSVD_VAL1      0xffffffffffe00000ULL
 #define VTD_SM_CONTEXT_ENTRY_PRE            0x10ULL
@@ -645,6 +646,7 @@ typedef struct VTDPIOTLBInvInfo {
 #define VTD_PASID_DIR_BITS_MASK       (0x3fffULL)
 #define VTD_PASID_DIR_INDEX(pasid)    (((pasid) >> 6) & VTD_PASID_DIR_BITS_MASK)
 #define VTD_PASID_DIR_FPD             (1ULL << 1) /* Fault Processing Disable */
+#define VTD_PASID_TABLE_ENTRY_NUM     (1ULL << 6)
 #define VTD_PASID_TABLE_BITS_MASK     (0x3fULL)
 #define VTD_PASID_TABLE_INDEX(pasid)  ((pasid) & VTD_PASID_TABLE_BITS_MASK)
 #define VTD_PASID_ENTRY_FPD           (1ULL << 1) /* Fault Processing Disable */
@@ -710,6 +712,7 @@ typedef struct VTDHostIOMMUDevice {
     PCIBus *bus;
     uint8_t devfn;
     HostIOMMUDevice *hiod;
+    QLIST_HEAD(, VTDAccelPASIDCacheEntry) pasid_cache_list;
 } VTDHostIOMMUDevice;
 
 /*
@@ -767,6 +770,11 @@ static inline int vtd_pasid_entry_compare(VTDPASIDEntry *p1, VTDPASIDEntry *p2)
     return memcmp(p1, p2, sizeof(*p1));
 }
 
+static inline uint32_t vtd_sm_ce_get_pdt_entry_num(VTDContextEntry *ce)
+{
+    return 1U << (VTD_SM_CONTEXT_ENTRY_PDTS(ce) + 7);
+}
+
 int vtd_get_pdire_from_pdir_table(dma_addr_t pasid_dir_base, uint32_t pasid,
                                   VTDPASIDDirEntry *pdire);
 int vtd_get_pe_in_pasid_leaf_table(IntelIOMMUState *s, uint32_t pasid,
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 017/106] intel_iommu_accel: Handle PASID entry removal for pc_inv_dsc request
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (15 preceding siblings ...)
  2026-06-14 19:06 ` [PULL 016/106] intel_iommu_accel: Handle PASID entry addition for pc_inv_dsc request Michael S. Tsirkin
@ 2026-06-14 19:06 ` Michael S. Tsirkin
  2026-06-14 19:06 ` [PULL 018/106] intel_iommu_accel: Bypass PASID entry addition for just deleted entry Michael S. Tsirkin
                   ` (89 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Zhenzhong Duan, Yi Liu, Xudong Hao, Jason Wang,
	Clément Mathieu--Drif, Paolo Bonzini, Richard Henderson

From: Zhenzhong Duan <zhenzhong.duan@intel.com>

When guest deletes PASID entries, QEMU will capture the pasid cache
invalidation request, walk through pasid_cache_list in each passthrough
device to find stale VTDAccelPASIDCacheEntry and delete them.

Co-developed-by: Yi Liu <yi.l.liu@intel.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Tested-by: Xudong Hao <xudong.hao@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260527054658.1021096-13-zhenzhong.duan@intel.com>
---
 hw/i386/intel_iommu_accel.c | 61 +++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/hw/i386/intel_iommu_accel.c b/hw/i386/intel_iommu_accel.c
index d2653f22ee..ed0d6bda7e 100644
--- a/hw/i386/intel_iommu_accel.c
+++ b/hw/i386/intel_iommu_accel.c
@@ -280,6 +280,59 @@ static void vtd_accel_fill_pc(VTDHostIOMMUDevice *vtd_hiod, uint32_t pasid,
     QLIST_INSERT_HEAD(&vtd_hiod->pasid_cache_list, vtd_pce, next);
 }
 
+static void vtd_accel_delete_pc(VTDAccelPASIDCacheEntry *vtd_pce)
+{
+    QLIST_REMOVE(vtd_pce, next);
+    g_free(vtd_pce);
+}
+
+static void
+vtd_accel_pasid_cache_invalidate_one(VTDAccelPASIDCacheEntry *vtd_pce,
+                                     VTDPASIDCacheInfo *pc_info)
+{
+    VTDHostIOMMUDevice *vtd_hiod = vtd_pce->vtd_hiod;
+    VTDPASIDEntry pe;
+    uint16_t did;
+
+    /*
+     * VTD_INV_DESC_PASIDC_G_DSI and VTD_INV_DESC_PASIDC_G_PASID_SI require
+     * DID check. If DID doesn't match the value in cache or memory, then
+     * it's not a pasid entry we want to invalidate.
+     */
+    switch (pc_info->type) {
+    case VTD_INV_DESC_PASIDC_G_PASID_SI:
+        if (pc_info->pasid != vtd_pce->pasid) {
+            return;
+        }
+        /* Fall through */
+    case VTD_INV_DESC_PASIDC_G_DSI:
+        did = VTD_SM_PASID_ENTRY_DID(&vtd_pce->pasid_entry);
+        if (pc_info->did != did) {
+            return;
+        }
+    }
+
+    if (vtd_dev_get_pe_from_pasid(vtd_hiod->iommu_state, vtd_hiod->bus,
+                                  vtd_hiod->devfn, vtd_pce->pasid, &pe)) {
+        /*
+         * No valid pasid entry in guest memory. e.g. pasid entry was modified
+         * to be either all-zero or non-present. Either case means existing
+         * pasid cache should be invalidated.
+         */
+        vtd_accel_delete_pc(vtd_pce);
+    }
+}
+
+static void vtd_accel_pasid_cache_invalidate(VTDHostIOMMUDevice *vtd_hiod,
+                                             VTDPASIDCacheInfo *pc_info)
+{
+    VTDAccelPASIDCacheEntry *vtd_pce, *next;
+
+    QLIST_FOREACH_SAFE(vtd_pce, &vtd_hiod->pasid_cache_list, next, next) {
+        vtd_accel_pasid_cache_invalidate_one(vtd_pce, pc_info);
+    }
+}
+
 /*
  * This function walks over PASID range within [start, end) in a single
  * PASID table for entries matching @info type/did, then create
@@ -411,6 +464,14 @@ void vtd_accel_pasid_cache_sync(IntelIOMMUState *s, VTDPASIDCacheInfo *pc_info)
                                  TYPE_HOST_IOMMU_DEVICE_IOMMUFD)) {
             continue;
         }
+
+        /*
+         * The replay path inevitably needs to iterate through existing
+         * PASID cache entries. Since cached PASID entries that are marked
+         * for removal don't need to be iterated, we intentionally handle
+         * removals before additions to optimize the replay process.
+         */
+        vtd_accel_pasid_cache_invalidate(vtd_hiod, pc_info);
         vtd_accel_replay_pasid_bind_for_dev(vtd_hiod, start, end, pc_info);
     }
 }
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 018/106] intel_iommu_accel: Bypass PASID entry addition for just deleted entry
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (16 preceding siblings ...)
  2026-06-14 19:06 ` [PULL 017/106] intel_iommu_accel: Handle PASID entry removal " Michael S. Tsirkin
@ 2026-06-14 19:06 ` Michael S. Tsirkin
  2026-06-14 19:06 ` [PULL 019/106] intel_iommu_accel: Handle PASID entry removal for system reset Michael S. Tsirkin
                   ` (88 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Zhenzhong Duan, Yi Liu, Xudong Hao, Jason Wang,
	Clément Mathieu--Drif, Paolo Bonzini, Richard Henderson

From: Zhenzhong Duan <zhenzhong.duan@intel.com>

For VTD_INV_DESC_PASIDC_G_PASID_SI typed pc_inv_dsc invalidation, if an
pasid entry is just removed, it can never be a new entry to add. So
calling vtd_replay_pasid_bind_for_dev() is unnecessary.

Introduce a new field accel_pce_deleted in VTDPASIDCacheInfo to mark
this case and to do the bypassing.

Suggested-by: Yi Liu <yi.l.liu@intel.com>
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Reviewed-by: Yi Liu <yi.l.liu@intel.com>
Tested-by: Xudong Hao <xudong.hao@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260527054658.1021096-14-zhenzhong.duan@intel.com>
---
 hw/i386/intel_iommu_accel.c    | 16 +++++++++++++---
 hw/i386/intel_iommu_internal.h |  1 +
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/hw/i386/intel_iommu_accel.c b/hw/i386/intel_iommu_accel.c
index ed0d6bda7e..b823c405a1 100644
--- a/hw/i386/intel_iommu_accel.c
+++ b/hw/i386/intel_iommu_accel.c
@@ -280,10 +280,15 @@ static void vtd_accel_fill_pc(VTDHostIOMMUDevice *vtd_hiod, uint32_t pasid,
     QLIST_INSERT_HEAD(&vtd_hiod->pasid_cache_list, vtd_pce, next);
 }
 
-static void vtd_accel_delete_pc(VTDAccelPASIDCacheEntry *vtd_pce)
+static void vtd_accel_delete_pc(VTDAccelPASIDCacheEntry *vtd_pce,
+                                VTDPASIDCacheInfo *pc_info)
 {
     QLIST_REMOVE(vtd_pce, next);
     g_free(vtd_pce);
+
+    if (pc_info->type == VTD_INV_DESC_PASIDC_G_PASID_SI) {
+        pc_info->accel_pce_deleted = true;
+    }
 }
 
 static void
@@ -319,7 +324,7 @@ vtd_accel_pasid_cache_invalidate_one(VTDAccelPASIDCacheEntry *vtd_pce,
          * to be either all-zero or non-present. Either case means existing
          * pasid cache should be invalidated.
          */
-        vtd_accel_delete_pc(vtd_pce);
+        vtd_accel_delete_pc(vtd_pce, pc_info);
     }
 }
 
@@ -472,7 +477,12 @@ void vtd_accel_pasid_cache_sync(IntelIOMMUState *s, VTDPASIDCacheInfo *pc_info)
          * removals before additions to optimize the replay process.
          */
         vtd_accel_pasid_cache_invalidate(vtd_hiod, pc_info);
-        vtd_accel_replay_pasid_bind_for_dev(vtd_hiod, start, end, pc_info);
+
+        if (pc_info->accel_pce_deleted) {
+            pc_info->accel_pce_deleted = false;
+        } else {
+            vtd_accel_replay_pasid_bind_for_dev(vtd_hiod, start, end, pc_info);
+        }
     }
 }
 
diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
index 9307825017..64a38afa85 100644
--- a/hw/i386/intel_iommu_internal.h
+++ b/hw/i386/intel_iommu_internal.h
@@ -630,6 +630,7 @@ typedef struct VTDPASIDCacheInfo {
     uint8_t type;
     uint16_t did;
     uint32_t pasid;
+    bool accel_pce_deleted;
 } VTDPASIDCacheInfo;
 
 typedef struct VTDPIOTLBInvInfo {
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 019/106] intel_iommu_accel: Handle PASID entry removal for system reset
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (17 preceding siblings ...)
  2026-06-14 19:06 ` [PULL 018/106] intel_iommu_accel: Bypass PASID entry addition for just deleted entry Michael S. Tsirkin
@ 2026-06-14 19:06 ` Michael S. Tsirkin
  2026-06-14 19:06 ` [PULL 020/106] intel_iommu_accel: Switch to VTDAccelPASIDCacheEntry for PASID bind/unbind and PIOTLB invalidation Michael S. Tsirkin
                   ` (87 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Zhenzhong Duan, Yi Liu, Xudong Hao, Jason Wang,
	Clément Mathieu--Drif, Paolo Bonzini, Richard Henderson

From: Zhenzhong Duan <zhenzhong.duan@intel.com>

When system level reset, DMA translation is turned off, all PASID
entries become stale and should be deleted.

vtd_hiod list is never accessed without BQL, so no need to guard with
iommu lock.

Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Reviewed-by: Yi Liu <yi.l.liu@intel.com>
Tested-by: Xudong Hao <xudong.hao@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260527054658.1021096-15-zhenzhong.duan@intel.com>
---
 hw/i386/intel_iommu.c       |  2 ++
 hw/i386/intel_iommu_accel.c | 13 +++++++++++++
 hw/i386/intel_iommu_accel.h |  5 +++++
 3 files changed, 20 insertions(+)

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 8e034efdfc..0b341f741e 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -391,6 +391,8 @@ static void vtd_reset_caches(IntelIOMMUState *s)
     vtd_reset_context_cache_locked(s);
     vtd_pasid_cache_reset_locked(s);
     vtd_iommu_unlock(s);
+
+    vtd_accel_pasid_cache_reset(s);
 }
 
 static uint64_t vtd_get_iotlb_gfn(hwaddr addr, uint32_t level)
diff --git a/hw/i386/intel_iommu_accel.c b/hw/i386/intel_iommu_accel.c
index b823c405a1..8308eb00cb 100644
--- a/hw/i386/intel_iommu_accel.c
+++ b/hw/i386/intel_iommu_accel.c
@@ -486,6 +486,19 @@ void vtd_accel_pasid_cache_sync(IntelIOMMUState *s, VTDPASIDCacheInfo *pc_info)
     }
 }
 
+/* Fake a global pasid cache invalidation to remove all pasid cache entries */
+void vtd_accel_pasid_cache_reset(IntelIOMMUState *s)
+{
+    VTDPASIDCacheInfo pc_info = { .type = VTD_INV_DESC_PASIDC_G_GLOBAL };
+    VTDHostIOMMUDevice *vtd_hiod;
+    GHashTableIter hiod_it;
+
+    g_hash_table_iter_init(&hiod_it, s->vtd_host_iommu_dev);
+    while (g_hash_table_iter_next(&hiod_it, NULL, (void **)&vtd_hiod)) {
+        vtd_accel_pasid_cache_invalidate(vtd_hiod, &pc_info);
+    }
+}
+
 static uint64_t vtd_get_host_iommu_quirks(uint32_t type,
                                           void *caps, uint32_t size)
 {
diff --git a/hw/i386/intel_iommu_accel.h b/hw/i386/intel_iommu_accel.h
index c9b1823745..a2226b28b6 100644
--- a/hw/i386/intel_iommu_accel.h
+++ b/hw/i386/intel_iommu_accel.h
@@ -28,6 +28,7 @@ void vtd_flush_host_piotlb_all_locked(IntelIOMMUState *s, uint16_t domain_id,
                                       uint32_t pasid, hwaddr addr,
                                       uint64_t npages, bool ih);
 void vtd_accel_pasid_cache_sync(IntelIOMMUState *s, VTDPASIDCacheInfo *pc_info);
+void vtd_accel_pasid_cache_reset(IntelIOMMUState *s);
 void vtd_iommu_ops_update_accel(PCIIOMMUOps *ops);
 #else
 static inline bool vtd_check_hiod_accel(IntelIOMMUState *s,
@@ -62,6 +63,10 @@ static inline void vtd_accel_pasid_cache_sync(IntelIOMMUState *s,
 {
 }
 
+static inline void vtd_accel_pasid_cache_reset(IntelIOMMUState *s)
+{
+}
+
 static inline void vtd_iommu_ops_update_accel(PCIIOMMUOps *ops)
 {
 }
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 020/106] intel_iommu_accel: Switch to VTDAccelPASIDCacheEntry for PASID bind/unbind and PIOTLB invalidation
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (18 preceding siblings ...)
  2026-06-14 19:06 ` [PULL 019/106] intel_iommu_accel: Handle PASID entry removal for system reset Michael S. Tsirkin
@ 2026-06-14 19:06 ` Michael S. Tsirkin
  2026-06-14 19:06 ` [PULL 021/106] intel_iommu_accel: Add pasid bits size check Michael S. Tsirkin
                   ` (86 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Zhenzhong Duan, Yi Liu, Xudong Hao, Jason Wang,
	Clément Mathieu--Drif, Paolo Bonzini, Richard Henderson

From: Zhenzhong Duan <zhenzhong.duan@intel.com>

This patch switches from VTDAddressSpace to VTDAccelPASIDCacheEntry for
handling PASID bind/unbind operations and PIOTLB invalidations in
passthrough scenarios. VTDAccelPASIDCacheEntry was introduced to cache
PASID entries for passthrough devices and is now ready to propagate
PASID bind/unbind operations and PIOTLB invalidations to the host.

Unlike the previous approach, VTDAccelPASIDCacheEntry supports both
IOMMU_NO_PASID (rid_pasid) and other valid PASIDs, so this switch drops
IOMMU_NO_PASID limitations that existed in the prior PASID bind/unbind
and PIOTLB invalidation path. For IOMMU_NO_PASID of passthrough devices,
VTDAddressSpace continues to handle shadow page modifications to the
host, but no longer manages PASID bind/unbind operations or PIOTLB
invalidations for passthrough scenarios.

Co-developed-by: Yi Liu <yi.l.liu@intel.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Tested-by: Xudong Hao <xudong.hao@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260527054658.1021096-16-zhenzhong.duan@intel.com>
---
 hw/i386/intel_iommu.c         |  17 +----
 hw/i386/intel_iommu_accel.c   | 131 +++++++++++++++++-----------------
 hw/i386/intel_iommu_accel.h   |   2 +-
 include/hw/i386/intel_iommu.h |   2 -
 4 files changed, 68 insertions(+), 84 deletions(-)

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 0b341f741e..31addb98e4 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -86,8 +86,6 @@ static void vtd_pasid_cache_reset_locked(IntelIOMMUState *s)
         VTDPASIDCacheEntry *pc_entry = &vtd_as->pasid_cache_entry;
         if (pc_entry->valid) {
             pc_entry->valid = false;
-            /* It's fatal to get failure during reset */
-            vtd_propagate_guest_pasid(vtd_as, &error_fatal);
         }
     }
 }
@@ -3104,8 +3102,6 @@ static void vtd_pasid_cache_sync_locked(gpointer key, gpointer value,
     VTDPASIDEntry pe;
     IOMMUNotifier *n;
     uint16_t did;
-    const char *err_prefix = "Attaching to HWPT failed: ";
-    Error *local_err = NULL;
 
     if (vtd_dev_get_pe_from_pasid(vtd_as->iommu_state, vtd_as->bus,
                                   vtd_as->devfn, vtd_as->pasid, &pe)) {
@@ -3127,9 +3123,6 @@ static void vtd_pasid_cache_sync_locked(gpointer key, gpointer value,
             vtd_address_space_unmap(vtd_as, n);
         }
         vtd_switch_address_space(vtd_as);
-
-        err_prefix = "Detaching from HWPT failed: ";
-        goto do_bind_unbind;
     }
 
     /*
@@ -3157,20 +3150,12 @@ static void vtd_pasid_cache_sync_locked(gpointer key, gpointer value,
     if (!pc_entry->valid) {
         pc_entry->pasid_entry = pe;
         pc_entry->valid = true;
-    } else if (vtd_pasid_entry_compare(&pe, &pc_entry->pasid_entry)) {
-        err_prefix = "Replacing HWPT attachment failed: ";
-    } else {
+    } else if (!vtd_pasid_entry_compare(&pe, &pc_entry->pasid_entry)) {
         return;
     }
 
     vtd_switch_address_space(vtd_as);
     vtd_address_space_sync(vtd_as);
-
-do_bind_unbind:
-    /* TODO: Fault event injection into guest, report error to QEMU for now */
-    if (!vtd_propagate_guest_pasid(vtd_as, &local_err)) {
-        error_reportf_err(local_err, "%s", err_prefix);
-    }
 }
 
 static void vtd_pasid_cache_sync(IntelIOMMUState *s, VTDPASIDCacheInfo *pc_info)
diff --git a/hw/i386/intel_iommu_accel.c b/hw/i386/intel_iommu_accel.c
index 8308eb00cb..97991fc0d9 100644
--- a/hw/i386/intel_iommu_accel.c
+++ b/hw/i386/intel_iommu_accel.c
@@ -89,24 +89,25 @@ static bool vtd_create_fs_hwpt(VTDHostIOMMUDevice *vtd_hiod,
                                       fs_hwpt_id, errp);
 }
 
-static void vtd_destroy_old_fs_hwpt(VTDHostIOMMUDevice *vtd_hiod,
-                                    VTDAddressSpace *vtd_as)
+static void vtd_destroy_old_fs_hwpt(VTDAccelPASIDCacheEntry *vtd_pce)
 {
-    HostIOMMUDeviceIOMMUFD *hiodi = HOST_IOMMU_DEVICE_IOMMUFD(vtd_hiod->hiod);
+    HostIOMMUDeviceIOMMUFD *hiodi =
+        HOST_IOMMU_DEVICE_IOMMUFD(vtd_pce->vtd_hiod->hiod);
 
-    if (!vtd_as->fs_hwpt_id) {
+    if (!vtd_pce->fs_hwpt_id) {
         return;
     }
-    iommufd_backend_free_id(hiodi->iommufd, vtd_as->fs_hwpt_id);
-    vtd_as->fs_hwpt_id = 0;
+    iommufd_backend_free_id(hiodi->iommufd, vtd_pce->fs_hwpt_id);
+    vtd_pce->fs_hwpt_id = 0;
 }
 
-static bool vtd_device_attach_iommufd(VTDHostIOMMUDevice *vtd_hiod,
-                                      VTDAddressSpace *vtd_as, Error **errp)
+static bool vtd_device_attach_iommufd(VTDAccelPASIDCacheEntry *vtd_pce,
+                                      Error **errp)
 {
+    VTDHostIOMMUDevice *vtd_hiod = vtd_pce->vtd_hiod;
     HostIOMMUDeviceIOMMUFD *hiodi = HOST_IOMMU_DEVICE_IOMMUFD(vtd_hiod->hiod);
-    VTDPASIDEntry *pe = &vtd_as->pasid_cache_entry.pasid_entry;
-    uint32_t hwpt_id = hiodi->hwpt_id;
+    VTDPASIDEntry *pe = &vtd_pce->pasid_entry;
+    uint32_t hwpt_id = hiodi->hwpt_id, pasid = vtd_pce->pasid;
     bool ret;
 
     /*
@@ -126,14 +127,13 @@ static bool vtd_device_attach_iommufd(VTDHostIOMMUDevice *vtd_hiod,
         }
     }
 
-    ret = host_iommu_device_iommufd_attach_hwpt(hiodi, IOMMU_NO_PASID, hwpt_id,
-                                                errp);
-    trace_vtd_device_attach_hwpt(hiodi->devid, IOMMU_NO_PASID, hwpt_id, ret);
+    ret = host_iommu_device_iommufd_attach_hwpt(hiodi, pasid, hwpt_id, errp);
+    trace_vtd_device_attach_hwpt(hiodi->devid, pasid, hwpt_id, ret);
     if (ret) {
         /* Destroy old fs_hwpt if it's a replacement */
-        vtd_destroy_old_fs_hwpt(vtd_hiod, vtd_as);
+        vtd_destroy_old_fs_hwpt(vtd_pce);
         if (vtd_pe_pgtt_is_fst(pe)) {
-            vtd_as->fs_hwpt_id = hwpt_id;
+            vtd_pce->fs_hwpt_id = hwpt_id;
         }
     } else if (vtd_pe_pgtt_is_fst(pe)) {
         iommufd_backend_free_id(hiodi->iommufd, hwpt_id);
@@ -142,17 +142,19 @@ static bool vtd_device_attach_iommufd(VTDHostIOMMUDevice *vtd_hiod,
     return ret;
 }
 
-static bool vtd_device_detach_iommufd(VTDHostIOMMUDevice *vtd_hiod,
-                                      VTDAddressSpace *vtd_as, Error **errp)
+static bool vtd_device_detach_iommufd(VTDAccelPASIDCacheEntry *vtd_pce,
+                                      Error **errp)
 {
+    VTDHostIOMMUDevice *vtd_hiod = vtd_pce->vtd_hiod;
     HostIOMMUDeviceIOMMUFD *hiodi = HOST_IOMMU_DEVICE_IOMMUFD(vtd_hiod->hiod);
-    IntelIOMMUState *s = vtd_as->iommu_state;
+
+    IntelIOMMUState *s = vtd_hiod->iommu_state;
+    uint32_t pasid = vtd_pce->pasid;
     bool ret;
 
-    if (s->dmar_enabled && s->root_scalable) {
-        ret = host_iommu_device_iommufd_detach_hwpt(hiodi, IOMMU_NO_PASID,
-                                                    errp);
-        trace_vtd_device_detach_hwpt(hiodi->devid, IOMMU_NO_PASID, ret);
+    if (pasid != IOMMU_NO_PASID || (s->dmar_enabled && s->root_scalable)) {
+        ret = host_iommu_device_iommufd_detach_hwpt(hiodi, pasid, errp);
+        trace_vtd_device_detach_hwpt(hiodi->devid, pasid, ret);
     } else {
         /*
          * If DMAR remapping is disabled or guest switches to legacy mode,
@@ -166,58 +168,32 @@ static bool vtd_device_detach_iommufd(VTDHostIOMMUDevice *vtd_hiod,
     }
 
     if (ret) {
-        vtd_destroy_old_fs_hwpt(vtd_hiod, vtd_as);
+        vtd_destroy_old_fs_hwpt(vtd_pce);
     }
 
     return ret;
 }
 
-bool vtd_propagate_guest_pasid(VTDAddressSpace *vtd_as, Error **errp)
-{
-    VTDPASIDCacheEntry *pc_entry = &vtd_as->pasid_cache_entry;
-    VTDHostIOMMUDevice *vtd_hiod = vtd_find_hiod_iommufd(vtd_as);
-
-    /* Ignore emulated device or legacy VFIO backed device */
-    if (!vtd_as->iommu_state->fsts || !vtd_hiod) {
-        return true;
-    }
-
-    if (pc_entry->valid) {
-        return vtd_device_attach_iommufd(vtd_hiod, vtd_as, errp);
-    }
-
-    return vtd_device_detach_iommufd(vtd_hiod, vtd_as, errp);
-}
-
 /*
- * This function is a loop function for the s->vtd_address_spaces
- * list with VTDPIOTLBInvInfo as execution filter. It propagates
- * the piotlb invalidation to host.
+ * This function is a loop function for the s->vtd_host_iommu_dev
+ * and vtd_hiod->pasid_cache_list lists with VTDPIOTLBInvInfo as
+ * execution filter. It propagates the piotlb invalidation to host.
  */
-static void vtd_flush_host_piotlb_locked(gpointer key, gpointer value,
-                                         gpointer user_data)
+static void vtd_flush_host_piotlb_locked(VTDAccelPASIDCacheEntry *vtd_pce,
+                                         VTDPIOTLBInvInfo *piotlb_info)
 {
-    VTDPIOTLBInvInfo *piotlb_info = user_data;
-    VTDAddressSpace *vtd_as = value;
-    VTDHostIOMMUDevice *vtd_hiod = vtd_find_hiod_iommufd(vtd_as);
-    VTDPASIDCacheEntry *pc_entry = &vtd_as->pasid_cache_entry;
+    VTDHostIOMMUDevice *vtd_hiod = vtd_pce->vtd_hiod;
+    VTDPASIDEntry *pe = &vtd_pce->pasid_entry;
     uint16_t did;
 
-    if (!vtd_hiod) {
-        return;
-    }
-
-    assert(vtd_as->pasid == IOMMU_NO_PASID);
-
     /* Nothing to do if there is no first stage HWPT attached */
-    if (!pc_entry->valid ||
-        !vtd_pe_pgtt_is_fst(&pc_entry->pasid_entry)) {
+    if (!vtd_pe_pgtt_is_fst(pe)) {
         return;
     }
 
-    did = VTD_SM_PASID_ENTRY_DID(&pc_entry->pasid_entry);
+    did = VTD_SM_PASID_ENTRY_DID(pe);
 
-    if (piotlb_info->domain_id == did && piotlb_info->pasid == IOMMU_NO_PASID) {
+    if (piotlb_info->domain_id == did && piotlb_info->pasid == vtd_pce->pasid) {
         HostIOMMUDeviceIOMMUFD *hiodi =
             HOST_IOMMU_DEVICE_IOMMUFD(vtd_hiod->hiod);
         uint32_t entry_num = 1; /* Only implement one request for simplicity */
@@ -225,7 +201,7 @@ static void vtd_flush_host_piotlb_locked(gpointer key, gpointer value,
         struct iommu_hwpt_vtd_s1_invalidate *cache = piotlb_info->inv_data;
 
         if (!iommufd_backend_invalidate_cache(hiodi->iommufd,
-                                              vtd_as->fs_hwpt_id,
+                                              vtd_pce->fs_hwpt_id,
                                               IOMMU_HWPT_INVALIDATE_DATA_VTD_S1,
                                               sizeof(*cache), &entry_num, cache,
                                               &local_err)) {
@@ -241,6 +217,8 @@ void vtd_flush_host_piotlb_all_locked(IntelIOMMUState *s, uint16_t domain_id,
 {
     struct iommu_hwpt_vtd_s1_invalidate cache_info = { 0 };
     VTDPIOTLBInvInfo piotlb_info;
+    VTDHostIOMMUDevice *vtd_hiod;
+    GHashTableIter hiod_it;
 
     cache_info.addr = addr;
     cache_info.npages = npages;
@@ -251,23 +229,36 @@ void vtd_flush_host_piotlb_all_locked(IntelIOMMUState *s, uint16_t domain_id,
     piotlb_info.inv_data = &cache_info;
 
     /*
-     * Go through each vtd_as instance in s->vtd_address_spaces, find out
-     * affected host devices which need host piotlb invalidation. Piotlb
-     * invalidation should check pasid cache per architecture point of view.
+     * Go through each vtd_pce in vtd_hiod->pasid_cache_list for each host
+     * device, find out affected host device pasid which need host piotlb
+     * invalidation. Piotlb invalidation should check pasid cache per
+     * architecture point of view.
      */
-    g_hash_table_foreach(s->vtd_address_spaces,
-                         vtd_flush_host_piotlb_locked, &piotlb_info);
+    g_hash_table_iter_init(&hiod_it, s->vtd_host_iommu_dev);
+    while (g_hash_table_iter_next(&hiod_it, NULL, (void **)&vtd_hiod)) {
+        VTDAccelPASIDCacheEntry *vtd_pce;
+
+        QLIST_FOREACH(vtd_pce, &vtd_hiod->pasid_cache_list, next) {
+            vtd_flush_host_piotlb_locked(vtd_pce, &piotlb_info);
+        }
+    }
 }
 
 static void vtd_accel_fill_pc(VTDHostIOMMUDevice *vtd_hiod, uint32_t pasid,
                               VTDPASIDEntry *pe)
 {
     VTDAccelPASIDCacheEntry *vtd_pce;
+    Error *local_err = NULL;
 
     QLIST_FOREACH(vtd_pce, &vtd_hiod->pasid_cache_list, next) {
         if (vtd_pce->pasid == pasid) {
             if (vtd_pasid_entry_compare(pe, &vtd_pce->pasid_entry)) {
                 vtd_pce->pasid_entry = *pe;
+
+                if (!vtd_device_attach_iommufd(vtd_pce, &local_err)) {
+                    error_reportf_err(local_err, "%s",
+                                      "Replacing HWPT attachment failed: ");
+                }
             }
             return;
         }
@@ -278,11 +269,21 @@ static void vtd_accel_fill_pc(VTDHostIOMMUDevice *vtd_hiod, uint32_t pasid,
     vtd_pce->pasid = pasid;
     vtd_pce->pasid_entry = *pe;
     QLIST_INSERT_HEAD(&vtd_hiod->pasid_cache_list, vtd_pce, next);
+
+    if (!vtd_device_attach_iommufd(vtd_pce, &local_err)) {
+        error_reportf_err(local_err, "%s", "Attaching to HWPT failed: ");
+    }
 }
 
 static void vtd_accel_delete_pc(VTDAccelPASIDCacheEntry *vtd_pce,
                                 VTDPASIDCacheInfo *pc_info)
 {
+    Error *local_err = NULL;
+
+    if (!vtd_device_detach_iommufd(vtd_pce, &local_err)) {
+        error_reportf_err(local_err, "%s", "Detaching from HWPT failed: ");
+    }
+
     QLIST_REMOVE(vtd_pce, next);
     g_free(vtd_pce);
 
diff --git a/hw/i386/intel_iommu_accel.h b/hw/i386/intel_iommu_accel.h
index a2226b28b6..4a9003c92d 100644
--- a/hw/i386/intel_iommu_accel.h
+++ b/hw/i386/intel_iommu_accel.h
@@ -16,6 +16,7 @@ typedef struct VTDAccelPASIDCacheEntry {
     VTDHostIOMMUDevice *vtd_hiod;
     VTDPASIDEntry pasid_entry;
     uint32_t pasid;
+    uint32_t fs_hwpt_id;
     QLIST_ENTRY(VTDAccelPASIDCacheEntry) next;
 } VTDAccelPASIDCacheEntry;
 
@@ -23,7 +24,6 @@ typedef struct VTDAccelPASIDCacheEntry {
 bool vtd_check_hiod_accel(IntelIOMMUState *s, VTDHostIOMMUDevice *vtd_hiod,
                           Error **errp);
 VTDHostIOMMUDevice *vtd_find_hiod_iommufd(VTDAddressSpace *as);
-bool vtd_propagate_guest_pasid(VTDAddressSpace *vtd_as, Error **errp);
 void vtd_flush_host_piotlb_all_locked(IntelIOMMUState *s, uint16_t domain_id,
                                       uint32_t pasid, hwaddr addr,
                                       uint64_t npages, bool ih);
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index 95c76015e4..1842ba5840 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -154,8 +154,6 @@ struct VTDAddressSpace {
      * with the guest IOMMU pgtables for a device.
      */
     IOVATree *iova_tree;
-
-    uint32_t fs_hwpt_id;
 };
 
 struct VTDIOTLBEntry {
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 021/106] intel_iommu_accel: Add pasid bits size check
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (19 preceding siblings ...)
  2026-06-14 19:06 ` [PULL 020/106] intel_iommu_accel: Switch to VTDAccelPASIDCacheEntry for PASID bind/unbind and PIOTLB invalidation Michael S. Tsirkin
@ 2026-06-14 19:06 ` Michael S. Tsirkin
  2026-06-14 19:06 ` [PULL 022/106] intel_iommu: Expose flag VIOMMU_FLAG_PASID_SUPPORTED and VIOMMU_FLAG_WANT_PASID_ATTACH Michael S. Tsirkin
                   ` (85 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Zhenzhong Duan, Xudong Hao, Clement Mathieu--Drif,
	Jason Wang, Yi Liu, Paolo Bonzini, Richard Henderson

From: Zhenzhong Duan <zhenzhong.duan@intel.com>

If pasid bits size is bigger than host side, host could fail to emulate
all bindings in guest. Add a check to fail device plug early.

Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Tested-by: Xudong Hao <xudong.hao@intel.com>
Reviewed-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: <20260527054658.1021096-17-zhenzhong.duan@intel.com>
---
 hw/i386/intel_iommu_accel.c    | 8 ++++++++
 hw/i386/intel_iommu_internal.h | 1 +
 2 files changed, 9 insertions(+)

diff --git a/hw/i386/intel_iommu_accel.c b/hw/i386/intel_iommu_accel.c
index 97991fc0d9..c03435f8a2 100644
--- a/hw/i386/intel_iommu_accel.c
+++ b/hw/i386/intel_iommu_accel.c
@@ -22,6 +22,7 @@ bool vtd_check_hiod_accel(IntelIOMMUState *s, VTDHostIOMMUDevice *vtd_hiod,
     HostIOMMUDevice *hiod = vtd_hiod->hiod;
     struct HostIOMMUDeviceCaps *caps = &hiod->caps;
     struct iommu_hw_info_vtd *vtd = &caps->vendor_caps.vtd;
+    uint8_t hpasid = VTD_ECAP_GET_PSS(vtd->ecap_reg) + 1;
     PCIBus *bus = vtd_hiod->bus;
     PCIDevice *pdev = bus->devices[vtd_hiod->devfn];
 
@@ -42,6 +43,13 @@ bool vtd_check_hiod_accel(IntelIOMMUState *s, VTDHostIOMMUDevice *vtd_hiod,
         return false;
     }
 
+    /* Only do the check when host device support PASIDs */
+    if (caps->max_pasid_log2 && s->pasid > hpasid) {
+        error_setg(errp, "PASID bits size %d > host IOMMU PASID bits size %d",
+                   s->pasid, hpasid);
+        return false;
+    }
+
     if (pci_device_get_iommu_bus_devfn(pdev, &bus, NULL, NULL)) {
         error_setg(errp, "Host device downstream to a PCI bridge is "
                    "unsupported when fsts=on");
diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
index 64a38afa85..924e91cb8a 100644
--- a/hw/i386/intel_iommu_internal.h
+++ b/hw/i386/intel_iommu_internal.h
@@ -196,6 +196,7 @@
 #define VTD_ECAP_SRS                (1ULL << 31)
 #define VTD_ECAP_NWFS               (1ULL << 33)
 #define VTD_ECAP_SET_PSS(x, v)      ((x)->ecap = deposit64((x)->ecap, 35, 5, v))
+#define VTD_ECAP_GET_PSS(ecap)      extract64(ecap, 35, 5)
 #define VTD_ECAP_PASID              (1ULL << 40)
 #define VTD_ECAP_PDS                (1ULL << 42)
 #define VTD_ECAP_SMTS               (1ULL << 43)
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 022/106] intel_iommu: Expose flag VIOMMU_FLAG_PASID_SUPPORTED and VIOMMU_FLAG_WANT_PASID_ATTACH
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (20 preceding siblings ...)
  2026-06-14 19:06 ` [PULL 021/106] intel_iommu_accel: Add pasid bits size check Michael S. Tsirkin
@ 2026-06-14 19:06 ` Michael S. Tsirkin
  2026-06-14 19:06 ` [PULL 023/106] hw/acpi/aml-build.c: add aml_irq() representing the 3-byte IRQ descriptor Michael S. Tsirkin
                   ` (84 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Zhenzhong Duan, Yi Liu, Clement Mathieu--Drif,
	Xudong Hao, Jason Wang, Paolo Bonzini, Richard Henderson

From: Zhenzhong Duan <zhenzhong.duan@intel.com>

VFIO device will check flag VIOMMU_FLAG_PASID_SUPPORTED and expose PASID
capability, also check VIOMMU_FLAG_WANT_PASID_ATTACH to enable pasid
attachment, without those guest could not enable PASID of this device even
if vIOMMU's pasid is configured.

We don't expose the two flags when fist stage translation is not configured
as we don't support shadow page table on a PASID.

This is the final knob to enable PASID.

Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Reviewed-by: Yi Liu <yi.l.liu@intel.com>
Reviewed-by: Clement Mathieu--Drif <clement.mathieu--drif@bull.com>
Tested-by: Xudong Hao <xudong.hao@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260527054658.1021096-18-zhenzhong.duan@intel.com>
---
 hw/i386/intel_iommu.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 31addb98e4..8bb2a1e339 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -4788,6 +4788,11 @@ static uint64_t vtd_get_viommu_flags(void *opaque)
     if (s->fsts) {
         flags = VIOMMU_FLAG_WANT_NESTING_PARENT |
                 VIOMMU_FLAG_WANT_NESTING_DIRTY_TRACKING;
+
+        if (s->pasid) {
+            flags |= VIOMMU_FLAG_PASID_SUPPORTED |
+                     VIOMMU_FLAG_WANT_PASID_ATTACH;
+        }
     }
 
     return flags;
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 023/106] hw/acpi/aml-build.c: add aml_irq() representing the 3-byte IRQ descriptor
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (21 preceding siblings ...)
  2026-06-14 19:06 ` [PULL 022/106] intel_iommu: Expose flag VIOMMU_FLAG_PASID_SUPPORTED and VIOMMU_FLAG_WANT_PASID_ATTACH Michael S. Tsirkin
@ 2026-06-14 19:06 ` Michael S. Tsirkin
  2026-06-14 19:06 ` [PULL 024/106] tests/acpi: allow DSDT acpi table changes Michael S. Tsirkin
                   ` (83 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:06 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Mark Cave-Ayland, Ani Sinha, Igor Mammedov

From: Mark Cave-Ayland <mark.caveayland@nutanix.com>

The existing aml_interrupt() uses the Extended Interrupt Descriptor to store
the interrupt information, however newer Windows will only parse the
standard IRQ Descriptor when enumerating ISA serial ports.

Signed-off-by: Mark Cave-Ayland <mark.caveayland@nutanix.com>
Reviewed-by: Ani Sinha <anisinha@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260515150634.2637533-2-mark.caveayland@nutanix.com>
---
 hw/acpi/aml-build-stub.c    |  6 ++++++
 hw/acpi/aml-build.c         | 27 +++++++++++++++++++++++++++
 include/hw/acpi/aml-build.h |  2 ++
 3 files changed, 35 insertions(+)

diff --git a/hw/acpi/aml-build-stub.c b/hw/acpi/aml-build-stub.c
index 89a8fec4af..3180c7c962 100644
--- a/hw/acpi/aml-build-stub.c
+++ b/hw/acpi/aml-build-stub.c
@@ -67,6 +67,12 @@ Aml *aml_irq_no_flags(uint8_t irq)
     return NULL;
 }
 
+Aml *aml_irq(uint8_t irq, AmlLevelAndEdge level_and_edge,
+             AmlActiveHighAndLow high_and_low, AmlShared shared)
+{
+    return NULL;
+}
+
 Aml *aml_interrupt(AmlConsumerAndProducer con_and_pro,
                    AmlLevelAndEdge level_and_edge,
                    AmlActiveHighAndLow high_and_low, AmlShared shared,
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 7edc8aed42..413d9b6240 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1061,6 +1061,33 @@ Aml *aml_irq_no_flags(uint8_t irq)
     return var;
 }
 
+/*
+ * ACPI 1.0b: 6.4.2.1.1 ASL Macro for IRQ Descriptor
+ *
+ * More verbose description at:
+ * ACPI 5.0: 19.5.63 IRQ (Interrupt Resource Descriptor Macro)
+ *           6.4.2.1 IRQ Descriptor
+ */
+Aml *aml_irq(uint8_t irq, AmlLevelAndEdge level_and_edge,
+             AmlActiveHighAndLow high_and_low, AmlShared shared)
+{
+    uint16_t irq_mask;
+    Aml *var = aml_alloc();
+    uint8_t irq_flags = level_and_edge | (high_and_low << 3) |
+                        (shared << 4);
+
+    assert((level_and_edge == AML_EDGE && high_and_low == AML_ACTIVE_HIGH) ||
+           (level_and_edge == AML_LEVEL && high_and_low == AML_ACTIVE_LOW));
+    assert(irq < 16);
+    build_append_byte(var->buf, 0x23); /* IRQ descriptor 3 byte form */
+
+    irq_mask = 1U << irq;
+    build_append_byte(var->buf, irq_mask & 0xFF); /* IRQ mask bits[7:0] */
+    build_append_byte(var->buf, irq_mask >> 8); /* IRQ mask bits[15:8] */
+    build_append_byte(var->buf, irq_flags); /* IRQ flags */
+    return var;
+}
+
 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLNot */
 Aml *aml_lnot(Aml *arg)
 {
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index e70e0643b1..eaff025d26 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -343,6 +343,8 @@ Aml *aml_io(AmlIODecode dec, uint16_t min_base, uint16_t max_base,
 Aml *aml_operation_region(const char *name, AmlRegionSpace rs,
                           Aml *offset, uint32_t len);
 Aml *aml_irq_no_flags(uint8_t irq);
+Aml *aml_irq(uint8_t irq, AmlLevelAndEdge level_and_edge,
+             AmlActiveHighAndLow high_and_low, AmlShared shared);
 Aml *aml_named_field(const char *name, unsigned length);
 Aml *aml_reserved_field(unsigned length);
 Aml *aml_local(int num);
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 024/106] tests/acpi: allow DSDT acpi table changes
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (22 preceding siblings ...)
  2026-06-14 19:06 ` [PULL 023/106] hw/acpi/aml-build.c: add aml_irq() representing the 3-byte IRQ descriptor Michael S. Tsirkin
@ 2026-06-14 19:06 ` Michael S. Tsirkin
  2026-06-14 19:06 ` [PULL 025/106] hw/char/serial-isa.c: declare IRQ as shared in ACPI IRQ descriptor Michael S. Tsirkin
                   ` (82 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:06 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Mark Cave-Ayland, Ani Sinha, Igor Mammedov

From: Mark Cave-Ayland <mark.caveayland@nutanix.com>

Signed-off-by: Mark Cave-Ayland <mark.caveayland@nutanix.com>
Acked-by: Ani Sinha <anisinha@redhat.com>
Acked-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260515150634.2637533-3-mark.caveayland@nutanix.com>
---
 tests/qtest/bios-tables-test-allowed-diff.h | 47 +++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523c8b..cef44135bc 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,48 @@
 /* List of comma-separated changed AML files to ignore */
+"tests/data/acpi/x86/pc/DSDT",
+"tests/data/acpi/x86/pc/DSDT.bridge",
+"tests/data/acpi/x86/pc/DSDT.ipmikcs",
+"tests/data/acpi/x86/pc/DSDT.cphp",
+"tests/data/acpi/x86/pc/DSDT.numamem",
+"tests/data/acpi/x86/pc/DSDT.nohpet",
+"tests/data/acpi/x86/pc/DSDT.memhp",
+"tests/data/acpi/x86/pc/DSDT.dimmpxm",
+"tests/data/acpi/x86/pc/DSDT.acpihmat",
+"tests/data/acpi/x86/pc/DSDT.acpierst",
+"tests/data/acpi/x86/pc/DSDT.roothp",
+"tests/data/acpi/x86/pc/DSDT.hpbridge",
+"tests/data/acpi/x86/pc/DSDT.hpbrroot",
+"tests/data/acpi/x86/q35/DSDT",
+"tests/data/acpi/x86/q35/DSDT.tis.tpm2",
+"tests/data/acpi/x86/q35/DSDT.tis.tpm12",
+"tests/data/acpi/x86/q35/DSDT.bridge",
+"tests/data/acpi/x86/q35/DSDT.noacpihp",
+"tests/data/acpi/x86/q35/DSDT.multi-bridge",
+"tests/data/acpi/x86/q35/DSDT.ipmibt",
+"tests/data/acpi/x86/q35/DSDT.cphp",
+"tests/data/acpi/x86/q35/DSDT.numamem",
+"tests/data/acpi/x86/q35/DSDT.nohpet",
+"tests/data/acpi/x86/q35/DSDT.acpihmat-noinitiator",
+"tests/data/acpi/x86/q35/DSDT.acpihmat-generic-x",
+"tests/data/acpi/x86/q35/DSDT.memhp",
+"tests/data/acpi/x86/q35/DSDT.dimmpxm",
+"tests/data/acpi/x86/q35/DSDT.acpihmat",
+"tests/data/acpi/x86/q35/DSDT.mmio64",
+"tests/data/acpi/x86/q35/DSDT.acpierst",
+"tests/data/acpi/x86/q35/DSDT.applesmc",
+"tests/data/acpi/x86/q35/DSDT.pvpanic-isa",
+"tests/data/acpi/x86/q35/DSDT.ivrs",
+"tests/data/acpi/x86/q35/DSDT.type4-count",
+"tests/data/acpi/x86/q35/DSDT.core-count",
+"tests/data/acpi/x86/q35/DSDT.core-count2",
+"tests/data/acpi/x86/q35/DSDT.thread-count",
+"tests/data/acpi/x86/q35/DSDT.thread-count2",
+"tests/data/acpi/x86/q35/DSDT.viot",
+"tests/data/acpi/x86/q35/DSDT.cxl",
+"tests/data/acpi/x86/q35/DSDT.ipmismbus",
+"tests/data/acpi/x86/q35/DSDT.xapic",
+"tests/data/acpi/x86/microvm/DSDT",
+"tests/data/acpi/x86/microvm/DSDT.usb",
+"tests/data/acpi/x86/microvm/DSDT.rtc",
+"tests/data/acpi/x86/microvm/DSDT.ioapic2",
+"tests/data/acpi/x86/microvm/DSDT.pcie",
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 025/106] hw/char/serial-isa.c: declare IRQ as shared in ACPI IRQ descriptor
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (23 preceding siblings ...)
  2026-06-14 19:06 ` [PULL 024/106] tests/acpi: allow DSDT acpi table changes Michael S. Tsirkin
@ 2026-06-14 19:06 ` Michael S. Tsirkin
  2026-06-14 19:06 ` [PULL 026/106] tests: data: update x86 ACPI tables Michael S. Tsirkin
                   ` (81 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Mark Cave-Ayland, Ani Sinha, Igor Mammedov,
	Paolo Bonzini, Marc-André Lureau

From: Mark Cave-Ayland <mark.caveayland@nutanix.com>

From Windows 8.1 onwards ISA serial IRQs cannot be shared when ACPI Revision
3.0 is used in the FACP table. The reason for this is that if a 2-byte IRQ
Descriptor is used then the interrupt is considered to be high true, edge
sensitive, non-shareable. Since legacy serial ports COM1/3 and COM2/4 share
an IRQ then if more than 2 serial ports are added, Windows indicates a
conflict in Device Manager and these combinations cannot be used together.

Change the 2-byte IRQ Descriptor in the _CRS resource to a 3-byte IRQ
Descriptor indicating that the ISA serial IRQ is low true, level sensitive and
shareable. This enables all 4 legacy serial ports to be used in Windows without
conflict.

Note that it was agreed during the list discussion that this change does not
require a compatibility property since it is not part of the default machine
configuration and was already broken.

Signed-off-by: Mark Cave-Ayland <mark.caveayland@nutanix.com>
Reviewed-by: Ani Sinha <anisinha@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260515150634.2637533-4-mark.caveayland@nutanix.com>
---
 hw/char/serial-isa.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/char/serial-isa.c b/hw/char/serial-isa.c
index a4be0492c5..eaa4e843c0 100644
--- a/hw/char/serial-isa.c
+++ b/hw/char/serial-isa.c
@@ -92,7 +92,8 @@ static void serial_isa_build_aml(AcpiDevAmlIf *adev, Aml *scope)
 
     crs = aml_resource_template();
     aml_append(crs, aml_io(AML_DECODE16, isa->iobase, isa->iobase, 0x00, 0x08));
-    aml_append(crs, aml_irq_no_flags(isa->isairq));
+    aml_append(crs, aml_irq(isa->isairq, AML_LEVEL, AML_ACTIVE_LOW,
+                            AML_SHARED));
 
     dev = aml_device("COM%d", isa->index + 1);
     aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0501")));
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 026/106] tests: data: update x86 ACPI tables
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (24 preceding siblings ...)
  2026-06-14 19:06 ` [PULL 025/106] hw/char/serial-isa.c: declare IRQ as shared in ACPI IRQ descriptor Michael S. Tsirkin
@ 2026-06-14 19:06 ` Michael S. Tsirkin
  2026-06-14 19:06 ` [PULL 027/106] vhost-user: rework enabling vrings Michael S. Tsirkin
                   ` (80 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:06 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Mark Cave-Ayland, Ani Sinha, Igor Mammedov

From: Mark Cave-Ayland <mark.caveayland@nutanix.com>

Update the x86 ACPI tables to reflect the IRQ descriptor changes for ISA serial
ports:

     Device (COM1)
     {
         Name (_HID, EisaId ("PNP0501") /* 16550A-compatible COM Serial Port */)  // _HID: Hardware ID
         Name (_UID, One)  // _UID: Unique ID
         Name (_STA, 0x0F)  // _STA: Status
         Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
         {
             IO (Decode16,
                 0x03F8,             // Range Minimum
                 0x03F8,             // Range Maximum
                 0x00,               // Alignment
                 0x08,               // Length
                 )
-            IRQNoFlags ()
+            IRQ (Level, ActiveLow, Shared, )
                 {4}
         })
     }

Signed-off-by: Mark Cave-Ayland <mark.caveayland@nutanix.com>
Acked-by: Ani Sinha <anisinha@redhat.com>
Acked-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260515150634.2637533-5-mark.caveayland@nutanix.com>
---
 tests/data/acpi/x86/microvm/DSDT              | Bin 365 -> 366 bytes
 tests/data/acpi/x86/microvm/DSDT.ioapic2      | Bin 365 -> 366 bytes
 tests/data/acpi/x86/microvm/DSDT.pcie         | Bin 2985 -> 2986 bytes
 tests/data/acpi/x86/microvm/DSDT.rtc          | Bin 404 -> 405 bytes
 tests/data/acpi/x86/microvm/DSDT.usb          | Bin 414 -> 415 bytes
 tests/data/acpi/x86/pc/DSDT                   | Bin 8598 -> 8599 bytes
 tests/data/acpi/x86/pc/DSDT.acpierst          | Bin 8509 -> 8510 bytes
 tests/data/acpi/x86/pc/DSDT.acpihmat          | Bin 9923 -> 9924 bytes
 tests/data/acpi/x86/pc/DSDT.bridge            | Bin 15469 -> 15470 bytes
 tests/data/acpi/x86/pc/DSDT.cphp              | Bin 9062 -> 9063 bytes
 tests/data/acpi/x86/pc/DSDT.dimmpxm           | Bin 10252 -> 10253 bytes
 tests/data/acpi/x86/pc/DSDT.hpbridge          | Bin 8549 -> 8550 bytes
 tests/data/acpi/x86/pc/DSDT.hpbrroot          | Bin 5087 -> 5088 bytes
 tests/data/acpi/x86/pc/DSDT.ipmikcs           | Bin 8670 -> 8671 bytes
 tests/data/acpi/x86/pc/DSDT.memhp             | Bin 9957 -> 9958 bytes
 tests/data/acpi/x86/pc/DSDT.nohpet            | Bin 8456 -> 8457 bytes
 tests/data/acpi/x86/pc/DSDT.numamem           | Bin 8604 -> 8605 bytes
 tests/data/acpi/x86/pc/DSDT.roothp            | Bin 12391 -> 12392 bytes
 tests/data/acpi/x86/q35/DSDT                  | Bin 8427 -> 8428 bytes
 tests/data/acpi/x86/q35/DSDT.acpierst         | Bin 8444 -> 8445 bytes
 tests/data/acpi/x86/q35/DSDT.acpihmat         | Bin 9752 -> 9753 bytes
 .../data/acpi/x86/q35/DSDT.acpihmat-generic-x | Bin 12637 -> 12638 bytes
 .../acpi/x86/q35/DSDT.acpihmat-noinitiator    | Bin 8706 -> 8707 bytes
 tests/data/acpi/x86/q35/DSDT.applesmc         | Bin 8473 -> 8474 bytes
 tests/data/acpi/x86/q35/DSDT.bridge           | Bin 12040 -> 12041 bytes
 tests/data/acpi/x86/q35/DSDT.core-count       | Bin 12985 -> 12986 bytes
 tests/data/acpi/x86/q35/DSDT.core-count2      | Bin 33842 -> 33843 bytes
 tests/data/acpi/x86/q35/DSDT.cphp             | Bin 8891 -> 8892 bytes
 tests/data/acpi/x86/q35/DSDT.cxl              | Bin 13218 -> 13219 bytes
 tests/data/acpi/x86/q35/DSDT.dimmpxm          | Bin 10081 -> 10082 bytes
 tests/data/acpi/x86/q35/DSDT.ipmibt           | Bin 8502 -> 8503 bytes
 tests/data/acpi/x86/q35/DSDT.ipmismbus        | Bin 8515 -> 8516 bytes
 tests/data/acpi/x86/q35/DSDT.ivrs             | Bin 8444 -> 8445 bytes
 tests/data/acpi/x86/q35/DSDT.memhp            | Bin 9786 -> 9787 bytes
 tests/data/acpi/x86/q35/DSDT.mmio64           | Bin 9557 -> 9558 bytes
 tests/data/acpi/x86/q35/DSDT.multi-bridge     | Bin 13280 -> 13281 bytes
 tests/data/acpi/x86/q35/DSDT.noacpihp         | Bin 8289 -> 8290 bytes
 tests/data/acpi/x86/q35/DSDT.nohpet           | Bin 8285 -> 8286 bytes
 tests/data/acpi/x86/q35/DSDT.numamem          | Bin 8433 -> 8434 bytes
 tests/data/acpi/x86/q35/DSDT.pvpanic-isa      | Bin 8528 -> 8529 bytes
 tests/data/acpi/x86/q35/DSDT.thread-count     | Bin 12985 -> 12986 bytes
 tests/data/acpi/x86/q35/DSDT.thread-count2    | Bin 33842 -> 33843 bytes
 tests/data/acpi/x86/q35/DSDT.tis.tpm12        | Bin 9033 -> 9034 bytes
 tests/data/acpi/x86/q35/DSDT.tis.tpm2         | Bin 9059 -> 9060 bytes
 tests/data/acpi/x86/q35/DSDT.type4-count      | Bin 18661 -> 18662 bytes
 tests/data/acpi/x86/q35/DSDT.viot             | Bin 14684 -> 14685 bytes
 tests/data/acpi/x86/q35/DSDT.xapic            | Bin 35790 -> 35791 bytes
 tests/qtest/bios-tables-test-allowed-diff.h   |  47 ------------------
 48 files changed, 47 deletions(-)

diff --git a/tests/data/acpi/x86/microvm/DSDT b/tests/data/acpi/x86/microvm/DSDT
index f477668f2ee80241e47b340ad4a30f5480df2049..5d03103170c7e22f903f3ccdb3d32be0a4405498 100644
GIT binary patch
delta 47
zcmaFM^p1(kCD<h-kCB0a>GMP`X-1EUYUYf_6XO*51-ba#8GkVUU}oS@7GRK=*!utg
DFN_Rz

delta 46
zcmaFI^p=UsCD<h-myv;iNpK>UG^6`OHFHLziE)a20$jZAj6axvFf(u{2{26TdjJ3k
C0}FKk

diff --git a/tests/data/acpi/x86/microvm/DSDT.ioapic2 b/tests/data/acpi/x86/microvm/DSDT.ioapic2
index e5924a49962e0cff4228bcfc77ebcf48cb4a2219..b48db019ffec202fb93a5cdd834581f5e8bdba66 100644
GIT binary patch
delta 47
zcmaFM^p1(kCD<h-kCB0aY3)QVX-1EUYUYf_6XO*51-ba#8GkVUU}oS@7GRK=*!utg
DCWZ_z

delta 46
zcmaFI^p=UsCD<h-myv;i>GVV{X-4;nYUYea6XO*51h{zJ8GkVUU}oS@5@49v_W%GN
CLkuqf

diff --git a/tests/data/acpi/x86/microvm/DSDT.pcie b/tests/data/acpi/x86/microvm/DSDT.pcie
index b646a05551c1ed902413a462442346ce246f8675..b92fb08532a24eaf5cfe0e6039e80688be3fffa7 100644
GIT binary patch
delta 48
zcmZ1}zDk_SCD<io6*mI|)2)eI(u^(>)yx@<C&nrA3v%(fGyY)y!OXy+EWjYKu~&v0
E05Eb3rvLx|

delta 47
zcmZ1_zEYgaCD<ioB{u^D(~pT<(u~d%)yx@<CdMi932^bcGyY)y!OXy+B*3t-Plg)+
DDIN=_

diff --git a/tests/data/acpi/x86/microvm/DSDT.rtc b/tests/data/acpi/x86/microvm/DSDT.rtc
index e375473b5f033d374dd2a64a9f814fd16c3e262f..c101332010f058824c8e11c7a1f844c752816f63 100644
GIT binary patch
delta 48
zcmbQjJe8TtCD<ioDkB2})4_>c(v1ES)yx@<C&nrA3v%(fGyY)y!OXy+EWjYKv6r0@
E02-DH2><{9

delta 47
zcmbQrJcXIdCD<io3L^sp)BTBD(u{r+)yx@<CdMi932^bcGyY)y!OXy+B*3t-kDU<!
D6Tu4!

diff --git a/tests/data/acpi/x86/microvm/DSDT.usb b/tests/data/acpi/x86/microvm/DSDT.usb
index d63fd84620a2689120b32262f964e6a098d71632..9261b67dc055d4cb2194892bc20bd869c7a467d1 100644
GIT binary patch
delta 48
zcmbQoJfE4%CD<ioJ|hDI6Z1qaX-3b9YUYf_6XO*51-ba#8GkVUU}oS@7GRLr*el2g
E00r_2Z2$lO

delta 47
zcmbQwJdc^nCD<io9wP$-lj1}!X-1EUYUYea6XO*51h{zJ8GkVUU}oS@5@6WaC&&l@
D|FjBi

diff --git a/tests/data/acpi/x86/pc/DSDT b/tests/data/acpi/x86/pc/DSDT
index 6ea2d36d138daffb59a8636759078500adc58f24..e30e7091ddcc00fef2171918f0f5fd69aba72f95 100644
GIT binary patch
delta 82
zcmbQ{Jl&bgCD<iox*`Ju<MoYP+lA!3p2frmJH-n)JqvL5G>C5E4mL1|=ZJT731WzD
ma^HMkD29>Ic(RR%BEKLPpF86Z<{!)q9LfR=5}UI{w0Qv-eisS=

delta 81
zcmbR4Jk6QQCD<ionj!-O<M)kR+lAyjpT)!nJH-n)J_~U6G>C5E4mL1|=ZJT731WzD
la@%}gD29>IXtIrnBA);kuRG%p<{!)q97+NVn{!08c>xKT7YYCX

diff --git a/tests/data/acpi/x86/pc/DSDT.acpierst b/tests/data/acpi/x86/pc/DSDT.acpierst
index d8c173aa613f51b1c76ea7b9dee19e899cba240d..4e044bb4eb2048a8ae15df102b78c6ebf0cd8f13 100644
GIT binary patch
delta 82
zcmdn%w9kplCD<jzPLY9uQGO%Wb|E>(hcWTNPVoYs4+5M$4WgU4gAEMgIpQ5%f*7Kk
m+&AABieY3lo@^tc$S=sn=g#<p`3Exthq3^J#O7>~OFRJNW)|K6

delta 81
zcmdnzwAYEtCD<jzR*`{$(S9S>b|E>3hcWTNPVoXB4+5M$4WgU4gAEMgIpQ5%f*7Kk
l+&14AieY3lnrtJY$S1(X>(2Ot`3Exthmrup<{XhrJOI{H7Ty2=

diff --git a/tests/data/acpi/x86/pc/DSDT.acpihmat b/tests/data/acpi/x86/pc/DSDT.acpihmat
index ba363d6af76af728b7c88bbaf47f7e0ea3dcb41f..54ce2df998b10a9c88efe8b76c7b2d533460d432 100644
GIT binary patch
delta 82
zcmX@?d&HN^CD<k8h#CU}<CKkDPsHWCp2frmJH-n)JqvL5G>C5E4mL1|=ZJT731WzD
ma^K7&5yQx6JULTRkzbID&z<oH^ABbQ4rKubiOn-4wRr(B>lZKp

delta 81
zcmX@&d)SxDCD<k8uo?pc<CcwFPsHUspT)!nJH-n)J_~U6G>C5E4mL1|=ZJT731WzD
la@))!5yQx6G&xgJkxzh&*PZbP^ABbQ4kZDG%`+vnc>y947cc+-

diff --git a/tests/data/acpi/x86/pc/DSDT.bridge b/tests/data/acpi/x86/pc/DSDT.bridge
index b68302363cb24181988d6e3dceb04a0946838d5e..957e12c296d76ef63877691947c94176ab40b08d 100644
GIT binary patch
delta 83
zcmaD`@vef)CD<h-&xV14@##jc?LrEDy-YFj!A|i4t-VYE&YlL*P29l-2Jsy6jxIqA
n(M|4~9}2}VG8#{|6H(+B<l=K@{K5Q#nSn!DfI(t$u80NzWKb95

delta 82
zcmaD?@wS4?CD<h-*M@<Ck#!^2b|Hn{UZ$A%V5fM2mR_a+XHSFZChlMZgLsa3N0%Um
m=q9(#4~1eF8I2~}i74_3aPhh`{$T#W%)p@}z_2(^L<0a2uNLC~

diff --git a/tests/data/acpi/x86/pc/DSDT.cphp b/tests/data/acpi/x86/pc/DSDT.cphp
index 20688edf2da41146ece4faa4141517408a42870c..64e1b6693d67138e6d6c58c43bbcef0dcfd215b4 100644
GIT binary patch
delta 82
zcmaFn_S}ujCD<h-U73M_(Q6}DyNI0EvzYi`r+5LUX93Qh2GLF2!3GBL9Py4WK@8DN
m?wi+(#4s`%Pv#L*<QL@Pb7%a){DYZ+Ls@`9VzafFHZK4K8WueO

delta 81
zcmaFv_RNjTCD<h-O__m#F>51NyNI0UvzYi`r+5L!X93Qh2GLF2!3GBL9Py4WK@8DN
lZkyMO#4s`%P393(<P+fHb!Ys+{DYZ+LrH*PvyGTGF97w$7Cis}

diff --git a/tests/data/acpi/x86/pc/DSDT.dimmpxm b/tests/data/acpi/x86/pc/DSDT.dimmpxm
index 8d4be05d2c71ca8de6d732d3e48e0e323143160c..3c27fd0d1ec7469b4cc2efbf2e476b3345c3d86d 100644
GIT binary patch
delta 95
zcmeAP=ndd<33dtL)nH&?{JxP(SCZ4~SxkJeQ@nuFWCuwRM)%F3k}-^i#?Jn}h8*!8
zo-RC&7g!lN;zK=M7&+pDLmavIIpUpzf&~S+_}m$PF#lj?;7}G|kl6fCN}Cq|t_~Nb

delta 75
zcmeAT=n3F*33dtL(O_U;6yM0DE6M5kEG9nKDPF*FvV)`uqub_C$rwg{BWHhKLymY4
fPZu7?3#^Qjd!!^de=z@GX5df~VA%XfN}Cq|+i4SC

diff --git a/tests/data/acpi/x86/pc/DSDT.hpbridge b/tests/data/acpi/x86/pc/DSDT.hpbridge
index 2b5b885b862a2fe8bc4a24446400dccf685dab85..89c4df716af921f4dac0c8ba1f7968ef1f93f717 100644
GIT binary patch
delta 82
zcmaFr^vsFNCD<h-O_70tk$WT8b|E>>$1(B2PVoYcj{}@N4WgU4gAEMgIpQ5%f*7Kk
m+&AABieY3lo@^tc$S=sn=g#<p`3Exthq3^J#O7>~UpxQ>h8J%D

delta 81
zcmaFn^wf#VCD<h-Rgr;#QF|lTb|E>B$1(B2PVoW`j{}@N4WgU4gAEMgIpQ5%f*7Kk
l+&14AieY3lnrtJY$S1(X>(2Ot`3Exthmrup<{Xh<JOK9l7jFOn

diff --git a/tests/data/acpi/x86/pc/DSDT.hpbrroot b/tests/data/acpi/x86/pc/DSDT.hpbrroot
index cc6f26a3f8fe85f34a8acb5432bab3cf4d3ab1f6..8cd0d2a4cf82d9fedbee74671e8ff5ad820a5c77 100644
GIT binary patch
delta 82
zcmcbw{y?3}CD<k8fiMFDqt`|*9zi)TotXGwr+5J;od9P~gXkviU;~4Aj(A6xAcp8B
m_su4PF^r7HlP3x(@(XhDxikJ?{=v+^p)9~4vH5_IJR<;>Fcj1P

delta 81
zcmaE$eqWu-CD<k8zAys=W7bA49zi)zotXGwr+5KJod9P~gXkviU;~4Aj(A6xAcp8B
lx6LMkF^r5xlP3x(@(FP9x-<S@{=v+^p(Mbt`Jj+IBLIoK6x09!

diff --git a/tests/data/acpi/x86/pc/DSDT.ipmikcs b/tests/data/acpi/x86/pc/DSDT.ipmikcs
index 052a84e294eee4ecef9a36341493f841caf887a5..97bfbf74ef1d00aaadfac066032677d72f2bc054 100644
GIT binary patch
delta 82
zcmV-Y0ImPtL*GLRL{mgm-yr}10aLLGw-O#g>s((`LSGO{>QF;TFk6BPQ!p@J2wy=&
oQUF_mPqW_=qyYgllY|r@4-pCuM*;W)_yYh4BM<->v$GT{4N6-WM*si-

delta 81
zcmV-X0IvVvL*7FQL{mgm-XQ=00duhmw-O#f>s((`LSGO`>QF;TFk6BPQ!p@J2wy=&
nQUF_mPP5+<qyYgklY|r@4iE|rM*;W)_yYh4A`k$xv=l21I)NBR

diff --git a/tests/data/acpi/x86/pc/DSDT.memhp b/tests/data/acpi/x86/pc/DSDT.memhp
index 7efc12a46cb87c0684b7d880b2cc94d302744e03..b2c4c70d9cbdf74ab07983f69b0315191a7ee142 100644
GIT binary patch
delta 82
zcmaFr`^=ZiCD<k8nHmEF<LZrEY!Y%_&tl?(o#F+Yo&`928bmj72OAi~bHqEk1TjQ6
mxo_5!h+$+jp4=^|$S=sn=g#<p`3Exthq3^J#O7U++PnZI^%ph(

delta 81
zcmaFn`_z}qCD<k8sTu<V<LQlDY!Y&w&tl?(o#F)?p9MI38bmj72OAi~bHqEk1TjQ6
lxoy^yh+$+jn%pg^$S1(X>(2Ot`3Exthmrup=G~IoyZ{$C7d8L@

diff --git a/tests/data/acpi/x86/pc/DSDT.nohpet b/tests/data/acpi/x86/pc/DSDT.nohpet
index 7eedfcd64ebd0193744864b4f6cbead35c7c3ab2..f762b83ee7a5001f5a92a73c201b814f7007afd5 100644
GIT binary patch
delta 82
zcmeBh>U83A33dtLRAgXaT(FT#Q%KJ1SxkJeQ@nuFvjAsLgXkviU;~4Aj(A6xAcp8B
m_sxMqF^r7Hlh+9=@(XhDxikJ?{=v+^p)9~4vH7mBHZK6K_Z95`

delta 81
zcmeBl>Tu$633dtLP-I|WJg|{VQ%KJ9SxkJeQ@nuVvjAsLgXkviU;~4Aj(A6xAcp8B
lx6Oe<F^r5xlh+9=@(FP9x-<S@{=v+^p(Mbt`JS*gF94yS73}~3

diff --git a/tests/data/acpi/x86/pc/DSDT.numamem b/tests/data/acpi/x86/pc/DSDT.numamem
index 910b4952a0757025cfed1c60416d16054e70846f..a215ea995a2f5a2bd4c7876fd79011b7ce5beabc 100644
GIT binary patch
delta 95
zcmbQ^JlC1aCD<iot|9{iWAa9>y+WK`&tl?(o#F+YCSMQ|VRYa8R49hg(Ae4E*N`LL
z!_$Sw@d7I&M|`NK3nNE-aEK!pKS#WCP_UpN7oR)h59S}t3>?Y=3=*3QMYMSV8UYx_

delta 75
zcmV-R0JQ&|L!3hjL{mgmoFM=J0fVs$y%GsY=3HM>LSGO;lh6_r0Y<as5?lcfGDA;I
hF$iBsNkj}m&;<dL926J{_yhO@00<%w0JCxwD-B#;6$k(T

diff --git a/tests/data/acpi/x86/pc/DSDT.roothp b/tests/data/acpi/x86/pc/DSDT.roothp
index 45d3dbe1b69143a956b4f829913ca47f07134741..6a1557bfd816c061c317e5fd35c417543d668050 100644
GIT binary patch
delta 84
zcmaE!@FIcBCD<h-!+?Q-F?l1`b|HnP^Nca^!A|i4o#z+>oIMSqo4A7w4B|QB9bJML
oqMO_|KNN~#WHg>^C!)wN$i?T*_=EWeGXsaR0E5KlT#;YW09}<Bi2wiq

delta 83
zcmaEn@H~ObCD<h--GG6Cv3Vocb|Hnv^Nca^!A|i49p@MWoIMSqo4A7w4B|QB9bJML
nqMO_{KNN~#WHg#=C!)wFz{Ts%_=EWeGXsZ`0K?`ykzdjPPD>bx

diff --git a/tests/data/acpi/x86/q35/DSDT b/tests/data/acpi/x86/q35/DSDT
index 377e880175f6f11101548c0c64da61b5aee00bd9..55b44cfa70f33986aff4eb2332248486689e13ec 100644
GIT binary patch
delta 65
zcmaFu_{NdTCD<k8jRFG$<I;^>^75Q+(lPPDPVoYMla1sZ7`-PK%YR@ro}8kf$S=sn
V=g#<p`3Exthq3^J#N^2e5dehL5)A+V

delta 64
zcmaFk_}Y=nCD<k8wE_bJ<I#;=^75Rn(lPPDPVoZ1la1sZ7`-MJ%YR@rnw+Ab$S1(X
U>(2Ot`3Exthmrup<S7af0C`ao4FCWD

diff --git a/tests/data/acpi/x86/q35/DSDT.acpierst b/tests/data/acpi/x86/q35/DSDT.acpierst
index 026bfdfebf66c1803f158ac8c115eb5f49b5cb19..50691d93ed45b697290ca32d0f56765fc3a77379 100644
GIT binary patch
delta 65
zcmez4_}7ukCD<k8uL1)Dqw7X4d3jEEnV9%sr+5MX$wu;ljNX%5<UcSPPcBtZ<QL@P
Vb7%a){DYZ+Ls@`9V)7D&2mpja5+?uv

delta 64
zcmezC_{WjUCD<k8j{*Y&W9mjOd3jDZnV9%sr+5Ls$wu;lj9!yl<UcSPO)gbX<P+fH
Ub!Ys+{DYZ+LrH*P@=}Ee0C=_%CjbBd

diff --git a/tests/data/acpi/x86/q35/DSDT.acpihmat b/tests/data/acpi/x86/q35/DSDT.acpihmat
index f1b8483d8da21dd57f3e5e7a1e4eb787df2c38ac..6b1b87699e96f06f315df529ee6306633d7fad0b 100644
GIT binary patch
delta 65
zcmbQ?Gt-C5CD<iIQjLLuF>xc8j|!)obWD7(Q@nuR<aiYaM(@cBR6Z~oPoAi%$S=sn
V=g#<p`3Exthq3^J#N-325dc9i5oQ1Y

delta 64
zcmbQ~GsB0=CD<iILXClev2i1pj|!)&bWD7(Q@nuh<aiYaMz6^WR6Z~oO`fQ#$S1(X
U>(2Ot`3Exthmrup<b$da05*jYW&i*H

diff --git a/tests/data/acpi/x86/q35/DSDT.acpihmat-generic-x b/tests/data/acpi/x86/q35/DSDT.acpihmat-generic-x
index a7731403f460a235bf705770a1547dafeee069ab..833e55273ca2e72c7fe047d1c2e593a6169b8dca 100644
GIT binary patch
delta 66
zcmcbcbT5g^CD<h-&X9qDQFJ5MI$cgDqnP+$r+5Lc%?EYYFfw{i&eQ+EXgoRIK#^aN
Wi_e|$2lEeR1`cHb28qdi2Im2*XcLqG

delta 65
zcmcbYbT^61CD<h-){udL(R3r%I$cgjqnP+$r+5L+%?EYYFfw{g&eQ+EXf!$AK#@;?
Vi`Sj;2lEeR1`Z_whROW~=K-Gm6O;e|

diff --git a/tests/data/acpi/x86/q35/DSDT.acpihmat-noinitiator b/tests/data/acpi/x86/q35/DSDT.acpihmat-noinitiator
index cb4995de7e33cd9f2d134ec96651d217873d6944..4bbff971ec2edd32f58272c0381c383839b75248 100644
GIT binary patch
delta 65
zcmZp2X?Edq33dr#R$^dal-|f?roibY9TOky6ffX6*;B!R(R*^2!Usm<$<>OA{DNG3
V?u<W}e=sv}C<`!1OkSlJ0RRxO5J&(3

delta 64
zcmZp6X>#Fm33dr#Qet3WwBE>Nroibc9TOky6ffXA*;B!R(Q9&-!Usm9$<>OAd;(m&
U?u<W}e=sv}C<!o3Uac4b00#>YNB{r;

diff --git a/tests/data/acpi/x86/q35/DSDT.applesmc b/tests/data/acpi/x86/q35/DSDT.applesmc
index 92c8fdb6cbb8ae8bdf5ede9679eea92486eaf372..01834e412bbc52e5a62364df94f5e1dbb637ef72 100644
GIT binary patch
delta 94
zcmbQ~G|P$0CD<iIN|Awqamq$6d3jD3xtRE1r+5LM$wu-HjGmi|<>eR+jh+2{4LRaH
yJY9GkFR(Il#D{viFml8Phd6TabHqCb1q%vt@wqepVE)0(z@aR_ATjx%LIeOoMiy-V

delta 74
zcmbQ`G}DR8CD<iIQjvjyamz+7d3jD}xtRE1r+5MH$wu-Hj2@ed<>eUpjhy{`4LRaH
eJY9GkFR(IB&QXxy{K5Q#nSnz|fMN0>g$Mw{l@kj9

diff --git a/tests/data/acpi/x86/q35/DSDT.bridge b/tests/data/acpi/x86/q35/DSDT.bridge
index 957b3ad90c787616eac212865bce0a19a5ac1e6e..e379a9be89a34551b2a5016ebcc24c08a28a3625 100644
GIT binary patch
delta 66
zcmeB(>x|=a33dtL)MsE|Jg|{VUY^tEYfOBwQ@nu7W+VA$yo}zHC3QbA8c*iZQ{)%q
W;&W&G!Tf`nfkRn<L1MC{-gy9XToMET

delta 65
zcmeB->xkoW33dtL&}U#^e6W#AUY^tYYfOBwQ@nulW+VA$yo_FxC3QbA8cpWXQ{)ri
V;&o^I!Tf`nfkR1vVX~Fpc>riC5(EGM

diff --git a/tests/data/acpi/x86/q35/DSDT.core-count b/tests/data/acpi/x86/q35/DSDT.core-count
index 50ca91b065d9a2ba95f97d01856865f0e7c615f6..50d6eac8ba070bf381aacd13ced47115f0897ebe 100644
GIT binary patch
delta 92
zcmdm)x+|5-CD<iomk|R4qwGemw+5VU(lPPDPVoYMlMEdgy(c>welRq4_V+d9i1+Yx
w;c>jc%E%EP>gmGB5g#1l$i>eQ?;I2?D9FX<&iI4*2QveQvH*j`<V2$g0Lv>FF#rGn

delta 72
zcmdm$x-*r_CD<iorx61KqwPknw+5W9(lPPDPVoZ1lMEdgy(T*ve&9E9_V+d9i1+Yx
c;c>jc$~c+FNP_bR^ABbQ4kZDG$w@{L03N6mfdBvi

diff --git a/tests/data/acpi/x86/q35/DSDT.core-count2 b/tests/data/acpi/x86/q35/DSDT.core-count2
index f460be2bf74ae512db8f24418b42e8cf2a56202d..69b31da613663a58f9adef8d3981d9ed7c824a28 100644
GIT binary patch
delta 67
zcmdng!L+%9iOVI}CB(Refq^k^BUf4zr<-(4e6UlzfZycGCI?3E$-A09Fd9!@-K@wj
X$i?T*_=EWeGXsaR0E5KjTg?#w%efTu

delta 66
zcmdno!L+G^iOVI}CB&$Ofq}7aBUf4zr>k^Ke6UlzfbZnWCI?2Z$-A09Fd9u>-K@wb
Wz{Ts%_=EWeGXsZ`0K??l%@F{-`xNs4

diff --git a/tests/data/acpi/x86/q35/DSDT.cphp b/tests/data/acpi/x86/q35/DSDT.cphp
index 7c87d41d03fcfd2b5b82f2581f16de6bc0bb10bf..d46bac4e257162b5ecc98c7c130c1654de192192 100644
GIT binary patch
delta 65
zcmdn(y2q8vCD<ioj}ij|qr^t8_X?bD(lPPDPVoYMlbIA97`-PuD}G=!o@}C|$S=sn
V=g#<p`3Exthq3^J#N=e92moK65fcCa

delta 64
zcmdnvy4#h@CD<iow-N&bqs2z9_X?b@(lPPDPVoZ1lbIA97`-MtD}G=!nrxz^$S1(X
U>(2Ot`3Exthmrup<P@a{095A@6951J

diff --git a/tests/data/acpi/x86/q35/DSDT.cxl b/tests/data/acpi/x86/q35/DSDT.cxl
index da86b25f51b550ab20771111cb0a2bc49e713186..9517048a5776d4668b2bc31a13da69865225f171 100644
GIT binary patch
delta 66
zcmZ3KzBrxBCD<iou`vS!<BN@4TMW58WMkrko#F)?WGA06Ol0()tY!3p(Ri}7u_C`9
W7oR)h59S}t3>?Y=3=)&Qj3WTAH4?S}

delta 65
zcmZ3Sz9^l`CD<iokud`U<Ijy;TMW6}Wn<!lo#F-jWhS36Ol0($tY!3p(P*-?u_B)U
V7q2_x59S}t3>-=V43oW$BLJcw61D&U

diff --git a/tests/data/acpi/x86/q35/DSDT.dimmpxm b/tests/data/acpi/x86/q35/DSDT.dimmpxm
index a2d812e5a23a3ce7739789246b342e703f8c96c0..e817aa6d91c5ee9355787b3d1cc7a126a7620b23 100644
GIT binary patch
delta 65
zcmV-H0KWg>PU21qL{mgmVkZCq0mZQjl_d#A8(d#gLSGP0lc*&?0ZWtVCGY_=liDUB
X4-pCuM*;W)_yYh4BM<->lL;qSucs3o

delta 64
zcmV-G0Kfm@PT@`pL{mgmVJ83p0p+m@l_d#98(d#gLSGO~lc*&?0ZNnUCGY_<liDUB
W4iE|rM*;W)_yYh4A`k$R3MW{ikrN#N

diff --git a/tests/data/acpi/x86/q35/DSDT.ipmibt b/tests/data/acpi/x86/q35/DSDT.ipmibt
index 43ac1bd693d1b3f67d2a9e89ccaf8a56656df22d..e004d4e385bedcae95c7c76f4f7bcbb9f3e8c015 100644
GIT binary patch
delta 66
zcmdnywB3ozCD<jzT#<o+@y13jd3jDpg_!tYr+5L+$wu-HjBcBY<*gYRjVG^HP~;cn
W;&W&G!Tf`nfkRn<L1OYfg$MvoRS_Hj

delta 65
zcmdn)w9SdjCD<jzOp$?s@yA9kd3jC;g_!tYr+5L6$wu-HjINuD<*gYRjV7;GP~;Qf
V;&o^I!Tf`nfkR1vVe);22mnPY5gY&j

diff --git a/tests/data/acpi/x86/q35/DSDT.ipmismbus b/tests/data/acpi/x86/q35/DSDT.ipmismbus
index 1b998820d46e522b3129e42a867ed691c1f83e8f..3cc9625a9b6020fd3008c16f4f8df6bfc609e337 100644
GIT binary patch
delta 65
zcmX@?bi|3vCD<jzMUjDl(Q_l0yga9$LQH(HQ@nuNWFvV8M(@eR@*fzDC#NVV@(XhD
VxikJ?{=v+^p)9~4F?q7W1^_$h5g7mg

delta 64
zcmX@&bl8c@CD<jzS&@N(F>@oAyga9`LQH(HQ@nudWFvV8Mz6`m@*fzDCZ{MU@(FP9
Ux-<S@{=v+^p(MaCd5XdY05P%=82|tP

diff --git a/tests/data/acpi/x86/q35/DSDT.ivrs b/tests/data/acpi/x86/q35/DSDT.ivrs
index 026bfdfebf66c1803f158ac8c115eb5f49b5cb19..50691d93ed45b697290ca32d0f56765fc3a77379 100644
GIT binary patch
delta 65
zcmez4_}7ukCD<k8uL1)Dqw7X4d3jEEnV9%sr+5MX$wu;ljNX%5<UcSPPcBtZ<QL@P
Vb7%a){DYZ+Ls@`9V)7D&2mpja5+?uv

delta 64
zcmezC_{WjUCD<k8j{*Y&W9mjOd3jDZnV9%sr+5Ls$wu;lj9!yl<UcSPO)gbX<P+fH
Ub!Ys+{DYZ+LrH*P@=}Ee0C=_%CjbBd

diff --git a/tests/data/acpi/x86/q35/DSDT.memhp b/tests/data/acpi/x86/q35/DSDT.memhp
index 7346125d23fb3174c0ce678a2cdf2fdc77c4a9fa..0dd16e8455912836401786a89eeaa04b803124f1 100644
GIT binary patch
delta 65
zcmdnxv)hNuCD<jzT8)8$v0@`vo(iX%bWD7(Q@nuR<VF<-M(@doR6Z~oPu{Gm$S=sn
V=g#<p`3Exthq3^J#N<b+5dd(A5{&==

delta 63
zcmV-F0KosdOu9@8L{mgmIwk-B0hqB0ZX^js8(d#gLSGO~lYt~a0ZNm?B=7+;ld~lu
Vlb|I93HSr}0{{pj5CD_oC0J)56LtUq

diff --git a/tests/data/acpi/x86/q35/DSDT.mmio64 b/tests/data/acpi/x86/q35/DSDT.mmio64
index 15a291dbfb62e6ceb0249e02eb25b319744e351f..0f436d68fc5852d4a282e26eb1b729d434c0aad2 100644
GIT binary patch
delta 65
zcmccWb<K;*CD<h-OqGFw(Q+eKg)*nROiX;RQ@nux<Zk6aM(@dYl|L{VPd=xj$S=sn
V=g#<p`3Exthq3^J#N@v!5deW@6Al0X

delta 64
zcmccSb=8Z@CD<h-RF#2&F>)hUg)*m`OiX;RQ@nuR<Zk6aMz6_tl|L{VO+Kfh$S1(X
U>(2Ot`3Exthmrup<bNs=0Ci6j4gdfE

diff --git a/tests/data/acpi/x86/q35/DSDT.multi-bridge b/tests/data/acpi/x86/q35/DSDT.multi-bridge
index 889a9040d950dd08980408d57f1037a5fc20c961..1e3f17690f8719f50adcbc4c9f11a8dc9075cf92 100644
GIT binary patch
delta 96
zcmaEm{xF@(CD<k8p)msk<F1Wd^733QI*c*#!A|i4-J6Z&eFYi4CpQ{=Ff?}d_ci2*
z_waP#alF9F$Ppjv>B7hn9~|Py#m^D%926`l$i?T*_=EWeGXsaR0E5Klg@*P_0A|@4
A-T(jq

delta 76
zcmaEu{ve&pCD<k8fiVLE<E@Qc^735GI*c*#!A|i4U7L;NeFYi4CN~;<;5Tyi_ci2*
g_waP#alF9FIN8Tgg7XLS4`v1qB>{%biwy0V0H1mmZ2$lO

diff --git a/tests/data/acpi/x86/q35/DSDT.noacpihp b/tests/data/acpi/x86/q35/DSDT.noacpihp
index 780616774f97a2d7305faf9e9a9d12afeb0e2fa2..2138ef2cad454ef202bfa2097e1c24a0603eb240 100644
GIT binary patch
delta 66
zcmaFp@W_G7CD<h-Nr8cZv3(;~i7cm!UQB$jQ@nuB=62aUMn><+-{d|p8c%*MugEXR
W#pllWgZT$D1BbEzgT!Pp1#bYROcKoi

delta 65
zcmaFl@X&$FCD<h-QGtPhars8B5?M}Xy_oo5r+5MH&F!*zjEr8BzsY@IG@ATeUXf3L
Vi`Sj;2lEeR1`Z_whRNaz-T;}L63qYr

diff --git a/tests/data/acpi/x86/q35/DSDT.nohpet b/tests/data/acpi/x86/q35/DSDT.nohpet
index 0f862ab2938e0e11aa8335630fad389095b37edd..20468b6b00431fad96dd158744c337821a37a1f9 100644
GIT binary patch
delta 65
zcmccXaL<9uCD<h-PJw}eF>fQ+L^)13>6rLnr+5Ls$xGxM7`-PymHWVGJo%cuBEKLP
VpF86Z<{!)q9LfR=5|ddKA^?p-5?}xT

delta 64
zcmccTaMyv$CD<h-R)K+mv2P>SL^)1Z>6rLnr+5M1$xGxM7`-MxmHWVGH2IpmBA);k
UuRG%p<{!)q97+NVli3s^0D#^SU;qFB

diff --git a/tests/data/acpi/x86/q35/DSDT.numamem b/tests/data/acpi/x86/q35/DSDT.numamem
index df8edc05b69ecd1331973b16e534b44616b50f58..c24caffd8dae778b3f37381834f528737849248d 100644
GIT binary patch
delta 65
zcmez9_{ovWCD<k8lL7++qv1v_Re4S~>6rLnr+5Ls$rkbsjNX$g<v%bQPtH<M<QL@P
Vb7%a){DYZ+Ls@`9V)9Id2mp0N5y=1m

delta 64
zcmez5_|cKeCD<k8qXGj1W8g+ERe4TV>6rLnr+5M1$rkbsj9!x~<v%bQP0mtK<P+fH
Ub!Ys+{DYZ+LrH*P@+^f20BQ>n$p8QV

diff --git a/tests/data/acpi/x86/q35/DSDT.pvpanic-isa b/tests/data/acpi/x86/q35/DSDT.pvpanic-isa
index da3ce12787c28e555b6ba5eacb26275bdd4587f1..9355f161aaf04b2a7af3064502868802d313e679 100644
GIT binary patch
delta 67
zcmccMbkT{+CD<h-P?3RwF>NE4ygaA3VoZFnQ@nulWFvV8CI{)wCGsJRjK-5sDk$;`
Xa`Cw{{$T#W%)p^6z#uXChe8AZU5yc8

delta 66
zcmccUbis+sCD<h-K#_rgv3w(!yga9uVoZFnQ@nuFWFvV8CV#2TCGsJRj7F1BDk$;^
WaPhh`{$T#W%)p@}z%cozLIeO(C=p=*

diff --git a/tests/data/acpi/x86/q35/DSDT.thread-count b/tests/data/acpi/x86/q35/DSDT.thread-count
index 50ca91b065d9a2ba95f97d01856865f0e7c615f6..50d6eac8ba070bf381aacd13ced47115f0897ebe 100644
GIT binary patch
delta 92
zcmdm)x+|5-CD<iomk|R4qwGemw+5VU(lPPDPVoYMlMEdgy(c>welRq4_V+d9i1+Yx
w;c>jc%E%EP>gmGB5g#1l$i>eQ?;I2?D9FX<&iI4*2QveQvH*j`<V2$g0Lv>FF#rGn

delta 72
zcmdm$x-*r_CD<iorx61KqwPknw+5W9(lPPDPVoZ1lMEdgy(T*ve&9E9_V+d9i1+Yx
c;c>jc$~c+FNP_bR^ABbQ4kZDG$w@{L03N6mfdBvi

diff --git a/tests/data/acpi/x86/q35/DSDT.thread-count2 b/tests/data/acpi/x86/q35/DSDT.thread-count2
index f460be2bf74ae512db8f24418b42e8cf2a56202d..69b31da613663a58f9adef8d3981d9ed7c824a28 100644
GIT binary patch
delta 67
zcmdng!L+%9iOVI}CB(Refq^k^BUf4zr<-(4e6UlzfZycGCI?3E$-A09Fd9!@-K@wj
X$i?T*_=EWeGXsaR0E5KjTg?#w%efTu

delta 66
zcmdno!L+G^iOVI}CB&$Ofq}7aBUf4zr>k^Ke6UlzfbZnWCI?2Z$-A09Fd9u>-K@wb
Wz{Ts%_=EWeGXsZ`0K??l%@F{-`xNs4

diff --git a/tests/data/acpi/x86/q35/DSDT.tis.tpm12 b/tests/data/acpi/x86/q35/DSDT.tis.tpm12
index 67ebd7c158759221b801ecb67d8562d92fa219d5..a16d232e61f64876cf0eddd9cf6c1d3a5141ce73 100644
GIT binary patch
delta 78
zcmX@<cFK**CD<jzOPPUz@ySLmZFw#ahnV<ar+5JehspNx_Kd!p>*bx8`Hh|ZeGNI{
iJv?1_951jkPJS;h#^cWTgZT$D1BbEzgT&;IN)Z5K*cF%n

delta 75
zcmX@*cG8W@CD<jzQ<;H*@#{t|ZFw$thnV<ar+5K>`^on5_KZH8>*bx8`Hh_YeGNI{
fJv?1_951jkPM)JA!TE#v2QveQk^sZxPf8I0DiRd}

diff --git a/tests/data/acpi/x86/q35/DSDT.tis.tpm2 b/tests/data/acpi/x86/q35/DSDT.tis.tpm2
index c6b58472157d575e2625557d1346586be06b927c..96e4b7b731c5d3142765979166a4ee8148e98490 100644
GIT binary patch
delta 66
zcmaFt_QZ|LCD<h-MVWztv410%wmhekQ%roYQ@nuJWIK5WM)%G2@-fVe#*^<TDe?<)
W@wqepVE)0(z@aR_ATgO+IRXH6I1w)Z

delta 65
zcmaFj_SlWfCD<h-S($->as5UvZFx>dr<nL)r+5L+$#(J%jBcCj<ztu`jV9kwQsfih
V;&o^I!Tf`nfkR1vVKR?$1ORF(5ibA$

diff --git a/tests/data/acpi/x86/q35/DSDT.type4-count b/tests/data/acpi/x86/q35/DSDT.type4-count
index 17a64adb2055ad3168754ca121bf29851d2ee496..dd0a3a7581a0d2f532c3bd4145f16a4d782ef2d6 100644
GIT binary patch
delta 67
zcmaDlk@49?MlP3Nmyl;33=E7`8@VLiIo+gV;)9*y1^g!KxH~X<PtJA!z-T-<&O?!3
Xkc-cq@dxt{W(E#r0S1Z5y&e$&v6~YF

delta 66
zcmaDhk@4w7MlP3Nmyo9(3=E7>8@VLiIbEe=;)9*y1$-y#xH~X<P0n@yz-Tl%&O?z;
WfQ#3i@dxt{W(E!=0fxza9uWYgL=yx6

diff --git a/tests/data/acpi/x86/q35/DSDT.viot b/tests/data/acpi/x86/q35/DSDT.viot
index 6eb30e8f4b2c54e4789c649475adff356c8c58a4..e00340c95587db1ed1a17b42ad4036f5fc51d06e 100644
GIT binary patch
delta 65
zcmcapbhn7hCD<h-){=pNv3w(!k2$B8d`x_>Q@nuF<aqNIM(@c_%s((1PrhoQ$S=sn
V=g#<p`3Exthq3^J#AFuB2mq@i6B7Uc

delta 64
zcmcaxbf<{RCD<h-#*%@7ar#CsA9GGm`Iz`%r+5L!$?@hbj9!zUn15h2ntatlkxzh&
U*PZbP^ABbQ4kZDG$*h(U0G=ch6951J

diff --git a/tests/data/acpi/x86/q35/DSDT.xapic b/tests/data/acpi/x86/q35/DSDT.xapic
index 111bb041dc0d114351add07c040dde61643d157a..50780e37eecd2f8bc328c3290b4cd0ce3427d8a7 100644
GIT binary patch
delta 67
zcmX>%o$35^CN7s?myq+_3=E7}8@ZUeINhXU;)9*y1^gz9b~!M5PY&z)z-T<#y<3rA
Xkc-cq@dxt{W(E#r0S1Z5W!(_~(y<gA

delta 66
zcmX><o$1_kCN7s?mymPa3=E828@ZUeI9;V<;)9*y1$-xqb~!M5O%Ch&z-Tnty<3q_
WfQ#3i@dxt{W(E!=0fx!t-4OuAZWJ5<

diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
index cef44135bc..dfb8523c8b 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1,48 +1 @@
 /* List of comma-separated changed AML files to ignore */
-"tests/data/acpi/x86/pc/DSDT",
-"tests/data/acpi/x86/pc/DSDT.bridge",
-"tests/data/acpi/x86/pc/DSDT.ipmikcs",
-"tests/data/acpi/x86/pc/DSDT.cphp",
-"tests/data/acpi/x86/pc/DSDT.numamem",
-"tests/data/acpi/x86/pc/DSDT.nohpet",
-"tests/data/acpi/x86/pc/DSDT.memhp",
-"tests/data/acpi/x86/pc/DSDT.dimmpxm",
-"tests/data/acpi/x86/pc/DSDT.acpihmat",
-"tests/data/acpi/x86/pc/DSDT.acpierst",
-"tests/data/acpi/x86/pc/DSDT.roothp",
-"tests/data/acpi/x86/pc/DSDT.hpbridge",
-"tests/data/acpi/x86/pc/DSDT.hpbrroot",
-"tests/data/acpi/x86/q35/DSDT",
-"tests/data/acpi/x86/q35/DSDT.tis.tpm2",
-"tests/data/acpi/x86/q35/DSDT.tis.tpm12",
-"tests/data/acpi/x86/q35/DSDT.bridge",
-"tests/data/acpi/x86/q35/DSDT.noacpihp",
-"tests/data/acpi/x86/q35/DSDT.multi-bridge",
-"tests/data/acpi/x86/q35/DSDT.ipmibt",
-"tests/data/acpi/x86/q35/DSDT.cphp",
-"tests/data/acpi/x86/q35/DSDT.numamem",
-"tests/data/acpi/x86/q35/DSDT.nohpet",
-"tests/data/acpi/x86/q35/DSDT.acpihmat-noinitiator",
-"tests/data/acpi/x86/q35/DSDT.acpihmat-generic-x",
-"tests/data/acpi/x86/q35/DSDT.memhp",
-"tests/data/acpi/x86/q35/DSDT.dimmpxm",
-"tests/data/acpi/x86/q35/DSDT.acpihmat",
-"tests/data/acpi/x86/q35/DSDT.mmio64",
-"tests/data/acpi/x86/q35/DSDT.acpierst",
-"tests/data/acpi/x86/q35/DSDT.applesmc",
-"tests/data/acpi/x86/q35/DSDT.pvpanic-isa",
-"tests/data/acpi/x86/q35/DSDT.ivrs",
-"tests/data/acpi/x86/q35/DSDT.type4-count",
-"tests/data/acpi/x86/q35/DSDT.core-count",
-"tests/data/acpi/x86/q35/DSDT.core-count2",
-"tests/data/acpi/x86/q35/DSDT.thread-count",
-"tests/data/acpi/x86/q35/DSDT.thread-count2",
-"tests/data/acpi/x86/q35/DSDT.viot",
-"tests/data/acpi/x86/q35/DSDT.cxl",
-"tests/data/acpi/x86/q35/DSDT.ipmismbus",
-"tests/data/acpi/x86/q35/DSDT.xapic",
-"tests/data/acpi/x86/microvm/DSDT",
-"tests/data/acpi/x86/microvm/DSDT.usb",
-"tests/data/acpi/x86/microvm/DSDT.rtc",
-"tests/data/acpi/x86/microvm/DSDT.ioapic2",
-"tests/data/acpi/x86/microvm/DSDT.pcie",
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 027/106] vhost-user: rework enabling vrings
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (25 preceding siblings ...)
  2026-06-14 19:06 ` [PULL 026/106] tests: data: update x86 ACPI tables Michael S. Tsirkin
@ 2026-06-14 19:06 ` Michael S. Tsirkin
  2026-06-14 19:06 ` [PULL 028/106] vhost: drop backend_features field Michael S. Tsirkin
                   ` (79 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Daniil Tatianin,
	Raphael Norwitz, Lei Yang, Stefano Garzarella, Gonglei (Arei),
	zhenwei pi, Jason Wang

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

We call the handler almost the same way in three places:

 - cryptodev-vhost.c
 - vhost_net.c
 - vhost.c

The only difference, is that in vhost.c we don't try to call the handler
for old vhost-user (when VHOST_USER_F_PROTOCOL_FEATURES is not supported).

cryptodev-vhost and vhost_net code will just fail in this case. Probably
they were developed only for newer vhost-user. Anyway, it doesn't seem
correct to rely on this error path, if these devices want to check,
that they don't communicate to old vhost-user protocol, they should
do that earlier.

Let's create the common helper, to call .vhost_set_vring_enable and
use in all three places. For vhost-user let's just always skip
enable/disable if it's unsupported.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Daniil Tatianin <d-tatianin@yandex-team.ru>
Reviewed-by: Raphael Norwitz <raphael.s.norwitz@gmail.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Tested-by: Lei Yang <leiyang@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420200339.708640-2-vsementsov@yandex-team.ru>
---
 backends/cryptodev-vhost.c |  8 +-------
 hw/net/vhost_net.c         |  7 +------
 hw/virtio/vhost-user.c     |  7 ++++++-
 hw/virtio/vhost.c          | 21 ---------------------
 include/hw/virtio/vhost.h  |  9 +++++++++
 5 files changed, 17 insertions(+), 35 deletions(-)

diff --git a/backends/cryptodev-vhost.c b/backends/cryptodev-vhost.c
index 943680a23a..abdfce33af 100644
--- a/backends/cryptodev-vhost.c
+++ b/backends/cryptodev-vhost.c
@@ -152,7 +152,6 @@ vhost_set_vring_enable(CryptoDevBackendClient *cc,
 {
     CryptoDevBackendVhost *crypto =
                        cryptodev_get_vhost(cc, b, queue);
-    const VhostOps *vhost_ops;
 
     cc->vring_enable = enable;
 
@@ -160,12 +159,7 @@ vhost_set_vring_enable(CryptoDevBackendClient *cc,
         return 0;
     }
 
-    vhost_ops = crypto->dev.vhost_ops;
-    if (vhost_ops->vhost_set_vring_enable) {
-        return vhost_ops->vhost_set_vring_enable(&crypto->dev, enable);
-    }
-
-    return 0;
+    return vhost_dev_set_vring_enable(&crypto->dev, enable);
 }
 
 int cryptodev_vhost_start(VirtIODevice *dev, int total_queues)
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index a8ee18a912..25e9f1fd24 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -587,7 +587,6 @@ VHostNetState *get_vhost_net(NetClientState *nc)
 int vhost_net_set_vring_enable(NetClientState *nc, int enable)
 {
     VHostNetState *net = get_vhost_net(nc);
-    const VhostOps *vhost_ops = net->dev.vhost_ops;
 
     /*
      * vhost-vdpa network devices need to enable dataplane virtqueues after
@@ -601,11 +600,7 @@ int vhost_net_set_vring_enable(NetClientState *nc, int enable)
 
     nc->vring_enable = enable;
 
-    if (vhost_ops && vhost_ops->vhost_set_vring_enable) {
-        return vhost_ops->vhost_set_vring_enable(&net->dev, enable);
-    }
-
-    return 0;
+    return vhost_dev_set_vring_enable(&net->dev, enable);
 }
 
 int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu)
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index a8907cca74..13c73e7b17 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -1230,7 +1230,12 @@ static int vhost_user_set_vring_enable(struct vhost_dev *dev, int enable)
     int i;
 
     if (!virtio_has_feature(dev->features, VHOST_USER_F_PROTOCOL_FEATURES)) {
-        return -EINVAL;
+        /*
+         * For vhost-user devices, if VHOST_USER_F_PROTOCOL_FEATURES has not
+         * been negotiated, the rings start directly in the enabled state,
+         * and can't be disabled.
+         */
+        return 0;
     }
 
     for (i = 0; i < dev->nvqs; ++i) {
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index b9dc4ed13b..b89797df95 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -2078,27 +2078,6 @@ int vhost_dev_get_inflight(struct vhost_dev *dev, uint16_t queue_size,
     return 0;
 }
 
-static int vhost_dev_set_vring_enable(struct vhost_dev *hdev, int enable)
-{
-    if (!hdev->vhost_ops->vhost_set_vring_enable) {
-        return 0;
-    }
-
-    /*
-     * For vhost-user devices, if VHOST_USER_F_PROTOCOL_FEATURES has not
-     * been negotiated, the rings start directly in the enabled state, and
-     * .vhost_set_vring_enable callback will fail since
-     * VHOST_USER_SET_VRING_ENABLE is not supported.
-     */
-    if (hdev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER &&
-        !virtio_has_feature(hdev->backend_features,
-                            VHOST_USER_F_PROTOCOL_FEATURES)) {
-        return 0;
-    }
-
-    return hdev->vhost_ops->vhost_set_vring_enable(hdev, enable);
-}
-
 /*
  * Host notifiers must be enabled at this point.
  *
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index 89817bd848..3dfec5e15c 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -215,6 +215,15 @@ static inline bool vhost_dev_is_started(struct vhost_dev *hdev)
     return hdev->started;
 }
 
+static inline int vhost_dev_set_vring_enable(struct vhost_dev *hdev, int enable)
+{
+    if (!hdev->vhost_ops->vhost_set_vring_enable) {
+        return 0;
+    }
+
+    return hdev->vhost_ops->vhost_set_vring_enable(hdev, enable);
+}
+
 /**
  * vhost_dev_start() - start the vhost device
  * @hdev: common vhost_dev structure
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 028/106] vhost: drop backend_features field
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (26 preceding siblings ...)
  2026-06-14 19:06 ` [PULL 027/106] vhost-user: rework enabling vrings Michael S. Tsirkin
@ 2026-06-14 19:06 ` Michael S. Tsirkin
  2026-06-14 19:06 ` [PULL 029/106] vhost-user: introduce vhost_user_has_protocol_feature() helper Michael S. Tsirkin
                   ` (78 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, devel,
	Markus Armbruster, Daniil Tatianin, Raphael Norwitz, Lei Yang,
	Raphael Norwitz, Stefano Garzarella, Kevin Wolf, Hanna Reitz,
	Jason Wang, Paolo Bonzini, Fam Zheng, Eric Blake, qemu-block

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

This field is mostly unused and sometimes confusing. We even have
a TODO-like comment to drop it, the comment is removed in this commit.

The field is used to held VHOST_USER_F_PROTOCOL_FEATURES for vhost-user
and/or VHOST_NET_F_VIRTIO_NET_HDR for vhost-net (which may be
vhost-user-net). But we can simply recalculate these two flags in place
from hdev->features, and from net-client for VHOST_NET_F_VIRTIO_NET_HDR.

Note: removing field from x-query-virtio-status result is incompatible
change. We can do it because the command is unstable.

Cc: devel@lists.libvirt.org
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Acked-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Daniil Tatianin <d-tatianin@yandex-team.ru>
Acked-by: Raphael Norwitz <raphael.s.norwitz@gmail.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Tested-by: Lei Yang <leiyang@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420200339.708640-3-vsementsov@yandex-team.ru>
---
 hw/block/vhost-user-blk.c   |  1 -
 hw/net/vhost_net.c          | 26 ++++++++++++++------------
 hw/scsi/vhost-scsi.c        |  1 -
 hw/scsi/vhost-user-scsi.c   |  1 -
 hw/virtio/vdpa-dev.c        |  1 -
 hw/virtio/vhost-user.c      | 17 ++++++++---------
 hw/virtio/virtio-hmp-cmds.c |  2 --
 hw/virtio/virtio-qmp.c      |  4 ----
 include/hw/virtio/vhost.h   |  7 -------
 qapi/virtio.json            |  3 ---
 10 files changed, 22 insertions(+), 41 deletions(-)

diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index c151e83677..dc99de0263 100644
--- a/hw/block/vhost-user-blk.c
+++ b/hw/block/vhost-user-blk.c
@@ -348,7 +348,6 @@ static int vhost_user_blk_connect(DeviceState *dev, Error **errp)
     s->dev.nvqs = s->num_queues;
     s->dev.vqs = s->vhost_vqs;
     s->dev.vq_index = 0;
-    s->dev.backend_features = 0;
 
     vhost_dev_set_config_notifier(&s->dev, &blk_ops);
 
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 25e9f1fd24..fda90e231e 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -52,8 +52,14 @@ int vhost_net_set_config(struct vhost_net *net, const uint8_t *data,
 
 void vhost_net_ack_features_ex(struct vhost_net *net, const uint64_t *features)
 {
-    virtio_features_copy(net->dev.acked_features_ex,
-                         net->dev.backend_features_ex);
+    virtio_features_clear(net->dev.acked_features_ex);
+    if (net->backend == -1) {
+        net->dev.acked_features =
+           net->dev.features & (1ULL << VHOST_USER_F_PROTOCOL_FEATURES);
+    } else if (!qemu_has_vnet_hdr(net->nc)) {
+        net->dev.acked_features = 1ULL << VHOST_NET_F_VIRTIO_NET_HDR;
+    }
+
     vhost_ack_features_ex(&net->dev, net->feature_bits, features);
 }
 
@@ -258,12 +264,9 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
         if (r < 0) {
             goto fail;
         }
-        net->dev.backend_features = qemu_has_vnet_hdr(options->net_backend)
-            ? 0 : (1ULL << VHOST_NET_F_VIRTIO_NET_HDR);
         net->backend = r;
         net->dev.protocol_features = 0;
     } else {
-        virtio_features_clear(net->dev.backend_features_ex);
         net->dev.protocol_features = 0;
         net->backend = -1;
 
@@ -284,13 +287,12 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
             net->dev.features &= ~(1ULL << VIRTIO_NET_F_MRG_RXBUF);
         }
 
-        if (virtio_features_andnot(missing_features,
-                                   net->dev.backend_features_ex,
-                                   net->dev.features_ex)) {
-            fprintf(stderr, "vhost lacks feature mask 0x" VIRTIO_FEATURES_FMT
-                   " for backend\n", VIRTIO_FEATURES_PR(missing_features));
-            goto fail;
-        }
+        if (!qemu_has_vnet_hdr(options->net_backend) &&
+            (~net->dev.features & (1ULL << VHOST_NET_F_VIRTIO_NET_HDR))) {
+            fprintf(stderr, "vhost lacks feature mask 0x%llx for backend\n",
+                    ~net->dev.features & (1ULL << VHOST_NET_F_VIRTIO_NET_HDR));
+             goto fail;
+         }
     }
 
     /* Set sane init value. Override when guest acks. */
diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index 699863cc10..859888fdba 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -275,7 +275,6 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp)
     vqs = g_new0(struct vhost_virtqueue, vsc->dev.nvqs);
     vsc->dev.vqs = vqs;
     vsc->dev.vq_index = 0;
-    vsc->dev.backend_features = 0;
 
     ret = vhost_dev_init(&vsc->dev, (void *)(uintptr_t)vhostfd,
                          VHOST_BACKEND_TYPE_KERNEL, 0, errp);
diff --git a/hw/scsi/vhost-user-scsi.c b/hw/scsi/vhost-user-scsi.c
index 3612897d4b..5070178dc2 100644
--- a/hw/scsi/vhost-user-scsi.c
+++ b/hw/scsi/vhost-user-scsi.c
@@ -159,7 +159,6 @@ static int vhost_user_scsi_connect(DeviceState *dev, Error **errp)
     vsc->dev.nvqs = VIRTIO_SCSI_VQ_NUM_FIXED + vs->conf.num_queues;
     vsc->dev.vqs = s->vhost_vqs;
     vsc->dev.vq_index = 0;
-    vsc->dev.backend_features = 0;
 
     ret = vhost_dev_init(&vsc->dev, &s->vhost_user, VHOST_BACKEND_TYPE_USER, 0,
                          errp);
diff --git a/hw/virtio/vdpa-dev.c b/hw/virtio/vdpa-dev.c
index 4532d63653..06179e402e 100644
--- a/hw/virtio/vdpa-dev.c
+++ b/hw/virtio/vdpa-dev.c
@@ -104,7 +104,6 @@ static void vhost_vdpa_device_realize(DeviceState *dev, Error **errp)
     v->dev.vqs = vqs;
     v->dev.vq_index = 0;
     v->dev.vq_index_end = v->dev.nvqs;
-    v->dev.backend_features = 0;
     v->started = false;
 
     ret = vhost_vdpa_get_iova_range(v->vhostfd, &iova_range);
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 13c73e7b17..7ce17c5b2d 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -1465,14 +1465,15 @@ static int vhost_user_set_features(struct vhost_dev *dev,
     int ret;
 
     /*
-     * We need to include any extra backend only feature bits that
-     * might be needed by our device. Currently this includes the
-     * VHOST_USER_F_PROTOCOL_FEATURES bit for enabling protocol
-     * features.
+     * Don't lose VHOST_USER_F_PROTOCOL_FEATURES, which is vhost-user
+     * specific.
      */
-    ret = vhost_user_set_u64(dev, VHOST_USER_SET_FEATURES,
-                              features | dev->backend_features,
-                              log_enabled);
+    if (virtio_has_feature(dev->features, VHOST_USER_F_PROTOCOL_FEATURES)) {
+        features |= 1ULL << VHOST_USER_F_PROTOCOL_FEATURES;
+    }
+
+    ret = vhost_user_set_u64(dev, VHOST_USER_SET_FEATURES, features,
+                             log_enabled);
 
     if (virtio_has_feature(dev->protocol_features,
                            VHOST_USER_PROTOCOL_F_STATUS)) {
@@ -2192,8 +2193,6 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque,
             (dev->config_ops && dev->config_ops->vhost_dev_config_notifier);
         uint64_t protocol_features;
 
-        dev->backend_features |= 1ULL << VHOST_USER_F_PROTOCOL_FEATURES;
-
         err = vhost_user_get_u64(dev, VHOST_USER_GET_PROTOCOL_FEATURES,
                                  &protocol_features);
         if (err < 0) {
diff --git a/hw/virtio/virtio-hmp-cmds.c b/hw/virtio/virtio-hmp-cmds.c
index 1daae482d3..4bf9a3109d 100644
--- a/hw/virtio/virtio-hmp-cmds.c
+++ b/hw/virtio/virtio-hmp-cmds.c
@@ -176,8 +176,6 @@ void hmp_virtio_status(Monitor *mon, const QDict *qdict)
         hmp_virtio_dump_features(mon, s->vhost_dev->features);
         monitor_printf(mon, "    Acked features:\n");
         hmp_virtio_dump_features(mon, s->vhost_dev->acked_features);
-        monitor_printf(mon, "    Backend features:\n");
-        hmp_virtio_dump_features(mon, s->vhost_dev->backend_features);
         monitor_printf(mon, "    Protocol features:\n");
         hmp_virtio_dump_protocols(mon, s->vhost_dev->protocol_features);
     }
diff --git a/hw/virtio/virtio-qmp.c b/hw/virtio/virtio-qmp.c
index f9cdca50d9..71717c56a4 100644
--- a/hw/virtio/virtio-qmp.c
+++ b/hw/virtio/virtio-qmp.c
@@ -710,8 +710,6 @@ VirtioStatus *qmp_x_query_virtio_status(const char *path, Error **errp)
                                                  vdev->guest_features_ex);
     status->host_features = qmp_decode_features(vdev->device_id,
                                                 vdev->host_features_ex);
-    status->backend_features = qmp_decode_features(vdev->device_id,
-                                                 vdev->backend_features_ex);
 
     switch (vdev->device_endian) {
     case VIRTIO_DEVICE_ENDIAN_LITTLE:
@@ -752,8 +750,6 @@ VirtioStatus *qmp_x_query_virtio_status(const char *path, Error **errp)
             qmp_decode_features(vdev->device_id, hdev->features_ex);
         status->vhost_dev->acked_features =
             qmp_decode_features(vdev->device_id, hdev->acked_features_ex);
-        status->vhost_dev->backend_features =
-            qmp_decode_features(vdev->device_id, hdev->backend_features_ex);
 
         status->vhost_dev->protocol_features =
             qmp_decode_protocols(hdev->protocol_features);
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index 3dfec5e15c..e139e05985 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -100,16 +100,9 @@ struct vhost_dev {
      *
      * @features: available features provided by the backend
      * @acked_features: final negotiated features with front-end driver
-     *
-     * @backend_features: this is used in a couple of places to either
-     * store VHOST_USER_F_PROTOCOL_FEATURES to apply to
-     * VHOST_USER_SET_FEATURES or VHOST_NET_F_VIRTIO_NET_HDR. Its
-     * future use should be discouraged and the variable retired as
-     * its easy to confuse with the VirtIO backend_features.
      */
     VIRTIO_DECLARE_FEATURES(features);
     VIRTIO_DECLARE_FEATURES(acked_features);
-    VIRTIO_DECLARE_FEATURES(backend_features);
 
     /**
      * @protocol_features: is the vhost-user only feature set by
diff --git a/qapi/virtio.json b/qapi/virtio.json
index 09dd0e6d05..671f1ad793 100644
--- a/qapi/virtio.json
+++ b/qapi/virtio.json
@@ -85,8 +85,6 @@
 #
 # @acked-features: vhost_dev acked_features
 #
-# @backend-features: vhost_dev backend_features
-#
 # @protocol-features: vhost_dev protocol_features
 #
 # @max-queues: vhost_dev max_queues
@@ -106,7 +104,6 @@
             'vq-index': 'int',
             'features': 'VirtioDeviceFeatures',
             'acked-features': 'VirtioDeviceFeatures',
-            'backend-features': 'VirtioDeviceFeatures',
             'protocol-features': 'VhostDeviceProtocols',
             'max-queues': 'uint64',
             'backend-cap': 'uint64',
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 029/106] vhost-user: introduce vhost_user_has_protocol_feature() helper
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (27 preceding siblings ...)
  2026-06-14 19:06 ` [PULL 028/106] vhost: drop backend_features field Michael S. Tsirkin
@ 2026-06-14 19:06 ` Michael S. Tsirkin
  2026-06-14 19:07 ` [PULL 030/106] vhost: move protocol_features to vhost_user Michael S. Tsirkin
                   ` (77 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:06 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Daniil Tatianin,
	Raphael Norwitz, Lei Yang, Stefano Garzarella

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

Make all protocol feature checks in the same way.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Daniil Tatianin <d-tatianin@yandex-team.ru>
Reviewed-by: Raphael Norwitz <raphael.s.norwitz@gmail.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Tested-by: Lei Yang <leiyang@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420200339.708640-4-vsementsov@yandex-team.ru>
---
 hw/virtio/vhost-user.c | 120 +++++++++++++++++++++--------------------
 1 file changed, 62 insertions(+), 58 deletions(-)

diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 7ce17c5b2d..72aeed26ca 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -267,6 +267,12 @@ struct scrub_regions {
     int fd_idx;
 };
 
+static bool vhost_user_has_protocol_feature(struct vhost_dev *dev,
+                                            uint64_t feature)
+{
+    return virtio_has_feature(dev->protocol_features, feature);
+}
+
 static int vhost_user_read_header(struct vhost_dev *dev, VhostUserMsg *msg)
 {
     struct vhost_user *u = dev->opaque;
@@ -430,8 +436,8 @@ static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base,
 {
     int fds[VHOST_USER_MAX_RAM_SLOTS];
     size_t fd_num = 0;
-    bool shmfd = virtio_has_feature(dev->protocol_features,
-                                    VHOST_USER_PROTOCOL_F_LOG_SHMFD);
+    bool shmfd =
+        vhost_user_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_LOG_SHMFD);
     int ret;
     VhostUserMsg msg = {
         .hdr.request = VHOST_USER_SET_LOG_BASE,
@@ -1001,11 +1007,11 @@ static int vhost_user_set_mem_table(struct vhost_dev *dev,
     int fds[VHOST_MEMORY_BASELINE_NREGIONS];
     size_t fd_num = 0;
     bool do_postcopy = u->postcopy_listen && u->postcopy_fd.handler;
-    bool reply_supported = virtio_has_feature(dev->protocol_features,
-                                              VHOST_USER_PROTOCOL_F_REPLY_ACK);
+    bool reply_supported =
+        vhost_user_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_REPLY_ACK);
     bool config_mem_slots =
-        virtio_has_feature(dev->protocol_features,
-                           VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS);
+        vhost_user_has_protocol_feature(
+            dev, VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS);
     int ret;
 
     if (do_postcopy) {
@@ -1053,8 +1059,9 @@ static int vhost_user_set_mem_table(struct vhost_dev *dev,
 static int vhost_user_set_vring_endian(struct vhost_dev *dev,
                                        struct vhost_vring_state *ring)
 {
-    bool cross_endian = virtio_has_feature(dev->protocol_features,
-                                           VHOST_USER_PROTOCOL_F_CROSS_ENDIAN);
+    bool cross_endian =
+        vhost_user_has_protocol_feature(
+            dev, VHOST_USER_PROTOCOL_F_CROSS_ENDIAN);
     VhostUserMsg msg = {
         .hdr.request = VHOST_USER_SET_VRING_ENDIAN,
         .hdr.flags = VHOST_USER_VERSION,
@@ -1124,8 +1131,9 @@ static int vhost_user_write_sync(struct vhost_dev *dev, VhostUserMsg *msg,
     int ret;
 
     if (wait_for_reply) {
-        bool reply_supported = virtio_has_feature(dev->protocol_features,
-                                          VHOST_USER_PROTOCOL_F_REPLY_ACK);
+        bool reply_supported =
+            vhost_user_has_protocol_feature(
+                dev, VHOST_USER_PROTOCOL_F_REPLY_ACK);
         if (reply_supported) {
             msg->hdr.flags |= VHOST_USER_NEED_REPLY_MASK;
         }
@@ -1475,8 +1483,7 @@ static int vhost_user_set_features(struct vhost_dev *dev,
     ret = vhost_user_set_u64(dev, VHOST_USER_SET_FEATURES, features,
                              log_enabled);
 
-    if (virtio_has_feature(dev->protocol_features,
-                           VHOST_USER_PROTOCOL_F_STATUS)) {
+    if (vhost_user_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_STATUS)) {
         if (!ret) {
             return vhost_user_add_status(dev, VIRTIO_CONFIG_S_FEATURES_OK);
         }
@@ -1530,8 +1537,8 @@ static int vhost_user_reset_device(struct vhost_dev *dev)
      * Historically, reset was not implemented so only reset devices
      * that are expecting it.
      */
-    if (!virtio_has_feature(dev->protocol_features,
-                            VHOST_USER_PROTOCOL_F_RESET_DEVICE)) {
+    if (!vhost_user_has_protocol_feature(
+            dev, VHOST_USER_PROTOCOL_F_RESET_DEVICE)) {
         return -ENOSYS;
     }
 
@@ -1588,8 +1595,8 @@ static int vhost_user_backend_handle_vring_host_notifier(struct vhost_dev *dev,
     void *addr;
     char *name;
 
-    if (!virtio_has_feature(dev->protocol_features,
-                            VHOST_USER_PROTOCOL_F_HOST_NOTIFIER) ||
+    if (!vhost_user_has_protocol_feature(
+            dev, VHOST_USER_PROTOCOL_F_HOST_NOTIFIER) ||
         vdev == NULL || queue_idx >= virtio_get_num_queues(vdev)) {
         return -EINVAL;
     }
@@ -1887,13 +1894,13 @@ static int vhost_setup_backend_channel(struct vhost_dev *dev)
     };
     struct vhost_user *u = dev->opaque;
     int sv[2], ret = 0;
-    bool reply_supported = virtio_has_feature(dev->protocol_features,
-                                              VHOST_USER_PROTOCOL_F_REPLY_ACK);
+    bool reply_supported =
+        vhost_user_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_REPLY_ACK);
     Error *local_err = NULL;
     QIOChannel *ioc;
 
-    if (!virtio_has_feature(dev->protocol_features,
-                            VHOST_USER_PROTOCOL_F_BACKEND_REQ)) {
+    if (!vhost_user_has_protocol_feature(
+            dev, VHOST_USER_PROTOCOL_F_BACKEND_REQ)) {
         return 0;
     }
 
@@ -2141,8 +2148,8 @@ static int vhost_user_postcopy_notifier(NotifierWithReturn *notifier,
 
     switch (pnd->reason) {
     case POSTCOPY_NOTIFY_PROBE:
-        if (!virtio_has_feature(dev->protocol_features,
-                                VHOST_USER_PROTOCOL_F_PAGEFAULT)) {
+        if (!vhost_user_has_protocol_feature(
+                dev, VHOST_USER_PROTOCOL_F_PAGEFAULT)) {
             /* TODO: Get the device name into this error somehow */
             error_setg(errp,
                        "vhost-user backend not capable of postcopy");
@@ -2240,7 +2247,7 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque,
         }
 
         /* query the max queues we support if backend supports Multiple Queue */
-        if (dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_MQ)) {
+        if (vhost_user_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_MQ)) {
             err = vhost_user_get_u64(dev, VHOST_USER_GET_QUEUE_NUM,
                                      &dev->max_queues);
             if (err < 0) {
@@ -2258,18 +2265,18 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque,
         }
 
         if (virtio_has_feature(features, VIRTIO_F_IOMMU_PLATFORM) &&
-                !(virtio_has_feature(dev->protocol_features,
-                    VHOST_USER_PROTOCOL_F_BACKEND_REQ) &&
-                 virtio_has_feature(dev->protocol_features,
-                    VHOST_USER_PROTOCOL_F_REPLY_ACK))) {
+            !(vhost_user_has_protocol_feature(
+                dev, VHOST_USER_PROTOCOL_F_BACKEND_REQ) &&
+            vhost_user_has_protocol_feature(
+                dev, VHOST_USER_PROTOCOL_F_REPLY_ACK))) {
             error_setg(errp, "IOMMU support requires reply-ack and "
                        "backend-req protocol features.");
             return -EINVAL;
         }
 
         /* get max memory regions if backend supports configurable RAM slots */
-        if (!virtio_has_feature(dev->protocol_features,
-                                VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS)) {
+        if (!vhost_user_has_protocol_feature(
+                dev, VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS)) {
             u->user->memory_slots = VHOST_MEMORY_BASELINE_NREGIONS;
         } else {
             err = vhost_user_get_max_memslots(dev, &ram_slots);
@@ -2293,8 +2300,8 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque,
     }
 
     if (dev->migration_blocker == NULL &&
-        !virtio_has_feature(dev->protocol_features,
-                            VHOST_USER_PROTOCOL_F_LOG_SHMFD)) {
+        !vhost_user_has_protocol_feature(
+            dev, VHOST_USER_PROTOCOL_F_LOG_SHMFD)) {
         error_setg(&dev->migration_blocker,
                    "Migration disabled: vhost-user backend lacks "
                    "VHOST_USER_PROTOCOL_F_LOG_SHMFD feature.");
@@ -2363,8 +2370,8 @@ static bool vhost_user_requires_shm_log(struct vhost_dev *dev)
 {
     assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
 
-    return virtio_has_feature(dev->protocol_features,
-                              VHOST_USER_PROTOCOL_F_LOG_SHMFD);
+    return vhost_user_has_protocol_feature(
+        dev, VHOST_USER_PROTOCOL_F_LOG_SHMFD);
 }
 
 static int vhost_user_migration_done(struct vhost_dev *dev, char* mac_addr)
@@ -2379,8 +2386,7 @@ static int vhost_user_migration_done(struct vhost_dev *dev, char* mac_addr)
     }
 
     /* if backend supports VHOST_USER_PROTOCOL_F_RARP ask it to send the RARP */
-    if (virtio_has_feature(dev->protocol_features,
-                           VHOST_USER_PROTOCOL_F_RARP)) {
+    if (vhost_user_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_RARP)) {
         msg.hdr.request = VHOST_USER_SEND_RARP;
         msg.hdr.flags = VHOST_USER_VERSION;
         memcpy((char *)&msg.payload.u64, mac_addr, 6);
@@ -2394,11 +2400,11 @@ static int vhost_user_migration_done(struct vhost_dev *dev, char* mac_addr)
 static int vhost_user_net_set_mtu(struct vhost_dev *dev, uint16_t mtu)
 {
     VhostUserMsg msg;
-    bool reply_supported = virtio_has_feature(dev->protocol_features,
-                                              VHOST_USER_PROTOCOL_F_REPLY_ACK);
+    bool reply_supported =
+        vhost_user_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_REPLY_ACK);
     int ret;
 
-    if (!(dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_NET_MTU))) {
+    if (!vhost_user_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_NET_MTU)) {
         return 0;
     }
 
@@ -2458,8 +2464,7 @@ static int vhost_user_get_config(struct vhost_dev *dev, uint8_t *config,
         .hdr.size = VHOST_USER_CONFIG_HDR_SIZE + config_len,
     };
 
-    if (!virtio_has_feature(dev->protocol_features,
-                VHOST_USER_PROTOCOL_F_CONFIG)) {
+    if (!vhost_user_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_CONFIG)) {
         error_setg(errp, "VHOST_USER_PROTOCOL_F_CONFIG not supported");
         return -EINVAL;
     }
@@ -2502,8 +2507,8 @@ static int vhost_user_set_config(struct vhost_dev *dev, const uint8_t *data,
 {
     int ret;
     uint8_t *p;
-    bool reply_supported = virtio_has_feature(dev->protocol_features,
-                                              VHOST_USER_PROTOCOL_F_REPLY_ACK);
+    bool reply_supported =
+        vhost_user_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_REPLY_ACK);
 
     VhostUserMsg msg = {
         .hdr.request = VHOST_USER_SET_CONFIG,
@@ -2511,8 +2516,7 @@ static int vhost_user_set_config(struct vhost_dev *dev, const uint8_t *data,
         .hdr.size = VHOST_USER_CONFIG_HDR_SIZE + size,
     };
 
-    if (!virtio_has_feature(dev->protocol_features,
-                VHOST_USER_PROTOCOL_F_CONFIG)) {
+    if (!vhost_user_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_CONFIG)) {
         return -ENOTSUP;
     }
 
@@ -2547,8 +2551,9 @@ static int vhost_user_crypto_create_session(struct vhost_dev *dev,
                                             uint64_t *session_id)
 {
     int ret;
-    bool crypto_session = virtio_has_feature(dev->protocol_features,
-                                       VHOST_USER_PROTOCOL_F_CRYPTO_SESSION);
+    bool crypto_session =
+        vhost_user_has_protocol_feature(
+            dev, VHOST_USER_PROTOCOL_F_CRYPTO_SESSION);
     CryptoDevBackendSessionInfo *backend_info = session_info;
     VhostUserMsg msg = {
         .hdr.request = VHOST_USER_CREATE_CRYPTO_SESSION,
@@ -2649,8 +2654,9 @@ static int
 vhost_user_crypto_close_session(struct vhost_dev *dev, uint64_t session_id)
 {
     int ret;
-    bool crypto_session = virtio_has_feature(dev->protocol_features,
-                                       VHOST_USER_PROTOCOL_F_CRYPTO_SESSION);
+    bool crypto_session =
+        vhost_user_has_protocol_feature(
+            dev, VHOST_USER_PROTOCOL_F_CRYPTO_SESSION);
     VhostUserMsg msg = {
         .hdr.request = VHOST_USER_CLOSE_CRYPTO_SESSION,
         .hdr.flags = VHOST_USER_VERSION,
@@ -2695,8 +2701,8 @@ static int vhost_user_get_inflight_fd(struct vhost_dev *dev,
         .hdr.size = sizeof(msg.payload.inflight),
     };
 
-    if (!virtio_has_feature(dev->protocol_features,
-                            VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)) {
+    if (!vhost_user_has_protocol_feature(
+            dev, VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)) {
         return 0;
     }
 
@@ -2763,8 +2769,8 @@ static int vhost_user_set_inflight_fd(struct vhost_dev *dev,
         .hdr.size = sizeof(msg.payload.inflight),
     };
 
-    if (!virtio_has_feature(dev->protocol_features,
-                            VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)) {
+    if (!vhost_user_has_protocol_feature(
+            dev, VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)) {
         return 0;
     }
 
@@ -2863,8 +2869,7 @@ void vhost_user_async_close(DeviceState *d,
 
 static int vhost_user_dev_start(struct vhost_dev *dev, bool started)
 {
-    if (!virtio_has_feature(dev->protocol_features,
-                            VHOST_USER_PROTOCOL_F_STATUS)) {
+    if (!vhost_user_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_STATUS)) {
         return 0;
     }
 
@@ -2889,16 +2894,15 @@ static void vhost_user_reset_status(struct vhost_dev *dev)
         return;
     }
 
-    if (virtio_has_feature(dev->protocol_features,
-                           VHOST_USER_PROTOCOL_F_STATUS)) {
+    if (vhost_user_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_STATUS)) {
         vhost_user_set_status(dev, 0);
     }
 }
 
 static bool vhost_user_supports_device_state(struct vhost_dev *dev)
 {
-    return virtio_has_feature(dev->protocol_features,
-                              VHOST_USER_PROTOCOL_F_DEVICE_STATE);
+    return vhost_user_has_protocol_feature(
+        dev, VHOST_USER_PROTOCOL_F_DEVICE_STATE);
 }
 
 static int vhost_user_set_device_state_fd(struct vhost_dev *dev,
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 030/106] vhost: move protocol_features to vhost_user
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (28 preceding siblings ...)
  2026-06-14 19:06 ` [PULL 029/106] vhost-user: introduce vhost_user_has_protocol_feature() helper Michael S. Tsirkin
@ 2026-06-14 19:07 ` Michael S. Tsirkin
  2026-06-14 19:07 ` [PULL 031/106] vhost-user-gpu: drop code duplication Michael S. Tsirkin
                   ` (76 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Stefano Garzarella,
	Gonglei (Arei), zhenwei pi, Raphael Norwitz, Kevin Wolf,
	Hanna Reitz, Jason Wang, qemu-block

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

As comment says: it's only for vhost-user. So, let's move it
to corresponding vhost backend realization.

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: <20260420200339.708640-5-vsementsov@yandex-team.ru>
---
 backends/cryptodev-vhost.c     |  1 -
 hw/block/vhost-user-blk.c      |  6 ++----
 hw/net/vhost_net.c             |  2 --
 hw/virtio/meson.build          |  1 +
 hw/virtio/vhost-user-stub.c    |  6 ++++++
 hw/virtio/vhost-user.c         | 36 +++++++++++++++++++++++++++-------
 hw/virtio/virtio-qmp.c         |  6 ++++--
 include/hw/virtio/vhost-user.h |  4 ++++
 include/hw/virtio/vhost.h      |  8 --------
 9 files changed, 46 insertions(+), 24 deletions(-)
 create mode 100644 hw/virtio/vhost-user-stub.c

diff --git a/backends/cryptodev-vhost.c b/backends/cryptodev-vhost.c
index abdfce33af..c6069f4e5b 100644
--- a/backends/cryptodev-vhost.c
+++ b/backends/cryptodev-vhost.c
@@ -60,7 +60,6 @@ cryptodev_vhost_init(
 
     crypto->cc = options->cc;
 
-    crypto->dev.protocol_features = 0;
     crypto->backend = -1;
 
     /* vhost-user needs vq_index to initiate a specific queue pair */
diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index dc99de0263..2831f3c053 100644
--- a/hw/block/vhost-user-blk.c
+++ b/hw/block/vhost-user-blk.c
@@ -572,10 +572,8 @@ 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 vhost_user_has_protocol_feature(
+        &s->dev, VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT);
 }
 
 static const VMStateDescription vmstate_vhost_user_blk_inflight = {
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index fda90e231e..ca19983126 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -265,9 +265,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
             goto fail;
         }
         net->backend = r;
-        net->dev.protocol_features = 0;
     } else {
-        net->dev.protocol_features = 0;
         net->backend = -1;
 
         /* vhost-user needs vq_index to initiate a specific queue pair */
diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
index e0566a60de..0ea89d8af4 100644
--- a/hw/virtio/meson.build
+++ b/hw/virtio/meson.build
@@ -94,6 +94,7 @@ system_virtio_ss.add_all(when: 'CONFIG_VIRTIO_PCI', if_true: virtio_pci_ss)
 
 system_ss.add_all(when: 'CONFIG_VIRTIO', if_true: system_virtio_ss)
 stub_ss.add(files('vhost-stub.c'))
+stub_ss.add(files('vhost-user-stub.c'))
 stub_ss.add(files('virtio-stub.c'))
 stub_ss.add(files('virtio-md-stubs.c'))
 
diff --git a/hw/virtio/vhost-user-stub.c b/hw/virtio/vhost-user-stub.c
new file mode 100644
index 0000000000..45559788dd
--- /dev/null
+++ b/hw/virtio/vhost-user-stub.c
@@ -0,0 +1,6 @@
+#include "qemu/osdep.h"
+#include "hw/virtio/vhost-user.h"
+
+void vhost_user_qmp_status(struct vhost_dev *dev, VirtioStatus *status)
+{
+}
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 72aeed26ca..fc2ed1f17e 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -11,6 +11,7 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "hw/virtio/virtio-dmabuf.h"
+#include "hw/virtio/virtio-qmp.h"
 #include "hw/virtio/vhost.h"
 #include "hw/virtio/virtio-crypto.h"
 #include "hw/virtio/vhost-user.h"
@@ -259,6 +260,14 @@ struct vhost_user {
     /* Our current regions */
     int num_shadow_regions;
     struct vhost_memory_region shadow_regions[VHOST_USER_MAX_RAM_SLOTS];
+
+    /**
+     * @protocol_features: the vhost-user protocol feature set by
+     * VHOST_USER_SET_PROTOCOL_FEATURES. Protocol features are only
+     * negotiated if VHOST_USER_F_PROTOCOL_FEATURES has been offered
+     * by the backend (see @features).
+     */
+    uint64_t protocol_features;
 };
 
 struct scrub_regions {
@@ -267,10 +276,13 @@ struct scrub_regions {
     int fd_idx;
 };
 
-static bool vhost_user_has_protocol_feature(struct vhost_dev *dev,
-                                            uint64_t feature)
+bool vhost_user_has_protocol_feature(struct vhost_dev *dev, uint64_t feature)
 {
-    return virtio_has_feature(dev->protocol_features, feature);
+    struct vhost_user *u = dev->opaque;
+
+    assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
+
+    return virtio_has_feature(u->protocol_features, feature);
 }
 
 static int vhost_user_read_header(struct vhost_dev *dev, VhostUserMsg *msg)
@@ -1338,8 +1350,8 @@ static int vhost_set_vring_file(struct vhost_dev *dev,
     int ret;
     int fds[VHOST_USER_MAX_RAM_SLOTS];
     size_t fd_num = 0;
-    bool reply_supported = virtio_has_feature(dev->protocol_features,
-                                              VHOST_USER_PROTOCOL_F_REPLY_ACK);
+    bool reply_supported =
+        vhost_user_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_REPLY_ACK);
     VhostUserMsg msg = {
         .hdr.request = request,
         .hdr.flags = VHOST_USER_VERSION,
@@ -2239,8 +2251,8 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque,
         }
 
         /* final set of protocol features */
-        dev->protocol_features = protocol_features;
-        err = vhost_user_set_protocol_features(dev, dev->protocol_features);
+        u->protocol_features = protocol_features;
+        err = vhost_user_set_protocol_features(dev, u->protocol_features);
         if (err < 0) {
             error_setg_errno(errp, EPROTO, "vhost_backend_init failed");
             return -EPROTO;
@@ -3033,6 +3045,16 @@ static int vhost_user_check_device_state(struct vhost_dev *dev, Error **errp)
     return 0;
 }
 
+void vhost_user_qmp_status(struct vhost_dev *dev, VirtioStatus *status)
+{
+    struct vhost_user *u = dev->opaque;
+
+    assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
+
+    status->vhost_dev->protocol_features =
+        qmp_decode_protocols(u->protocol_features);
+}
+
 const VhostOps user_ops = {
         .backend_type = VHOST_BACKEND_TYPE_USER,
         .vhost_backend_init = vhost_user_backend_init,
diff --git a/hw/virtio/virtio-qmp.c b/hw/virtio/virtio-qmp.c
index 71717c56a4..c8bf702d38 100644
--- a/hw/virtio/virtio-qmp.c
+++ b/hw/virtio/virtio-qmp.c
@@ -751,12 +751,14 @@ VirtioStatus *qmp_x_query_virtio_status(const char *path, Error **errp)
         status->vhost_dev->acked_features =
             qmp_decode_features(vdev->device_id, hdev->acked_features_ex);
 
-        status->vhost_dev->protocol_features =
-            qmp_decode_protocols(hdev->protocol_features);
         status->vhost_dev->max_queues = hdev->max_queues;
         status->vhost_dev->backend_cap = hdev->backend_cap;
         status->vhost_dev->log_enabled = hdev->log_enabled;
         status->vhost_dev->log_size = hdev->log_size;
+
+        if (hdev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER) {
+            vhost_user_qmp_status(hdev, status);
+        }
     }
 
     return status;
diff --git a/include/hw/virtio/vhost-user.h b/include/hw/virtio/vhost-user.h
index 53fe996686..0e576fc538 100644
--- a/include/hw/virtio/vhost-user.h
+++ b/include/hw/virtio/vhost-user.h
@@ -10,6 +10,7 @@
 
 #include "chardev/char-fe.h"
 #include "hw/virtio/virtio.h"
+#include "qapi/qapi-types-virtio.h"
 
 enum VhostUserProtocolFeature {
     VHOST_USER_PROTOCOL_F_MQ = 0,
@@ -113,4 +114,7 @@ void vhost_user_async_close(DeviceState *d,
                             CharFrontend *chardev, struct vhost_dev *vhost,
                             vu_async_close_fn cb);
 
+void vhost_user_qmp_status(struct vhost_dev *dev, VirtioStatus *status);
+bool vhost_user_has_protocol_feature(struct vhost_dev *dev, uint64_t feature);
+
 #endif
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index e139e05985..4a9bd3effe 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -104,14 +104,6 @@ struct vhost_dev {
     VIRTIO_DECLARE_FEATURES(features);
     VIRTIO_DECLARE_FEATURES(acked_features);
 
-    /**
-     * @protocol_features: is the vhost-user only feature set by
-     * VHOST_USER_SET_PROTOCOL_FEATURES. Protocol features are only
-     * negotiated if VHOST_USER_F_PROTOCOL_FEATURES has been offered
-     * by the backend (see @features).
-     */
-    uint64_t protocol_features;
-
     uint64_t max_queues;
     uint64_t backend_cap;
     /* @started: is the vhost device started? */
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 031/106] vhost-user-gpu: drop code duplication
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (29 preceding siblings ...)
  2026-06-14 19:07 ` [PULL 030/106] vhost: move protocol_features to vhost_user Michael S. Tsirkin
@ 2026-06-14 19:07 ` Michael S. Tsirkin
  2026-06-14 19:07 ` [PULL 032/106] vhost: make vhost_dev.features private Michael S. Tsirkin
                   ` (75 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy,
	Philippe Mathieu-Daudé, Raphael Norwitz, Daniil Tatianin,
	Lei Yang, Stefano Garzarella, Marc-André Lureau

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

Obviously, this duplicated fragment doesn't make any sense.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Raphael Norwitz <raphael.s.norwitz@gmail.com>
Reviewed-by: Daniil Tatianin <d-tatianin@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Tested-by: Lei Yang <leiyang@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420200339.708640-6-vsementsov@yandex-team.ru>
---
 hw/display/vhost-user-gpu.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c
index 6e5e6540a4..6f02314356 100644
--- a/hw/display/vhost-user-gpu.c
+++ b/hw/display/vhost-user-gpu.c
@@ -644,10 +644,6 @@ vhost_user_gpu_device_realize(DeviceState *qdev, Error **errp)
         VIRTIO_GPU_F_RESOURCE_UUID)) {
         g->parent_obj.conf.flags |= 1 << VIRTIO_GPU_FLAG_RESOURCE_UUID_ENABLED;
     }
-    if (virtio_has_feature(g->vhost->dev.features,
-        VIRTIO_GPU_F_RESOURCE_UUID)) {
-        g->parent_obj.conf.flags |= 1 << VIRTIO_GPU_FLAG_RESOURCE_UUID_ENABLED;
-    }
 
     if (!virtio_gpu_base_device_realize(qdev, NULL, NULL, errp)) {
         return;
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 032/106] vhost: make vhost_dev.features private
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (30 preceding siblings ...)
  2026-06-14 19:07 ` [PULL 031/106] vhost-user-gpu: drop code duplication Michael S. Tsirkin
@ 2026-06-14 19:07 ` Michael S. Tsirkin
  2026-06-14 19:07 ` [PULL 033/106] virtio: move common part of _set_guest_notifier to generic code Michael S. Tsirkin
                   ` (74 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Daniil Tatianin,
	Lei Yang, Stefano Garzarella, Marc-André Lureau, Jason Wang,
	Alex Bennée

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

It's hard to control where and how do we use this field. Let's
cover all usages by getters/setters, and keep direct access to the
field only in vhost.c. It will help to control migration of this
field in further commits.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Daniil Tatianin <d-tatianin@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Tested-by: Lei Yang <leiyang@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420200339.708640-7-vsementsov@yandex-team.ru>
---
 hw/display/vhost-user-gpu.c |  7 +++----
 hw/net/vhost_net.c          | 18 ++++++++---------
 hw/virtio/vdpa-dev.c        |  2 +-
 hw/virtio/vhost-user-base.c |  8 ++++++--
 hw/virtio/vhost-user.c      |  4 ++--
 hw/virtio/vhost.c           |  6 +++---
 hw/virtio/virtio-qmp.c      |  2 +-
 include/hw/virtio/vhost.h   | 39 +++++++++++++++++++++++++++++++++++--
 net/vhost-vdpa.c            |  7 +++----
 9 files changed, 65 insertions(+), 28 deletions(-)

diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c
index 6f02314356..57360898ca 100644
--- a/hw/display/vhost-user-gpu.c
+++ b/hw/display/vhost-user-gpu.c
@@ -631,17 +631,16 @@ vhost_user_gpu_device_realize(DeviceState *qdev, Error **errp)
 
     /* existing backend may send DMABUF, so let's add that requirement */
     g->parent_obj.conf.flags |= 1 << VIRTIO_GPU_FLAG_DMABUF_ENABLED;
-    if (virtio_has_feature(g->vhost->dev.features, VIRTIO_GPU_F_VIRGL)) {
+    if (vhost_dev_has_feature(&g->vhost->dev, VIRTIO_GPU_F_VIRGL)) {
         g->parent_obj.conf.flags |= 1 << VIRTIO_GPU_FLAG_VIRGL_ENABLED;
     }
-    if (virtio_has_feature(g->vhost->dev.features, VIRTIO_GPU_F_EDID)) {
+    if (vhost_dev_has_feature(&g->vhost->dev, VIRTIO_GPU_F_EDID)) {
         g->parent_obj.conf.flags |= 1 << VIRTIO_GPU_FLAG_EDID_ENABLED;
     } else {
         error_report("EDID requested but the backend doesn't support it.");
         g->parent_obj.conf.flags &= ~(1 << VIRTIO_GPU_FLAG_EDID_ENABLED);
     }
-    if (virtio_has_feature(g->vhost->dev.features,
-        VIRTIO_GPU_F_RESOURCE_UUID)) {
+    if (vhost_dev_has_feature(&g->vhost->dev, VIRTIO_GPU_F_RESOURCE_UUID)) {
         g->parent_obj.conf.flags |= 1 << VIRTIO_GPU_FLAG_RESOURCE_UUID_ENABLED;
     }
 
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index ca19983126..323d117735 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -54,8 +54,8 @@ void vhost_net_ack_features_ex(struct vhost_net *net, const uint64_t *features)
 {
     virtio_features_clear(net->dev.acked_features_ex);
     if (net->backend == -1) {
-        net->dev.acked_features =
-           net->dev.features & (1ULL << VHOST_USER_F_PROTOCOL_FEATURES);
+        net->dev.acked_features = (vhost_dev_features(&net->dev) &
+            (1ULL << VHOST_USER_F_PROTOCOL_FEATURES));
     } else if (!qemu_has_vnet_hdr(net->nc)) {
         net->dev.acked_features = 1ULL << VHOST_NET_F_VIRTIO_NET_HDR;
     }
@@ -282,15 +282,15 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
     if (backend_kernel) {
         if (!qemu_has_vnet_hdr_len(options->net_backend,
                                sizeof(struct virtio_net_hdr_mrg_rxbuf))) {
-            net->dev.features &= ~(1ULL << VIRTIO_NET_F_MRG_RXBUF);
+            vhost_dev_clear_feature(&net->dev, VIRTIO_NET_F_MRG_RXBUF);
         }
 
         if (!qemu_has_vnet_hdr(options->net_backend) &&
-            (~net->dev.features & (1ULL << VHOST_NET_F_VIRTIO_NET_HDR))) {
-            fprintf(stderr, "vhost lacks feature mask 0x%llx for backend\n",
-                    ~net->dev.features & (1ULL << VHOST_NET_F_VIRTIO_NET_HDR));
-             goto fail;
-         }
+            !vhost_dev_has_feature(&net->dev, VHOST_NET_F_VIRTIO_NET_HDR)) {
+            fprintf(stderr, "vhost lacks VHOST_NET_F_VIRTIO_NET_HDR "
+                    "feature for backend\n");
+            goto fail;
+        }
     }
 
     /* Set sane init value. Override when guest acks. */
@@ -298,7 +298,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
         virtio_features_from_u64(features,
                                  options->get_acked_features(net->nc));
         if (virtio_features_andnot(missing_features, features,
-                                   net->dev.features_ex)) {
+                                   vhost_dev_features_ex(&net->dev))) {
             fprintf(stderr, "vhost lacks feature mask 0x" VIRTIO_FEATURES_FMT
                     " for backend\n", VIRTIO_FEATURES_PR(missing_features));
             goto fail;
diff --git a/hw/virtio/vdpa-dev.c b/hw/virtio/vdpa-dev.c
index 06179e402e..94188d37bb 100644
--- a/hw/virtio/vdpa-dev.c
+++ b/hw/virtio/vdpa-dev.c
@@ -224,7 +224,7 @@ static uint64_t vhost_vdpa_device_get_features(VirtIODevice *vdev,
                                                Error **errp)
 {
     VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev);
-    uint64_t backend_features = s->dev.features;
+    uint64_t backend_features = vhost_dev_features(&s->dev);
 
     if (!virtio_has_feature(features, VIRTIO_F_IOMMU_PLATFORM)) {
         virtio_clear_feature(&backend_features, VIRTIO_F_IOMMU_PLATFORM);
diff --git a/hw/virtio/vhost-user-base.c b/hw/virtio/vhost-user-base.c
index 01ab9ca56b..5bbf4a7367 100644
--- a/hw/virtio/vhost-user-base.c
+++ b/hw/virtio/vhost-user-base.c
@@ -118,9 +118,13 @@ static uint64_t vub_get_features(VirtIODevice *vdev,
                                  uint64_t requested_features, Error **errp)
 {
     VHostUserBase *vub = VHOST_USER_BASE(vdev);
+    uint64_t backend_features = vhost_dev_features(&vub->vhost_dev);
+
     /* This should be set when the vhost connection initialises */
-    g_assert(vub->vhost_dev.features);
-    return vub->vhost_dev.features & ~(1ULL << VHOST_USER_F_PROTOCOL_FEATURES);
+    g_assert(backend_features);
+    virtio_clear_feature(&backend_features, VHOST_USER_F_PROTOCOL_FEATURES);
+
+    return backend_features;
 }
 
 /*
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index fc2ed1f17e..68dd89cd8f 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -1249,7 +1249,7 @@ static int vhost_user_set_vring_enable(struct vhost_dev *dev, int enable)
 {
     int i;
 
-    if (!virtio_has_feature(dev->features, VHOST_USER_F_PROTOCOL_FEATURES)) {
+    if (!vhost_dev_has_feature(dev, VHOST_USER_F_PROTOCOL_FEATURES)) {
         /*
          * For vhost-user devices, if VHOST_USER_F_PROTOCOL_FEATURES has not
          * been negotiated, the rings start directly in the enabled state,
@@ -1488,7 +1488,7 @@ static int vhost_user_set_features(struct vhost_dev *dev,
      * Don't lose VHOST_USER_F_PROTOCOL_FEATURES, which is vhost-user
      * specific.
      */
-    if (virtio_has_feature(dev->features, VHOST_USER_F_PROTOCOL_FEATURES)) {
+    if (vhost_dev_has_feature(dev, VHOST_USER_F_PROTOCOL_FEATURES)) {
         features |= 1ULL << VHOST_USER_F_PROTOCOL_FEATURES;
     }
 
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index b89797df95..e39e0676e0 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1612,7 +1612,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
         }
     }
 
-    virtio_features_copy(hdev->features_ex, features);
+    virtio_features_copy(hdev->_features_ex, features);
 
     hdev->memory_listener = (MemoryListener) {
         .name = "vhost",
@@ -1635,7 +1635,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
     };
 
     if (hdev->migration_blocker == NULL) {
-        if (!virtio_has_feature_ex(hdev->features_ex, VHOST_F_LOG_ALL)) {
+        if (!vhost_dev_has_feature_ex(hdev, VHOST_F_LOG_ALL)) {
             error_setg(&hdev->migration_blocker,
                        "Migration disabled: vhost lacks VHOST_F_LOG_ALL feature.");
         } else if (vhost_dev_log_is_shared(hdev) && !qemu_memfd_alloc_check()) {
@@ -1909,7 +1909,7 @@ void vhost_get_features_ex(struct vhost_dev *hdev,
     const int *bit = feature_bits;
 
     while (*bit != VHOST_INVALID_FEATURE_BIT) {
-        if (!virtio_has_feature_ex(hdev->features_ex, *bit)) {
+        if (!vhost_dev_has_feature_ex(hdev, *bit)) {
             virtio_clear_feature_ex(features, *bit);
         }
         bit++;
diff --git a/hw/virtio/virtio-qmp.c b/hw/virtio/virtio-qmp.c
index c8bf702d38..51e3a42c4c 100644
--- a/hw/virtio/virtio-qmp.c
+++ b/hw/virtio/virtio-qmp.c
@@ -747,7 +747,7 @@ VirtioStatus *qmp_x_query_virtio_status(const char *path, Error **errp)
         status->vhost_dev->nvqs = hdev->nvqs;
         status->vhost_dev->vq_index = hdev->vq_index;
         status->vhost_dev->features =
-            qmp_decode_features(vdev->device_id, hdev->features_ex);
+            qmp_decode_features(vdev->device_id, vhost_dev_features_ex(hdev));
         status->vhost_dev->acked_features =
             qmp_decode_features(vdev->device_id, hdev->acked_features_ex);
 
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index 4a9bd3effe..54862f9b44 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -98,10 +98,11 @@ struct vhost_dev {
      * offered by a backend which may be a subset of the total
      * features eventually offered to the guest.
      *
-     * @features: available features provided by the backend
+     * @_features: available features provided by the backend, private,
+     *             direct access only in vhost.h/vhost.c
      * @acked_features: final negotiated features with front-end driver
      */
-    VIRTIO_DECLARE_FEATURES(features);
+    VIRTIO_DECLARE_FEATURES(_features);
     VIRTIO_DECLARE_FEATURES(acked_features);
 
     uint64_t max_queues;
@@ -403,6 +404,40 @@ int vhost_dev_get_inflight(struct vhost_dev *dev, uint16_t queue_size,
                            struct vhost_inflight *inflight);
 bool vhost_dev_has_iommu(struct vhost_dev *dev);
 
+static inline bool vhost_dev_has_feature(struct vhost_dev *dev,
+                                         uint64_t feature)
+{
+    return virtio_has_feature(dev->_features, feature);
+}
+
+static inline bool vhost_dev_has_feature_ex(struct vhost_dev *dev,
+                                            uint64_t feature)
+{
+    return virtio_has_feature_ex(dev->_features_ex, feature);
+}
+
+static inline uint64_t vhost_dev_features(struct vhost_dev *dev)
+{
+    return dev->_features;
+}
+
+static inline const uint64_t *vhost_dev_features_ex(struct vhost_dev *dev)
+{
+    return dev->_features_ex;
+}
+
+static inline void vhost_dev_clear_feature(struct vhost_dev *dev,
+                                           uint64_t feature)
+{
+    virtio_clear_feature(&dev->_features, feature);
+}
+
+static inline void vhost_dev_clear_feature_ex(struct vhost_dev *dev,
+                                              uint64_t feature)
+{
+    virtio_clear_feature_ex(dev->_features_ex, feature);
+}
+
 #ifdef CONFIG_VHOST
 int vhost_reset_device(struct vhost_dev *hdev);
 #else
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
index f1523697e2..c85956a04b 100644
--- a/net/vhost-vdpa.c
+++ b/net/vhost-vdpa.c
@@ -257,15 +257,14 @@ static bool vhost_vdpa_get_vnet_hash_supported_types(NetClientState *nc,
 {
     assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
     VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
-    uint64_t features = s->vhost_vdpa.dev->features;
     int fd = s->vhost_vdpa.shared->device_fd;
     struct {
         struct vhost_vdpa_config hdr;
         uint32_t supported_hash_types;
     } config;
 
-    if (!virtio_has_feature(features, VIRTIO_NET_F_HASH_REPORT) &&
-        !virtio_has_feature(features, VIRTIO_NET_F_RSS)) {
+    if (!vhost_dev_has_feature(s->vhost_vdpa.dev, VIRTIO_NET_F_HASH_REPORT) &&
+        !vhost_dev_has_feature(s->vhost_vdpa.dev, VIRTIO_NET_F_RSS)) {
         return false;
     }
 
@@ -586,7 +585,7 @@ static int vhost_vdpa_net_cvq_start(NetClientState *nc)
      * If we early return in these cases SVQ will not be enabled. The migration
      * will be blocked as long as vhost-vdpa backends will not offer _F_LOG.
      */
-    if (!vhost_vdpa_net_valid_svq_features(v->dev->features, NULL)) {
+    if (!vhost_vdpa_net_valid_svq_features(vhost_dev_features(v->dev), NULL)) {
         return 0;
     }
 
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 033/106] virtio: move common part of _set_guest_notifier to generic code
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (31 preceding siblings ...)
  2026-06-14 19:07 ` [PULL 032/106] vhost: make vhost_dev.features private Michael S. Tsirkin
@ 2026-06-14 19:07 ` Michael S. Tsirkin
  2026-06-14 19:07 ` [PULL 034/106] virtio: drop *_set_guest_notifier_fd_handler() helpers Michael S. Tsirkin
                   ` (73 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Eric Farman,
	Cornelia Huck, Halil Pasic, Christian Borntraeger, Matthew Rosato,
	Richard Henderson, Ilya Leoshkevich, David Hildenbrand,
	qemu-s390x

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

virtio-pci, virtio-mmio and virtio-ccw handle config notifier equally
but with different code (mmio adds a separate function, when pci use
common function). Let's chose the more compact way (pci) and reuse it
for mmio.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Acked-by: Eric Farman <farman@linux.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420200339.708640-8-vsementsov@yandex-team.ru>
---
 hw/s390x/virtio-ccw.c          | 35 ++++++++++++-------------
 hw/virtio/virtio-mmio.c        | 41 +++++------------------------
 hw/virtio/virtio-pci.c         | 34 +++---------------------
 hw/virtio/virtio.c             | 47 +++++++++++++++++++++++++++++++---
 include/hw/virtio/virtio-pci.h |  3 ---
 include/hw/virtio/virtio.h     | 15 ++++++++---
 6 files changed, 82 insertions(+), 93 deletions(-)

diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index ba55bf4fe9..cdad862ec2 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -1025,20 +1025,27 @@ static int virtio_ccw_set_guest_notifier(VirtioCcwDevice *dev, int n,
     VirtQueue *vq = virtio_get_queue(vdev, n);
     EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
     VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
+    int r;
+
+    if (!assign) {
+        if (k->guest_notifier_mask && vdev->use_guest_notifier_mask) {
+            k->guest_notifier_mask(vdev, n, true);
+        }
+        if (with_irqfd) {
+            virtio_ccw_remove_irqfd(dev, n);
+        }
+    }
+
+    r = virtio_set_guest_notifier(vdev, n, assign, with_irqfd);
+    if (r < 0) {
+        return r;
+    }
 
     if (assign) {
-        int r = event_notifier_init(notifier, 0);
-
-        if (r < 0) {
-            return r;
-        }
-        virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd);
         if (with_irqfd) {
             r = virtio_ccw_add_irqfd(dev, n);
             if (r) {
-                virtio_queue_set_guest_notifier_fd_handler(vq, false,
-                                                           with_irqfd);
-                event_notifier_cleanup(notifier);
+                virtio_set_guest_notifier(vdev, n, false, with_irqfd);
                 return r;
             }
         }
@@ -1054,16 +1061,8 @@ static int virtio_ccw_set_guest_notifier(VirtioCcwDevice *dev, int n,
             k->guest_notifier_pending(vdev, n)) {
             event_notifier_set(notifier);
         }
-    } else {
-        if (k->guest_notifier_mask && vdev->use_guest_notifier_mask) {
-            k->guest_notifier_mask(vdev, n, true);
-        }
-        if (with_irqfd) {
-            virtio_ccw_remove_irqfd(dev, n);
-        }
-        virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd);
-        event_notifier_cleanup(notifier);
     }
+
     return 0;
 }
 
diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c
index 742ca3d3e4..58c6d46aab 100644
--- a/hw/virtio/virtio-mmio.c
+++ b/hw/virtio/virtio-mmio.c
@@ -670,18 +670,11 @@ static int virtio_mmio_set_guest_notifier(DeviceState *d, int n, bool assign,
     VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
     VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
     VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
-    VirtQueue *vq = virtio_get_queue(vdev, n);
-    EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
+    int r;
 
-    if (assign) {
-        int r = event_notifier_init(notifier, 0);
-        if (r < 0) {
-            return r;
-        }
-        virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd);
-    } else {
-        virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd);
-        event_notifier_cleanup(notifier);
+    r = virtio_set_guest_notifier(vdev, n, assign, with_irqfd);
+    if (r < 0) {
+        return r;
     }
 
     if (vdc->guest_notifier_mask && vdev->use_guest_notifier_mask) {
@@ -690,30 +683,7 @@ static int virtio_mmio_set_guest_notifier(DeviceState *d, int n, bool assign,
 
     return 0;
 }
-static int virtio_mmio_set_config_guest_notifier(DeviceState *d, bool assign,
-                                                 bool with_irqfd)
-{
-    VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
-    VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
-    VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
-    EventNotifier *notifier = virtio_config_get_guest_notifier(vdev);
-    int r = 0;
 
-    if (assign) {
-        r = event_notifier_init(notifier, 0);
-        if (r < 0) {
-            return r;
-        }
-        virtio_config_set_guest_notifier_fd_handler(vdev, assign, with_irqfd);
-    } else {
-        virtio_config_set_guest_notifier_fd_handler(vdev, assign, with_irqfd);
-        event_notifier_cleanup(notifier);
-    }
-    if (vdc->guest_notifier_mask && vdev->use_guest_notifier_mask) {
-        vdc->guest_notifier_mask(vdev, VIRTIO_CONFIG_IRQ_IDX, !assign);
-    }
-    return r;
-}
 static int virtio_mmio_set_guest_notifiers(DeviceState *d, int nvqs,
                                            bool assign)
 {
@@ -735,7 +705,8 @@ static int virtio_mmio_set_guest_notifiers(DeviceState *d, int nvqs,
             goto assign_error;
         }
     }
-    r = virtio_mmio_set_config_guest_notifier(d, assign, with_irqfd);
+    r = virtio_mmio_set_guest_notifier(d, VIRTIO_CONFIG_IRQ_IDX, assign,
+                                       with_irqfd);
     if (r < 0) {
         goto assign_error;
     }
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index bcab2d18b8..fd9719547f 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1208,43 +1208,17 @@ static void virtio_pci_vector_poll(PCIDevice *dev,
     }
 }
 
-void virtio_pci_set_guest_notifier_fd_handler(VirtIODevice *vdev, VirtQueue *vq,
-                                              int n, bool assign,
-                                              bool with_irqfd)
-{
-    if (n == VIRTIO_CONFIG_IRQ_IDX) {
-        virtio_config_set_guest_notifier_fd_handler(vdev, assign, with_irqfd);
-    } else {
-        virtio_queue_set_guest_notifier_fd_handler(vq, assign, with_irqfd);
-    }
-}
-
 static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign,
                                          bool with_irqfd)
 {
     VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
     VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
     VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
-    VirtQueue *vq = NULL;
-    EventNotifier *notifier = NULL;
+    int r;
 
-    if (n == VIRTIO_CONFIG_IRQ_IDX) {
-        notifier = virtio_config_get_guest_notifier(vdev);
-    } else {
-        vq = virtio_get_queue(vdev, n);
-        notifier = virtio_queue_get_guest_notifier(vq);
-    }
-
-    if (assign) {
-        int r = event_notifier_init(notifier, 0);
-        if (r < 0) {
-            return r;
-        }
-        virtio_pci_set_guest_notifier_fd_handler(vdev, vq, n, true, with_irqfd);
-    } else {
-        virtio_pci_set_guest_notifier_fd_handler(vdev, vq, n, false,
-                                                 with_irqfd);
-        event_notifier_cleanup(notifier);
+    r = virtio_set_guest_notifier(vdev, n, assign, with_irqfd);
+    if (r < 0) {
+        return r;
     }
 
     if (!msix_enabled(&proxy->pci_dev) &&
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 63e2faee99..3780e86039 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -3835,8 +3835,10 @@ static void virtio_config_guest_notifier_read(EventNotifier *n)
         virtio_notify_config(vdev);
     }
 }
-void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign,
-                                                bool with_irqfd)
+
+static void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq,
+                                                       bool assign,
+                                                       bool with_irqfd)
 {
     if (assign && !with_irqfd) {
         event_notifier_set_handler(&vq->guest_notifier,
@@ -3851,7 +3853,7 @@ void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign,
     }
 }
 
-void virtio_config_set_guest_notifier_fd_handler(VirtIODevice *vdev,
+static void virtio_config_set_guest_notifier_fd_handler(VirtIODevice *vdev,
                                                  bool assign, bool with_irqfd)
 {
     EventNotifier *n;
@@ -3868,6 +3870,45 @@ void virtio_config_set_guest_notifier_fd_handler(VirtIODevice *vdev,
     }
 }
 
+static void virtio_set_guest_notifier_fd_handler(VirtIODevice *vdev,
+                                                 VirtQueue *vq,
+                                                 int n, bool assign,
+                                                 bool with_irqfd)
+{
+    if (n == VIRTIO_CONFIG_IRQ_IDX) {
+        virtio_config_set_guest_notifier_fd_handler(vdev, assign, with_irqfd);
+    } else {
+        virtio_queue_set_guest_notifier_fd_handler(vq, assign, with_irqfd);
+    }
+}
+
+int virtio_set_guest_notifier(VirtIODevice *vdev, int n, bool assign,
+                              bool with_irqfd)
+{
+    VirtQueue *vq = NULL;
+    EventNotifier *notifier = NULL;
+
+    if (n == VIRTIO_CONFIG_IRQ_IDX) {
+        notifier = virtio_config_get_guest_notifier(vdev);
+    } else {
+        vq = virtio_get_queue(vdev, n);
+        notifier = virtio_queue_get_guest_notifier(vq);
+    }
+
+    if (assign) {
+        int r = event_notifier_init(notifier, 0);
+        if (r < 0) {
+            return r;
+        }
+        virtio_set_guest_notifier_fd_handler(vdev, vq, n, true, with_irqfd);
+    } else {
+        virtio_set_guest_notifier_fd_handler(vdev, vq, n, false, with_irqfd);
+        event_notifier_cleanup(notifier);
+    }
+
+    return 0;
+}
+
 EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq)
 {
     return &vq->guest_notifier;
diff --git a/include/hw/virtio/virtio-pci.h b/include/hw/virtio/virtio-pci.h
index 5cb20b73f6..ee50fb0d55 100644
--- a/include/hw/virtio/virtio-pci.h
+++ b/include/hw/virtio/virtio-pci.h
@@ -250,9 +250,6 @@ void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t);
  * @fixed_queues.
  */
 unsigned virtio_pci_optimal_num_queues(unsigned fixed_queues);
-void virtio_pci_set_guest_notifier_fd_handler(VirtIODevice *vdev, VirtQueue *vq,
-                                              int n, bool assign,
-                                              bool with_irqfd);
 
 int virtio_pci_add_shm_cap(VirtIOPCIProxy *proxy, uint8_t bar, uint64_t offset,
                            uint64_t length, uint8_t id);
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 6344bd7b68..d9fde42558 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -420,8 +420,6 @@ void virtio_queue_update_used_idx(VirtIODevice *vdev, int n);
 VirtQueue *virtio_get_queue(VirtIODevice *vdev, int n);
 uint16_t virtio_get_queue_index(VirtQueue *vq);
 EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq);
-void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign,
-                                                bool with_irqfd);
 int virtio_device_start_ioeventfd(VirtIODevice *vdev);
 int virtio_device_grab_ioeventfd(VirtIODevice *vdev);
 void virtio_device_release_ioeventfd(VirtIODevice *vdev);
@@ -435,8 +433,17 @@ void virtio_queue_aio_detach_host_notifier(VirtQueue *vq, AioContext *ctx);
 VirtQueue *virtio_vector_first_queue(VirtIODevice *vdev, uint16_t vector);
 VirtQueue *virtio_vector_next_queue(VirtQueue *vq);
 EventNotifier *virtio_config_get_guest_notifier(VirtIODevice *vdev);
-void virtio_config_set_guest_notifier_fd_handler(VirtIODevice *vdev,
-                                                 bool assign, bool with_irqfd);
+
+/**
+ * virtio_set_guest_notifier - set/unset queue or config guest notifier
+ *
+ * @vdev: the VirtIO device
+ * @n: queue number, or VIRTIO_CONFIG_IRQ_IDX to set config notifer
+ * @assign: true to set notifier, false to unset
+ * @with_irqfd: irqfd enabled
+ */
+int virtio_set_guest_notifier(VirtIODevice *vdev, int n, bool assign,
+                              bool with_irqfd);
 
 static inline void virtio_add_feature(uint64_t *features, unsigned int fbit)
 {
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 034/106] virtio: drop *_set_guest_notifier_fd_handler() helpers
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (32 preceding siblings ...)
  2026-06-14 19:07 ` [PULL 033/106] virtio: move common part of _set_guest_notifier to generic code Michael S. Tsirkin
@ 2026-06-14 19:07 ` Michael S. Tsirkin
  2026-06-14 19:07 ` [PULL 035/106] vhost-user: keep QIOChannelSocket for backend channel Michael S. Tsirkin
                   ` (72 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:07 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Daniil Tatianin

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

Now they don't make code more readable. Let's better put the whole
logic into virtio_queue_set_guest_notifier().

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Daniil Tatianin <d-tatianin@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420200339.708640-9-vsementsov@yandex-team.ru>
---
 hw/virtio/virtio.c | 75 +++++++++++-----------------------------------
 1 file changed, 17 insertions(+), 58 deletions(-)

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 3780e86039..fb7f7f0f06 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -3836,73 +3836,32 @@ static void virtio_config_guest_notifier_read(EventNotifier *n)
     }
 }
 
-static void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq,
-                                                       bool assign,
-                                                       bool with_irqfd)
-{
-    if (assign && !with_irqfd) {
-        event_notifier_set_handler(&vq->guest_notifier,
-                                   virtio_queue_guest_notifier_read);
-    } else {
-        event_notifier_set_handler(&vq->guest_notifier, NULL);
-    }
-    if (!assign) {
-        /* Test and clear notifier before closing it,
-         * in case poll callback didn't have time to run. */
-        virtio_queue_guest_notifier_read(&vq->guest_notifier);
-    }
-}
-
-static void virtio_config_set_guest_notifier_fd_handler(VirtIODevice *vdev,
-                                                 bool assign, bool with_irqfd)
-{
-    EventNotifier *n;
-    n = &vdev->config_notifier;
-    if (assign && !with_irqfd) {
-        event_notifier_set_handler(n, virtio_config_guest_notifier_read);
-    } else {
-        event_notifier_set_handler(n, NULL);
-    }
-    if (!assign) {
-        /* Test and clear notifier before closing it,*/
-        /* in case poll callback didn't have time to run. */
-        virtio_config_guest_notifier_read(n);
-    }
-}
-
-static void virtio_set_guest_notifier_fd_handler(VirtIODevice *vdev,
-                                                 VirtQueue *vq,
-                                                 int n, bool assign,
-                                                 bool with_irqfd)
-{
-    if (n == VIRTIO_CONFIG_IRQ_IDX) {
-        virtio_config_set_guest_notifier_fd_handler(vdev, assign, with_irqfd);
-    } else {
-        virtio_queue_set_guest_notifier_fd_handler(vq, assign, with_irqfd);
-    }
-}
-
 int virtio_set_guest_notifier(VirtIODevice *vdev, int n, bool assign,
                               bool with_irqfd)
 {
-    VirtQueue *vq = NULL;
-    EventNotifier *notifier = NULL;
-
-    if (n == VIRTIO_CONFIG_IRQ_IDX) {
-        notifier = virtio_config_get_guest_notifier(vdev);
-    } else {
-        vq = virtio_get_queue(vdev, n);
-        notifier = virtio_queue_get_guest_notifier(vq);
-    }
+    bool is_config = n == VIRTIO_CONFIG_IRQ_IDX;
+    VirtQueue *vq = is_config ? NULL : virtio_get_queue(vdev, n);
+    EventNotifier *notifier = is_config ?
+        virtio_config_get_guest_notifier(vdev) :
+        virtio_queue_get_guest_notifier(vq);
+    EventNotifierHandler *read_fn = is_config ?
+        virtio_config_guest_notifier_read :
+        virtio_queue_guest_notifier_read;
 
     if (assign) {
         int r = event_notifier_init(notifier, 0);
         if (r < 0) {
             return r;
         }
-        virtio_set_guest_notifier_fd_handler(vdev, vq, n, true, with_irqfd);
-    } else {
-        virtio_set_guest_notifier_fd_handler(vdev, vq, n, false, with_irqfd);
+    }
+
+    event_notifier_set_handler(notifier,
+                               (assign && !with_irqfd) ? read_fn : NULL);
+
+    if (!assign) {
+        /* Test and clear notifier before closing it,*/
+        /* in case poll callback didn't have time to run. */
+        read_fn(notifier);
         event_notifier_cleanup(notifier);
     }
 
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 035/106] vhost-user: keep QIOChannelSocket for backend channel
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (33 preceding siblings ...)
  2026-06-14 19:07 ` [PULL 034/106] virtio: drop *_set_guest_notifier_fd_handler() helpers Michael S. Tsirkin
@ 2026-06-14 19:07 ` Michael S. Tsirkin
  2026-06-14 19:07 ` [PULL 036/106] vhost: vhost_virtqueue_start(): fix failure path Michael S. Tsirkin
                   ` (71 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Raphael Norwitz,
	Daniil Tatianin, Lei Yang, Stefano Garzarella

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

Keep QIOChannelSocket pointer instead of more generic
QIOChannel. No real difference for now, but it would
be simpler to migrate socket fd in further commit.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Acked-by: Raphael Norwitz <raphael.s.norwitz@gmail.com>
Reviewed-by: Daniil Tatianin <d-tatianin@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Tested-by: Lei Yang <leiyang@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420200339.708640-10-vsementsov@yandex-team.ru>
---
 hw/virtio/vhost-user.c | 21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 68dd89cd8f..31eaf65430 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -239,7 +239,7 @@ struct vhost_user {
     struct vhost_dev *dev;
     /* Shared between vhost devs of the same virtio device */
     VhostUserState *user;
-    QIOChannel *backend_ioc;
+    QIOChannelSocket *backend_sioc;
     GSource *backend_src;
     NotifierWithReturn postcopy_notifier;
     struct PostCopyFD  postcopy_fd;
@@ -1796,8 +1796,8 @@ static void close_backend_channel(struct vhost_user *u)
     g_source_destroy(u->backend_src);
     g_source_unref(u->backend_src);
     u->backend_src = NULL;
-    object_unref(OBJECT(u->backend_ioc));
-    u->backend_ioc = NULL;
+    object_unref(OBJECT(u->backend_sioc));
+    u->backend_sioc = NULL;
 }
 
 static gboolean backend_read(QIOChannel *ioc, GIOCondition condition,
@@ -1909,7 +1909,6 @@ static int vhost_setup_backend_channel(struct vhost_dev *dev)
     bool reply_supported =
         vhost_user_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_REPLY_ACK);
     Error *local_err = NULL;
-    QIOChannel *ioc;
 
     if (!vhost_user_has_protocol_feature(
             dev, VHOST_USER_PROTOCOL_F_BACKEND_REQ)) {
@@ -1922,15 +1921,15 @@ static int vhost_setup_backend_channel(struct vhost_dev *dev)
         return -saved_errno;
     }
 
-    ioc = QIO_CHANNEL(qio_channel_socket_new_fd(sv[0], &local_err));
-    if (!ioc) {
+    u->backend_sioc = qio_channel_socket_new_fd(sv[0], &local_err);
+    if (!u->backend_sioc) {
         error_report_err(local_err);
         return -ECONNREFUSED;
     }
-    u->backend_ioc = ioc;
-    u->backend_src = qio_channel_add_watch_source(u->backend_ioc,
-                                                G_IO_IN | G_IO_HUP,
-                                                backend_read, dev, NULL, NULL);
+    u->backend_src = qio_channel_add_watch_source(QIO_CHANNEL(u->backend_sioc),
+                                                  G_IO_IN | G_IO_HUP,
+                                                  backend_read, dev,
+                                                  NULL, NULL);
 
     if (reply_supported) {
         msg.hdr.flags |= VHOST_USER_NEED_REPLY_MASK;
@@ -2350,7 +2349,7 @@ static int vhost_user_backend_cleanup(struct vhost_dev *dev)
         close(u->postcopy_fd.fd);
         u->postcopy_fd.handler = NULL;
     }
-    if (u->backend_ioc) {
+    if (u->backend_sioc) {
         close_backend_channel(u);
     }
     g_free(u->region_rb);
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 036/106] vhost: vhost_virtqueue_start(): fix failure path
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (34 preceding siblings ...)
  2026-06-14 19:07 ` [PULL 035/106] vhost-user: keep QIOChannelSocket for backend channel Michael S. Tsirkin
@ 2026-06-14 19:07 ` Michael S. Tsirkin
  2026-06-14 19:07 ` [PULL 037/106] vhost: make vhost_memory_unmap() null-safe Michael S. Tsirkin
                   ` (70 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Raphael Norwitz,
	Stefano Garzarella

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

We miss call to unmap in cases when vhost_memory_map() returns
lenght less than requested (still we consider such cases as an
error). Let's fix it in vhost_memory_map().

Fixes: c471ad0e9b ("vhost_net: device IOTLB support")
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Raphael Norwitz <raphael.s.norwitz@gmail.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420200339.708640-11-vsementsov@yandex-team.ru>
---
 hw/virtio/vhost.c | 27 ++++++++++++++++++---------
 1 file changed, 18 insertions(+), 9 deletions(-)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index e39e0676e0..131a2fbf87 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -454,11 +454,20 @@ static inline void vhost_dev_log_resize(struct vhost_dev *dev, uint64_t size)
 }
 
 static void *vhost_memory_map(struct vhost_dev *dev, hwaddr addr,
-                              hwaddr *plen, bool is_write)
+                              hwaddr len, bool is_write)
 {
     if (!vhost_dev_has_iommu(dev)) {
-        return address_space_map(dev->vdev->dma_as, addr, plen, is_write,
-                                 MEMTXATTRS_UNSPECIFIED);
+        hwaddr mapped_len = len;
+        void *res = address_space_map(dev->vdev->dma_as, addr, &mapped_len,
+                                      is_write, MEMTXATTRS_UNSPECIFIED);
+        if (!res) {
+            return NULL;
+        }
+        if (len != mapped_len) {
+            address_space_unmap(dev->vdev->dma_as, res, mapped_len, 0, 0);
+            return NULL;
+        }
+        return res;
     } else {
         return (void *)(uintptr_t)addr;
     }
@@ -1312,22 +1321,22 @@ int vhost_virtqueue_start(struct vhost_dev *dev,
     }
 
     l = vq->desc_size;
-    vq->desc = vhost_memory_map(dev, vq->desc_phys, &l, false);
-    if (!vq->desc || l != vq->desc_size) {
+    vq->desc = vhost_memory_map(dev, vq->desc_phys, l, false);
+    if (!vq->desc) {
         r = -ENOMEM;
         goto fail_alloc_desc;
     }
 
     l = vq->avail_size;
-    vq->avail = vhost_memory_map(dev, vq->avail_phys, &l, false);
-    if (!vq->avail || l != vq->avail_size) {
+    vq->avail = vhost_memory_map(dev, vq->avail_phys, l, false);
+    if (!vq->avail) {
         r = -ENOMEM;
         goto fail_alloc_avail;
     }
 
     l = vq->used_size;
-    vq->used = vhost_memory_map(dev, vq->used_phys, &l, true);
-    if (!vq->used || l != vq->used_size) {
+    vq->used = vhost_memory_map(dev, vq->used_phys, l, true);
+    if (!vq->used) {
         r = -ENOMEM;
         goto fail_alloc_used;
     }
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 037/106] vhost: make vhost_memory_unmap() null-safe
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (35 preceding siblings ...)
  2026-06-14 19:07 ` [PULL 036/106] vhost: vhost_virtqueue_start(): fix failure path Michael S. Tsirkin
@ 2026-06-14 19:07 ` Michael S. Tsirkin
  2026-06-14 19:07 ` [PULL 038/106] vhost: simplify calls to vhost_memory_unmap() Michael S. Tsirkin
                   ` (69 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Daniil Tatianin,
	Raphael Norwitz, Stefano Garzarella

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

This helps to simplify failure paths of vhost_virtqueue_start()
a lot. We also need to zero-out pointers on unmap, to not try
to unmap invalid pointers.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Daniil Tatianin <d-tatianin@yandex-team.ru>
Reviewed-by: Raphael Norwitz <raphael.s.norwitz@gmail.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420200339.708640-12-vsementsov@yandex-team.ru>
---
 hw/virtio/vhost.c | 41 +++++++++++++++++++++--------------------
 1 file changed, 21 insertions(+), 20 deletions(-)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 131a2fbf87..b9b7a984e3 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -473,14 +473,20 @@ static void *vhost_memory_map(struct vhost_dev *dev, hwaddr addr,
     }
 }
 
-static void vhost_memory_unmap(struct vhost_dev *dev, void *buffer,
+static void vhost_memory_unmap(struct vhost_dev *dev, void **buffer,
                                hwaddr len, int is_write,
                                hwaddr access_len)
 {
+    if (!*buffer) {
+        return;
+    }
+
     if (!vhost_dev_has_iommu(dev)) {
-        address_space_unmap(dev->vdev->dma_as, buffer, len, is_write,
+        address_space_unmap(dev->vdev->dma_as, *buffer, len, is_write,
                             access_len);
     }
+
+    *buffer = NULL;
 }
 
 static int vhost_verify_ring_part_mapping(void *ring_hva,
@@ -1324,33 +1330,33 @@ int vhost_virtqueue_start(struct vhost_dev *dev,
     vq->desc = vhost_memory_map(dev, vq->desc_phys, l, false);
     if (!vq->desc) {
         r = -ENOMEM;
-        goto fail_alloc_desc;
+        goto fail;
     }
 
     l = vq->avail_size;
     vq->avail = vhost_memory_map(dev, vq->avail_phys, l, false);
     if (!vq->avail) {
         r = -ENOMEM;
-        goto fail_alloc_avail;
+        goto fail;
     }
 
     l = vq->used_size;
     vq->used = vhost_memory_map(dev, vq->used_phys, l, true);
     if (!vq->used) {
         r = -ENOMEM;
-        goto fail_alloc_used;
+        goto fail;
     }
 
     r = vhost_virtqueue_set_addr(dev, vq, vhost_vq_index, dev->log_enabled);
     if (r < 0) {
-        goto fail_alloc;
+        goto fail;
     }
 
     file.fd = event_notifier_get_fd(virtio_queue_get_host_notifier(vvq));
     r = dev->vhost_ops->vhost_set_vring_kick(dev, &file);
     if (r) {
         VHOST_OPS_DEBUG(r, "vhost_set_vring_kick failed");
-        goto fail_kick;
+        goto fail;
     }
 
     /* Clear and discard previous events if any. */
@@ -1370,24 +1376,19 @@ int vhost_virtqueue_start(struct vhost_dev *dev,
         file.fd = -1;
         r = dev->vhost_ops->vhost_set_vring_call(dev, &file);
         if (r) {
-            goto fail_vector;
+            goto fail;
         }
     }
 
     return 0;
 
-fail_vector:
-fail_kick:
-fail_alloc:
-    vhost_memory_unmap(dev, vq->used, virtio_queue_get_used_size(vdev, idx),
+fail:
+    vhost_memory_unmap(dev, &vq->used, virtio_queue_get_used_size(vdev, idx),
                        0, 0);
-fail_alloc_used:
-    vhost_memory_unmap(dev, vq->avail, virtio_queue_get_avail_size(vdev, idx),
+    vhost_memory_unmap(dev, &vq->avail, virtio_queue_get_avail_size(vdev, idx),
                        0, 0);
-fail_alloc_avail:
-    vhost_memory_unmap(dev, vq->desc, virtio_queue_get_desc_size(vdev, idx),
+    vhost_memory_unmap(dev, &vq->desc, virtio_queue_get_desc_size(vdev, idx),
                        0, 0);
-fail_alloc_desc:
     return r;
 }
 
@@ -1434,11 +1435,11 @@ static int do_vhost_virtqueue_stop(struct vhost_dev *dev,
                                                 vhost_vq_index);
     }
 
-    vhost_memory_unmap(dev, vq->used, virtio_queue_get_used_size(vdev, idx),
+    vhost_memory_unmap(dev, &vq->used, virtio_queue_get_used_size(vdev, idx),
                        1, virtio_queue_get_used_size(vdev, idx));
-    vhost_memory_unmap(dev, vq->avail, virtio_queue_get_avail_size(vdev, idx),
+    vhost_memory_unmap(dev, &vq->avail, virtio_queue_get_avail_size(vdev, idx),
                        0, virtio_queue_get_avail_size(vdev, idx));
-    vhost_memory_unmap(dev, vq->desc, virtio_queue_get_desc_size(vdev, idx),
+    vhost_memory_unmap(dev, &vq->desc, virtio_queue_get_desc_size(vdev, idx),
                        0, virtio_queue_get_desc_size(vdev, idx));
     return r;
 }
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 038/106] vhost: simplify calls to vhost_memory_unmap()
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (36 preceding siblings ...)
  2026-06-14 19:07 ` [PULL 037/106] vhost: make vhost_memory_unmap() null-safe Michael S. Tsirkin
@ 2026-06-14 19:07 ` Michael S. Tsirkin
  2026-06-14 19:07 ` [PULL 039/106] vhost: move vrings mapping to the top of vhost_virtqueue_start() Michael S. Tsirkin
                   ` (68 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Daniil Tatianin,
	Raphael Norwitz, Lei Yang, Stefano Garzarella

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

No reason to calculate memory size again, as we have corresponding
variable for each vring.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Daniil Tatianin <d-tatianin@yandex-team.ru>
Reviewed-by: Raphael Norwitz <raphael.s.norwitz@gmail.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Tested-by: Lei Yang <leiyang@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420200339.708640-13-vsementsov@yandex-team.ru>
---
 hw/virtio/vhost.c | 18 ++++++------------
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index b9b7a984e3..f43e563f0d 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1383,12 +1383,9 @@ int vhost_virtqueue_start(struct vhost_dev *dev,
     return 0;
 
 fail:
-    vhost_memory_unmap(dev, &vq->used, virtio_queue_get_used_size(vdev, idx),
-                       0, 0);
-    vhost_memory_unmap(dev, &vq->avail, virtio_queue_get_avail_size(vdev, idx),
-                       0, 0);
-    vhost_memory_unmap(dev, &vq->desc, virtio_queue_get_desc_size(vdev, idx),
-                       0, 0);
+    vhost_memory_unmap(dev, &vq->used, vq->used_size, 0, 0);
+    vhost_memory_unmap(dev, &vq->avail, vq->avail_size, 0, 0);
+    vhost_memory_unmap(dev, &vq->desc, vq->desc_size, 0, 0);
     return r;
 }
 
@@ -1435,12 +1432,9 @@ static int do_vhost_virtqueue_stop(struct vhost_dev *dev,
                                                 vhost_vq_index);
     }
 
-    vhost_memory_unmap(dev, &vq->used, virtio_queue_get_used_size(vdev, idx),
-                       1, virtio_queue_get_used_size(vdev, idx));
-    vhost_memory_unmap(dev, &vq->avail, virtio_queue_get_avail_size(vdev, idx),
-                       0, virtio_queue_get_avail_size(vdev, idx));
-    vhost_memory_unmap(dev, &vq->desc, virtio_queue_get_desc_size(vdev, idx),
-                       0, virtio_queue_get_desc_size(vdev, idx));
+    vhost_memory_unmap(dev, &vq->used, vq->used_size, 1, vq->used_size);
+    vhost_memory_unmap(dev, &vq->avail, vq->avail_size, 0, vq->avail_size);
+    vhost_memory_unmap(dev, &vq->desc, vq->desc_size, 0, vq->desc_size);
     return r;
 }
 
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 039/106] vhost: move vrings mapping to the top of vhost_virtqueue_start()
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (37 preceding siblings ...)
  2026-06-14 19:07 ` [PULL 038/106] vhost: simplify calls to vhost_memory_unmap() Michael S. Tsirkin
@ 2026-06-14 19:07 ` Michael S. Tsirkin
  2026-06-14 19:07 ` [PULL 040/106] vhost: vhost_virtqueue_start(): drop extra local variables Michael S. Tsirkin
                   ` (67 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Raphael Norwitz,
	Daniil Tatianin, Stefano Garzarella

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

This simplifies further refactoring and final introduction
of vhost backend live migration.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Raphael Norwitz <raphael.s.norwitz@gmail.com>
Reviewed-by: Daniil Tatianin <d-tatianin@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420200339.708640-14-vsementsov@yandex-team.ru>
---
 hw/virtio/vhost.c | 45 ++++++++++++++++++++++-----------------------
 1 file changed, 22 insertions(+), 23 deletions(-)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index f43e563f0d..d5bafbcc4b 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1303,29 +1303,6 @@ int vhost_virtqueue_start(struct vhost_dev *dev,
         return 0;
     }
 
-    vq->num = state.num = virtio_queue_get_num(vdev, idx);
-    r = dev->vhost_ops->vhost_set_vring_num(dev, &state);
-    if (r) {
-        VHOST_OPS_DEBUG(r, "vhost_set_vring_num failed");
-        return r;
-    }
-
-    state.num = virtio_queue_get_last_avail_idx(vdev, idx);
-    r = dev->vhost_ops->vhost_set_vring_base(dev, &state);
-    if (r) {
-        VHOST_OPS_DEBUG(r, "vhost_set_vring_base failed");
-        return r;
-    }
-
-    if (vhost_needs_vring_endian(vdev)) {
-        r = vhost_virtqueue_set_vring_endian_legacy(dev,
-                                                    virtio_vdev_is_big_endian(vdev),
-                                                    vhost_vq_index);
-        if (r) {
-            return r;
-        }
-    }
-
     l = vq->desc_size;
     vq->desc = vhost_memory_map(dev, vq->desc_phys, l, false);
     if (!vq->desc) {
@@ -1347,6 +1324,28 @@ int vhost_virtqueue_start(struct vhost_dev *dev,
         goto fail;
     }
 
+    vq->num = state.num = virtio_queue_get_num(vdev, idx);
+    r = dev->vhost_ops->vhost_set_vring_num(dev, &state);
+    if (r) {
+        VHOST_OPS_DEBUG(r, "vhost_set_vring_num failed");
+        goto fail;
+    }
+
+    state.num = virtio_queue_get_last_avail_idx(vdev, idx);
+    r = dev->vhost_ops->vhost_set_vring_base(dev, &state);
+    if (r) {
+        VHOST_OPS_DEBUG(r, "vhost_set_vring_base failed");
+        goto fail;
+    }
+
+    if (vhost_needs_vring_endian(vdev)) {
+        r = vhost_virtqueue_set_vring_endian_legacy(
+            dev, virtio_vdev_is_big_endian(vdev), vhost_vq_index);
+        if (r) {
+            goto fail;
+        }
+    }
+
     r = vhost_virtqueue_set_addr(dev, vq, vhost_vq_index, dev->log_enabled);
     if (r < 0) {
         goto fail;
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 040/106] vhost: vhost_virtqueue_start(): drop extra local variables
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (38 preceding siblings ...)
  2026-06-14 19:07 ` [PULL 039/106] vhost: move vrings mapping to the top of vhost_virtqueue_start() Michael S. Tsirkin
@ 2026-06-14 19:07 ` Michael S. Tsirkin
  2026-06-14 19:07 ` [PULL 041/106] vhost: final refactoring of vhost vrings map/unmap Michael S. Tsirkin
                   ` (66 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Raphael Norwitz,
	Stefano Garzarella

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

One letter named variables doesn't really help to read the code,
and they simply duplicate structure fields.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Raphael Norwitz <raphael.s.norwitz@gmail.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420200339.708640-15-vsementsov@yandex-team.ru>
---
 hw/virtio/vhost.c | 13 +++----------
 1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index d5bafbcc4b..a3bf7e5a9b 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1277,7 +1277,6 @@ int vhost_virtqueue_start(struct vhost_dev *dev,
     BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
     VirtioBusState *vbus = VIRTIO_BUS(qbus);
     VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
-    hwaddr l;
     int r;
     int vhost_vq_index = dev->vhost_ops->vhost_get_vq_index(dev, idx);
     struct vhost_vring_file file = {
@@ -1302,23 +1301,17 @@ int vhost_virtqueue_start(struct vhost_dev *dev,
         /* Queue might not be ready for start */
         return 0;
     }
-
-    l = vq->desc_size;
-    vq->desc = vhost_memory_map(dev, vq->desc_phys, l, false);
+    vq->desc = vhost_memory_map(dev, vq->desc_phys, vq->desc_size, false);
     if (!vq->desc) {
         r = -ENOMEM;
         goto fail;
     }
-
-    l = vq->avail_size;
-    vq->avail = vhost_memory_map(dev, vq->avail_phys, l, false);
+    vq->avail = vhost_memory_map(dev, vq->avail_phys, vq->avail_size, false);
     if (!vq->avail) {
         r = -ENOMEM;
         goto fail;
     }
-
-    l = vq->used_size;
-    vq->used = vhost_memory_map(dev, vq->used_phys, l, true);
+    vq->used = vhost_memory_map(dev, vq->used_phys, vq->used_size, true);
     if (!vq->used) {
         r = -ENOMEM;
         goto fail;
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 041/106] vhost: final refactoring of vhost vrings map/unmap
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (39 preceding siblings ...)
  2026-06-14 19:07 ` [PULL 040/106] vhost: vhost_virtqueue_start(): drop extra local variables Michael S. Tsirkin
@ 2026-06-14 19:07 ` Michael S. Tsirkin
  2026-06-14 19:07 ` [PULL 042/106] vhost: simplify vhost_dev_init() error-path Michael S. Tsirkin
                   ` (65 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Raphael Norwitz,
	Stefano Garzarella

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

Introduce helper functions vhost_vrings_map() and
vhost_vrings_unmap() and use them.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Raphael Norwitz <raphael.s.norwitz@gmail.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420200339.708640-16-vsementsov@yandex-team.ru>
---
 hw/virtio/vhost.c | 89 +++++++++++++++++++++++++++++------------------
 1 file changed, 55 insertions(+), 34 deletions(-)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index a3bf7e5a9b..c71b18cfc8 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -489,6 +489,56 @@ static void vhost_memory_unmap(struct vhost_dev *dev, void **buffer,
     *buffer = NULL;
 }
 
+static void vhost_vrings_unmap(struct vhost_dev *dev,
+                               struct vhost_virtqueue *vq, bool touched)
+{
+    vhost_memory_unmap(dev, &vq->used, vq->used_size, touched,
+                       touched ? vq->used_size : 0);
+    vhost_memory_unmap(dev, &vq->avail, vq->avail_size, 0,
+                       touched ? vq->avail_size : 0);
+    vhost_memory_unmap(dev, &vq->desc, vq->desc_size, 0,
+                       touched ? vq->desc_size : 0);
+}
+
+static int vhost_vrings_map(struct vhost_dev *dev,
+                            struct VirtIODevice *vdev,
+                            struct vhost_virtqueue *vq,
+                            unsigned idx)
+{
+    vq->desc_size = virtio_queue_get_desc_size(vdev, idx);
+    vq->desc_phys = virtio_queue_get_desc_addr(vdev, idx);
+    vq->desc = NULL;
+    vq->avail_size = virtio_queue_get_avail_size(vdev, idx);
+    vq->avail_phys = virtio_queue_get_avail_addr(vdev, idx);
+    vq->avail = NULL;
+    vq->used_size = virtio_queue_get_used_size(vdev, idx);
+    vq->used_phys = virtio_queue_get_used_addr(vdev, idx);
+    vq->used = NULL;
+
+    if (vq->desc_phys == 0) {
+        /* Queue might not be ready for start */
+        return 0;
+    }
+    vq->desc = vhost_memory_map(dev, vq->desc_phys, vq->desc_size, false);
+    if (!vq->desc) {
+        goto fail;
+    }
+    vq->avail = vhost_memory_map(dev, vq->avail_phys, vq->avail_size, false);
+    if (!vq->avail) {
+        goto fail;
+    }
+    vq->used = vhost_memory_map(dev, vq->used_phys, vq->used_size, true);
+    if (!vq->used) {
+        goto fail;
+    }
+
+    return 1;
+
+fail:
+    vhost_vrings_unmap(dev, vq, false);
+    return -ENOMEM;
+}
+
 static int vhost_verify_ring_part_mapping(void *ring_hva,
                                           uint64_t ring_gpa,
                                           uint64_t ring_size,
@@ -1287,34 +1337,9 @@ int vhost_virtqueue_start(struct vhost_dev *dev,
     };
     struct VirtQueue *vvq = virtio_get_queue(vdev, idx);
 
-    vq->desc_size = virtio_queue_get_desc_size(vdev, idx);
-    vq->desc_phys = virtio_queue_get_desc_addr(vdev, idx);
-    vq->desc = NULL;
-    vq->avail_size = virtio_queue_get_avail_size(vdev, idx);
-    vq->avail_phys = virtio_queue_get_avail_addr(vdev, idx);
-    vq->avail = NULL;
-    vq->used_size = virtio_queue_get_used_size(vdev, idx);
-    vq->used_phys = virtio_queue_get_used_addr(vdev, idx);
-    vq->used = NULL;
-
-    if (vq->desc_phys == 0) {
-        /* Queue might not be ready for start */
-        return 0;
-    }
-    vq->desc = vhost_memory_map(dev, vq->desc_phys, vq->desc_size, false);
-    if (!vq->desc) {
-        r = -ENOMEM;
-        goto fail;
-    }
-    vq->avail = vhost_memory_map(dev, vq->avail_phys, vq->avail_size, false);
-    if (!vq->avail) {
-        r = -ENOMEM;
-        goto fail;
-    }
-    vq->used = vhost_memory_map(dev, vq->used_phys, vq->used_size, true);
-    if (!vq->used) {
-        r = -ENOMEM;
-        goto fail;
+    r = vhost_vrings_map(dev, vdev, vq, idx);
+    if (r <= 0) {
+        return r;
     }
 
     vq->num = state.num = virtio_queue_get_num(vdev, idx);
@@ -1375,9 +1400,7 @@ int vhost_virtqueue_start(struct vhost_dev *dev,
     return 0;
 
 fail:
-    vhost_memory_unmap(dev, &vq->used, vq->used_size, 0, 0);
-    vhost_memory_unmap(dev, &vq->avail, vq->avail_size, 0, 0);
-    vhost_memory_unmap(dev, &vq->desc, vq->desc_size, 0, 0);
+    vhost_vrings_unmap(dev, vq, false);
     return r;
 }
 
@@ -1424,9 +1447,7 @@ static int do_vhost_virtqueue_stop(struct vhost_dev *dev,
                                                 vhost_vq_index);
     }
 
-    vhost_memory_unmap(dev, &vq->used, vq->used_size, 1, vq->used_size);
-    vhost_memory_unmap(dev, &vq->avail, vq->avail_size, 0, vq->avail_size);
-    vhost_memory_unmap(dev, &vq->desc, vq->desc_size, 0, vq->desc_size);
+    vhost_vrings_unmap(dev, vq, true);
     return r;
 }
 
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 042/106] vhost: simplify vhost_dev_init() error-path
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (40 preceding siblings ...)
  2026-06-14 19:07 ` [PULL 041/106] vhost: final refactoring of vhost vrings map/unmap Michael S. Tsirkin
@ 2026-06-14 19:07 ` Michael S. Tsirkin
  2026-06-14 19:07 ` [PULL 043/106] vhost: move busyloop timeout initialization to vhost_virtqueue_init() Michael S. Tsirkin
                   ` (64 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Raphael Norwitz,
	Daniil Tatianin, Lei Yang, Stefano Garzarella

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

No reason to rollback setting up busyloop timeout on failure.
We don't do such rollback for other things we setup in backend.
Also, look at vhost_net_init() in hw/net/vhost_net.c: we may fail
after successfully called vhost_dev_init(), and in this case we'll
just call vhost_dev_cleanup(), which doesn't rollback busyloop
timeout.

So, let's keep it simple.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Acked-by: Raphael Norwitz <raphael.s.norwitz@gmail.com>
Reviewed-by: Daniil Tatianin <d-tatianin@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Tested-by: Lei Yang <leiyang@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420200339.708640-17-vsementsov@yandex-team.ru>
---
 hw/virtio/vhost.c | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index c71b18cfc8..7f370f393e 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1624,7 +1624,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
                                                      busyloop_timeout);
             if (r < 0) {
                 error_setg_errno(errp, -r, "Failed to set busyloop timeout");
-                goto fail_busyloop;
+                goto fail;
             }
         }
     }
@@ -1664,7 +1664,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
     if (hdev->migration_blocker != NULL) {
         r = migrate_add_blocker_normal(&hdev->migration_blocker, errp);
         if (r < 0) {
-            goto fail_busyloop;
+            goto fail;
         }
     }
 
@@ -1696,17 +1696,11 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
                    " than current number of used (%d) and reserved (%d)"
                    " memory slots for memory devices.", limit, used, reserved);
         r = -EINVAL;
-        goto fail_busyloop;
+        goto fail;
     }
 
     return 0;
 
-fail_busyloop:
-    if (busyloop_timeout) {
-        while (--i >= 0) {
-            vhost_virtqueue_set_busyloop_timeout(hdev, hdev->vq_index + i, 0);
-        }
-    }
 fail:
     hdev->nvqs = n_initialized_vqs;
     vhost_dev_cleanup(hdev);
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 043/106] vhost: move busyloop timeout initialization to vhost_virtqueue_init()
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (41 preceding siblings ...)
  2026-06-14 19:07 ` [PULL 042/106] vhost: simplify vhost_dev_init() error-path Michael S. Tsirkin
@ 2026-06-14 19:07 ` Michael S. Tsirkin
  2026-06-14 19:07 ` [PULL 044/106] vhost: vhost_dev_init(): simplify features initialization Michael S. Tsirkin
                   ` (63 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Raphael Norwitz,
	Daniil Tatianin, Lei Yang, Stefano Garzarella

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

Let's all per-virtqueue initializations be in one place.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Raphael Norwitz <raphael.s.norwitz@gmail.com>
Reviewed-by: Daniil Tatianin <d-tatianin@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Tested-by: Lei Yang <leiyang@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420200339.708640-18-vsementsov@yandex-team.ru>
---
 hw/virtio/vhost.c | 25 ++++++++++++-------------
 1 file changed, 12 insertions(+), 13 deletions(-)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 7f370f393e..55ce7ae977 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1496,7 +1496,8 @@ static void vhost_virtqueue_error_notifier(EventNotifier *n)
 }
 
 static int vhost_virtqueue_init(struct vhost_dev *dev,
-                                struct vhost_virtqueue *vq, int n)
+                                struct vhost_virtqueue *vq, int n,
+                                bool busyloop_timeout)
 {
     int vhost_vq_index = dev->vhost_ops->vhost_get_vq_index(dev, n);
     struct vhost_vring_file file = {
@@ -1533,6 +1534,14 @@ static int vhost_virtqueue_init(struct vhost_dev *dev,
                                    vhost_virtqueue_error_notifier);
     }
 
+    if (busyloop_timeout) {
+        r = vhost_virtqueue_set_busyloop_timeout(dev, n, busyloop_timeout);
+        if (r < 0) {
+            VHOST_OPS_DEBUG(r, "Failed to set busyloop timeout");
+            goto fail_err;
+        }
+    }
+
     return 0;
 
 fail_err:
@@ -1611,24 +1620,14 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
     }
 
     for (i = 0; i < hdev->nvqs; ++i, ++n_initialized_vqs) {
-        r = vhost_virtqueue_init(hdev, hdev->vqs + i, hdev->vq_index + i);
+        r = vhost_virtqueue_init(hdev, hdev->vqs + i, hdev->vq_index + i,
+                                 busyloop_timeout);
         if (r < 0) {
             error_setg_errno(errp, -r, "Failed to initialize virtqueue %d", i);
             goto fail;
         }
     }
 
-    if (busyloop_timeout) {
-        for (i = 0; i < hdev->nvqs; ++i) {
-            r = vhost_virtqueue_set_busyloop_timeout(hdev, hdev->vq_index + i,
-                                                     busyloop_timeout);
-            if (r < 0) {
-                error_setg_errno(errp, -r, "Failed to set busyloop timeout");
-                goto fail;
-            }
-        }
-    }
-
     virtio_features_copy(hdev->_features_ex, features);
 
     hdev->memory_listener = (MemoryListener) {
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 044/106] vhost: vhost_dev_init(): simplify features initialization
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (42 preceding siblings ...)
  2026-06-14 19:07 ` [PULL 043/106] vhost: move busyloop timeout initialization to vhost_virtqueue_init() Michael S. Tsirkin
@ 2026-06-14 19:07 ` Michael S. Tsirkin
  2026-06-14 19:07 ` [PULL 045/106] hw/virtio/virtio-bus: refactor virtio_bus_set_host_notifier() Michael S. Tsirkin
                   ` (62 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Daniil Tatianin,
	Raphael Norwitz, Stefano Garzarella

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

Drop extra variable and extra function parameter passing, initialize
dev._features directly.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Daniil Tatianin <d-tatianin@yandex-team.ru>
Reviewed-by: Raphael Norwitz <raphael.s.norwitz@gmail.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420200339.708640-19-vsementsov@yandex-team.ru>
---
 hw/virtio/vhost.c | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 55ce7ae977..93c6a5f5e9 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1560,18 +1560,17 @@ static void vhost_virtqueue_cleanup(struct vhost_virtqueue *vq)
     }
 }
 
-static int vhost_dev_get_features(struct vhost_dev *hdev,
-                                  uint64_t *features)
+static int vhost_dev_init_features(struct vhost_dev *hdev)
 {
     uint64_t features64;
     int r;
 
     if (hdev->vhost_ops->vhost_get_features_ex) {
-        return hdev->vhost_ops->vhost_get_features_ex(hdev, features);
+        return hdev->vhost_ops->vhost_get_features_ex(hdev, hdev->_features_ex);
     }
 
     r = hdev->vhost_ops->vhost_get_features(hdev, &features64);
-    virtio_features_from_u64(features, features64);
+    virtio_features_from_u64(hdev->_features_ex, features64);
     return r;
 }
 
@@ -1579,7 +1578,6 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
                    VhostBackendType backend_type, uint32_t busyloop_timeout,
                    Error **errp)
 {
-    uint64_t features[VIRTIO_FEATURES_NU64S];
     unsigned int used, reserved, limit;
     int i, r, n_initialized_vqs = 0;
 
@@ -1600,9 +1598,9 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
         goto fail;
     }
 
-    r = vhost_dev_get_features(hdev, features);
+    r = vhost_dev_init_features(hdev);
     if (r < 0) {
-        error_setg_errno(errp, -r, "vhost_get_features failed");
+        error_setg_errno(errp, -r, "vhost_init_features failed");
         goto fail;
     }
 
@@ -1628,8 +1626,6 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
         }
     }
 
-    virtio_features_copy(hdev->_features_ex, features);
-
     hdev->memory_listener = (MemoryListener) {
         .name = "vhost",
         .begin = vhost_begin,
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 045/106] hw/virtio/virtio-bus: refactor virtio_bus_set_host_notifier()
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (43 preceding siblings ...)
  2026-06-14 19:07 ` [PULL 044/106] vhost: vhost_dev_init(): simplify features initialization Michael S. Tsirkin
@ 2026-06-14 19:07 ` Michael S. Tsirkin
  2026-06-14 19:07 ` [PULL 046/106] vhost-user: make trace events more readable Michael S. Tsirkin
                   ` (61 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy,
	Philippe Mathieu-Daudé, Raphael Norwitz, Daniil Tatianin,
	Lei Yang

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

The logic kept as is. Refactor to simplify further changes.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Raphael Norwitz <raphael.s.norwitz@gmail.com>
Reviewed-by: Daniil Tatianin <d-tatianin@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Tested-by: Lei Yang <leiyang@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420200339.708640-20-vsementsov@yandex-team.ru>
---
 hw/virtio/virtio-bus.c | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c
index cef944e015..9b545acda3 100644
--- a/hw/virtio/virtio-bus.c
+++ b/hw/virtio/virtio-bus.c
@@ -298,20 +298,18 @@ int virtio_bus_set_host_notifier(VirtioBusState *bus, int n, bool assign)
                          __func__, strerror(-r), r);
             return r;
         }
-        r = k->ioeventfd_assign(proxy, notifier, n, true);
-        if (r < 0) {
-            error_report("%s: unable to assign ioeventfd: %d", __func__, r);
-            virtio_bus_cleanup_host_notifier(bus, n);
-        }
-    } else {
-        k->ioeventfd_assign(proxy, notifier, n, false);
     }
 
-    if (r == 0) {
-        virtio_queue_set_host_notifier_enabled(vq, assign);
+    r = k->ioeventfd_assign(proxy, notifier, n, assign);
+    if (r < 0 && assign) {
+        error_report("%s: unable to assign ioeventfd: %d", __func__, r);
+        virtio_bus_cleanup_host_notifier(bus, n);
+        return r;
     }
 
-    return r;
+    virtio_queue_set_host_notifier_enabled(vq, assign);
+
+    return 0;
 }
 
 void virtio_bus_cleanup_host_notifier(VirtioBusState *bus, int n)
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 046/106] vhost-user: make trace events more readable
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (44 preceding siblings ...)
  2026-06-14 19:07 ` [PULL 045/106] hw/virtio/virtio-bus: refactor virtio_bus_set_host_notifier() Michael S. Tsirkin
@ 2026-06-14 19:07 ` Michael S. Tsirkin
  2026-06-14 19:07 ` [PULL 047/106] vhost-user-blk: add some useful trace-points Michael S. Tsirkin
                   ` (60 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Raphael Norwitz,
	Stefano Garzarella

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Raphael Norwitz <raphael.s.norwitz@gmail.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420200339.708640-21-vsementsov@yandex-team.ru>
---
 hw/virtio/trace-events |  4 +--
 hw/virtio/vhost-user.c | 63 ++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 63 insertions(+), 4 deletions(-)

diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index 658cc365e7..aa1ffa5e94 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -25,8 +25,8 @@ vhost_user_set_mem_table_withfd(int index, const char *name, uint64_t memory_siz
 vhost_user_postcopy_waker(const char *rb, uint64_t rb_offset) "%s + 0x%"PRIx64
 vhost_user_postcopy_waker_found(uint64_t client_addr) "0x%"PRIx64
 vhost_user_postcopy_waker_nomatch(const char *rb, uint64_t rb_offset) "%s + 0x%"PRIx64
-vhost_user_read(uint32_t req, uint32_t flags) "req:%d flags:0x%"PRIx32""
-vhost_user_write(uint32_t req, uint32_t flags) "req:%d flags:0x%"PRIx32""
+vhost_user_read(uint32_t req, const char *req_name, uint32_t flags) "req:%d (%s) flags:0x%"PRIx32""
+vhost_user_write(uint32_t req, const char *req_name, uint32_t flags) "req:%d (%s) flags:0x%"PRIx32""
 vhost_user_create_notifier(int idx, void *n) "idx:%d n:%p"
 
 # vhost-vdpa.c
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 31eaf65430..4fb136b7b3 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -114,6 +114,63 @@ typedef enum VhostUserBackendRequest {
     VHOST_USER_BACKEND_MAX
 }  VhostUserBackendRequest;
 
+#define VHOST_USER_CASE(name) \
+    case VHOST_USER_##name: \
+        return #name;
+
+static const char *vhost_req_name(VhostUserRequest req)
+{
+    switch (req) {
+    VHOST_USER_CASE(NONE)
+    VHOST_USER_CASE(GET_FEATURES)
+    VHOST_USER_CASE(SET_FEATURES)
+    VHOST_USER_CASE(SET_OWNER)
+    VHOST_USER_CASE(RESET_OWNER)
+    VHOST_USER_CASE(SET_MEM_TABLE)
+    VHOST_USER_CASE(SET_LOG_BASE)
+    VHOST_USER_CASE(SET_LOG_FD)
+    VHOST_USER_CASE(SET_VRING_NUM)
+    VHOST_USER_CASE(SET_VRING_ADDR)
+    VHOST_USER_CASE(SET_VRING_BASE)
+    VHOST_USER_CASE(GET_VRING_BASE)
+    VHOST_USER_CASE(SET_VRING_KICK)
+    VHOST_USER_CASE(SET_VRING_CALL)
+    VHOST_USER_CASE(SET_VRING_ERR)
+    VHOST_USER_CASE(GET_PROTOCOL_FEATURES)
+    VHOST_USER_CASE(SET_PROTOCOL_FEATURES)
+    VHOST_USER_CASE(GET_QUEUE_NUM)
+    VHOST_USER_CASE(SET_VRING_ENABLE)
+    VHOST_USER_CASE(SEND_RARP)
+    VHOST_USER_CASE(NET_SET_MTU)
+    VHOST_USER_CASE(SET_BACKEND_REQ_FD)
+    VHOST_USER_CASE(IOTLB_MSG)
+    VHOST_USER_CASE(SET_VRING_ENDIAN)
+    VHOST_USER_CASE(GET_CONFIG)
+    VHOST_USER_CASE(SET_CONFIG)
+    VHOST_USER_CASE(CREATE_CRYPTO_SESSION)
+    VHOST_USER_CASE(CLOSE_CRYPTO_SESSION)
+    VHOST_USER_CASE(POSTCOPY_ADVISE)
+    VHOST_USER_CASE(POSTCOPY_LISTEN)
+    VHOST_USER_CASE(POSTCOPY_END)
+    VHOST_USER_CASE(GET_INFLIGHT_FD)
+    VHOST_USER_CASE(SET_INFLIGHT_FD)
+    VHOST_USER_CASE(GPU_SET_SOCKET)
+    VHOST_USER_CASE(RESET_DEVICE)
+    VHOST_USER_CASE(GET_MAX_MEM_SLOTS)
+    VHOST_USER_CASE(ADD_MEM_REG)
+    VHOST_USER_CASE(REM_MEM_REG)
+    VHOST_USER_CASE(SET_STATUS)
+    VHOST_USER_CASE(GET_STATUS)
+    VHOST_USER_CASE(GET_SHARED_OBJECT)
+    VHOST_USER_CASE(SET_DEVICE_STATE_FD)
+    VHOST_USER_CASE(CHECK_DEVICE_STATE)
+    default:
+        return "<unknown>";
+    }
+}
+
+#undef VHOST_USER_CASE
+
 typedef struct VhostUserMemoryRegion {
     uint64_t guest_phys_addr;
     uint64_t memory_size;
@@ -308,7 +365,8 @@ static int vhost_user_read_header(struct vhost_dev *dev, VhostUserMsg *msg)
         return -EPROTO;
     }
 
-    trace_vhost_user_read(msg->hdr.request, msg->hdr.flags);
+    trace_vhost_user_read(msg->hdr.request,
+                          vhost_req_name(msg->hdr.request), msg->hdr.flags);
 
     return 0;
 }
@@ -428,7 +486,8 @@ static int vhost_user_write(struct vhost_dev *dev, VhostUserMsg *msg,
         return ret < 0 ? -saved_errno : -EIO;
     }
 
-    trace_vhost_user_write(msg->hdr.request, msg->hdr.flags);
+    trace_vhost_user_write(msg->hdr.request, vhost_req_name(msg->hdr.request),
+                           msg->hdr.flags);
 
     return 0;
 }
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 047/106] vhost-user-blk: add some useful trace-points
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (45 preceding siblings ...)
  2026-06-14 19:07 ` [PULL 046/106] vhost-user: make trace events more readable Michael S. Tsirkin
@ 2026-06-14 19:07 ` Michael S. Tsirkin
  2026-06-14 19:07 ` [PULL 048/106] vhost: " Michael S. Tsirkin
                   ` (59 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Daniil Tatianin,
	Raphael Norwitz, Lei Yang, Kevin Wolf, Hanna Reitz,
	Stefano Garzarella, Raphael Norwitz, qemu-block

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Daniil Tatianin <d-tatianin@yandex-team.ru>
Reviewed-by: Raphael Norwitz <raphael.s.norwitz@gmail.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Tested-by: Lei Yang <leiyang@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420200339.708640-22-vsementsov@yandex-team.ru>
---
 hw/block/trace-events     | 10 ++++++++++
 hw/block/vhost-user-blk.c | 19 +++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/hw/block/trace-events b/hw/block/trace-events
index cc9a9f2460..dbaa5ca6cb 100644
--- a/hw/block/trace-events
+++ b/hw/block/trace-events
@@ -58,6 +58,16 @@ virtio_blk_handle_zone_mgmt(void *vdev, void *req, uint8_t op, int64_t sector, i
 virtio_blk_handle_zone_reset_all(void *vdev, void *req, int64_t sector, int64_t len) "vdev %p req %p sector 0x%" PRIx64 " cap 0x%" PRIx64 ""
 virtio_blk_handle_zone_append(void *vdev, void *req, int64_t sector) "vdev %p req %p, append sector 0x%" PRIx64 ""
 
+# vhost-user-blk.c
+vhost_user_blk_start_in(void *vdev) "vdev %p"
+vhost_user_blk_start_out(void *vdev) "vdev %p"
+vhost_user_blk_stop_in(void *vdev) "vdev %p"
+vhost_user_blk_stop_out(void *vdev) "vdev %p"
+vhost_user_blk_connect_in(void *vdev) "vdev %p"
+vhost_user_blk_connect_out(void *vdev) "vdev %p"
+vhost_user_blk_device_realize_in(void *vdev) "vdev %p"
+vhost_user_blk_device_realize_out(void *vdev) "vdev %p"
+
 # hd-geometry.c
 hd_geometry_lchs_guess(void *blk, int cyls, int heads, int secs) "blk %p LCHS %d %d %d"
 hd_geometry_guess(void *blk, uint32_t cyls, uint32_t heads, uint32_t secs, int trans) "blk %p CHS %u %u %u trans %d"
diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index 2831f3c053..530f44ab52 100644
--- a/hw/block/vhost-user-blk.c
+++ b/hw/block/vhost-user-blk.c
@@ -31,6 +31,7 @@
 #include "hw/virtio/virtio-access.h"
 #include "system/system.h"
 #include "system/runstate.h"
+#include "trace.h"
 
 static const int user_feature_bits[] = {
     VIRTIO_BLK_F_SIZE_MAX,
@@ -137,6 +138,8 @@ static int vhost_user_blk_start(VirtIODevice *vdev, Error **errp)
     VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
     int i, ret;
 
+    trace_vhost_user_blk_start_in(vdev);
+
     if (!k->set_guest_notifiers) {
         error_setg(errp, "binding does not support guest notifiers");
         return -ENOSYS;
@@ -192,6 +195,8 @@ static int vhost_user_blk_start(VirtIODevice *vdev, Error **errp)
     }
     s->started_vu = true;
 
+    trace_vhost_user_blk_start_out(vdev);
+
     return ret;
 
 err_guest_notifiers:
@@ -212,6 +217,8 @@ static int vhost_user_blk_stop(VirtIODevice *vdev)
     int ret;
     bool force_stop = false;
 
+    trace_vhost_user_blk_stop_in(vdev);
+
     if (!s->started_vu) {
         return 0;
     }
@@ -233,6 +240,9 @@ static int vhost_user_blk_stop(VirtIODevice *vdev)
     }
 
     vhost_dev_disable_notifiers(&s->dev, vdev);
+
+    trace_vhost_user_blk_stop_out(vdev);
+
     return ret;
 }
 
@@ -340,6 +350,8 @@ static int vhost_user_blk_connect(DeviceState *dev, Error **errp)
     VHostUserBlk *s = VHOST_USER_BLK(vdev);
     int ret = 0;
 
+    trace_vhost_user_blk_connect_in(vdev);
+
     if (s->connected) {
         return 0;
     }
@@ -366,6 +378,8 @@ static int vhost_user_blk_connect(DeviceState *dev, Error **errp)
         ret = vhost_user_blk_start(vdev, errp);
     }
 
+    trace_vhost_user_blk_connect_out(vdev);
+
     return ret;
 }
 
@@ -456,6 +470,8 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
     int retries;
     int i, ret;
 
+    trace_vhost_user_blk_device_realize_in(vdev);
+
     if (!s->chardev.chr) {
         error_setg(errp, "chardev is mandatory");
         return;
@@ -515,6 +531,9 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
     qemu_chr_fe_set_handlers(&s->chardev,  NULL, NULL,
                              vhost_user_blk_event, NULL, (void *)dev,
                              NULL, true);
+
+    trace_vhost_user_blk_device_realize_out(vdev);
+
     return;
 
 virtio_err:
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 048/106] vhost: add some useful trace-points
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (46 preceding siblings ...)
  2026-06-14 19:07 ` [PULL 047/106] vhost-user-blk: add some useful trace-points Michael S. Tsirkin
@ 2026-06-14 19:07 ` Michael S. Tsirkin
  2026-06-14 19:07 ` [PULL 049/106] vhost: move IOTLB functions from vhost-backend.c to vhost.c Michael S. Tsirkin
                   ` (58 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Daniil Tatianin,
	Raphael Norwitz, Stefano Garzarella

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Daniil Tatianin <d-tatianin@yandex-team.ru>
Reviewed-by: Raphael Norwitz <raphael.s.norwitz@gmail.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420200339.708640-23-vsementsov@yandex-team.ru>
---
 hw/virtio/trace-events | 12 ++++++++++--
 hw/virtio/vhost.c      | 20 ++++++++++++++++++--
 2 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index aa1ffa5e94..2a57edc21e 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -9,8 +9,16 @@ vhost_section(const char *name) "%s"
 vhost_reject_section(const char *name, int d) "%s:%d"
 vhost_iotlb_miss(void *dev, int step) "%p step %d"
 vhost_dev_cleanup(void *dev) "%p"
-vhost_dev_start(void *dev, const char *name, bool vrings) "%p:%s vrings:%d"
-vhost_dev_stop(void *dev, const char *name, bool vrings) "%p:%s vrings:%d"
+vhost_dev_start_in(void *dev, const char *name, bool vrings) "%p:%s vrings:%d"
+vhost_dev_start_out(void *dev, const char *name) "%p:%s"
+vhost_dev_stop_in(void *dev, const char *name, bool vrings) "%p:%s vrings:%d"
+vhost_dev_stop_out(void *dev, const char *name) "%p:%s"
+vhost_virtqueue_start_in(void *dev, const char *name, int idx) "%p:%s %d"
+vhost_virtqueue_start_out(void *dev, const char *name, int idx) "%p:%s %d"
+vhost_virtqueue_stop_in(void *dev, const char *name, int idx) "%p:%s %d"
+vhost_virtqueue_stop_out(void *dev, const char *name, int idx) "%p:%s %d"
+vhost_dev_init_in(void *dev) "%p"
+vhost_dev_init_out(void *dev) "%p"
 
 
 # vhost-user.c
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 93c6a5f5e9..c610007e81 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1337,6 +1337,8 @@ int vhost_virtqueue_start(struct vhost_dev *dev,
     };
     struct VirtQueue *vvq = virtio_get_queue(vdev, idx);
 
+    trace_vhost_virtqueue_start_in(dev, vdev->name, idx);
+
     r = vhost_vrings_map(dev, vdev, vq, idx);
     if (r <= 0) {
         return r;
@@ -1397,6 +1399,8 @@ int vhost_virtqueue_start(struct vhost_dev *dev,
         }
     }
 
+    trace_vhost_virtqueue_start_out(dev, vdev->name, idx);
+
     return 0;
 
 fail:
@@ -1415,6 +1419,8 @@ static int do_vhost_virtqueue_stop(struct vhost_dev *dev,
     };
     int r = 0;
 
+    trace_vhost_virtqueue_stop_in(dev, vdev->name, idx);
+
     if (virtio_queue_get_desc_addr(vdev, idx) == 0) {
         /* Don't stop the virtqueue which might have not been started */
         return 0;
@@ -1448,6 +1454,8 @@ static int do_vhost_virtqueue_stop(struct vhost_dev *dev,
     }
 
     vhost_vrings_unmap(dev, vq, true);
+
+    trace_vhost_virtqueue_stop_out(dev, vdev->name, idx);
     return r;
 }
 
@@ -1581,6 +1589,8 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
     unsigned int used, reserved, limit;
     int i, r, n_initialized_vqs = 0;
 
+    trace_vhost_dev_init_in(hdev);
+
     hdev->vdev = NULL;
     hdev->migration_blocker = NULL;
 
@@ -1694,6 +1704,8 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
         goto fail;
     }
 
+    trace_vhost_dev_init_out(hdev);
+
     return 0;
 
 fail:
@@ -2098,7 +2110,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings)
     /* should only be called after backend is connected */
     assert(hdev->vhost_ops);
 
-    trace_vhost_dev_start(hdev, vdev->name, vrings);
+    trace_vhost_dev_start_in(hdev, vdev->name, vrings);
 
     vdev->vhost_started = true;
     hdev->started = true;
@@ -2183,6 +2195,8 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings)
         }
     }
     vhost_start_config_intr(hdev);
+
+    trace_vhost_dev_start_out(hdev, vdev->name);
     return 0;
 fail_iotlb:
     if (vhost_dev_has_iommu(hdev) &&
@@ -2232,7 +2246,7 @@ static int do_vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev,
     event_notifier_cleanup(
         &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier);
 
-    trace_vhost_dev_stop(hdev, vdev->name, vrings);
+    trace_vhost_dev_stop_in(hdev, vdev->name, vrings);
 
     if (hdev->vhost_ops->vhost_dev_start) {
         hdev->vhost_ops->vhost_dev_start(hdev, false);
@@ -2262,6 +2276,8 @@ static int do_vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev,
     hdev->started = false;
     vdev->vhost_started = false;
     hdev->vdev = NULL;
+
+    trace_vhost_dev_stop_out(hdev, vdev->name);
     return rc;
 }
 
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 049/106] vhost: move IOTLB functions from vhost-backend.c to vhost.c
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (47 preceding siblings ...)
  2026-06-14 19:07 ` [PULL 048/106] vhost: " Michael S. Tsirkin
@ 2026-06-14 19:07 ` Michael S. Tsirkin
  2026-06-14 19:07 ` [PULL 050/106] vhost: use consistent naming for backend handlers Michael S. Tsirkin
                   ` (57 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Stefano Garzarella

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

Move and rename vhost_backend_update_device_iotlb(),
vhost_backend_invalidate_device_iotlb(), and
vhost_backend_handle_iotlb_msg() from vhost-backend.c to vhost.c.
vhost-backend.c is actually about vhost-kernel backend. But these
functions are shared with vhost-user, so let's move them into
generic place. Moreover, two of three functions becomes static as
they are used only in vhost.c.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Based-on: <20260206095258.894504-1-vsementsov@yandex-team.ru>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420202032.714884-2-vsementsov@yandex-team.ru>
---
 hw/virtio/vhost-backend.c         | 82 +----------------------------
 hw/virtio/vhost-user.c            |  2 +-
 hw/virtio/vhost.c                 | 85 +++++++++++++++++++++++++++++--
 include/hw/virtio/vhost-backend.h | 11 ----
 include/hw/virtio/vhost.h         |  2 +
 5 files changed, 86 insertions(+), 96 deletions(-)

diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c
index 4367db0d95..fea88afc39 100644
--- a/hw/virtio/vhost-backend.c
+++ b/hw/virtio/vhost-backend.c
@@ -298,7 +298,7 @@ static void vhost_kernel_iotlb_read(void *opaque)
                 break;
             }
 
-            vhost_backend_handle_iotlb_msg(dev, &msg.iotlb);
+            vhost_handle_iotlb_msg(dev, &msg.iotlb);
         }
     } else {
         struct vhost_msg msg;
@@ -313,7 +313,7 @@ static void vhost_kernel_iotlb_read(void *opaque)
                 break;
             }
 
-            vhost_backend_handle_iotlb_msg(dev, &msg.iotlb);
+            vhost_handle_iotlb_msg(dev, &msg.iotlb);
         }
     }
 }
@@ -392,81 +392,3 @@ const VhostOps kernel_ops = {
         .vhost_send_device_iotlb_msg = vhost_kernel_send_device_iotlb_msg,
 };
 #endif
-
-int vhost_backend_update_device_iotlb(struct vhost_dev *dev,
-                                             uint64_t iova, uint64_t uaddr,
-                                             uint64_t len,
-                                             IOMMUAccessFlags perm)
-{
-    struct vhost_iotlb_msg imsg;
-
-    imsg.iova =  iova;
-    imsg.uaddr = uaddr;
-    imsg.size = len;
-    imsg.type = VHOST_IOTLB_UPDATE;
-
-    switch (perm) {
-    case IOMMU_RO:
-        imsg.perm = VHOST_ACCESS_RO;
-        break;
-    case IOMMU_WO:
-        imsg.perm = VHOST_ACCESS_WO;
-        break;
-    case IOMMU_RW:
-        imsg.perm = VHOST_ACCESS_RW;
-        break;
-    default:
-        return -EINVAL;
-    }
-
-    if (dev->vhost_ops && dev->vhost_ops->vhost_send_device_iotlb_msg)
-        return dev->vhost_ops->vhost_send_device_iotlb_msg(dev, &imsg);
-
-    return -ENODEV;
-}
-
-int vhost_backend_invalidate_device_iotlb(struct vhost_dev *dev,
-                                                 uint64_t iova, uint64_t len)
-{
-    struct vhost_iotlb_msg imsg;
-
-    imsg.iova = iova;
-    imsg.size = len;
-    imsg.type = VHOST_IOTLB_INVALIDATE;
-
-    if (dev->vhost_ops && dev->vhost_ops->vhost_send_device_iotlb_msg)
-        return dev->vhost_ops->vhost_send_device_iotlb_msg(dev, &imsg);
-
-    return -ENODEV;
-}
-
-int vhost_backend_handle_iotlb_msg(struct vhost_dev *dev,
-                                          struct vhost_iotlb_msg *imsg)
-{
-    int ret = 0;
-
-    if (unlikely(!dev->vdev)) {
-        error_report("Unexpected IOTLB message when virtio device is stopped");
-        return -EINVAL;
-    }
-
-    switch (imsg->type) {
-    case VHOST_IOTLB_MISS:
-        ret = vhost_device_iotlb_miss(dev, imsg->iova,
-                                      imsg->perm != VHOST_ACCESS_RO);
-        break;
-    case VHOST_IOTLB_ACCESS_FAIL:
-        /* FIXME: report device iotlb error */
-        error_report("Access failure IOTLB message type not supported");
-        ret = -ENOTSUP;
-        break;
-    case VHOST_IOTLB_UPDATE:
-    case VHOST_IOTLB_INVALIDATE:
-    default:
-        error_report("Unexpected IOTLB message type");
-        ret = -EINVAL;
-        break;
-    }
-
-    return ret;
-}
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 4fb136b7b3..6978d8ee94 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -1901,7 +1901,7 @@ static gboolean backend_read(QIOChannel *ioc, GIOCondition condition,
 
     switch (hdr.request) {
     case VHOST_USER_BACKEND_IOTLB_MSG:
-        ret = vhost_backend_handle_iotlb_msg(dev, &payload.iotlb);
+        ret = vhost_handle_iotlb_msg(dev, &payload.iotlb);
         break;
     case VHOST_USER_BACKEND_CONFIG_CHANGE_MSG:
         ret = vhost_user_backend_handle_config_change(dev);
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index c610007e81..4d42f8bda4 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -916,14 +916,92 @@ static void vhost_region_addnop(MemoryListener *listener,
     vhost_region_add_section(dev, section);
 }
 
+static int vhost_update_device_iotlb(struct vhost_dev *dev,
+                                     uint64_t iova, uint64_t uaddr,
+                                     uint64_t len,
+                                     IOMMUAccessFlags perm)
+{
+    struct vhost_iotlb_msg imsg;
+
+    imsg.iova =  iova;
+    imsg.uaddr = uaddr;
+    imsg.size = len;
+    imsg.type = VHOST_IOTLB_UPDATE;
+
+    switch (perm) {
+    case IOMMU_RO:
+        imsg.perm = VHOST_ACCESS_RO;
+        break;
+    case IOMMU_WO:
+        imsg.perm = VHOST_ACCESS_WO;
+        break;
+    case IOMMU_RW:
+        imsg.perm = VHOST_ACCESS_RW;
+        break;
+    default:
+        return -EINVAL;
+    }
+
+    if (dev->vhost_ops && dev->vhost_ops->vhost_send_device_iotlb_msg) {
+        return dev->vhost_ops->vhost_send_device_iotlb_msg(dev, &imsg);
+    }
+
+    return -ENODEV;
+}
+
+static int vhost_invalidate_device_iotlb(struct vhost_dev *dev,
+                                         uint64_t iova, uint64_t len)
+{
+    struct vhost_iotlb_msg imsg;
+
+    imsg.iova = iova;
+    imsg.size = len;
+    imsg.type = VHOST_IOTLB_INVALIDATE;
+
+    if (dev->vhost_ops && dev->vhost_ops->vhost_send_device_iotlb_msg) {
+        return dev->vhost_ops->vhost_send_device_iotlb_msg(dev, &imsg);
+    }
+
+    return -ENODEV;
+}
+
+int vhost_handle_iotlb_msg(struct vhost_dev *dev, struct vhost_iotlb_msg *imsg)
+{
+    int ret = 0;
+
+    if (unlikely(!dev->vdev)) {
+        error_report("Unexpected IOTLB message when virtio device is stopped");
+        return -EINVAL;
+    }
+
+    switch (imsg->type) {
+    case VHOST_IOTLB_MISS:
+        ret = vhost_device_iotlb_miss(dev, imsg->iova,
+                                      imsg->perm != VHOST_ACCESS_RO);
+        break;
+    case VHOST_IOTLB_ACCESS_FAIL:
+        /* FIXME: report device iotlb error */
+        error_report("Access failure IOTLB message type not supported");
+        ret = -ENOTSUP;
+        break;
+    case VHOST_IOTLB_UPDATE:
+    case VHOST_IOTLB_INVALIDATE:
+    default:
+        error_report("Unexpected IOTLB message type");
+        ret = -EINVAL;
+        break;
+    }
+
+    return ret;
+}
+
 static void vhost_iommu_unmap_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb)
 {
     struct vhost_iommu *iommu = container_of(n, struct vhost_iommu, n);
     struct vhost_dev *hdev = iommu->hdev;
     hwaddr iova = iotlb->iova + iommu->iommu_offset;
 
-    if (vhost_backend_invalidate_device_iotlb(hdev, iova,
-                                              iotlb->addr_mask + 1)) {
+    if (vhost_invalidate_device_iotlb(hdev, iova, iotlb->addr_mask + 1)) {
         error_report("Fail to invalidate device iotlb");
     }
 }
@@ -1304,8 +1382,7 @@ int vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t iova, int write)
         len = MIN(iotlb.addr_mask + 1, len);
         iova = iova & ~iotlb.addr_mask;
 
-        ret = vhost_backend_update_device_iotlb(dev, iova, uaddr,
-                                                len, iotlb.perm);
+        ret = vhost_update_device_iotlb(dev, iova, uaddr, len, iotlb.perm);
         if (ret) {
             trace_vhost_iotlb_miss(dev, 4);
             error_report("Fail to update device iotlb");
diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h
index ff94fa1734..57497e197a 100644
--- a/include/hw/virtio/vhost-backend.h
+++ b/include/hw/virtio/vhost-backend.h
@@ -222,17 +222,6 @@ typedef struct VhostOps {
     vhost_check_device_state_op vhost_check_device_state;
 } VhostOps;
 
-int vhost_backend_update_device_iotlb(struct vhost_dev *dev,
-                                             uint64_t iova, uint64_t uaddr,
-                                             uint64_t len,
-                                             IOMMUAccessFlags perm);
-
-int vhost_backend_invalidate_device_iotlb(struct vhost_dev *dev,
-                                                 uint64_t iova, uint64_t len);
-
-int vhost_backend_handle_iotlb_msg(struct vhost_dev *dev,
-                                          struct vhost_iotlb_msg *imsg);
-
 int vhost_user_gpu_set_socket(struct vhost_dev *dev, int fd);
 
 int vhost_user_get_shared_object(struct vhost_dev *dev, unsigned char *uuid,
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index 54862f9b44..b292e9f0fe 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -403,6 +403,8 @@ int vhost_dev_set_inflight(struct vhost_dev *dev,
 int vhost_dev_get_inflight(struct vhost_dev *dev, uint16_t queue_size,
                            struct vhost_inflight *inflight);
 bool vhost_dev_has_iommu(struct vhost_dev *dev);
+int vhost_handle_iotlb_msg(struct vhost_dev *dev, struct vhost_iotlb_msg *imsg);
+
 
 static inline bool vhost_dev_has_feature(struct vhost_dev *dev,
                                          uint64_t feature)
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 050/106] vhost: use consistent naming for backend handlers
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (48 preceding siblings ...)
  2026-06-14 19:07 ` [PULL 049/106] vhost: move IOTLB functions from vhost-backend.c to vhost.c Michael S. Tsirkin
@ 2026-06-14 19:07 ` Michael S. Tsirkin
  2026-06-14 19:07 ` [PULL 051/106] vhost: rename vhost-backend.c to vhost-kernel.c Michael S. Tsirkin
                   ` (56 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Stefano Garzarella

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

Most of handlers start from simply .vhost_, except for these
four, starting from .vhost_backend_. Let's rename them to be
consistent.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Based-on: <20260206095258.894504-1-vsementsov@yandex-team.ru>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420202032.714884-3-vsementsov@yandex-team.ru>
---
 hw/virtio/vhost-backend.c         |  6 +++---
 hw/virtio/vhost-user.c            |  8 ++++----
 hw/virtio/vhost-vdpa.c            |  6 +++---
 hw/virtio/vhost.c                 | 14 +++++++-------
 include/hw/virtio/vhost-backend.h | 17 ++++++++---------
 5 files changed, 25 insertions(+), 26 deletions(-)

diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c
index fea88afc39..caeadd069b 100644
--- a/hw/virtio/vhost-backend.c
+++ b/hw/virtio/vhost-backend.c
@@ -358,9 +358,9 @@ static void vhost_kernel_set_iotlb_callback(struct vhost_dev *dev,
 
 const VhostOps kernel_ops = {
         .backend_type = VHOST_BACKEND_TYPE_KERNEL,
-        .vhost_backend_init = vhost_kernel_init,
-        .vhost_backend_cleanup = vhost_kernel_cleanup,
-        .vhost_backend_memslots_limit = vhost_kernel_memslots_limit,
+        .vhost_init = vhost_kernel_init,
+        .vhost_cleanup = vhost_kernel_cleanup,
+        .vhost_memslots_limit = vhost_kernel_memslots_limit,
         .vhost_net_set_backend = vhost_kernel_net_set_backend,
         .vhost_scsi_set_endpoint = vhost_kernel_scsi_set_endpoint,
         .vhost_scsi_clear_endpoint = vhost_kernel_scsi_clear_endpoint,
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 6978d8ee94..78ffb25d6b 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -3115,10 +3115,10 @@ void vhost_user_qmp_status(struct vhost_dev *dev, VirtioStatus *status)
 
 const VhostOps user_ops = {
         .backend_type = VHOST_BACKEND_TYPE_USER,
-        .vhost_backend_init = vhost_user_backend_init,
-        .vhost_backend_cleanup = vhost_user_backend_cleanup,
-        .vhost_backend_memslots_limit = vhost_user_memslots_limit,
-        .vhost_backend_no_private_memslots = vhost_user_no_private_memslots,
+        .vhost_init = vhost_user_backend_init,
+        .vhost_cleanup = vhost_user_backend_cleanup,
+        .vhost_memslots_limit = vhost_user_memslots_limit,
+        .vhost_no_private_memslots = vhost_user_no_private_memslots,
         .vhost_set_log_base = vhost_user_set_log_base,
         .vhost_set_mem_table = vhost_user_set_mem_table,
         .vhost_set_vring_addr = vhost_user_set_vring_addr,
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index 9c7634e243..9347462489 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -1590,8 +1590,8 @@ static bool  vhost_vdpa_force_iommu(struct vhost_dev *dev)
 
 const VhostOps vdpa_ops = {
         .backend_type = VHOST_BACKEND_TYPE_VDPA,
-        .vhost_backend_init = vhost_vdpa_init,
-        .vhost_backend_cleanup = vhost_vdpa_cleanup,
+        .vhost_init = vhost_vdpa_init,
+        .vhost_cleanup = vhost_vdpa_cleanup,
         .vhost_set_log_base = vhost_vdpa_set_log_base,
         .vhost_set_vring_addr = vhost_vdpa_set_vring_addr,
         .vhost_set_vring_num = vhost_vdpa_set_vring_num,
@@ -1602,7 +1602,7 @@ const VhostOps vdpa_ops = {
         .vhost_get_features = vhost_vdpa_get_features,
         .vhost_set_owner = vhost_vdpa_set_owner,
         .vhost_set_vring_endian = NULL,
-        .vhost_backend_memslots_limit = vhost_vdpa_memslots_limit,
+        .vhost_memslots_limit = vhost_vdpa_memslots_limit,
         .vhost_set_mem_table = vhost_vdpa_set_mem_table,
         .vhost_set_features = vhost_vdpa_set_features,
         .vhost_reset_device = vhost_vdpa_reset_device,
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 4d42f8bda4..ffd7d404cc 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -58,7 +58,7 @@ unsigned int vhost_get_max_memslots(void)
     struct vhost_dev *hdev;
 
     QLIST_FOREACH(hdev, &vhost_devices, entry) {
-        max = MIN(max, hdev->vhost_ops->vhost_backend_memslots_limit(hdev));
+        max = MIN(max, hdev->vhost_ops->vhost_memslots_limit(hdev));
     }
     return max;
 }
@@ -69,7 +69,7 @@ unsigned int vhost_get_free_memslots(void)
     struct vhost_dev *hdev;
 
     QLIST_FOREACH(hdev, &vhost_devices, entry) {
-        unsigned int r = hdev->vhost_ops->vhost_backend_memslots_limit(hdev);
+        unsigned int r = hdev->vhost_ops->vhost_memslots_limit(hdev);
         unsigned int cur_free = r - hdev->mem->nregions;
 
         if (unlikely(r < hdev->mem->nregions)) {
@@ -664,8 +664,8 @@ static bool vhost_section(struct vhost_dev *dev, MemoryRegionSection *section)
          */
         if ((memory_region_get_fd(section->mr) < 0 ||
             !qemu_ram_is_shared(section->mr->ram_block)) &&
-            dev->vhost_ops->vhost_backend_no_private_memslots &&
-            dev->vhost_ops->vhost_backend_no_private_memslots(dev)) {
+            dev->vhost_ops->vhost_no_private_memslots &&
+            dev->vhost_ops->vhost_no_private_memslots(dev)) {
             trace_vhost_reject_section(mr->name, 2);
             return false;
         }
@@ -1674,7 +1674,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
     r = vhost_set_backend_type(hdev, backend_type);
     assert(r >= 0);
 
-    r = hdev->vhost_ops->vhost_backend_init(hdev, opaque, errp);
+    r = hdev->vhost_ops->vhost_init(hdev, opaque, errp);
     if (r < 0) {
         goto fail;
     }
@@ -1691,7 +1691,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
         goto fail;
     }
 
-    limit = hdev->vhost_ops->vhost_backend_memslots_limit(hdev);
+    limit = hdev->vhost_ops->vhost_memslots_limit(hdev);
     if (limit < MEMORY_DEVICES_SAFE_MAX_MEMSLOTS &&
         memory_devices_memslot_auto_decision_active()) {
         error_setg(errp, "some memory device (like virtio-mem)"
@@ -1809,7 +1809,7 @@ void vhost_dev_cleanup(struct vhost_dev *hdev)
     g_free(hdev->mem);
     g_free(hdev->mem_sections);
     if (hdev->vhost_ops) {
-        hdev->vhost_ops->vhost_backend_cleanup(hdev);
+        hdev->vhost_ops->vhost_cleanup(hdev);
     }
     assert(!hdev->log);
 
diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h
index 57497e197a..aab6bf3ef7 100644
--- a/include/hw/virtio/vhost-backend.h
+++ b/include/hw/virtio/vhost-backend.h
@@ -51,10 +51,9 @@ struct vhost_scsi_target;
 struct vhost_iotlb_msg;
 struct vhost_virtqueue;
 
-typedef int (*vhost_backend_init)(struct vhost_dev *dev, void *opaque,
-                                  Error **errp);
-typedef int (*vhost_backend_cleanup)(struct vhost_dev *dev);
-typedef int (*vhost_backend_memslots_limit)(struct vhost_dev *dev);
+typedef int (*vhost_init)(struct vhost_dev *dev, void *opaque, Error **errp);
+typedef int (*vhost_cleanup)(struct vhost_dev *dev);
+typedef int (*vhost_memslots_limit)(struct vhost_dev *dev);
 
 typedef int (*vhost_net_set_backend_op)(struct vhost_dev *dev,
                                 struct vhost_vring_file *file);
@@ -131,7 +130,7 @@ typedef int (*vhost_crypto_create_session_op)(struct vhost_dev *dev,
 typedef int (*vhost_crypto_close_session_op)(struct vhost_dev *dev,
                                              uint64_t session_id);
 
-typedef bool (*vhost_backend_no_private_memslots_op)(struct vhost_dev *dev);
+typedef bool (*vhost_no_private_memslots_op)(struct vhost_dev *dev);
 
 typedef int (*vhost_get_inflight_fd_op)(struct vhost_dev *dev,
                                         uint16_t queue_size,
@@ -166,10 +165,10 @@ typedef int (*vhost_check_device_state_op)(struct vhost_dev *dev, Error **errp);
 
 typedef struct VhostOps {
     VhostBackendType backend_type;
-    vhost_backend_init vhost_backend_init;
-    vhost_backend_cleanup vhost_backend_cleanup;
-    vhost_backend_memslots_limit vhost_backend_memslots_limit;
-    vhost_backend_no_private_memslots_op vhost_backend_no_private_memslots;
+    vhost_init vhost_init;
+    vhost_cleanup vhost_cleanup;
+    vhost_memslots_limit vhost_memslots_limit;
+    vhost_no_private_memslots_op vhost_no_private_memslots;
     vhost_net_set_backend_op vhost_net_set_backend;
     vhost_net_set_mtu_op vhost_net_set_mtu;
     vhost_scsi_set_endpoint_op vhost_scsi_set_endpoint;
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 051/106] vhost: rename vhost-backend.c to vhost-kernel.c
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (49 preceding siblings ...)
  2026-06-14 19:07 ` [PULL 050/106] vhost: use consistent naming for backend handlers Michael S. Tsirkin
@ 2026-06-14 19:07 ` Michael S. Tsirkin
  2026-06-14 19:07 ` [PULL 052/106] vhost: replace .vhost_vq_get_addr() with .vhost_phys_vring_addr() Michael S. Tsirkin
                   ` (55 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Stefano Garzarella

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

This file is totally about vhost-kernel implementation, not generic
code. Let's finally give it corresponding name.

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: <20260420202032.714884-4-vsementsov@yandex-team.ru>
---
 hw/virtio/meson.build                         | 2 +-
 hw/virtio/{vhost-backend.c => vhost-kernel.c} | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
 rename hw/virtio/{vhost-backend.c => vhost-kernel.c} (99%)

diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
index 0ea89d8af4..3943e0d006 100644
--- a/hw/virtio/meson.build
+++ b/hw/virtio/meson.build
@@ -14,7 +14,7 @@ system_virtio_ss.add(files('virtio-qmp.c'))
 
 if have_vhost
   system_virtio_ss.add(files('vhost.c'))
-  system_virtio_ss.add(files('vhost-backend.c', 'vhost-iova-tree.c'))
+  system_virtio_ss.add(files('vhost-kernel.c', 'vhost-iova-tree.c'))
   if have_vhost_user
     system_virtio_ss.add(files('vhost-user.c'))
     system_virtio_ss.add(files('vhost-user-base.c'))
diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-kernel.c
similarity index 99%
rename from hw/virtio/vhost-backend.c
rename to hw/virtio/vhost-kernel.c
index caeadd069b..3390b48c6f 100644
--- a/hw/virtio/vhost-backend.c
+++ b/hw/virtio/vhost-kernel.c
@@ -1,5 +1,5 @@
 /*
- * vhost-backend
+ * vhost-kernel
  *
  * Copyright (c) 2013 Virtual Open Systems Sarl.
  *
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 052/106] vhost: replace .vhost_vq_get_addr() with .vhost_phys_vring_addr()
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (50 preceding siblings ...)
  2026-06-14 19:07 ` [PULL 051/106] vhost: rename vhost-backend.c to vhost-kernel.c Michael S. Tsirkin
@ 2026-06-14 19:07 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 053/106] vhost: simplify vhost_memory_map() and vhost_memory_unmap() Michael S. Tsirkin
                   ` (54 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Stefano Garzarella

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

Make a simper handler to consolidate the logic in one place. That
helps further changes.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Based-on: <20260206095258.894504-1-vsementsov@yandex-team.ru>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420202032.714884-5-vsementsov@yandex-team.ru>
---
 hw/virtio/vhost-vdpa.c            | 13 +++----------
 hw/virtio/vhost.c                 | 12 ++++++------
 include/hw/virtio/vhost-backend.h |  6 ++----
 3 files changed, 11 insertions(+), 20 deletions(-)

diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index 9347462489..9e1aa4860a 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -1571,16 +1571,9 @@ static int vhost_vdpa_set_owner(struct vhost_dev *dev)
     return 0;
 }
 
-static int vhost_vdpa_vq_get_addr(struct vhost_dev *dev,
-                    struct vhost_vring_addr *addr, struct vhost_virtqueue *vq)
+static bool vhost_vdpa_phys_vring_addr(struct vhost_dev *dev)
 {
-    assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA);
-    addr->desc_user_addr = (uint64_t)(unsigned long)vq->desc_phys;
-    addr->avail_user_addr = (uint64_t)(unsigned long)vq->avail_phys;
-    addr->used_user_addr = (uint64_t)(unsigned long)vq->used_phys;
-    trace_vhost_vdpa_vq_get_addr(dev, vq, addr->desc_user_addr,
-                                 addr->avail_user_addr, addr->used_user_addr);
-    return 0;
+    return true;
 }
 
 static bool  vhost_vdpa_force_iommu(struct vhost_dev *dev)
@@ -1617,7 +1610,7 @@ const VhostOps vdpa_ops = {
         .vhost_send_device_iotlb_msg = NULL,
         .vhost_dev_start = vhost_vdpa_dev_start,
         .vhost_get_device_id = vhost_vdpa_get_device_id,
-        .vhost_vq_get_addr = vhost_vdpa_vq_get_addr,
+        .vhost_phys_vring_addr = vhost_vdpa_phys_vring_addr,
         .vhost_force_iommu = vhost_vdpa_force_iommu,
         .vhost_set_config_call = vhost_vdpa_set_config_call,
         .vhost_reset_status = vhost_vdpa_reset_status,
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index ffd7d404cc..564a5d4698 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1093,16 +1093,16 @@ static int vhost_virtqueue_set_addr(struct vhost_dev *dev,
                                     struct vhost_virtqueue *vq,
                                     unsigned idx, bool enable_log)
 {
+    bool phys = dev->vhost_ops->vhost_phys_vring_addr &&
+        dev->vhost_ops->vhost_phys_vring_addr(dev);
     struct vhost_vring_addr addr;
     int r;
     memset(&addr, 0, sizeof(struct vhost_vring_addr));
 
-    if (dev->vhost_ops->vhost_vq_get_addr) {
-        r = dev->vhost_ops->vhost_vq_get_addr(dev, &addr, vq);
-        if (r < 0) {
-            VHOST_OPS_DEBUG(r, "vhost_vq_get_addr failed");
-            return r;
-        }
+    if (phys) {
+        addr.desc_user_addr = (uint64_t)(unsigned long)vq->desc_phys;
+        addr.avail_user_addr = (uint64_t)(unsigned long)vq->avail_phys;
+        addr.used_user_addr = (uint64_t)(unsigned long)vq->used_phys;
     } else {
         addr.desc_user_addr = (uint64_t)(unsigned long)vq->desc;
         addr.avail_user_addr = (uint64_t)(unsigned long)vq->avail;
diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h
index aab6bf3ef7..7cc3bb5441 100644
--- a/include/hw/virtio/vhost-backend.h
+++ b/include/hw/virtio/vhost-backend.h
@@ -141,9 +141,7 @@ typedef int (*vhost_set_inflight_fd_op)(struct vhost_dev *dev,
 
 typedef int (*vhost_dev_start_op)(struct vhost_dev *dev, bool started);
 
-typedef int (*vhost_vq_get_addr_op)(struct vhost_dev *dev,
-                    struct vhost_vring_addr *addr,
-                    struct vhost_virtqueue *vq);
+typedef bool (*vhost_phys_vring_addr_op)(struct vhost_dev *dev);
 
 typedef int (*vhost_get_device_id_op)(struct vhost_dev *dev, uint32_t *dev_id);
 
@@ -211,7 +209,7 @@ typedef struct VhostOps {
     vhost_get_inflight_fd_op vhost_get_inflight_fd;
     vhost_set_inflight_fd_op vhost_set_inflight_fd;
     vhost_dev_start_op vhost_dev_start;
-    vhost_vq_get_addr_op  vhost_vq_get_addr;
+    vhost_phys_vring_addr_op vhost_phys_vring_addr;
     vhost_get_device_id_op vhost_get_device_id;
     vhost_force_iommu_op vhost_force_iommu;
     vhost_set_config_call_op vhost_set_config_call;
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 053/106] vhost: simplify vhost_memory_map() and vhost_memory_unmap()
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (51 preceding siblings ...)
  2026-06-14 19:07 ` [PULL 052/106] vhost: replace .vhost_vq_get_addr() with .vhost_phys_vring_addr() Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 054/106] qapi: remove user addresses from x-query-virtio-vhost-queue-status Michael S. Tsirkin
                   ` (53 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Stefano Garzarella

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

Make these functions simple wrappers around address_space_map() and
address_space_unmap(). Move IOMMU handling logic one layer up to the
callers.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Based-on: <20260206095258.894504-1-vsementsov@yandex-team.ru>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420202032.714884-6-vsementsov@yandex-team.ru>
---
 hw/virtio/vhost.c | 43 ++++++++++++++++++++++++-------------------
 1 file changed, 24 insertions(+), 19 deletions(-)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 564a5d4698..cc083572f4 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -456,21 +456,17 @@ static inline void vhost_dev_log_resize(struct vhost_dev *dev, uint64_t size)
 static void *vhost_memory_map(struct vhost_dev *dev, hwaddr addr,
                               hwaddr len, bool is_write)
 {
-    if (!vhost_dev_has_iommu(dev)) {
-        hwaddr mapped_len = len;
-        void *res = address_space_map(dev->vdev->dma_as, addr, &mapped_len,
-                                      is_write, MEMTXATTRS_UNSPECIFIED);
-        if (!res) {
-            return NULL;
-        }
-        if (len != mapped_len) {
-            address_space_unmap(dev->vdev->dma_as, res, mapped_len, 0, 0);
-            return NULL;
-        }
-        return res;
-    } else {
-        return (void *)(uintptr_t)addr;
+    hwaddr mapped_len = len;
+    void *res = address_space_map(dev->vdev->dma_as, addr, &mapped_len,
+                                  is_write, MEMTXATTRS_UNSPECIFIED);
+    if (!res) {
+        return NULL;
     }
+    if (len != mapped_len) {
+        address_space_unmap(dev->vdev->dma_as, res, mapped_len, 0, 0);
+        return NULL;
+    }
+    return res;
 }
 
 static void vhost_memory_unmap(struct vhost_dev *dev, void **buffer,
@@ -481,17 +477,18 @@ static void vhost_memory_unmap(struct vhost_dev *dev, void **buffer,
         return;
     }
 
-    if (!vhost_dev_has_iommu(dev)) {
-        address_space_unmap(dev->vdev->dma_as, *buffer, len, is_write,
-                            access_len);
-    }
-
+    address_space_unmap(dev->vdev->dma_as, *buffer, len, is_write,
+                        access_len);
     *buffer = NULL;
 }
 
 static void vhost_vrings_unmap(struct vhost_dev *dev,
                                struct vhost_virtqueue *vq, bool touched)
 {
+    if (vhost_dev_has_iommu(dev)) {
+        return;
+    }
+
     vhost_memory_unmap(dev, &vq->used, vq->used_size, touched,
                        touched ? vq->used_size : 0);
     vhost_memory_unmap(dev, &vq->avail, vq->avail_size, 0,
@@ -519,6 +516,14 @@ static int vhost_vrings_map(struct vhost_dev *dev,
         /* Queue might not be ready for start */
         return 0;
     }
+
+    if (vhost_dev_has_iommu(dev)) {
+        vq->desc = (void *)(uintptr_t)vq->desc_phys;
+        vq->avail = (void *)(uintptr_t)vq->avail_phys;
+        vq->used = (void *)(uintptr_t)vq->used_phys;
+        return 1;
+    }
+
     vq->desc = vhost_memory_map(dev, vq->desc_phys, vq->desc_size, false);
     if (!vq->desc) {
         goto fail;
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 054/106] qapi: remove user addresses from x-query-virtio-vhost-queue-status
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (52 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 053/106] vhost: simplify vhost_memory_map() and vhost_memory_unmap() Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 055/106] vhost: stop reusing vq->desc (and friends) to store physical address Michael S. Tsirkin
                   ` (52 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Markus Armbruster,
	Eric Blake

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

Semantics of these (actually, internal) fields is not simple, they may
contain either virtual or physical addresses. We are going to change
this to simplify the logic. Keeping this logic only for unstable
info command seems too much. Changing semantics of info fields doesn't
seem to make real sense too. So, let's just drop them. We can dot it,
as command is experimental.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Acked-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Based-on: <20260206095258.894504-1-vsementsov@yandex-team.ru>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420202032.714884-7-vsementsov@yandex-team.ru>
---
 hw/virtio/virtio-hmp-cmds.c |  3 ---
 hw/virtio/virtio-qmp.c      |  3 ---
 qapi/virtio.json            | 15 ---------------
 3 files changed, 21 deletions(-)

diff --git a/hw/virtio/virtio-hmp-cmds.c b/hw/virtio/virtio-hmp-cmds.c
index 4bf9a3109d..a91bb7dbed 100644
--- a/hw/virtio/virtio-hmp-cmds.c
+++ b/hw/virtio/virtio-hmp-cmds.c
@@ -203,15 +203,12 @@ void hmp_vhost_queue_status(Monitor *mon, const QDict *qdict)
     monitor_printf(mon, "  call:                 %"PRId64"\n", s->call);
     monitor_printf(mon, "  VRing:\n");
     monitor_printf(mon, "    num:         %"PRId64"\n", s->num);
-    monitor_printf(mon, "    desc:        0x%016"PRIx64"\n", s->desc);
     monitor_printf(mon, "    desc_phys:   0x%016"PRIx64"\n",
                    s->desc_phys);
     monitor_printf(mon, "    desc_size:   %"PRId32"\n", s->desc_size);
-    monitor_printf(mon, "    avail:       0x%016"PRIx64"\n", s->avail);
     monitor_printf(mon, "    avail_phys:  0x%016"PRIx64"\n",
                    s->avail_phys);
     monitor_printf(mon, "    avail_size:  %"PRId32"\n", s->avail_size);
-    monitor_printf(mon, "    used:        0x%016"PRIx64"\n", s->used);
     monitor_printf(mon, "    used_phys:   0x%016"PRIx64"\n",
                    s->used_phys);
     monitor_printf(mon, "    used_size:   %"PRId32"\n", s->used_size);
diff --git a/hw/virtio/virtio-qmp.c b/hw/virtio/virtio-qmp.c
index 51e3a42c4c..ae9be0a00f 100644
--- a/hw/virtio/virtio-qmp.c
+++ b/hw/virtio/virtio-qmp.c
@@ -794,9 +794,6 @@ VirtVhostQueueStatus *qmp_x_query_virtio_vhost_queue_status(const char *path,
     status->name = g_strdup(vdev->name);
     status->kick = hdev->vqs[queue].kick;
     status->call = hdev->vqs[queue].call;
-    status->desc = (uintptr_t)hdev->vqs[queue].desc;
-    status->avail = (uintptr_t)hdev->vqs[queue].avail;
-    status->used = (uintptr_t)hdev->vqs[queue].used;
     status->num = hdev->vqs[queue].num;
     status->desc_phys = hdev->vqs[queue].desc_phys;
     status->desc_size = hdev->vqs[queue].desc_size;
diff --git a/qapi/virtio.json b/qapi/virtio.json
index 671f1ad793..1fc4e38a44 100644
--- a/qapi/virtio.json
+++ b/qapi/virtio.json
@@ -650,12 +650,6 @@
 #
 # @call: vhost_virtqueue call
 #
-# @desc: vhost_virtqueue desc
-#
-# @avail: vhost_virtqueue avail
-#
-# @used: vhost_virtqueue used
-#
 # @num: vhost_virtqueue num
 #
 # @desc-phys: vhost_virtqueue desc_phys (descriptor area physical
@@ -678,9 +672,6 @@
   'data': { 'name': 'str',
             'kick': 'int',
             'call': 'int',
-            'desc': 'uint64',
-            'avail': 'uint64',
-            'used': 'uint64',
             'num': 'int',
             'desc-phys': 'uint64',
             'desc-size': 'uint32',
@@ -720,12 +711,9 @@
 #              "avail-size": 2054,
 #              "desc-size": 16384,
 #              "used-size": 8198,
-#              "desc": 140141447430144,
 #              "num": 1024,
 #              "call": 0,
-#              "avail": 140141447446528,
 #              "desc-phys": 5216108544,
-#              "used": 140141447448640,
 #              "kick": 0
 #          }
 #        }
@@ -744,12 +732,9 @@
 #              "avail-size": 262,
 #              "desc-size": 2048,
 #              "used-size": 1030,
-#              "desc": 140141413580800,
 #              "num": 128,
 #              "call": 0,
-#              "avail": 140141413582848,
 #              "desc-phys": 5182259200,
-#              "used": 140141413583168,
 #              "kick": 0
 #          }
 #        }
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 055/106] vhost: stop reusing vq->desc (and friends) to store physical address
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (53 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 054/106] qapi: remove user addresses from x-query-virtio-vhost-queue-status Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 056/106] vhost: rename vring pointer fields to reflect user addresses Michael S. Tsirkin
                   ` (51 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Stefano Garzarella

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

Remove the hack of storing physical addresses in vq->desc/avail/used
pointers when IOMMU is present. Instead, handle this case directly in
vhost_virtqueue_set_addr() by checking for IOMMU presence.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Based-on: <20260206095258.894504-1-vsementsov@yandex-team.ru>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420202032.714884-8-vsementsov@yandex-team.ru>
---
 hw/virtio/vhost.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index cc083572f4..6bb6b07e19 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -518,9 +518,6 @@ static int vhost_vrings_map(struct vhost_dev *dev,
     }
 
     if (vhost_dev_has_iommu(dev)) {
-        vq->desc = (void *)(uintptr_t)vq->desc_phys;
-        vq->avail = (void *)(uintptr_t)vq->avail_phys;
-        vq->used = (void *)(uintptr_t)vq->used_phys;
         return 1;
     }
 
@@ -1104,7 +1101,7 @@ static int vhost_virtqueue_set_addr(struct vhost_dev *dev,
     int r;
     memset(&addr, 0, sizeof(struct vhost_vring_addr));
 
-    if (phys) {
+    if (phys || vhost_dev_has_iommu(dev)) {
         addr.desc_user_addr = (uint64_t)(unsigned long)vq->desc_phys;
         addr.avail_user_addr = (uint64_t)(unsigned long)vq->avail_phys;
         addr.used_user_addr = (uint64_t)(unsigned long)vq->used_phys;
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 056/106] vhost: rename vring pointer fields to reflect user addresses
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (54 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 055/106] vhost: stop reusing vq->desc (and friends) to store physical address Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 057/106] vhost: add .vhost_phys_iotlb_msg() handler Michael S. Tsirkin
                   ` (50 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Stefano Garzarella

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

Rename vq->desc/avail/used to vq->desc_user/avail_user/used_user to
clearly indicate these fields contain user space addresses, not
physical addresses.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Based-on: <20260206095258.894504-1-vsementsov@yandex-team.ru>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420202032.714884-9-vsementsov@yandex-team.ru>
---
 hw/virtio/vhost.c         | 37 +++++++++++++++++++------------------
 include/hw/virtio/vhost.h |  6 +++---
 2 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 6bb6b07e19..e3d452a763 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -489,11 +489,11 @@ static void vhost_vrings_unmap(struct vhost_dev *dev,
         return;
     }
 
-    vhost_memory_unmap(dev, &vq->used, vq->used_size, touched,
+    vhost_memory_unmap(dev, &vq->used_user, vq->used_size, touched,
                        touched ? vq->used_size : 0);
-    vhost_memory_unmap(dev, &vq->avail, vq->avail_size, 0,
+    vhost_memory_unmap(dev, &vq->avail_user, vq->avail_size, 0,
                        touched ? vq->avail_size : 0);
-    vhost_memory_unmap(dev, &vq->desc, vq->desc_size, 0,
+    vhost_memory_unmap(dev, &vq->desc_user, vq->desc_size, 0,
                        touched ? vq->desc_size : 0);
 }
 
@@ -504,13 +504,13 @@ static int vhost_vrings_map(struct vhost_dev *dev,
 {
     vq->desc_size = virtio_queue_get_desc_size(vdev, idx);
     vq->desc_phys = virtio_queue_get_desc_addr(vdev, idx);
-    vq->desc = NULL;
+    vq->desc_user = NULL;
     vq->avail_size = virtio_queue_get_avail_size(vdev, idx);
     vq->avail_phys = virtio_queue_get_avail_addr(vdev, idx);
-    vq->avail = NULL;
+    vq->avail_user = NULL;
     vq->used_size = virtio_queue_get_used_size(vdev, idx);
     vq->used_phys = virtio_queue_get_used_addr(vdev, idx);
-    vq->used = NULL;
+    vq->used_user = NULL;
 
     if (vq->desc_phys == 0) {
         /* Queue might not be ready for start */
@@ -521,16 +521,17 @@ static int vhost_vrings_map(struct vhost_dev *dev,
         return 1;
     }
 
-    vq->desc = vhost_memory_map(dev, vq->desc_phys, vq->desc_size, false);
-    if (!vq->desc) {
+    vq->desc_user = vhost_memory_map(dev, vq->desc_phys, vq->desc_size, false);
+    if (!vq->desc_user) {
         goto fail;
     }
-    vq->avail = vhost_memory_map(dev, vq->avail_phys, vq->avail_size, false);
-    if (!vq->avail) {
+    vq->avail_user = vhost_memory_map(dev, vq->avail_phys, vq->avail_size,
+                                      false);
+    if (!vq->avail_user) {
         goto fail;
     }
-    vq->used = vhost_memory_map(dev, vq->used_phys, vq->used_size, true);
-    if (!vq->used) {
+    vq->used_user = vhost_memory_map(dev, vq->used_phys, vq->used_size, true);
+    if (!vq->used_user) {
         goto fail;
     }
 
@@ -594,7 +595,7 @@ static int vhost_verify_ring_mappings(struct vhost_dev *dev,
 
         j = 0;
         r = vhost_verify_ring_part_mapping(
-                vq->desc, vq->desc_phys, vq->desc_size,
+                vq->desc_user, vq->desc_phys, vq->desc_size,
                 reg_hva, reg_gpa, reg_size);
         if (r) {
             break;
@@ -602,7 +603,7 @@ static int vhost_verify_ring_mappings(struct vhost_dev *dev,
 
         j++;
         r = vhost_verify_ring_part_mapping(
-                vq->avail, vq->avail_phys, vq->avail_size,
+                vq->avail_user, vq->avail_phys, vq->avail_size,
                 reg_hva, reg_gpa, reg_size);
         if (r) {
             break;
@@ -610,7 +611,7 @@ static int vhost_verify_ring_mappings(struct vhost_dev *dev,
 
         j++;
         r = vhost_verify_ring_part_mapping(
-                vq->used, vq->used_phys, vq->used_size,
+                vq->used_user, vq->used_phys, vq->used_size,
                 reg_hva, reg_gpa, reg_size);
         if (r) {
             break;
@@ -1106,9 +1107,9 @@ static int vhost_virtqueue_set_addr(struct vhost_dev *dev,
         addr.avail_user_addr = (uint64_t)(unsigned long)vq->avail_phys;
         addr.used_user_addr = (uint64_t)(unsigned long)vq->used_phys;
     } else {
-        addr.desc_user_addr = (uint64_t)(unsigned long)vq->desc;
-        addr.avail_user_addr = (uint64_t)(unsigned long)vq->avail;
-        addr.used_user_addr = (uint64_t)(unsigned long)vq->used;
+        addr.desc_user_addr = (uint64_t)(unsigned long)vq->desc_user;
+        addr.avail_user_addr = (uint64_t)(unsigned long)vq->avail_user;
+        addr.used_user_addr = (uint64_t)(unsigned long)vq->used_user;
     }
     addr.index = idx;
     addr.log_guest_addr = vq->used_phys;
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index b292e9f0fe..684bafcaad 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -24,9 +24,9 @@ struct vhost_inflight {
 struct vhost_virtqueue {
     int kick;
     int call;
-    void *desc;
-    void *avail;
-    void *used;
+    void *desc_user;
+    void *avail_user;
+    void *used_user;
     int num;
     unsigned long long desc_phys;
     unsigned desc_size;
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 057/106] vhost: add .vhost_phys_iotlb_msg() handler
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (55 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 056/106] vhost: rename vring pointer fields to reflect user addresses Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 058/106] vhost-user: add VHOST_USER_PROTOCOL_F_GPA_ADDRESSES Michael S. Tsirkin
                   ` (49 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Stefano Garzarella

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

Allow backends to chose, which addr to put into vhost_iotlb_msg:
user or physical. To be used in further commit.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Based-on: <20260206095258.894504-1-vsementsov@yandex-team.ru>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420202032.714884-10-vsementsov@yandex-team.ru>
---
 hw/virtio/vhost.c                 | 11 ++++++++---
 include/hw/virtio/vhost-backend.h |  3 +++
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index e3d452a763..af41841b52 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -920,14 +920,18 @@ static void vhost_region_addnop(MemoryListener *listener,
 }
 
 static int vhost_update_device_iotlb(struct vhost_dev *dev,
-                                     uint64_t iova, uint64_t uaddr,
+                                     uint64_t iova,
+                                     uint64_t paddr,
+                                     uint64_t uaddr,
                                      uint64_t len,
                                      IOMMUAccessFlags perm)
 {
+    bool phys = dev->vhost_ops->vhost_phys_iotlb_msg &&
+        dev->vhost_ops->vhost_phys_iotlb_msg(dev);
     struct vhost_iotlb_msg imsg;
 
     imsg.iova =  iova;
-    imsg.uaddr = uaddr;
+    imsg.uaddr = phys ? paddr : uaddr;
     imsg.size = len;
     imsg.type = VHOST_IOTLB_UPDATE;
 
@@ -1385,7 +1389,8 @@ int vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t iova, int write)
         len = MIN(iotlb.addr_mask + 1, len);
         iova = iova & ~iotlb.addr_mask;
 
-        ret = vhost_update_device_iotlb(dev, iova, uaddr, len, iotlb.perm);
+        ret = vhost_update_device_iotlb(dev, iova, iotlb.translated_addr, uaddr,
+                                        len, iotlb.perm);
         if (ret) {
             trace_vhost_iotlb_miss(dev, 4);
             error_report("Fail to update device iotlb");
diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h
index 7cc3bb5441..00881a0bd4 100644
--- a/include/hw/virtio/vhost-backend.h
+++ b/include/hw/virtio/vhost-backend.h
@@ -143,6 +143,8 @@ typedef int (*vhost_dev_start_op)(struct vhost_dev *dev, bool started);
 
 typedef bool (*vhost_phys_vring_addr_op)(struct vhost_dev *dev);
 
+typedef bool (*vhost_phys_iotlb_msg_op)(struct vhost_dev *dev);
+
 typedef int (*vhost_get_device_id_op)(struct vhost_dev *dev, uint32_t *dev_id);
 
 typedef bool (*vhost_force_iommu_op)(struct vhost_dev *dev);
@@ -210,6 +212,7 @@ typedef struct VhostOps {
     vhost_set_inflight_fd_op vhost_set_inflight_fd;
     vhost_dev_start_op vhost_dev_start;
     vhost_phys_vring_addr_op vhost_phys_vring_addr;
+    vhost_phys_iotlb_msg_op vhost_phys_iotlb_msg;
     vhost_get_device_id_op vhost_get_device_id;
     vhost_force_iommu_op vhost_force_iommu;
     vhost_set_config_call_op vhost_set_config_call;
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 058/106] vhost-user: add VHOST_USER_PROTOCOL_F_GPA_ADDRESSES
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (56 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 057/106] vhost: add .vhost_phys_iotlb_msg() handler Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 059/106] libvhost-user: fix buffer overflow in virtqueue_read_indirect_desc() Michael S. Tsirkin
                   ` (48 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Vladimir Sementsov-Ogievskiy, Stefano Garzarella,
	Pierrick Bouvier

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

Unlike the kernel, vhost-user backend knows nothing about QEMU's
userspace addresses. We can pass GPA instead and nothing changes.
Generally, vhost-user servers need these addresses only to calculate
offsets inside memory regions. Still, some servers (QEMU's internal
is one example) may do checks for passed addresses to be "userspace
addresses", for example check for non-zero. That's why we need
additional negotiation for the feature.

The benefit: this opens the doors for further implementation of
local migration (live-update) with passing open vhost-related FDs
through UNIX domain socket. This way the connection with backend is
kept live and untouched.

Without this change, we would have to communicate with backend to
inform it about UVA address changes, but it's better to simply use
more stable GPA numbers, which don't change after migration.

Additionally, the current implementation exposes QEMU's process
address space by passing UVA, which breaks ASLR. New protocol
feature avoids that.

Note, that we do nothing with backend messages and replies.
Frontends have to work with backends userspace addresses anyway,
because they come from userfaultfd.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Based-on: <20260206095258.894504-1-vsementsov@yandex-team.ru>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260420202032.714884-11-vsementsov@yandex-team.ru>
---
 docs/interop/vhost-user.rst    | 21 +++++++++++++++++----
 hw/virtio/vhost-user.c         | 22 +++++++++++++++++-----
 include/hw/virtio/vhost-user.h |  1 +
 3 files changed, 35 insertions(+), 9 deletions(-)

diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst
index 137c9f3669..8dcb030c53 100644
--- a/docs/interop/vhost-user.rst
+++ b/docs/interop/vhost-user.rst
@@ -164,8 +164,16 @@ A vring address description
 
 :log: a 64-bit guest address for logging
 
-Note that a ring address is an IOVA if ``VIRTIO_F_IOMMU_PLATFORM`` has
-been negotiated. Otherwise it is a user address.
+.. Note::
+   When ``VIRTIO_F_IOMMU_PLATFORM`` is negotiated, ring addresses are IOVAs.
+
+   Otherwise, when ``VHOST_USER_PROTOCOL_F_GPA_ADDRESSES`` is negotiated, the
+   ring addresses are guest physical addresses for frontend messages. That
+   does not apply to backend replies.
+
+   Finally, when neither ``VIRTIO_F_IOMMU_PLATFORM`` nor
+   ``VHOST_USER_PROTOCOL_F_GPA_ADDRESSES`` features are negotiated, ring
+   addresses are user virtual addresses.
 
 .. _memory_region_description:
 
@@ -180,7 +188,9 @@ Memory region description
 
 :size: a 64-bit size
 
-:user address: a 64-bit user address
+:user address: a 64-bit user address. When ``VHOST_USER_PROTOCOL_F_GPA_ADDRESSES``
+  is negotiated, this field contain guest physical address instead and must
+  duplicate ``guest address`` field.
 
 :mmap offset: a 64-bit offset where region starts in the mapped memory
 
@@ -252,7 +262,9 @@ An IOTLB message
 
 :size: a 64-bit size
 
-:user address: a 64-bit user address
+:user address: a 64-bit user address. When ``VHOST_USER_PROTOCOL_F_GPA_ADDRESSES``
+  is negotiated, this field contain guest physical address instead, except for
+  ``VHOST_USER_BACKEND_IOTLB_MSG``, where it's user address anyway.
 
 :permissions flags: an 8-bit value:
   - 0: No access
@@ -1063,6 +1075,7 @@ Protocol features
   #define VHOST_USER_PROTOCOL_F_SHARED_OBJECT           18
   #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
 
 Front-end message types
 -----------------------
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 78ffb25d6b..15042c0f3c 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -563,12 +563,22 @@ static MemoryRegion *vhost_user_get_mr_data(uint64_t addr, ram_addr_t *offset,
     return mr;
 }
 
-static void vhost_user_fill_msg_region(VhostUserMemoryRegion *dst,
+static bool vhost_user_gpa_addresses(struct vhost_dev *dev)
+{
+    return vhost_user_has_protocol_feature(
+        dev, VHOST_USER_PROTOCOL_F_GPA_ADDRESSES);
+}
+
+static void vhost_user_fill_msg_region(struct vhost_dev *dev,
+                                       VhostUserMemoryRegion *dst,
                                        struct vhost_memory_region *src,
                                        uint64_t mmap_offset)
 {
+    bool use_phys = vhost_user_gpa_addresses(dev);
+
     assert(src != NULL && dst != NULL);
-    dst->userspace_addr = src->userspace_addr;
+
+    dst->userspace_addr = use_phys ? src->guest_phys_addr : src->userspace_addr;
     dst->memory_size = src->memory_size;
     dst->guest_phys_addr = src->guest_phys_addr;
     dst->mmap_offset = mmap_offset;
@@ -606,7 +616,7 @@ static int vhost_user_fill_set_mem_table_msg(struct vhost_user *u,
                 error_report("Failed preparing vhost-user memory table msg");
                 return -ENOBUFS;
             }
-            vhost_user_fill_msg_region(&region_buffer, reg, offset);
+            vhost_user_fill_msg_region(dev, &region_buffer, reg, offset);
             msg->payload.memory.regions[*fd_num] = region_buffer;
             fds[(*fd_num)++] = fd;
         } else if (track_ramblocks) {
@@ -752,7 +762,7 @@ static int send_remove_regions(struct vhost_dev *dev,
 
         if (fd > 0) {
             msg->hdr.request = VHOST_USER_REM_MEM_REG;
-            vhost_user_fill_msg_region(&region_buffer, shadow_reg, 0);
+            vhost_user_fill_msg_region(dev, &region_buffer, shadow_reg, 0);
             msg->payload.mem_reg.region = region_buffer;
 
             ret = vhost_user_write(dev, msg, NULL, 0);
@@ -813,7 +823,7 @@ static int send_add_regions(struct vhost_dev *dev,
                 u->region_rb[reg_idx] = mr->ram_block;
             }
             msg->hdr.request = VHOST_USER_ADD_MEM_REG;
-            vhost_user_fill_msg_region(&region_buffer, reg, offset);
+            vhost_user_fill_msg_region(dev, &region_buffer, reg, offset);
             msg->payload.mem_reg.region = region_buffer;
 
             ret = vhost_user_write(dev, msg, &fd, 1);
@@ -3151,4 +3161,6 @@ const VhostOps user_ops = {
         .vhost_supports_device_state = vhost_user_supports_device_state,
         .vhost_set_device_state_fd = vhost_user_set_device_state_fd,
         .vhost_check_device_state = vhost_user_check_device_state,
+        .vhost_phys_vring_addr = vhost_user_gpa_addresses,
+        .vhost_phys_iotlb_msg = vhost_user_gpa_addresses,
 };
diff --git a/include/hw/virtio/vhost-user.h b/include/hw/virtio/vhost-user.h
index 0e576fc538..5ab70dab7e 100644
--- a/include/hw/virtio/vhost-user.h
+++ b/include/hw/virtio/vhost-user.h
@@ -34,6 +34,7 @@ enum VhostUserProtocolFeature {
     VHOST_USER_PROTOCOL_F_SHARED_OBJECT = 18,
     VHOST_USER_PROTOCOL_F_DEVICE_STATE = 19,
     VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT = 20,
+    VHOST_USER_PROTOCOL_F_GPA_ADDRESSES = 21,
     VHOST_USER_PROTOCOL_F_MAX
 };
 
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 059/106] libvhost-user: fix buffer overflow in virtqueue_read_indirect_desc()
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (57 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 058/106] vhost-user: add VHOST_USER_PROTOCOL_F_GPA_ADDRESSES Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 060/106] libvduse: fix buffer overflow in vduse_queue_read_indirect_desc() Michael S. Tsirkin
                   ` (47 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Stefano Garzarella, qemu-stable, DARKNAVY,
	Daniel P. Berrangé

From: Stefano Garzarella <sgarzare@redhat.com>

virtqueue_read_indirect_desc() copies an indirect descriptor table
into a buffer in chunks when the table crosses a memory region
boundary. The destination is a struct vring_desc pointer but is
advanced by a byte count, so each increment moves the pointer by
read_len elements instead of read_len bytes, writing beyond the
buffer.

Use a char pointer for the destination so that the arithmetic
advances correctly.

While at it, change the source from a struct vring_desc pointer
to a void pointer: when the table is split across regions,
vu_gpa_to_va() can return a pointer into the middle of a descriptor,
so casting it to a struct vring_desc pointer is wrong. The pointer is
only used as a memcpy() source, so a void pointer is fine.

Fixes: CVE-2026-6425
Fixes: 293084a719 ("libvhost-user: Support across-memory-boundary access")
Cc: qemu-stable@nongnu.org
Reported-by: DARKNAVY <vr@darknavy.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
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: <20260417132645.121192-2-sgarzare@redhat.com>
---
 subprojects/libvhost-user/libvhost-user.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/subprojects/libvhost-user/libvhost-user.c b/subprojects/libvhost-user/libvhost-user.c
index 9c630c2170..014d210748 100644
--- a/subprojects/libvhost-user/libvhost-user.c
+++ b/subprojects/libvhost-user/libvhost-user.c
@@ -2391,8 +2391,9 @@ static int
 virtqueue_read_indirect_desc(VuDev *dev, struct vring_desc *desc,
                              uint64_t addr, size_t len)
 {
-    struct vring_desc *ori_desc;
+    char *dst_desc = (char *)desc;
     uint64_t read_len;
+    void *ori_desc;
 
     if (len > (VIRTQUEUE_MAX_SIZE * sizeof(struct vring_desc))) {
         return -1;
@@ -2409,10 +2410,10 @@ virtqueue_read_indirect_desc(VuDev *dev, struct vring_desc *desc,
             return -1;
         }
 
-        memcpy(desc, ori_desc, read_len);
+        memcpy(dst_desc, ori_desc, read_len);
         len -= read_len;
         addr += read_len;
-        desc += read_len;
+        dst_desc += read_len;
     }
 
     return 0;
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 060/106] libvduse: fix buffer overflow in vduse_queue_read_indirect_desc()
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (58 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 059/106] libvhost-user: fix buffer overflow in virtqueue_read_indirect_desc() Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 061/106] MAINTAINERS: Update CXL maintainers entry including adding linux-cxl list Michael S. Tsirkin
                   ` (46 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Stefano Garzarella, qemu-stable, DARKNAVY,
	Daniel P. Berrangé, Xie Yongji

From: Stefano Garzarella <sgarzare@redhat.com>

vduse_queue_read_indirect_desc() copies an indirect descriptor table
into a buffer in chunks when the table crosses a memory region
boundary. The destination is a struct vring_desc pointer but is
advanced by a byte count, so each increment moves the pointer by
read_len elements instead of read_len bytes, writing beyond the
buffer.

Use a char pointer for the destination so that the arithmetic
advances correctly.

While at it, change the source from a struct vring_desc pointer
to a void pointer: when the table is split across regions,
iova_to_va() can return a pointer into the middle of a descriptor,
so casting it to a struct vring_desc pointer is wrong. The pointer is
only used as a memcpy() source, so a void pointer is fine.

Fixes: CVE-2026-6425
Fixes: a6caeee811 ("libvduse: Add VDUSE (vDPA Device in Userspace) library")
Cc: qemu-stable@nongnu.org
Reported-by: DARKNAVY <vr@darknavy.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
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: <20260417132645.121192-3-sgarzare@redhat.com>
---
 subprojects/libvduse/libvduse.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/subprojects/libvduse/libvduse.c b/subprojects/libvduse/libvduse.c
index 21ffbb5b8d..df9ca5e56f 100644
--- a/subprojects/libvduse/libvduse.c
+++ b/subprojects/libvduse/libvduse.c
@@ -465,8 +465,9 @@ static int
 vduse_queue_read_indirect_desc(VduseDev *dev, struct vring_desc *desc,
                                uint64_t addr, size_t len)
 {
-    struct vring_desc *ori_desc;
+    char *dst_desc = (char *)desc;
     uint64_t read_len;
+    void *ori_desc;
 
     if (len > (VIRTQUEUE_MAX_SIZE * sizeof(struct vring_desc))) {
         return -1;
@@ -483,10 +484,10 @@ vduse_queue_read_indirect_desc(VduseDev *dev, struct vring_desc *desc,
             return -1;
         }
 
-        memcpy(desc, ori_desc, read_len);
+        memcpy(dst_desc, ori_desc, read_len);
         len -= read_len;
         addr += read_len;
-        desc += read_len;
+        dst_desc += read_len;
     }
 
     return 0;
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 061/106] MAINTAINERS: Update CXL maintainers entry including adding linux-cxl list
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (59 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 060/106] libvduse: fix buffer overflow in vduse_queue_read_indirect_desc() Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 062/106] vhost-user.rst: Explicitly allow front-end to write to kick FDs Michael S. Tsirkin
                   ` (45 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Jonathan Cameron, Philippe Mathieu-Daudé,
	Thomas Huth, Pierrick Bouvier, Richard Henderson

From: Jonathan Cameron <Jonathan.Cameron@huawei.com>

The CXL maintainers entry needs an update.
For a while convention has been to +CC linux-cxl@vger.kernel.org to get
better coverage for CXL aspects so formalize that with an L entry.

Drop Fan as he has not been at Samsung for a while now.
Switch my email address over to my kernel.org one.

Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260415143040.22223-1-Jonathan.Cameron@huawei.com>
---
 MAINTAINERS | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 3b768fc080..5a82aa3a05 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3203,8 +3203,8 @@ F: tests/qtest/migration/cpr*
 F: docs/devel/migration/CPR.rst
 
 Compute Express Link
-M: Jonathan Cameron <jonathan.cameron@huawei.com>
-R: Fan Ni <fan.ni@samsung.com>
+M: Jonathan Cameron <jic23@kernel.org>
+L: linux-cxl@vger.kernel.org
 S: Supported
 F: hw/cxl/
 F: hw/mem/cxl_type3.c
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 062/106] vhost-user.rst: Explicitly allow front-end to write to kick FDs
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (60 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 061/106] MAINTAINERS: Update CXL maintainers entry including adding linux-cxl list Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 063/106] amd_iommu: Follow root pointer before page walk and use 1-based levels Michael S. Tsirkin
                   ` (44 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Jorge E. Moreira, Stefano Garzarella,
	Pierrick Bouvier

From: "Jorge E. Moreira" <jemoreira@google.com>

Migration of back-end state happens while the device is suspended (i.e
all vrings are stopped). To resume normal operation on the destination,
the vrings need to be started again with a kick (either a write on the
FD or the VHOST_USER_VRING_KICK in-band message if negotiated). While
these notifications are typically sent by the driver, it has no reason
to send them in the destination if it already sent them in the source as
the driver is unaware that a migration took place. Therefore it should
be the responsibility of the vhost-user front-end to ensure these vrings
are started. This is particularly necessary for queues where data only
flows from device to driver, such as those used by the vsock and input
devices.

This behavior is already used by some qemu vhost-user front-ends (e.g
vhost-user-blk) and by front-ends implemented on other VMMs(e.g CrosVm).
Adding it to the vhost-user documentation makes it explicit that this
strategy is permitted and suggest it to vhost-user front-end authors.
Explicitly documenting it is necessary because vring kicks appear
designed to originate in the driver, so having some originate in the
front-end can be counterintuitive and cause developers to waste time
looking for other alternatives or face pushback during code review.

Signed-off-by: Jorge E. Moreira <jemoreira@google.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260411021205.3592118-1-jemoreira@google.com>
---
 docs/interop/vhost-user.rst | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst
index 8dcb030c53..e8554a3859 100644
--- a/docs/interop/vhost-user.rst
+++ b/docs/interop/vhost-user.rst
@@ -668,7 +668,10 @@ destination, following the usual protocol for establishing a connection
 to a vhost-user back-end: This includes, for example, setting up memory
 mappings and kick and call FDs as necessary, negotiating protocol
 features, or setting the initial vring base indices (to the same value
-as on the source side, so that operation can resume).
+as on the source side, so that operation can resume). The vhost-user front-end
+may also write to the kick FDs of vrings containing unused buffers or send
+``VHOST_USER_VRING_KICK`` if negotiated to start those vrings in the destination
+since the driver likely already kicked them in the source and won't do it again.
 
 Both on the source and on the destination side, after the respective
 front-end has seen all data transferred (when the transfer FD has been
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 063/106] amd_iommu: Follow root pointer before page walk and use 1-based levels
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (61 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 062/106] vhost-user.rst: Explicitly allow front-end to write to kick FDs Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 064/106] amd_iommu: Reject non-decreasing NextLevel in fetch_pte() Michael S. Tsirkin
                   ` (43 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Alejandro Jimenez, qemu-stable,
	David Hoppenbrouwers, Sairaj Kodilkar, Paolo Bonzini,
	Richard Henderson

From: Alejandro Jimenez <alejandro.j.jimenez@oracle.com>

DTE[Mode] and PTE NextLevel encode page table levels as 1-based values, but
fetch_pte() currently uses a 0-based level counter, making the logic
harder to follow and requiring conversions between DTE mode and level.

Switch the page table walk logic to use 1-based level accounting in
fetch_pte() and the relevant macro helpers. To further simplify the page
walking loop, split the root page table access from the walk i.e. rework
fetch_pte() to follow the DTE Page Table Root Pointer and retrieve the top
level pagetable entry before entering the loop, then iterate only over the
PDE/PTE entries.

The reworked algorithm fixes a page walk bug where the page size was
calculated for the next level before checking if the current PTE was already
a leaf/hugepage. That caused hugepage mappings to be reported as 4K pages,
leading to performance degradation and failures in some setups.

Fixes: a74bb3110a5b ("amd_iommu: Add helpers to walk AMD v1 Page Table format")
Cc: qemu-stable@nongnu.org
Reported-by: David Hoppenbrouwers <qemu@demindiro.com>
Reviewed-By: David Hoppenbrouwers <qemu@demindiro.com>
Reviewed-by: Sairaj Kodilkar <sarunkod@amd.com>
Signed-off-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: <20260330212817.992673-2-alejandro.j.jimenez@oracle.com>
---
 hw/i386/amd_iommu.c | 134 ++++++++++++++++++++++++++++++--------------
 hw/i386/amd_iommu.h |  11 ++--
 2 files changed, 98 insertions(+), 47 deletions(-)

diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
index 5d6a405263..bc083d0073 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -648,6 +648,52 @@ static uint64_t large_pte_page_size(uint64_t pte)
     return PTE_LARGE_PAGE_SIZE(pte);
 }
 
+/*
+ * Validate DTE fields and extract permissions and top level data required to
+ * initiate the page table walk.
+ *
+ * On success, returns 0 and stores:
+ *   - top_level: highest page-table level encoded in DTE[Mode]
+ *   - dte_perms: effective permissions from the DTE
+ *
+ * On failure, returns -AMDVI_FR_PT_ROOT_INV. This includes cases where:
+ *   - DTE permissions disallow read AND write
+ *   - DTE[Mode] is invalid for translation
+ *   - IOVA exceeds the address width supported by DTE[Mode]
+ * In all such cases a page walk must be aborted.
+ */
+static uint64_t amdvi_get_top_pt_level_and_perms(hwaddr address, uint64_t dte,
+                                                 uint8_t *top_level,
+                                                 IOMMUAccessFlags *dte_perms)
+{
+    *dte_perms = amdvi_get_perms(dte);
+    if (*dte_perms == IOMMU_NONE) {
+        return -AMDVI_FR_PT_ROOT_INV;
+    }
+
+    /* Verifying a valid mode is encoded in DTE */
+    *top_level = get_pte_translation_mode(dte);
+
+    /*
+     * Page Table Root pointer is only valid for GPA->SPA translation on
+     * supported modes.
+     */
+    if (*top_level == 0 || *top_level > 6) {
+        return -AMDVI_FR_PT_ROOT_INV;
+    }
+
+    /*
+     * If IOVA is larger than the max supported by the highest pgtable level,
+     * there is nothing to do.
+     */
+    if (address > PT_LEVEL_MAX_ADDR(*top_level)) {
+        /* IOVA too large for the current DTE */
+        return -AMDVI_FR_PT_ROOT_INV;
+    }
+
+    return 0;
+}
+
 /*
  * Helper function to fetch a PTE using AMD v1 pgtable format.
  * On successful page walk, returns 0 and pte parameter points to a valid PTE.
@@ -662,40 +708,49 @@ static uint64_t large_pte_page_size(uint64_t pte)
 static uint64_t fetch_pte(AMDVIAddressSpace *as, hwaddr address, uint64_t dte,
                           uint64_t *pte, hwaddr *page_size)
 {
-    IOMMUAccessFlags perms = amdvi_get_perms(dte);
-
-    uint8_t level, mode;
     uint64_t pte_addr;
+    uint8_t pt_level, next_pt_level;
+    IOMMUAccessFlags perms;
+    int ret;
 
-    *pte = dte;
     *page_size = 0;
 
-    if (perms == IOMMU_NONE) {
+    /*
+     * Verify the DTE is properly configured before page walk, and extract
+     * top pagetable level and permissions.
+     */
+    ret = amdvi_get_top_pt_level_and_perms(address, dte, &pt_level, &perms);
+    if (ret < 0) {
+        return ret;
+    }
+
+    /*
+     * Retrieve the top pagetable entry by following the DTE Page Table Root
+     * Pointer and indexing the top level table using the IOVA from the request.
+     */
+    pte_addr = NEXT_PTE_ADDR(dte, pt_level, address);
+    *pte = amdvi_get_pte_entry(as->iommu_state, pte_addr, as->devfn);
+
+    if (*pte == (uint64_t)-1) {
+        /*
+         * A returned PTE of -1 here indicates a failure to read the top level
+         * page table from guest memory. A page walk is not possible and page
+         * size must be returned as 0.
+         */
         return -AMDVI_FR_PT_ROOT_INV;
     }
 
     /*
-     * The Linux kernel driver initializes the default mode to 3, corresponding
-     * to a 39-bit GPA space, where each entry in the pagetable translates to a
-     * 1GB (2^30) page size.
+     * Calculate page size for the top level page table entry.
+     * This ensures correct results for a single level Page Table setup.
      */
-    level = mode = get_pte_translation_mode(dte);
-    assert(mode > 0 && mode < 7);
+    *page_size = PTE_LEVEL_PAGE_SIZE(pt_level);
 
     /*
-     * If IOVA is larger than the max supported by the current pgtable level,
-     * there is nothing to do.
+     * The root page table entry and its level have been determined. Begin the
+     * page walk.
      */
-    if (address > PT_LEVEL_MAX_ADDR(mode - 1)) {
-        /* IOVA too large for the current DTE */
-        return -AMDVI_FR_PT_ROOT_INV;
-    }
-
-    do {
-        level -= 1;
-
-        /* Update the page_size */
-        *page_size = PTE_LEVEL_PAGE_SIZE(level);
+    while (pt_level > 0) {
 
         /* Permission bits are ANDed at every level, including the DTE */
         perms &= amdvi_get_perms(*pte);
@@ -708,37 +763,34 @@ static uint64_t fetch_pte(AMDVIAddressSpace *as, hwaddr address, uint64_t dte,
             return 0;
         }
 
+        next_pt_level = PTE_NEXT_LEVEL(*pte);
+
         /* Large or Leaf PTE found */
-        if (PTE_NEXT_LEVEL(*pte) == 7 || PTE_NEXT_LEVEL(*pte) == 0) {
+        if (next_pt_level == 0 || next_pt_level == 7) {
             /* Leaf PTE found */
             break;
         }
 
+        pt_level = next_pt_level;
+
         /*
-         * Index the pgtable using the IOVA bits corresponding to current level
-         * and walk down to the lower level.
+         * The current entry is a Page Directory Entry. Descend to the lower
+         * page table level encoded in current pte, and index the new table
+         * using the appropriate IOVA bits to retrieve the new entry.
          */
-        pte_addr = NEXT_PTE_ADDR(*pte, level, address);
+        *page_size = PTE_LEVEL_PAGE_SIZE(pt_level);
+
+        pte_addr = NEXT_PTE_ADDR(*pte, pt_level, address);
         *pte = amdvi_get_pte_entry(as->iommu_state, pte_addr, as->devfn);
 
         if (*pte == (uint64_t)-1) {
-            /*
-             * A returned PTE of -1 indicates a failure to read the page table
-             * entry from guest memory.
-             */
-            if (level == mode - 1) {
-                /* Failure to retrieve the Page Table from Root Pointer */
-                *page_size = 0;
-                return -AMDVI_FR_PT_ROOT_INV;
-            } else {
-                /* Failure to read PTE. Page walk skips a page_size chunk */
-                return -AMDVI_FR_PT_ENTRY_INV;
-            }
+            /* Failure to read PTE. Page walk skips a page_size chunk */
+            return -AMDVI_FR_PT_ENTRY_INV;
         }
-    } while (level > 0);
+    }
+
+    assert(PTE_NEXT_LEVEL(*pte) == 0 || PTE_NEXT_LEVEL(*pte) == 7);
 
-    assert(PTE_NEXT_LEVEL(*pte) == 0 || PTE_NEXT_LEVEL(*pte) == 7 ||
-           level == 0);
     /*
      * Page walk ends when Next Level field on PTE shows that either a leaf PTE
      * or a series of large PTEs have been reached. In the latter case, even if
diff --git a/hw/i386/amd_iommu.h b/hw/i386/amd_iommu.h
index 302ccca512..7af3c742b7 100644
--- a/hw/i386/amd_iommu.h
+++ b/hw/i386/amd_iommu.h
@@ -186,17 +186,16 @@
 
 #define IOMMU_PTE_PRESENT(pte)          ((pte) & AMDVI_PTE_PR)
 
-/* Using level=0 for leaf PTE at 4K page size */
-#define PT_LEVEL_SHIFT(level)           (12 + ((level) * 9))
+/* Using level=1 for leaf PTE at 4K page size */
+#define PT_LEVEL_SHIFT(level)           (12 + (((level) - 1) * 9))
 
 /* Return IOVA bit group used to index the Page Table at specific level */
 #define PT_LEVEL_INDEX(level, iova)     (((iova) >> PT_LEVEL_SHIFT(level)) & \
                                         GENMASK64(8, 0))
 
-/* Return the max address for a specified level i.e. max_oaddr */
-#define PT_LEVEL_MAX_ADDR(x)    (((x) < 5) ? \
-                                ((1ULL << PT_LEVEL_SHIFT((x + 1))) - 1) : \
-                                (~(0ULL)))
+/* Return the maximum output address for a specified page table level */
+#define PT_LEVEL_MAX_ADDR(level)    (((level) > 5) ? (~(0ULL)) : \
+                                    ((1ULL << PT_LEVEL_SHIFT((level) + 1)) - 1))
 
 /* Extract the NextLevel field from PTE/PDE */
 #define PTE_NEXT_LEVEL(pte)     (((pte) & AMDVI_PTE_NEXT_LEVEL_MASK) >> 9)
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 064/106] amd_iommu: Reject non-decreasing NextLevel in fetch_pte()
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (62 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 063/106] amd_iommu: Follow root pointer before page walk and use 1-based levels Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 065/106] vhost-user-blk-server: do not advertise VIRTIO_BLK_F_SIZE_MAX with size_max=0 Michael S. Tsirkin
                   ` (42 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Alejandro Jimenez, qemu-stable, Sairaj Kodilkar,
	Paolo Bonzini, Richard Henderson

From: Alejandro Jimenez <alejandro.j.jimenez@oracle.com>

The AMD-Vi specification requires that the NextLevel field for a page table
entry must not be greater or equal to the current page table entry level.
Enforce this to avoid infinite page walk loops on corrupted or buggy guest
page tables.

The initial implementation of fetch_pte() did not implement this check, but
was not vulnerable since the page walk code explicitly decremented the level
instead of retrieving it from the page table entry.

Cc: qemu-stable@nongnu.org
Reviewed-by: Sairaj Kodilkar <sarunkod@amd.com>
Signed-off-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: <20260330212817.992673-3-alejandro.j.jimenez@oracle.com>
---
 hw/i386/amd_iommu.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
index bc083d0073..99b05b2ab6 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -771,6 +771,10 @@ static uint64_t fetch_pte(AMDVIAddressSpace *as, hwaddr address, uint64_t dte,
             break;
         }
 
+        /* Next level must always be less than current level */
+        if (pt_level <= next_pt_level) {
+            return -AMDVI_FR_PT_ENTRY_INV;
+        }
         pt_level = next_pt_level;
 
         /*
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 065/106] vhost-user-blk-server: do not advertise VIRTIO_BLK_F_SIZE_MAX with size_max=0
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (63 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 064/106] amd_iommu: Reject non-decreasing NextLevel in fetch_pte() Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 066/106] vhost-user-blk: do not force VIRTIO_BLK_F_SIZE_MAX Michael S. Tsirkin
                   ` (41 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Max Makarov, Max Makarov, Stefano Garzarella,
	Kevin Wolf, Hanna Reitz, qemu-block

From: Max Makarov <maxpain177@gmail.com>

The QSD vhost-user-blk backend advertises VIRTIO_BLK_F_SIZE_MAX but
sets size_max=0 in config, creating a contradictory state. The feature
bit tells the guest that size_max is valid, but the value is zero.

Windows viostor trusts the feature bit, reads size_max=0, and uses it
in scatter-gather calculations producing zero-length segments that hang
I/O. The disk appears empty (no GPT, no partitions), causing
INACCESSIBLE_BOOT_DEVICE BSOD. Linux tolerates this because
blk_validate_limits() silently corrects max_segment_size=0 to
BLK_MAX_SEGMENT_SIZE (65536).

This affects any VMM using QSD as a vhost-user-blk backend (QEMU,
Cloud Hypervisor, etc.), since both pass through SIZE_MAX from the
backend to the guest via feature intersection.

Remove VIRTIO_BLK_F_SIZE_MAX from the backend feature bits. The
size_max config field remains zero but is now ignored by guests since
the feature is not negotiated.

Signed-off-by: Max Makarov <maxpain@linux.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260331152856.1802-1-maxpain@linux.com>
---
 block/export/vhost-user-blk-server.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/block/export/vhost-user-blk-server.c b/block/export/vhost-user-blk-server.c
index 67912a3e17..46c0d303df 100644
--- a/block/export/vhost-user-blk-server.c
+++ b/block/export/vhost-user-blk-server.c
@@ -119,7 +119,7 @@ static uint64_t vu_blk_get_features(VuDev *dev)
     uint64_t features;
     VuServer *server = container_of(dev, VuServer, vu_dev);
     VuBlkExport *vexp = container_of(server, VuBlkExport, vu_server);
-    features = 1ull << VIRTIO_BLK_F_SIZE_MAX |
+    features =
                1ull << VIRTIO_BLK_F_SEG_MAX |
                1ull << VIRTIO_BLK_F_TOPOLOGY |
                1ull << VIRTIO_BLK_F_BLK_SIZE |
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 066/106] vhost-user-blk: do not force VIRTIO_BLK_F_SIZE_MAX
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (64 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 065/106] vhost-user-blk-server: do not advertise VIRTIO_BLK_F_SIZE_MAX with size_max=0 Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 067/106] ppc/pnv_phb3: Error out on invalid config access Michael S. Tsirkin
                   ` (40 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Max Makarov, Max Makarov, Raphael Norwitz,
	Stefano Garzarella, Kevin Wolf, Hanna Reitz, qemu-block

From: Max Makarov <maxpain177@gmail.com>

vhost_user_blk_get_features() unconditionally advertises
VIRTIO_BLK_F_SIZE_MAX regardless of what the backend reports in
its config. The built-in QSD vhost-user-blk backend sets
size_max=0, creating a contradictory state where the feature bit
tells the guest that size_max is valid but the value is zero.

The in-process virtio-blk device does not advertise
VIRTIO_BLK_F_SIZE_MAX (it also sets size_max=0 in config), so
guests never see this contradiction with native virtio-blk.

Linux tolerates size_max=0 because blk_validate_limits() silently
corrects max_segment_size=0 to BLK_MAX_SEGMENT_SIZE (65536).
Windows viostor, however, trusts the feature bit and uses the raw
size_max=0 in its scatter-gather calculations, producing
zero-length segments that hang I/O. The disk appears empty to
Windows (no GPT, no partitions), causing INACCESSIBLE_BOOT_DEVICE.

Stop force-adding VIRTIO_BLK_F_SIZE_MAX in the frontend. The
feature remains in user_feature_bits[], so backends that properly
advertise it with a valid config value will still work.

Signed-off-by: Max Makarov <maxpain@linux.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260331134721.96047-1-maxpain@linux.com>
---
 hw/block/vhost-user-blk.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index 530f44ab52..5c73a58ee0 100644
--- a/hw/block/vhost-user-blk.c
+++ b/hw/block/vhost-user-blk.c
@@ -283,7 +283,6 @@ static uint64_t vhost_user_blk_get_features(VirtIODevice *vdev,
     VHostUserBlk *s = VHOST_USER_BLK(vdev);
 
     /* Turn on pre-defined features */
-    virtio_add_feature(&features, VIRTIO_BLK_F_SIZE_MAX);
     virtio_add_feature(&features, VIRTIO_BLK_F_SEG_MAX);
     virtio_add_feature(&features, VIRTIO_BLK_F_GEOMETRY);
     virtio_add_feature(&features, VIRTIO_BLK_F_TOPOLOGY);
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 067/106] ppc/pnv_phb3: Error out on invalid config access
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (65 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 066/106] vhost-user-blk: do not force VIRTIO_BLK_F_SIZE_MAX Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 068/106] hw/pci: Replace assert with bounds check and return Michael S. Tsirkin
                   ` (39 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Aditya Gupta, Zexiang Zhang, Nicholas Piggin,
	Glenn Miles, Harsh Prateek Bora, qemu-ppc

From: Aditya Gupta <adityag@linux.ibm.com>

PHB in Power8 supports 8 byte registers, and hence the ops structure
allows accessing of 8 bytes in 'pnv_phb3_reg_ops'

Both 'pnv_phb3_reg_read' & 'pnv_phb3_reg_write' pass the arguments as is
to 'pnv_phb3_config_{read,write}', if offset is PHB_CONFIG_DATA.

This when called with size as 8, causes following assert failure in
'pci_host_config_read_common' & 'pci_host_config_write_common':

    assert(len <= 4);

Validate that size is <=4, before jumping to pci_host_config_{read,write}_common

Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3334
Reported-by: Zexiang Zhang <chan9yan9@gmail.com>
Fixes: 9ae1329ee2fe ("ppc/pnv: Add models for POWER8 PHB3 PCIe Host bridge")
Signed-off-by: Aditya Gupta <adityag@linux.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260326190438.734239-2-adityag@linux.ibm.com>
---
 hw/pci-host/pnv_phb3.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c
index d6ab515337..4ffdb4ce31 100644
--- a/hw/pci-host/pnv_phb3.c
+++ b/hw/pci-host/pnv_phb3.c
@@ -475,6 +475,11 @@ void pnv_phb3_reg_write(void *opaque, hwaddr off, uint64_t val, unsigned size)
 
     /* Special case configuration data */
     if ((off & 0xfffc) == PHB_CONFIG_DATA) {
+        if (size > 4) {
+            phb3_error(phb, "Invalid config access, offset: 0x%"PRIx64" size: %d",
+                      off, size);
+            return;
+        }
         pnv_phb3_config_write(phb, off & 0x3, size, val);
         return;
     }
@@ -597,6 +602,11 @@ uint64_t pnv_phb3_reg_read(void *opaque, hwaddr off, unsigned size)
     uint64_t val;
 
     if ((off & 0xfffc) == PHB_CONFIG_DATA) {
+        if (size > 4) {
+            phb3_error(phb, "Invalid config access, offset: 0x%"PRIx64" size: %d",
+                      off, size);
+            return ~0ull;
+        }
         return pnv_phb3_config_read(phb, off & 0x3, size);
     }
 
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 068/106] hw/pci: Replace assert with bounds check and return
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (66 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 067/106] ppc/pnv_phb3: Error out on invalid config access Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 069/106] vhost-user: Fix stale error logs and return values in teardown paths Michael S. Tsirkin
                   ` (38 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Aditya Gupta, Zexiang Zhang

From: Aditya Gupta <adityag@linux.ibm.com>

As reported in https://gitlab.com/qemu-project/qemu/-/work_items/3334,
callers of 'pci_host_config_{read,write}_common' can pass length as 8,
causing an assert failure

The original issue with pnv_phb3 triggering the assert was fixed in a
previous commit

Instead of asserting on invalid length, check if the length is valid
(<=4), otherwise return (with the failure error code in read)

Reported-by: Zexiang Zhang <chan9yan9@gmail.com>
Signed-off-by: Aditya Gupta <adityag@linux.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260326190438.734239-3-adityag@linux.ibm.com>
---
 hw/pci/pci_host.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c
index 91e3885c7f..2a7fdfa563 100644
--- a/hw/pci/pci_host.c
+++ b/hw/pci/pci_host.c
@@ -81,7 +81,12 @@ void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,
         return;
     }
 
-    assert(len <= 4);
+    if (len > 4) {
+        PCI_DPRINTF("%s: invalid length access: addr " HWADDR_FMT_plx " \
+            len %d val %"PRIx32"\n", __func__, addr, len, val);
+        return;
+    }
+
     /* non-zero functions are only exposed when function 0 is present,
      * allowing direct removal of unexposed functions.
      */
@@ -106,7 +111,12 @@ uint32_t pci_host_config_read_common(PCIDevice *pci_dev, uint32_t addr,
         return ~0x0;
     }
 
-    assert(len <= 4);
+    if (len > 4) {
+        PCI_DPRINTF("%s: invalid length access: addr " HWADDR_FMT_plx " \
+            len %d val %"PRIx32"\n", __func__, addr, len, val);
+        return ~0x0;
+    }
+
     /* non-zero functions are only exposed when function 0 is present,
      * allowing direct removal of unexposed functions.
      */
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 069/106] vhost-user: Fix stale error logs and return values in teardown paths
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (67 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 068/106] hw/pci: Replace assert with bounds check and return Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 070/106] q35: Fix incorrect values for PCIEXBAR masks Michael S. Tsirkin
                   ` (37 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Kuan-Wei Chiu, Stefano Garzarella, Raphael Norwitz,
	Kevin Wolf, Hanna Reitz, Paolo Bonzini, Fam Zheng,
	Alex Bennée, Stefan Hajnoczi, Milan Zamazal, qemu-block,
	virtio-fs

From: Kuan-Wei Chiu <visitorckw@gmail.com>

Commit bc85aae42045 ("vhost-user: return failure if backend crash when
live migration") refactored the set_guest_notifiers error handling but
introduced two regressions across multiple vhost devices.

By moving the function call directly into the if condition, the
subsequent error_report prints the stale ret variable instead of the
actual error code. Additionally, the refactoring hardcoded a return
value of -1 rather than propagating the true error status to the
caller.

Fix these issues by storing the set_guest_notifiers result in a local
err variable.

Fixes: bc85aae42045 ("vhost-user: return failure if backend crash when live migration")
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: <20260315231047.310029-1-visitorckw@gmail.com>
---
 backends/vhost-user.c          | 8 ++++----
 hw/block/vhost-user-blk.c      | 9 +++++----
 hw/scsi/vhost-scsi-common.c    | 2 +-
 hw/virtio/vhost-user-base.c    | 9 +++++----
 hw/virtio/vhost-user-fs.c      | 9 +++++----
 hw/virtio/vhost-user-scmi.c    | 9 +++++----
 hw/virtio/vhost-vsock-common.c | 9 +++++----
 7 files changed, 30 insertions(+), 25 deletions(-)

diff --git a/backends/vhost-user.c b/backends/vhost-user.c
index 42845329e7..380d825023 100644
--- a/backends/vhost-user.c
+++ b/backends/vhost-user.c
@@ -102,7 +102,7 @@ vhost_user_backend_stop(VhostUserBackend *b)
 {
     BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(b->vdev)));
     VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
-    int ret;
+    int ret, err;
 
     if (!b->started) {
         return 0;
@@ -111,9 +111,9 @@ vhost_user_backend_stop(VhostUserBackend *b)
     ret = vhost_dev_stop(&b->dev, b->vdev, true);
 
     if (k->set_guest_notifiers &&
-        k->set_guest_notifiers(qbus->parent, b->dev.nvqs, false) < 0) {
-        error_report("vhost guest notifier cleanup failed: %d", ret);
-        return -1;
+        (err = k->set_guest_notifiers(qbus->parent, b->dev.nvqs, false)) < 0) {
+        error_report("vhost guest notifier cleanup failed: %d", err);
+        return err;
     }
 
     vhost_dev_disable_notifiers(&b->dev, b->vdev);
diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index 5c73a58ee0..b2e46eb3f9 100644
--- a/hw/block/vhost-user-blk.c
+++ b/hw/block/vhost-user-blk.c
@@ -214,7 +214,7 @@ static int vhost_user_blk_stop(VirtIODevice *vdev)
     VHostUserBlk *s = VHOST_USER_BLK(vdev);
     BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
     VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
-    int ret;
+    int ret, err;
     bool force_stop = false;
 
     trace_vhost_user_blk_stop_in(vdev);
@@ -234,9 +234,10 @@ static int vhost_user_blk_stop(VirtIODevice *vdev)
     ret = force_stop ? vhost_dev_force_stop(&s->dev, vdev, true) :
                        vhost_dev_stop(&s->dev, vdev, true);
 
-    if (k->set_guest_notifiers(qbus->parent, s->dev.nvqs, false) < 0) {
-        error_report("vhost guest notifier cleanup failed: %d", ret);
-        return -1;
+    err = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, false);
+    if (err < 0) {
+        error_report("vhost guest notifier cleanup failed: %d", err);
+        return err;
     }
 
     vhost_dev_disable_notifiers(&s->dev, vdev);
diff --git a/hw/scsi/vhost-scsi-common.c b/hw/scsi/vhost-scsi-common.c
index 0bb4305de6..e19800a0bc 100644
--- a/hw/scsi/vhost-scsi-common.c
+++ b/hw/scsi/vhost-scsi-common.c
@@ -113,7 +113,7 @@ int vhost_scsi_common_stop(VHostSCSICommon *vsc)
     if (k->set_guest_notifiers) {
         int r = k->set_guest_notifiers(qbus->parent, vsc->dev.nvqs, false);
         if (r < 0) {
-            error_report("vhost guest notifier cleanup failed: %d", ret);
+            error_report("vhost guest notifier cleanup failed: %d", r);
             return r;
         }
     }
diff --git a/hw/virtio/vhost-user-base.c b/hw/virtio/vhost-user-base.c
index 5bbf4a7367..8b62c6c36e 100644
--- a/hw/virtio/vhost-user-base.c
+++ b/hw/virtio/vhost-user-base.c
@@ -71,7 +71,7 @@ static int vub_stop(VirtIODevice *vdev)
     VHostUserBase *vub = VHOST_USER_BASE(vdev);
     BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
     VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
-    int ret;
+    int ret, err;
 
     if (!k->set_guest_notifiers) {
         return 0;
@@ -79,9 +79,10 @@ static int vub_stop(VirtIODevice *vdev)
 
     ret = vhost_dev_stop(&vub->vhost_dev, vdev, true);
 
-    if (k->set_guest_notifiers(qbus->parent, vub->vhost_dev.nvqs, false) < 0) {
-        error_report("vhost guest notifier cleanup failed: %d", ret);
-        return -1;
+    err = k->set_guest_notifiers(qbus->parent, vub->vhost_dev.nvqs, false);
+    if (err < 0) {
+        error_report("vhost guest notifier cleanup failed: %d", err);
+        return err;
     }
 
     vhost_dev_disable_notifiers(&vub->vhost_dev, vdev);
diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c
index ad6fcacf06..209993918a 100644
--- a/hw/virtio/vhost-user-fs.c
+++ b/hw/virtio/vhost-user-fs.c
@@ -105,7 +105,7 @@ static int vuf_stop(VirtIODevice *vdev)
     VHostUserFS *fs = VHOST_USER_FS(vdev);
     BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
     VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
-    int ret;
+    int ret, err;
 
     if (!k->set_guest_notifiers) {
         return 0;
@@ -113,9 +113,10 @@ static int vuf_stop(VirtIODevice *vdev)
 
     ret = vhost_dev_stop(&fs->vhost_dev, vdev, true);
 
-    if (k->set_guest_notifiers(qbus->parent, fs->vhost_dev.nvqs, false) < 0) {
-        error_report("vhost guest notifier cleanup failed: %d", ret);
-        return -1;
+    err = k->set_guest_notifiers(qbus->parent, fs->vhost_dev.nvqs, false);
+    if (err < 0) {
+        error_report("vhost guest notifier cleanup failed: %d", err);
+        return err;
     }
 
     vhost_dev_disable_notifiers(&fs->vhost_dev, vdev);
diff --git a/hw/virtio/vhost-user-scmi.c b/hw/virtio/vhost-user-scmi.c
index f9264c4374..9470f68c1f 100644
--- a/hw/virtio/vhost-user-scmi.c
+++ b/hw/virtio/vhost-user-scmi.c
@@ -89,7 +89,7 @@ static int vu_scmi_stop(VirtIODevice *vdev)
     BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
     VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
     struct vhost_dev *vhost_dev = &scmi->vhost_dev;
-    int ret;
+    int ret, err;
 
     /* vhost_dev_is_started() check in the callers is not fully reliable. */
     if (!scmi->started_vu) {
@@ -103,9 +103,10 @@ static int vu_scmi_stop(VirtIODevice *vdev)
 
     ret = vhost_dev_stop(vhost_dev, vdev, true);
 
-    if (k->set_guest_notifiers(qbus->parent, vhost_dev->nvqs, false) < 0) {
-        error_report("vhost guest notifier cleanup failed: %d", ret);
-        return -1;
+    err = k->set_guest_notifiers(qbus->parent, vhost_dev->nvqs, false);
+    if (err < 0) {
+        error_report("vhost guest notifier cleanup failed: %d", err);
+        return err;
     }
     vhost_dev_disable_notifiers(vhost_dev, vdev);
     return ret;
diff --git a/hw/virtio/vhost-vsock-common.c b/hw/virtio/vhost-vsock-common.c
index b33def900a..b79f4c9ce6 100644
--- a/hw/virtio/vhost-vsock-common.c
+++ b/hw/virtio/vhost-vsock-common.c
@@ -100,7 +100,7 @@ int vhost_vsock_common_stop(VirtIODevice *vdev)
     VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
     BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
     VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
-    int ret;
+    int ret, err;
 
     if (!k->set_guest_notifiers) {
         return 0;
@@ -108,9 +108,10 @@ int vhost_vsock_common_stop(VirtIODevice *vdev)
 
     ret = vhost_dev_stop(&vvc->vhost_dev, vdev, true);
 
-    if (k->set_guest_notifiers(qbus->parent, vvc->vhost_dev.nvqs, false) < 0) {
-        error_report("vhost guest notifier cleanup failed: %d", ret);
-        return -1;
+    err = k->set_guest_notifiers(qbus->parent, vvc->vhost_dev.nvqs, false);
+    if (err < 0) {
+        error_report("vhost guest notifier cleanup failed: %d", err);
+        return err;
     }
 
     vhost_dev_disable_notifiers(&vvc->vhost_dev, vdev);
-- 
MST


^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 070/106] q35: Fix incorrect values for PCIEXBAR masks
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (68 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 069/106] vhost-user: Fix stale error logs and return values in teardown paths Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 071/106] net/vhost-vdpa: enable vqs before DRIVER_OK if no cvq Michael S. Tsirkin
                   ` (36 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Alexey Gerasimenko, Thierry Escande

From: Alexey Gerasimenko <x1917x@gmail.com>

There are two small issues in PCIEXBAR address mask handling:
- wrong bit positions for address mask bits (see PCIEXBAR description
  in Q35 datasheet)
- incorrect usage of 64ADR_MASK

Due to this, attempting to write a valid PCIEXBAR address may cause it
to shift to another address, causing memory layout corruption where
emulated MMIO regions may overlap real (passed through) MMIO ranges. Fix
this by providing correct values.

Fixes: df2d8b3ed4 ("q35: Introduce q35 pc based chipset emulator")
Signed-off-by: Alexey Gerasimenko <x1917x@gmail.com>
Signed-off-by: Thierry Escande <thierry.escande@vates.tech>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260313164649.794591-4-thierry.escande@vates.tech>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/pci-host/q35.c         | 6 +++---
 include/hw/pci-host/q35.h | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index e85e4227b3..7368e3c598 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -306,12 +306,12 @@ static void mch_update_pciexbar(MCHPCIState *mch)
         break;
     case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_128M:
         length = 128 * 1024 * 1024;
-        addr_mask |= MCH_HOST_BRIDGE_PCIEXBAR_128ADMSK |
-            MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK;
+        addr_mask |= MCH_HOST_BRIDGE_PCIEXBAR_128ADMSK;
         break;
     case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_64M:
         length = 64 * 1024 * 1024;
-        addr_mask |= MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK;
+        addr_mask |= MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK |
+            MCH_HOST_BRIDGE_PCIEXBAR_128ADMSK;
         break;
     case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_RVD:
         qemu_log_mask(LOG_GUEST_ERROR, "Q35: Reserved PCIEXBAR LENGTH\n");
diff --git a/include/hw/pci-host/q35.h b/include/hw/pci-host/q35.h
index ddafc3f2e3..f31a71010b 100644
--- a/include/hw/pci-host/q35.h
+++ b/include/hw/pci-host/q35.h
@@ -100,8 +100,8 @@ struct Q35PCIHost {
 #define MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT       0xb0000000
 #define MCH_HOST_BRIDGE_PCIEXBAR_MAX           (0x10000000) /* 256M */
 #define MCH_HOST_BRIDGE_PCIEXBAR_ADMSK         Q35_MASK(64, 35, 28)
-#define MCH_HOST_BRIDGE_PCIEXBAR_128ADMSK      ((uint64_t)(1 << 26))
-#define MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK       ((uint64_t)(1 << 25))
+#define MCH_HOST_BRIDGE_PCIEXBAR_128ADMSK      ((uint64_t)(1 << 27))
+#define MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK       ((uint64_t)(1 << 26))
 #define MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_MASK   ((uint64_t)(0x3 << 1))
 #define MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_256M   ((uint64_t)(0x0 << 1))
 #define MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_128M   ((uint64_t)(0x1 << 1))
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 071/106] net/vhost-vdpa: enable vqs before DRIVER_OK if no cvq
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (69 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 070/106] q35: Fix incorrect values for PCIEXBAR masks Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 072/106] virtio: Allow to fill a whole virtqueue in order Michael S. Tsirkin
                   ` (35 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Eugenio Pérez, Jason Wang, Stefano Garzarella

From: Eugenio Pérez <eperezma@redhat.com>

VDUSE do not forward the enable message to the userland device at the
moment, leaving the dataplane disabled.  As there is no functional
difference if the device have no CVQ, enable them before DRIVER_OK in
that case.

For devices with a control vq, keep the enabling of the dataplane after
CVQ so QEMU can restore the device configuration.

Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
Fixes: 6c4825476a43 ("vdpa: move vhost_vdpa_set_vring_ready to the caller")
Acked-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260304173857.2705296-1-eperezma@redhat.com>
---
 net/vhost-vdpa.c | 30 ++++++++++--------------------
 1 file changed, 10 insertions(+), 20 deletions(-)

diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
index c85956a04b..c526c2b2dc 100644
--- a/net/vhost-vdpa.c
+++ b/net/vhost-vdpa.c
@@ -396,6 +396,7 @@ static int vhost_vdpa_net_data_start(NetClientState *nc)
 {
     VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
     struct vhost_vdpa *v = &s->vhost_vdpa;
+    bool has_cvq = v->dev->vq_index_end % 2;
 
     assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
 
@@ -405,6 +406,15 @@ static int vhost_vdpa_net_data_start(NetClientState *nc)
         v->shadow_vqs_enabled = false;
     }
 
+    if (!has_cvq) {
+        for (int i = 0; i < v->dev->nvqs; ++i) {
+            int ret = vhost_vdpa_set_vring_ready(v, i + v->dev->vq_index);
+            if (ret < 0) {
+                return ret;
+            }
+        }
+    }
+
     if (v->index == 0) {
         v->shared->shadow_data = v->shadow_vqs_enabled;
         vhost_vdpa_net_data_start_first(s);
@@ -414,25 +424,6 @@ static int vhost_vdpa_net_data_start(NetClientState *nc)
     return 0;
 }
 
-static int vhost_vdpa_net_data_load(NetClientState *nc)
-{
-    VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
-    struct vhost_vdpa *v = &s->vhost_vdpa;
-    bool has_cvq = v->dev->vq_index_end % 2;
-
-    if (has_cvq) {
-        return 0;
-    }
-
-    for (int i = 0; i < v->dev->nvqs; ++i) {
-        int ret = vhost_vdpa_set_vring_ready(v, i + v->dev->vq_index);
-        if (ret < 0) {
-            return ret;
-        }
-    }
-    return 0;
-}
-
 static void vhost_vdpa_net_client_stop(NetClientState *nc)
 {
     VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
@@ -449,7 +440,6 @@ static NetClientInfo net_vhost_vdpa_info = {
         .size = sizeof(VhostVDPAState),
         .receive = vhost_vdpa_receive,
         .start = vhost_vdpa_net_data_start,
-        .load = vhost_vdpa_net_data_load,
         .stop = vhost_vdpa_net_client_stop,
         .cleanup = vhost_vdpa_cleanup,
         .has_vnet_hdr = vhost_vdpa_has_vnet_hdr,
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 072/106] virtio: Allow to fill a whole virtqueue in order
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (70 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 071/106] net/vhost-vdpa: enable vqs before DRIVER_OK if no cvq Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 073/106] vhost: move svq next desc array to descs state struct Michael S. Tsirkin
                   ` (34 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Eugenio Pérez

From: Eugenio Pérez <eperezma@redhat.com>

As the while steps < max_steps is already one less than the vq size, the
right maximum max_steps variable is queue length, not the maximum
possible remainder of % vq->vring.num.

Fixes: b44135daa37 ("virtio: virtqueue_ordered_fill - VIRTIO_F_IN_ORDER support")
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260304173535.2702587-2-eperezma@redhat.com>
---
 hw/virtio/virtio.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index fb7f7f0f06..ed58c1af9f 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -986,7 +986,7 @@ static void virtqueue_ordered_fill(VirtQueue *vq, const VirtQueueElement *elem,
      * We shouldn't need to increase 'i' by more than or equal to
      * the distance between used_idx and last_avail_idx (max_steps).
      */
-    max_steps = (vq->last_avail_idx - vq->used_idx) % vq->vring.num;
+    max_steps = MIN(vq->last_avail_idx - vq->used_idx, vq->vring.num);
 
     /* Search for element in vq->used_elems */
     while (steps < max_steps) {
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 073/106] vhost: move svq next desc array to descs state struct
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (71 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 072/106] virtio: Allow to fill a whole virtqueue in order Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 074/106] vhost: factor out the descriptor next fetching Michael S. Tsirkin
                   ` (33 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Eugenio Pérez, Jason Wang, Stefano Garzarella

From: Eugenio Pérez <eperezma@redhat.com>

It's the right place for it as it is part of the descriptor state.  We
save the memory management of the array, and make the code changes of
the next patches easier.

Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
Acked-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260304173535.2702587-3-eperezma@redhat.com>
---
 hw/virtio/vhost-shadow-virtqueue.c | 14 ++++++--------
 hw/virtio/vhost-shadow-virtqueue.h | 12 ++++++------
 2 files changed, 12 insertions(+), 14 deletions(-)

diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
index 6242aeb69c..901253d06e 100644
--- a/hw/virtio/vhost-shadow-virtqueue.c
+++ b/hw/virtio/vhost-shadow-virtqueue.c
@@ -175,7 +175,7 @@ static bool vhost_svq_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg,
     for (n = 0; n < num; n++) {
         if (more_descs || (n + 1 < num)) {
             descs[i].flags = flags | cpu_to_le16(VRING_DESC_F_NEXT);
-            descs[i].next = cpu_to_le16(svq->desc_next[i]);
+            descs[i].next = cpu_to_le16(svq->desc_state[i].next);
         } else {
             descs[i].flags = flags;
         }
@@ -183,10 +183,10 @@ static bool vhost_svq_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg,
         descs[i].len = cpu_to_le32(iovec[n].iov_len);
 
         last = i;
-        i = svq->desc_next[i];
+        i = svq->desc_state[i].next;
     }
 
-    svq->free_head = svq->desc_next[last];
+    svq->free_head = svq->desc_state[last].next;
     return true;
 }
 
@@ -432,7 +432,7 @@ static uint16_t vhost_svq_last_desc_of_chain(const VhostShadowVirtqueue *svq,
                                              uint16_t num, uint16_t i)
 {
     for (uint16_t j = 0; j < (num - 1); ++j) {
-        i = svq->desc_next[i];
+        i = svq->desc_state[i].next;
     }
 
     return i;
@@ -473,7 +473,7 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
     num = svq->desc_state[used_elem.id].ndescs;
     svq->desc_state[used_elem.id].ndescs = 0;
     last_used_chain = vhost_svq_last_desc_of_chain(svq, num, used_elem.id);
-    svq->desc_next[last_used_chain] = svq->free_head;
+    svq->desc_state[last_used_chain].next = svq->free_head;
     svq->free_head = used_elem.id;
     svq->num_free += num;
 
@@ -705,9 +705,8 @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev,
                            PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,
                            -1, 0);
     svq->desc_state = g_new0(SVQDescState, svq->vring.num);
-    svq->desc_next = g_new0(uint16_t, svq->vring.num);
     for (unsigned i = 0; i < svq->vring.num - 1; i++) {
-        svq->desc_next[i] = i + 1;
+        svq->desc_state[i].next = i + 1;
     }
 }
 
@@ -744,7 +743,6 @@ void vhost_svq_stop(VhostShadowVirtqueue *svq)
         virtqueue_unpop(svq->vq, next_avail_elem, 0);
     }
     svq->vq = NULL;
-    g_free(svq->desc_next);
     g_free(svq->desc_state);
     munmap(svq->vring.desc, vhost_svq_driver_area_size(svq));
     munmap(svq->vring.used, vhost_svq_device_area_size(svq));
diff --git a/hw/virtio/vhost-shadow-virtqueue.h b/hw/virtio/vhost-shadow-virtqueue.h
index 9c273739d6..f52c33e650 100644
--- a/hw/virtio/vhost-shadow-virtqueue.h
+++ b/hw/virtio/vhost-shadow-virtqueue.h
@@ -23,6 +23,12 @@ typedef struct SVQDescState {
      * guest's
      */
     unsigned int ndescs;
+
+    /*
+     * Backup next field for each descriptor so we can recover securely, not
+     * needing to trust the device access.
+     */
+    uint16_t next;
 } SVQDescState;
 
 typedef struct VhostShadowVirtqueue VhostShadowVirtqueue;
@@ -84,12 +90,6 @@ typedef struct VhostShadowVirtqueue {
     /* Next VirtQueue element that guest made available */
     VirtQueueElement *next_guest_avail_elem;
 
-    /*
-     * Backup next field for each descriptor so we can recover securely, not
-     * needing to trust the device access.
-     */
-    uint16_t *desc_next;
-
     /* Caller callbacks */
     const VhostShadowVirtqueueOps *ops;
 
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 074/106] vhost: factor out the descriptor next fetching
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (72 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 073/106] vhost: move svq next desc array to descs state struct Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 075/106] vhost: factor out the get of last used desc in SVQ Michael S. Tsirkin
                   ` (32 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Eugenio Pérez, Jason Wang, Stefano Garzarella

From: Eugenio Pérez <eperezma@redhat.com>

The next field will not be used if IN_ORDER is enabled.

Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
Acked-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260304173535.2702587-4-eperezma@redhat.com>
---
 hw/virtio/vhost-shadow-virtqueue.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
index 901253d06e..7adacd4f54 100644
--- a/hw/virtio/vhost-shadow-virtqueue.c
+++ b/hw/virtio/vhost-shadow-virtqueue.c
@@ -139,6 +139,20 @@ static bool vhost_svq_translate_addr(const VhostShadowVirtqueue *svq,
     return true;
 }
 
+/**
+ * Get the next descriptor in the chain in SVQ vring from a descriptor id
+ *
+ * @svq Shadow Virtqueue
+ * @id ID of the descriptor
+ *
+ * Return the id of the next descriptor.
+ */
+static uint16_t vhost_svq_next_desc(const VhostShadowVirtqueue *svq,
+                                    uint16_t id)
+{
+    return svq->desc_state[id].next;
+}
+
 /**
  * Write descriptors to SVQ vring
  *
@@ -173,9 +187,11 @@ static bool vhost_svq_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg,
     }
 
     for (n = 0; n < num; n++) {
+        uint16_t next = vhost_svq_next_desc(svq, i);
+
         if (more_descs || (n + 1 < num)) {
             descs[i].flags = flags | cpu_to_le16(VRING_DESC_F_NEXT);
-            descs[i].next = cpu_to_le16(svq->desc_state[i].next);
+            descs[i].next = cpu_to_le16(next);
         } else {
             descs[i].flags = flags;
         }
@@ -183,10 +199,10 @@ static bool vhost_svq_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg,
         descs[i].len = cpu_to_le32(iovec[n].iov_len);
 
         last = i;
-        i = svq->desc_state[i].next;
+        i = next;
     }
 
-    svq->free_head = svq->desc_state[last].next;
+    svq->free_head = vhost_svq_next_desc(svq, last);
     return true;
 }
 
@@ -432,7 +448,7 @@ static uint16_t vhost_svq_last_desc_of_chain(const VhostShadowVirtqueue *svq,
                                              uint16_t num, uint16_t i)
 {
     for (uint16_t j = 0; j < (num - 1); ++j) {
-        i = svq->desc_state[i].next;
+        i = vhost_svq_next_desc(svq, i);
     }
 
     return i;
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 075/106] vhost: factor out the get of last used desc in SVQ
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (73 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 074/106] vhost: factor out the descriptor next fetching Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 076/106] vhost: factor out the detach buf logic " Michael S. Tsirkin
                   ` (31 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Eugenio Pérez, Stefano Garzarella

From: Eugenio Pérez <eperezma@redhat.com>

This code path is modified to handle in order devices.  Abstract here so
we can generalize on the caller.

Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260304173535.2702587-5-eperezma@redhat.com>
---
 hw/virtio/vhost-shadow-virtqueue.c | 45 +++++++++++++++++++-----------
 1 file changed, 29 insertions(+), 16 deletions(-)

diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
index 7adacd4f54..e7e3c9155c 100644
--- a/hw/virtio/vhost-shadow-virtqueue.c
+++ b/hw/virtio/vhost-shadow-virtqueue.c
@@ -444,6 +444,25 @@ static void vhost_svq_disable_notification(VhostShadowVirtqueue *svq)
     }
 }
 
+/*
+ * Gets the next buffer id and moves forward the used idx, so the next time
+ * SVQ calls this function will get the next one.
+ *
+ * @svq: Shadow VirtQueue
+ * @len: Consumed length by the device.
+ *
+ * Return the next descriptor consumed by the device.
+ */
+static uint16_t vhost_svq_get_last_used_split(VhostShadowVirtqueue *svq,
+                                              uint32_t *len)
+{
+    const vring_used_t *used = svq->vring.used;
+    uint16_t last_used = svq->last_used_idx++ & (svq->vring.num - 1);
+
+    *len = le32_to_cpu(used->ring[last_used].len);
+    return le32_to_cpu(used->ring[last_used].id);
+}
+
 static uint16_t vhost_svq_last_desc_of_chain(const VhostShadowVirtqueue *svq,
                                              uint16_t num, uint16_t i)
 {
@@ -458,8 +477,6 @@ G_GNUC_WARN_UNUSED_RESULT
 static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
                                            uint32_t *len)
 {
-    const vring_used_t *used = svq->vring.used;
-    vring_used_elem_t used_elem;
     uint16_t last_used, last_used_chain, num;
 
     if (!vhost_svq_more_used(svq)) {
@@ -468,33 +485,29 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
 
     /* Only get used array entries after they have been exposed by dev */
     smp_rmb();
-    last_used = svq->last_used_idx & (svq->vring.num - 1);
-    used_elem.id = le32_to_cpu(used->ring[last_used].id);
-    used_elem.len = le32_to_cpu(used->ring[last_used].len);
+    last_used = vhost_svq_get_last_used_split(svq, len);
 
-    svq->last_used_idx++;
-    if (unlikely(used_elem.id >= svq->vring.num)) {
+    if (unlikely(last_used >= svq->vring.num)) {
         qemu_log_mask(LOG_GUEST_ERROR, "Device %s says index %u is used",
-                      svq->vdev->name, used_elem.id);
+                      svq->vdev->name, last_used);
         return NULL;
     }
 
-    if (unlikely(!svq->desc_state[used_elem.id].ndescs)) {
+    if (unlikely(!svq->desc_state[last_used].ndescs)) {
         qemu_log_mask(LOG_GUEST_ERROR,
             "Device %s says index %u is used, but it was not available",
-            svq->vdev->name, used_elem.id);
+            svq->vdev->name, last_used);
         return NULL;
     }
 
-    num = svq->desc_state[used_elem.id].ndescs;
-    svq->desc_state[used_elem.id].ndescs = 0;
-    last_used_chain = vhost_svq_last_desc_of_chain(svq, num, used_elem.id);
+    num = svq->desc_state[last_used].ndescs;
+    svq->desc_state[last_used].ndescs = 0;
+    last_used_chain = vhost_svq_last_desc_of_chain(svq, num, last_used);
     svq->desc_state[last_used_chain].next = svq->free_head;
-    svq->free_head = used_elem.id;
+    svq->free_head = last_used;
     svq->num_free += num;
 
-    *len = used_elem.len;
-    return g_steal_pointer(&svq->desc_state[used_elem.id].elem);
+    return g_steal_pointer(&svq->desc_state[last_used].elem);
 }
 
 /**
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 076/106] vhost: factor out the detach buf logic in SVQ
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (74 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 075/106] vhost: factor out the get of last used desc in SVQ Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:08 ` [PULL 077/106] vhost: add in_order feature to shadow virtqueue Michael S. Tsirkin
                   ` (30 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Eugenio Pérez, Stefano Garzarella

From: Eugenio Pérez <eperezma@redhat.com>

This code path is modified to handle in order devices.  Abstract here so
we can generalize on the caller.

Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260304173535.2702587-6-eperezma@redhat.com>
---
 hw/virtio/vhost-shadow-virtqueue.c | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
index e7e3c9155c..2d8fc82cc0 100644
--- a/hw/virtio/vhost-shadow-virtqueue.c
+++ b/hw/virtio/vhost-shadow-virtqueue.c
@@ -473,11 +473,24 @@ static uint16_t vhost_svq_last_desc_of_chain(const VhostShadowVirtqueue *svq,
     return i;
 }
 
+G_GNUC_WARN_UNUSED_RESULT
+static VirtQueueElement *vhost_svq_detach_buf(VhostShadowVirtqueue *svq,
+                                              uint16_t id)
+{
+    uint16_t num = svq->desc_state[id].ndescs;
+    uint16_t last_used_chain = vhost_svq_last_desc_of_chain(svq, num, id);
+
+    svq->desc_state[last_used_chain].next = svq->free_head;
+    svq->free_head = id;
+
+    return g_steal_pointer(&svq->desc_state[id].elem);
+}
+
 G_GNUC_WARN_UNUSED_RESULT
 static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
                                            uint32_t *len)
 {
-    uint16_t last_used, last_used_chain, num;
+    uint16_t last_used;
 
     if (!vhost_svq_more_used(svq)) {
         return NULL;
@@ -500,14 +513,9 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
         return NULL;
     }
 
-    num = svq->desc_state[last_used].ndescs;
+    svq->num_free += svq->desc_state[last_used].ndescs;
     svq->desc_state[last_used].ndescs = 0;
-    last_used_chain = vhost_svq_last_desc_of_chain(svq, num, last_used);
-    svq->desc_state[last_used_chain].next = svq->free_head;
-    svq->free_head = last_used;
-    svq->num_free += num;
-
-    return g_steal_pointer(&svq->desc_state[last_used].elem);
+    return vhost_svq_detach_buf(svq, last_used);
 }
 
 /**
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 077/106] vhost: add in_order feature to shadow virtqueue
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (75 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 076/106] vhost: factor out the detach buf logic " Michael S. Tsirkin
@ 2026-06-14 19:08 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 078/106] vhost: accept in order feature flag Michael S. Tsirkin
                   ` (29 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Eugenio Pérez, Jason Wang, Stefano Garzarella

From: Eugenio Pérez <eperezma@redhat.com>

Some vdpa devices benefit from the in order feature.  Add support to SVQ
so QEMU can migrate these.

Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
Acked-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260304173535.2702587-7-eperezma@redhat.com>
---
 hw/virtio/vhost-shadow-virtqueue.c | 137 +++++++++++++++++++++++++++--
 hw/virtio/vhost-shadow-virtqueue.h |  36 ++++++--
 2 files changed, 160 insertions(+), 13 deletions(-)

diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
index 2d8fc82cc0..60212fcd7b 100644
--- a/hw/virtio/vhost-shadow-virtqueue.c
+++ b/hw/virtio/vhost-shadow-virtqueue.c
@@ -12,11 +12,14 @@
 
 #include "qemu/error-report.h"
 #include "qapi/error.h"
+#include "qemu/iov.h"
 #include "qemu/main-loop.h"
 #include "qemu/log.h"
 #include "qemu/memalign.h"
 #include "linux-headers/linux/vhost.h"
 
+#define VIRTIO_RING_NOT_IN_BATCH UINT16_MAX
+
 /**
  * Validate the transport device features that both guests can use with the SVQ
  * and SVQs can use with the device.
@@ -150,7 +153,33 @@ static bool vhost_svq_translate_addr(const VhostShadowVirtqueue *svq,
 static uint16_t vhost_svq_next_desc(const VhostShadowVirtqueue *svq,
                                     uint16_t id)
 {
-    return svq->desc_state[id].next;
+    if (virtio_vdev_has_feature(svq->vdev, VIRTIO_F_IN_ORDER)) {
+        return (id == svq->vring.num) ? 0 : ++id;
+    } else {
+        return svq->desc_state[id].next;
+    }
+}
+
+/**
+ * Updates the SVQ free_head member after adding them to the SVQ avail ring.
+ * The new free_head is the next descriptor that SVQ will make available by
+ * forwarding a new guest descriptor.
+ *
+ * @svq Shadow Virtqueue
+ * @num Number of descriptors added
+ * @id ID of the last descriptor added to the SVQ avail ring.
+ */
+static void vhost_svq_update_free_head(VhostShadowVirtqueue *svq,
+                                       size_t num, uint16_t id)
+{
+    if (virtio_vdev_has_feature(svq->vdev, VIRTIO_F_IN_ORDER)) {
+        svq->free_head += num;
+        if (svq->free_head >= svq->vring.num) {
+            svq->free_head -= svq->vring.num;
+        }
+    } else {
+        svq->free_head = vhost_svq_next_desc(svq, id);
+    }
 }
 
 /**
@@ -202,7 +231,7 @@ static bool vhost_svq_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg,
         i = next;
     }
 
-    svq->free_head = vhost_svq_next_desc(svq, last);
+    vhost_svq_update_free_head(svq, num, last);
     return true;
 }
 
@@ -306,6 +335,9 @@ int vhost_svq_add(VhostShadowVirtqueue *svq, const struct iovec *out_sg,
     svq->num_free -= ndescs;
     svq->desc_state[qemu_head].elem = elem;
     svq->desc_state[qemu_head].ndescs = ndescs;
+    if (virtio_vdev_has_feature(svq->vdev, VIRTIO_F_IN_ORDER)) {
+        svq->desc_state[qemu_head].in_bytes = iov_size(in_sg, in_num);
+    }
     vhost_svq_kick(svq);
     return 0;
 }
@@ -401,6 +433,12 @@ static void vhost_handle_guest_kick_notifier(EventNotifier *n)
 static bool vhost_svq_more_used(VhostShadowVirtqueue *svq)
 {
     uint16_t *used_idx = &svq->vring.used->idx;
+
+    if (virtio_vdev_has_feature(svq->vdev, VIRTIO_F_IN_ORDER) &&
+        svq->batch_last.id != VIRTIO_RING_NOT_IN_BATCH) {
+        return true;
+    }
+
     if (svq->last_used_idx != svq->shadow_used_idx) {
         return true;
     }
@@ -463,6 +501,47 @@ static uint16_t vhost_svq_get_last_used_split(VhostShadowVirtqueue *svq,
     return le32_to_cpu(used->ring[last_used].id);
 }
 
+/*
+ * Gets the next buffer id and moves forward the used idx, so the next time
+ * SVQ calls this function will get the next one.  IN_ORDER version
+ *
+ * @svq: Shadow VirtQueue
+ * @len: Consumed length by the device.
+ *
+ * Return the next descriptor consumed by the device.
+ */
+static int32_t vhost_svq_get_last_used_split_in_order(
+        VhostShadowVirtqueue *svq,
+        uint32_t *len)
+{
+    unsigned num = svq->vring.num;
+    const vring_used_t *used = svq->vring.used;
+    uint16_t last_used = svq->last_used & (num - 1);
+    uint16_t last_used_idx = svq->last_used_idx & (num - 1);
+
+    if (svq->batch_last.id == VIRTIO_RING_NOT_IN_BATCH) {
+        svq->batch_last.id = le32_to_cpu(used->ring[last_used_idx].id);
+        svq->batch_last.len = le32_to_cpu(used->ring[last_used_idx].len);
+    }
+
+    if (unlikely(last_used >= num)) {
+        qemu_log_mask(LOG_GUEST_ERROR, "Device %s says index %u is used",
+                      svq->vdev->name, last_used);
+        return -1;
+    }
+
+    if (svq->batch_last.id == last_used) {
+        svq->batch_last.id = VIRTIO_RING_NOT_IN_BATCH;
+        *len = svq->batch_last.len;
+    } else {
+        *len = svq->desc_state[last_used].in_bytes;
+    }
+
+    svq->last_used += svq->desc_state[last_used].ndescs;
+    svq->last_used_idx++;
+    return last_used;
+}
+
 static uint16_t vhost_svq_last_desc_of_chain(const VhostShadowVirtqueue *svq,
                                              uint16_t num, uint16_t i)
 {
@@ -474,8 +553,8 @@ static uint16_t vhost_svq_last_desc_of_chain(const VhostShadowVirtqueue *svq,
 }
 
 G_GNUC_WARN_UNUSED_RESULT
-static VirtQueueElement *vhost_svq_detach_buf(VhostShadowVirtqueue *svq,
-                                              uint16_t id)
+static VirtQueueElement *vhost_svq_detach_buf_split(VhostShadowVirtqueue *svq,
+                                                    uint16_t id)
 {
     uint16_t num = svq->desc_state[id].ndescs;
     uint16_t last_used_chain = vhost_svq_last_desc_of_chain(svq, num, id);
@@ -486,6 +565,33 @@ static VirtQueueElement *vhost_svq_detach_buf(VhostShadowVirtqueue *svq,
     return g_steal_pointer(&svq->desc_state[id].elem);
 }
 
+G_GNUC_WARN_UNUSED_RESULT
+static VirtQueueElement *vhost_svq_detach_buf_split_in_order(
+        VhostShadowVirtqueue *svq,
+        uint16_t id)
+{
+    return g_steal_pointer(&svq->desc_state[id].elem);
+}
+
+/*
+ * Return the descriptor id (and the chain of ids) to the free list
+ *
+ * @svq: Shadow Virtqueue
+ * @id: Id of the buffer to return.
+ *
+ * Return the element associated to the buffer if any.
+ */
+G_GNUC_WARN_UNUSED_RESULT
+static VirtQueueElement *vhost_svq_detach_buf(VhostShadowVirtqueue *svq,
+                                              uint16_t id)
+{
+    if (virtio_vdev_has_feature(svq->vdev, VIRTIO_F_IN_ORDER)) {
+        return vhost_svq_detach_buf_split_in_order(svq, id);
+    } else {
+        return vhost_svq_detach_buf_split(svq, id);
+    }
+}
+
 G_GNUC_WARN_UNUSED_RESULT
 static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
                                            uint32_t *len)
@@ -498,7 +604,18 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
 
     /* Only get used array entries after they have been exposed by dev */
     smp_rmb();
-    last_used = vhost_svq_get_last_used_split(svq, len);
+
+    if (virtio_vdev_has_feature(svq->vdev, VIRTIO_F_IN_ORDER)) {
+        int32_t r;
+        r = vhost_svq_get_last_used_split_in_order(svq, len);
+        if (r < 0) {
+            return NULL;
+        }
+
+        last_used = r;
+    } else {
+        last_used = vhost_svq_get_last_used_split(svq, len);
+    }
 
     if (unlikely(last_used >= svq->vring.num)) {
         qemu_log_mask(LOG_GUEST_ERROR, "Device %s says index %u is used",
@@ -726,6 +843,8 @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev,
     svq->next_guest_avail_elem = NULL;
     svq->shadow_avail_idx = 0;
     svq->shadow_used_idx = 0;
+    memset(&svq->batch_last, 0, sizeof(svq->batch_last));
+    svq->last_used = 0;
     svq->last_used_idx = 0;
     svq->vdev = vdev;
     svq->vq = vq;
@@ -742,8 +861,12 @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev,
                            PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,
                            -1, 0);
     svq->desc_state = g_new0(SVQDescState, svq->vring.num);
-    for (unsigned i = 0; i < svq->vring.num - 1; i++) {
-        svq->desc_state[i].next = i + 1;
+    if (virtio_vdev_has_feature(svq->vdev, VIRTIO_F_IN_ORDER)) {
+        svq->batch_last.id = VIRTIO_RING_NOT_IN_BATCH;
+    } else {
+        for (unsigned i = 0; i < svq->vring.num - 1; i++) {
+            svq->desc_state[i].next = i + 1;
+        }
     }
 }
 
diff --git a/hw/virtio/vhost-shadow-virtqueue.h b/hw/virtio/vhost-shadow-virtqueue.h
index f52c33e650..ec16a1e838 100644
--- a/hw/virtio/vhost-shadow-virtqueue.h
+++ b/hw/virtio/vhost-shadow-virtqueue.h
@@ -24,11 +24,19 @@ typedef struct SVQDescState {
      */
     unsigned int ndescs;
 
-    /*
-     * Backup next field for each descriptor so we can recover securely, not
-     * needing to trust the device access.
-     */
-    uint16_t next;
+    union {
+        /*
+         * Total length of the available buffer that is writable by the device.
+         * Only used in packed vq.
+         */
+        uint32_t in_bytes;
+
+        /*
+         * Backup next field for each descriptor so we can recover securely, not
+         * needing to trust the device access.  Only used in split vq.
+         */
+        uint16_t next;
+    };
 } SVQDescState;
 
 typedef struct VhostShadowVirtqueue VhostShadowVirtqueue;
@@ -99,9 +107,25 @@ typedef struct VhostShadowVirtqueue {
     /* Next head to expose to the device */
     uint16_t shadow_avail_idx;
 
-    /* Next free descriptor */
+    /*
+     * Next free descriptor.
+     *
+     * Without IN_ORDER free_head is used as a linked list head, and
+     * desc_next[id] is the next element.
+     * With IN_ORDER free_head is the next available buffer index.
+     */
     uint16_t free_head;
 
+    /*
+     * Last used element of the processing batch of used descriptors if
+     * IN_ORDER.
+     * If SVQ is not processing a batch of descriptors id is set to UINT_MAX.
+     */
+    vring_used_elem_t batch_last;
+
+    /* Last used id if IN_ORDER and split vq */
+    uint16_t last_used;
+
     /* Last seen used idx */
     uint16_t shadow_used_idx;
 
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 078/106] vhost: accept in order feature flag
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (76 preceding siblings ...)
  2026-06-14 19:08 ` [PULL 077/106] vhost: add in_order feature to shadow virtqueue Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 079/106] amd_iommu: Use switch case to determine mmio register name Michael S. Tsirkin
                   ` (28 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Eugenio Pérez, Jason Wang, Stefano Garzarella

From: Eugenio Pérez <eperezma@redhat.com>

Let's accept the feature flag with all the infrastructure to process it
in place.

Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
Acked-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260304173535.2702587-8-eperezma@redhat.com>
---
 hw/virtio/vhost-shadow-virtqueue.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
index 60212fcd7b..bcb7f2ffc7 100644
--- a/hw/virtio/vhost-shadow-virtqueue.c
+++ b/hw/virtio/vhost-shadow-virtqueue.c
@@ -38,6 +38,7 @@ bool vhost_svq_valid_features(uint64_t features, Error **errp)
         case VIRTIO_F_ANY_LAYOUT:
         case VIRTIO_RING_F_EVENT_IDX:
         case VIRTIO_RING_F_INDIRECT_DESC:
+        case VIRTIO_F_IN_ORDER:
             continue;
 
         case VIRTIO_F_ACCESS_PLATFORM:
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 079/106] amd_iommu: Use switch case to determine mmio register name
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (77 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 078/106] vhost: accept in order feature flag Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 080/106] amd_iommu: Turn on XT support only when guest has enabled it Michael S. Tsirkin
                   ` (27 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Sairaj Kodilkar, Vasant Hegde, Alejandro Jimenez,
	Paolo Bonzini, Richard Henderson

From: Sairaj Kodilkar <sarunkod@amd.com>

This makes it easier to add new MMIO registers for tracing and removes
the unnecessary complexity introduced by amdvi_mmio_(low/high) array.

Signed-off-by: Sairaj Kodilkar <sarunkod@amd.com>
Reviewed-by: Vasant Hegde <vasant.hegde@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: <20260302115130.5903-2-sarunkod@amd.com>
---
 hw/i386/amd_iommu.c | 74 ++++++++++++++++-----------------------------
 hw/i386/amd_iommu.h |  4 ---
 2 files changed, 26 insertions(+), 52 deletions(-)

diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
index 99b05b2ab6..1c44848aa9 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -35,29 +35,6 @@
 #include "kvm/kvm_i386.h"
 #include "qemu/iova-tree.h"
 
-/* used AMD-Vi MMIO registers */
-const char *amdvi_mmio_low[] = {
-    "AMDVI_MMIO_DEVTAB_BASE",
-    "AMDVI_MMIO_CMDBUF_BASE",
-    "AMDVI_MMIO_EVTLOG_BASE",
-    "AMDVI_MMIO_CONTROL",
-    "AMDVI_MMIO_EXCL_BASE",
-    "AMDVI_MMIO_EXCL_LIMIT",
-    "AMDVI_MMIO_EXT_FEATURES",
-    "AMDVI_MMIO_PPR_BASE",
-    "UNHANDLED"
-};
-const char *amdvi_mmio_high[] = {
-    "AMDVI_MMIO_COMMAND_HEAD",
-    "AMDVI_MMIO_COMMAND_TAIL",
-    "AMDVI_MMIO_EVTLOG_HEAD",
-    "AMDVI_MMIO_EVTLOG_TAIL",
-    "AMDVI_MMIO_STATUS",
-    "AMDVI_MMIO_PPR_HEAD",
-    "AMDVI_MMIO_PPR_TAIL",
-    "UNHANDLED"
-};
-
 struct AMDVIAddressSpace {
     PCIBus *bus;                /* PCIBus (for bus number)              */
     uint8_t devfn;              /* device function                      */
@@ -1540,31 +1517,31 @@ static void amdvi_cmdbuf_run(AMDVIState *s)
     }
 }
 
-static inline uint8_t amdvi_mmio_get_index(hwaddr addr)
+static inline
+const char *amdvi_mmio_get_name(hwaddr addr)
 {
-    uint8_t index = (addr & ~0x2000) / 8;
-
-    if ((addr & 0x2000)) {
-        /* high table */
-        index = index >= AMDVI_MMIO_REGS_HIGH ? AMDVI_MMIO_REGS_HIGH : index;
-    } else {
-        index = index >= AMDVI_MMIO_REGS_LOW ? AMDVI_MMIO_REGS_LOW : index;
+    /* Return MMIO names as string literals */
+    switch (addr) {
+#define MMIO_REG_TO_STRING(mmio_reg) case mmio_reg: return #mmio_reg
+    MMIO_REG_TO_STRING(AMDVI_MMIO_DEVICE_TABLE);
+    MMIO_REG_TO_STRING(AMDVI_MMIO_COMMAND_BASE);
+    MMIO_REG_TO_STRING(AMDVI_MMIO_EVENT_BASE);
+    MMIO_REG_TO_STRING(AMDVI_MMIO_CONTROL);
+    MMIO_REG_TO_STRING(AMDVI_MMIO_EXCL_BASE);
+    MMIO_REG_TO_STRING(AMDVI_MMIO_EXCL_LIMIT);
+    MMIO_REG_TO_STRING(AMDVI_MMIO_EXT_FEATURES);
+    MMIO_REG_TO_STRING(AMDVI_MMIO_COMMAND_HEAD);
+    MMIO_REG_TO_STRING(AMDVI_MMIO_COMMAND_TAIL);
+    MMIO_REG_TO_STRING(AMDVI_MMIO_EVENT_HEAD);
+    MMIO_REG_TO_STRING(AMDVI_MMIO_EVENT_TAIL);
+    MMIO_REG_TO_STRING(AMDVI_MMIO_STATUS);
+    MMIO_REG_TO_STRING(AMDVI_MMIO_PPR_BASE);
+    MMIO_REG_TO_STRING(AMDVI_MMIO_PPR_HEAD);
+    MMIO_REG_TO_STRING(AMDVI_MMIO_PPR_TAIL);
+#undef MMIO_REG_TO_STRING
+    default:
+        return "UNHANDLED";
     }
-
-    return index;
-}
-
-static void amdvi_mmio_trace_read(hwaddr addr, unsigned size)
-{
-    uint8_t index = amdvi_mmio_get_index(addr);
-    trace_amdvi_mmio_read(amdvi_mmio_low[index], addr, size, addr & ~0x07);
-}
-
-static void amdvi_mmio_trace_write(hwaddr addr, unsigned size, uint64_t val)
-{
-    uint8_t index = amdvi_mmio_get_index(addr);
-    trace_amdvi_mmio_write(amdvi_mmio_low[index], addr, size, val,
-                           addr & ~0x07);
 }
 
 static uint64_t amdvi_mmio_read(void *opaque, hwaddr addr, unsigned size)
@@ -1584,7 +1561,7 @@ static uint64_t amdvi_mmio_read(void *opaque, hwaddr addr, unsigned size)
     } else if (size == 8) {
         val = amdvi_readq(s, addr);
     }
-    amdvi_mmio_trace_read(addr, size);
+    trace_amdvi_mmio_read(amdvi_mmio_get_name(addr), addr, size, addr & ~0x07);
 
     return val;
 }
@@ -1742,7 +1719,8 @@ static void amdvi_mmio_write(void *opaque, hwaddr addr, uint64_t val,
         return;
     }
 
-    amdvi_mmio_trace_write(addr, size, val);
+    trace_amdvi_mmio_write(amdvi_mmio_get_name(addr), addr, size, val, offset);
+
     switch (addr & ~0x07) {
     case AMDVI_MMIO_CONTROL:
         amdvi_mmio_reg_write(s, size, val, addr);
diff --git a/hw/i386/amd_iommu.h b/hw/i386/amd_iommu.h
index 7af3c742b7..17b7ba899f 100644
--- a/hw/i386/amd_iommu.h
+++ b/hw/i386/amd_iommu.h
@@ -45,10 +45,6 @@
 #define AMDVI_CAPAB_FLAG_IOTLBSUP     (1 << 24)
 #define AMDVI_CAPAB_INIT_TYPE         (3 << 16)
 
-/* No. of used MMIO registers */
-#define AMDVI_MMIO_REGS_HIGH  7
-#define AMDVI_MMIO_REGS_LOW   8
-
 /* MMIO registers */
 #define AMDVI_MMIO_DEVICE_TABLE       0x0000
 #define AMDVI_MMIO_COMMAND_BASE       0x0008
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 080/106] amd_iommu: Turn on XT support only when guest has enabled it
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (78 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 079/106] amd_iommu: Use switch case to determine mmio register name Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 081/106] amd_iommu: Generate XT interrupts when xt support is enabled Michael S. Tsirkin
                   ` (26 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Sairaj Kodilkar, Vasant Hegde, Alejandro Jimenez,
	Paolo Bonzini, Richard Henderson

From: Sairaj Kodilkar <sarunkod@amd.com>

Current code uses 32 bit destination ID irrespective of the fact that
guest has enabled x2APIC support through control register[XTEn] and
completely depends on command line parameter xtsup=on. This is not a
correct hardware behaviour and can cause problems in the guest which has
not enabled XT mode.

Introduce new flag "xten", which is enabled when guest writes 1 to the
control register bit 50 (XTEn). Also, add a new subsection in
`VMStateDescription` for backward compatibility during vm migration.

Signed-off-by: Sairaj Kodilkar <sarunkod@amd.com>
Reviewed-by: Vasant Hegde <vasant.hegde@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: <20260302115130.5903-3-sarunkod@amd.com>
---
 hw/i386/amd_iommu.c | 21 +++++++++++++++++++--
 hw/i386/amd_iommu.h |  4 +++-
 2 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
index 1c44848aa9..5947d3aecf 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -1579,6 +1579,8 @@ static void amdvi_handle_control_write(AMDVIState *s)
     s->cmdbuf_enabled = s->enabled && !!(control &
                         AMDVI_MMIO_CONTROL_CMDBUFLEN);
     s->ga_enabled = !!(control & AMDVI_MMIO_CONTROL_GAEN);
+    s->xten = !!(control & AMDVI_MMIO_CONTROL_XTEN) && s->xtsup &&
+              s->ga_enabled;
 
     /* update the flags depending on the control register */
     if (s->cmdbuf_enabled) {
@@ -2054,7 +2056,7 @@ static int amdvi_int_remap_ga(AMDVIState *iommu,
     irq->vector = irte.hi.fields.vector;
     irq->dest_mode = irte.lo.fields_remap.dm;
     irq->redir_hint = irte.lo.fields_remap.rq_eoi;
-    if (iommu->xtsup) {
+    if (iommu->xten) {
         irq->dest = irte.lo.fields_remap.destination |
                     (irte.hi.fields.destination_hi << 24);
     } else {
@@ -2437,6 +2439,7 @@ static void amdvi_init(AMDVIState *s)
     s->mmio_enabled = false;
     s->enabled = false;
     s->cmdbuf_enabled = false;
+    s->xten = false;
 
     /* reset MMIO */
     memset(s->mmior, 0, AMDVI_MMIO_SIZE);
@@ -2501,6 +2504,16 @@ static void amdvi_sysbus_reset(DeviceState *dev)
     amdvi_reset_address_translation_all(s);
 }
 
+static const VMStateDescription vmstate_xt = {
+       .name = "amd-iommu-xt",
+       .version_id = 1,
+       .minimum_version_id = 1,
+       .fields = (VMStateField[]) {
+           VMSTATE_BOOL(xten, AMDVIState),
+           VMSTATE_END_OF_LIST()
+       }
+};
+
 static const VMStateDescription vmstate_amdvi_sysbus_migratable = {
     .name = "amd-iommu",
     .version_id = 1,
@@ -2545,7 +2558,11 @@ static const VMStateDescription vmstate_amdvi_sysbus_migratable = {
       VMSTATE_UINT8_ARRAY(romask, AMDVIState, AMDVI_MMIO_SIZE),
       VMSTATE_UINT8_ARRAY(w1cmask, AMDVIState, AMDVI_MMIO_SIZE),
       VMSTATE_END_OF_LIST()
-    }
+    },
+    .subsections = (const VMStateDescription *const []) {
+                    &vmstate_xt,
+                    NULL
+     }
 };
 
 static void amdvi_sysbus_realize(DeviceState *dev, Error **errp)
diff --git a/hw/i386/amd_iommu.h b/hw/i386/amd_iommu.h
index 17b7ba899f..300d91b34d 100644
--- a/hw/i386/amd_iommu.h
+++ b/hw/i386/amd_iommu.h
@@ -102,6 +102,7 @@
 #define AMDVI_MMIO_CONTROL_COMWAITINTEN   (1ULL << 4)
 #define AMDVI_MMIO_CONTROL_CMDBUFLEN      (1ULL << 12)
 #define AMDVI_MMIO_CONTROL_GAEN           (1ULL << 17)
+#define AMDVI_MMIO_CONTROL_XTEN           (1ULL << 50)
 
 /* MMIO status register bits */
 #define AMDVI_MMIO_STATUS_CMDBUF_RUN  (1 << 4)
@@ -413,7 +414,8 @@ struct AMDVIState {
 
     /* Interrupt remapping */
     bool ga_enabled;
-    bool xtsup;
+    bool xtsup;     /* xtsup=on command line */
+    bool xten;      /* guest controlled, x2apic mode enabled */
 
     /* DMA address translation */
     bool dma_remap;
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 081/106] amd_iommu: Generate XT interrupts when xt support is enabled
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (79 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 080/106] amd_iommu: Turn on XT support only when guest has enabled it Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 082/106] standard-headers: Add virtio_rtc.h from Linux 7.0-rc1 Michael S. Tsirkin
                   ` (25 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Sairaj Kodilkar, Vasant Hegde, Alejandro Jimenez,
	Paolo Bonzini, Richard Henderson

From: Sairaj Kodilkar <sarunkod@amd.com>

When MMIO 0x18[IntCapXTEn]=1, interrupts originating from the IOMMU itself are
sent based on the programming in XT IOMMU Interrupt Control Registers in MMIO
0x170-0x180 instead of the programming in the IOMMU's MSI capability registers.
The guest programs these registers with appropriate vector and destination
ID instead of writing to PCI MSI capability.

Current AMD vIOMMU is capable of generating interrupts only through PCI
MSI capability and does not care about xt mode. Because of this AMD
vIOMMU cannot generate event log interrupts when the guest has enabled
xt mode.

Introduce a new flag "intcapxten" which is set when guest writes control
register [IntCapXTEn] (bit 51) and use vector and destination field in
the XT MMIO register (0x170) to support XT mode.

Signed-off-by: Sairaj Kodilkar <sarunkod@amd.com>
Reviewed-by: Vasant Hegde <vasant.hegde@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: <20260302115130.5903-4-sarunkod@amd.com>
---
 hw/i386/amd_iommu.c  | 47 ++++++++++++++++++++++++++++++++++++++------
 hw/i386/amd_iommu.h  | 17 ++++++++++++++++
 hw/i386/trace-events |  1 +
 3 files changed, 59 insertions(+), 6 deletions(-)

diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
index 5947d3aecf..79216fb305 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -192,18 +192,38 @@ static void amdvi_assign_andq(AMDVIState *s, hwaddr addr, uint64_t val)
    amdvi_writeq_raw(s, addr, amdvi_readq(s, addr) & val);
 }
 
+static void amdvi_build_xt_msi_msg(AMDVIState *s, MSIMessage *msg)
+{
+    union mmio_xt_intr xt_reg;
+    struct X86IOMMUIrq irq;
+
+    xt_reg.val = amdvi_readq(s, AMDVI_MMIO_XT_GEN_INTR);
+
+    irq.vector = xt_reg.vector;
+    irq.delivery_mode = xt_reg.delivery_mode;
+    irq.dest_mode = xt_reg.destination_mode;
+    irq.dest = (xt_reg.destination_hi << 24) | xt_reg.destination_lo;
+    irq.trigger_mode = 0;
+    irq.redir_hint = 0;
+
+    x86_iommu_irq_to_msi_message(&irq, msg);
+}
+
 static void amdvi_generate_msi_interrupt(AMDVIState *s)
 {
     MSIMessage msg = {};
-    MemTxAttrs attrs = {
-        .requester_id = pci_requester_id(&s->pci->dev)
-    };
 
-    if (msi_enabled(&s->pci->dev)) {
+    if (s->intcapxten) {
+        trace_amdvi_generate_msi_interrupt("XT GEN");
+        amdvi_build_xt_msi_msg(s, &msg);
+    } else if (msi_enabled(&s->pci->dev)) {
+        trace_amdvi_generate_msi_interrupt("MSI");
         msg = msi_get_message(&s->pci->dev, 0);
-        address_space_stl_le(&address_space_memory, msg.address, msg.data,
-                             attrs, NULL);
+    } else {
+        trace_amdvi_generate_msi_interrupt("NO MSI");
+        return;
     }
+    apic_get_class(NULL)->send_msi(&msg);
 }
 
 static uint32_t get_next_eventlog_entry(AMDVIState *s)
@@ -1538,6 +1558,7 @@ const char *amdvi_mmio_get_name(hwaddr addr)
     MMIO_REG_TO_STRING(AMDVI_MMIO_PPR_BASE);
     MMIO_REG_TO_STRING(AMDVI_MMIO_PPR_HEAD);
     MMIO_REG_TO_STRING(AMDVI_MMIO_PPR_TAIL);
+    MMIO_REG_TO_STRING(AMDVI_MMIO_XT_GEN_INTR);
 #undef MMIO_REG_TO_STRING
     default:
         return "UNHANDLED";
@@ -1581,6 +1602,15 @@ static void amdvi_handle_control_write(AMDVIState *s)
     s->ga_enabled = !!(control & AMDVI_MMIO_CONTROL_GAEN);
     s->xten = !!(control & AMDVI_MMIO_CONTROL_XTEN) && s->xtsup &&
               s->ga_enabled;
+    /*
+     * IntCapXTEn controls whether IOMMU-originated interrupts are sent based
+     * on the information in XT IOMMU Interrupt Control Registers rather than
+     * the IOMMU’s MSI capability registers. Therefore it requires IOMMU
+     * x2APIC support capabilities (i.e. XTSup=1), but it is independent of
+     * whether a driver chooses to enable x2APIC mode for interrupt remapping
+     * (i.e. XTEn=1).
+     */
+    s->intcapxten = !!(control & AMDVI_MMIO_CONTROL_INTCAPXTEN) && s->xtsup;
 
     /* update the flags depending on the control register */
     if (s->cmdbuf_enabled) {
@@ -1790,6 +1820,9 @@ static void amdvi_mmio_write(void *opaque, hwaddr addr, uint64_t val,
     case AMDVI_MMIO_STATUS:
         amdvi_mmio_reg_write(s, size, val, addr);
         break;
+    case AMDVI_MMIO_XT_GEN_INTR:
+        amdvi_mmio_reg_write(s, size, val, addr);
+        break;
     }
 }
 
@@ -2440,6 +2473,7 @@ static void amdvi_init(AMDVIState *s)
     s->enabled = false;
     s->cmdbuf_enabled = false;
     s->xten = false;
+    s->intcapxten = false;
 
     /* reset MMIO */
     memset(s->mmior, 0, AMDVI_MMIO_SIZE);
@@ -2510,6 +2544,7 @@ static const VMStateDescription vmstate_xt = {
        .minimum_version_id = 1,
        .fields = (VMStateField[]) {
            VMSTATE_BOOL(xten, AMDVIState),
+           VMSTATE_BOOL(intcapxten, AMDVIState),
            VMSTATE_END_OF_LIST()
        }
 };
diff --git a/hw/i386/amd_iommu.h b/hw/i386/amd_iommu.h
index 300d91b34d..3cab04a6d4 100644
--- a/hw/i386/amd_iommu.h
+++ b/hw/i386/amd_iommu.h
@@ -53,6 +53,7 @@
 #define AMDVI_MMIO_EXCL_BASE          0x0020
 #define AMDVI_MMIO_EXCL_LIMIT         0x0028
 #define AMDVI_MMIO_EXT_FEATURES       0x0030
+#define AMDVI_MMIO_XT_GEN_INTR        0x0170
 #define AMDVI_MMIO_COMMAND_HEAD       0x2000
 #define AMDVI_MMIO_COMMAND_TAIL       0x2008
 #define AMDVI_MMIO_EVENT_HEAD         0x2010
@@ -103,6 +104,7 @@
 #define AMDVI_MMIO_CONTROL_CMDBUFLEN      (1ULL << 12)
 #define AMDVI_MMIO_CONTROL_GAEN           (1ULL << 17)
 #define AMDVI_MMIO_CONTROL_XTEN           (1ULL << 50)
+#define AMDVI_MMIO_CONTROL_INTCAPXTEN     (1ULL << 51)
 
 /* MMIO status register bits */
 #define AMDVI_MMIO_STATUS_CMDBUF_RUN  (1 << 4)
@@ -338,6 +340,20 @@ struct irte_ga {
   union irte_ga_hi hi;
 };
 
+union mmio_xt_intr {
+    uint64_t val;
+    struct {
+        uint64_t rsvd_1:2,
+                 destination_mode:1,
+                 rsvd_2:5,
+                 destination_lo:24,
+                 vector:8,
+                 delivery_mode:1,
+                 rsvd_3:15,
+                 destination_hi:8;
+    };
+};
+
 #define TYPE_AMD_IOMMU_DEVICE "amd-iommu"
 OBJECT_DECLARE_SIMPLE_TYPE(AMDVIState, AMD_IOMMU_DEVICE)
 
@@ -416,6 +432,7 @@ struct AMDVIState {
     bool ga_enabled;
     bool xtsup;     /* xtsup=on command line */
     bool xten;      /* guest controlled, x2apic mode enabled */
+    bool intcapxten; /* guest controlled, IOMMU x2apic interrupts enabled */
 
     /* DMA address translation */
     bool dma_remap;
diff --git a/hw/i386/trace-events b/hw/i386/trace-events
index 5fa5e93b68..a1dfade20f 100644
--- a/hw/i386/trace-events
+++ b/hw/i386/trace-events
@@ -118,6 +118,7 @@ amdvi_ir_intctl(uint8_t val) "int_ctl 0x%"PRIx8
 amdvi_ir_target_abort(const char *str) "%s"
 amdvi_ir_delivery_mode(const char *str) "%s"
 amdvi_ir_irte_ga_val(uint64_t hi, uint64_t lo) "hi 0x%"PRIx64" lo 0x%"PRIx64
+amdvi_generate_msi_interrupt(const char *str) "Mode: %s"
 
 # vmport.c
 vmport_register(unsigned char command, void *func, void *opaque) "command: 0x%02x func: %p opaque: %p"
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 082/106] standard-headers: Add virtio_rtc.h from Linux 7.0-rc1
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (80 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 081/106] amd_iommu: Generate XT interrupts when xt support is enabled Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 083/106] virtio-rtc: Add basic virtio-rtc support Michael S. Tsirkin
                   ` (24 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Kuan-Wei Chiu, Cornelia Huck, Paolo Bonzini

From: Kuan-Wei Chiu <visitorckw@gmail.com>

Add virtio_rtc.h from the upstream Linux kernel using
scripts/update-linux-headers.sh.

Source:
- Linux commit 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f (v7.0-rc1)
- Author: Linus Torvalds <torvalds@linux-foundation.org>
- Date:   Sun Feb 22 13:18:59 2026 -0800

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: <20260228182246.700714-2-visitorckw@gmail.com>
---
 include/standard-headers/linux/virtio_rtc.h | 237 ++++++++++++++++++++
 1 file changed, 237 insertions(+)
 create mode 100644 include/standard-headers/linux/virtio_rtc.h

diff --git a/include/standard-headers/linux/virtio_rtc.h b/include/standard-headers/linux/virtio_rtc.h
new file mode 100644
index 0000000000..7e2c21ebff
--- /dev/null
+++ b/include/standard-headers/linux/virtio_rtc.h
@@ -0,0 +1,237 @@
+/* SPDX-License-Identifier: ((GPL-2.0+ WITH Linux-syscall-note) OR BSD-3-Clause) */
+/*
+ * Copyright (C) 2022-2024 OpenSynergy GmbH
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _LINUX_VIRTIO_RTC_H
+#define _LINUX_VIRTIO_RTC_H
+
+#include "standard-headers/linux/types.h"
+
+/* alarm feature */
+#define VIRTIO_RTC_F_ALARM	0
+
+/* read request message types */
+
+#define VIRTIO_RTC_REQ_READ			0x0001
+#define VIRTIO_RTC_REQ_READ_CROSS		0x0002
+
+/* control request message types */
+
+#define VIRTIO_RTC_REQ_CFG			0x1000
+#define VIRTIO_RTC_REQ_CLOCK_CAP		0x1001
+#define VIRTIO_RTC_REQ_CROSS_CAP		0x1002
+#define VIRTIO_RTC_REQ_READ_ALARM		0x1003
+#define VIRTIO_RTC_REQ_SET_ALARM		0x1004
+#define VIRTIO_RTC_REQ_SET_ALARM_ENABLED	0x1005
+
+/* alarmq message types */
+
+#define VIRTIO_RTC_NOTIF_ALARM			0x2000
+
+/* Message headers */
+
+/** common request header */
+struct virtio_rtc_req_head {
+	uint16_t msg_type;
+	uint8_t reserved[6];
+};
+
+/** common response header */
+struct virtio_rtc_resp_head {
+#define VIRTIO_RTC_S_OK			0
+#define VIRTIO_RTC_S_EOPNOTSUPP		2
+#define VIRTIO_RTC_S_ENODEV		3
+#define VIRTIO_RTC_S_EINVAL		4
+#define VIRTIO_RTC_S_EIO		5
+	uint8_t status;
+	uint8_t reserved[7];
+};
+
+/** common notification header */
+struct virtio_rtc_notif_head {
+	uint16_t msg_type;
+	uint8_t reserved[6];
+};
+
+/* read requests */
+
+/* VIRTIO_RTC_REQ_READ message */
+
+struct virtio_rtc_req_read {
+	struct virtio_rtc_req_head head;
+	uint16_t clock_id;
+	uint8_t reserved[6];
+};
+
+struct virtio_rtc_resp_read {
+	struct virtio_rtc_resp_head head;
+	uint64_t clock_reading;
+};
+
+/* VIRTIO_RTC_REQ_READ_CROSS message */
+
+struct virtio_rtc_req_read_cross {
+	struct virtio_rtc_req_head head;
+	uint16_t clock_id;
+/* Arm Generic Timer Counter-timer Virtual Count Register (CNTVCT_EL0) */
+#define VIRTIO_RTC_COUNTER_ARM_VCT	0
+/* x86 Time-Stamp Counter */
+#define VIRTIO_RTC_COUNTER_X86_TSC	1
+/* Invalid */
+#define VIRTIO_RTC_COUNTER_INVALID	0xFF
+	uint8_t hw_counter;
+	uint8_t reserved[5];
+};
+
+struct virtio_rtc_resp_read_cross {
+	struct virtio_rtc_resp_head head;
+	uint64_t clock_reading;
+	uint64_t counter_cycles;
+};
+
+/* control requests */
+
+/* VIRTIO_RTC_REQ_CFG message */
+
+struct virtio_rtc_req_cfg {
+	struct virtio_rtc_req_head head;
+	/* no request params */
+};
+
+struct virtio_rtc_resp_cfg {
+	struct virtio_rtc_resp_head head;
+	/** # of clocks -> clock ids < num_clocks are valid */
+	uint16_t num_clocks;
+	uint8_t reserved[6];
+};
+
+/* VIRTIO_RTC_REQ_CLOCK_CAP message */
+
+struct virtio_rtc_req_clock_cap {
+	struct virtio_rtc_req_head head;
+	uint16_t clock_id;
+	uint8_t reserved[6];
+};
+
+struct virtio_rtc_resp_clock_cap {
+	struct virtio_rtc_resp_head head;
+#define VIRTIO_RTC_CLOCK_UTC			0
+#define VIRTIO_RTC_CLOCK_TAI			1
+#define VIRTIO_RTC_CLOCK_MONOTONIC		2
+#define VIRTIO_RTC_CLOCK_UTC_SMEARED		3
+#define VIRTIO_RTC_CLOCK_UTC_MAYBE_SMEARED	4
+	uint8_t type;
+#define VIRTIO_RTC_SMEAR_UNSPECIFIED	0
+#define VIRTIO_RTC_SMEAR_NOON_LINEAR	1
+#define VIRTIO_RTC_SMEAR_UTC_SLS	2
+	uint8_t leap_second_smearing;
+#define VIRTIO_RTC_FLAG_ALARM_CAP		(1 << 0)
+	uint8_t flags;
+	uint8_t reserved[5];
+};
+
+/* VIRTIO_RTC_REQ_CROSS_CAP message */
+
+struct virtio_rtc_req_cross_cap {
+	struct virtio_rtc_req_head head;
+	uint16_t clock_id;
+	uint8_t hw_counter;
+	uint8_t reserved[5];
+};
+
+struct virtio_rtc_resp_cross_cap {
+	struct virtio_rtc_resp_head head;
+#define VIRTIO_RTC_FLAG_CROSS_CAP	(1 << 0)
+	uint8_t flags;
+	uint8_t reserved[7];
+};
+
+/* VIRTIO_RTC_REQ_READ_ALARM message */
+
+struct virtio_rtc_req_read_alarm {
+	struct virtio_rtc_req_head head;
+	uint16_t clock_id;
+	uint8_t reserved[6];
+};
+
+struct virtio_rtc_resp_read_alarm {
+	struct virtio_rtc_resp_head head;
+	uint64_t alarm_time;
+#define VIRTIO_RTC_FLAG_ALARM_ENABLED	(1 << 0)
+	uint8_t flags;
+	uint8_t reserved[7];
+};
+
+/* VIRTIO_RTC_REQ_SET_ALARM message */
+
+struct virtio_rtc_req_set_alarm {
+	struct virtio_rtc_req_head head;
+	uint64_t alarm_time;
+	uint16_t clock_id;
+	/* flag VIRTIO_RTC_FLAG_ALARM_ENABLED */
+	uint8_t flags;
+	uint8_t reserved[5];
+};
+
+struct virtio_rtc_resp_set_alarm {
+	struct virtio_rtc_resp_head head;
+	/* no response params */
+};
+
+/* VIRTIO_RTC_REQ_SET_ALARM_ENABLED message */
+
+struct virtio_rtc_req_set_alarm_enabled {
+	struct virtio_rtc_req_head head;
+	uint16_t clock_id;
+	/* flag VIRTIO_RTC_ALARM_ENABLED */
+	uint8_t flags;
+	uint8_t reserved[5];
+};
+
+struct virtio_rtc_resp_set_alarm_enabled {
+	struct virtio_rtc_resp_head head;
+	/* no response params */
+};
+
+/** Union of request types for requestq */
+union virtio_rtc_req_requestq {
+	struct virtio_rtc_req_read read;
+	struct virtio_rtc_req_read_cross read_cross;
+	struct virtio_rtc_req_cfg cfg;
+	struct virtio_rtc_req_clock_cap clock_cap;
+	struct virtio_rtc_req_cross_cap cross_cap;
+	struct virtio_rtc_req_read_alarm read_alarm;
+	struct virtio_rtc_req_set_alarm set_alarm;
+	struct virtio_rtc_req_set_alarm_enabled set_alarm_enabled;
+};
+
+/** Union of response types for requestq */
+union virtio_rtc_resp_requestq {
+	struct virtio_rtc_resp_read read;
+	struct virtio_rtc_resp_read_cross read_cross;
+	struct virtio_rtc_resp_cfg cfg;
+	struct virtio_rtc_resp_clock_cap clock_cap;
+	struct virtio_rtc_resp_cross_cap cross_cap;
+	struct virtio_rtc_resp_read_alarm read_alarm;
+	struct virtio_rtc_resp_set_alarm set_alarm;
+	struct virtio_rtc_resp_set_alarm_enabled set_alarm_enabled;
+};
+
+/* alarmq notifications */
+
+/* VIRTIO_RTC_NOTIF_ALARM notification */
+
+struct virtio_rtc_notif_alarm {
+	struct virtio_rtc_notif_head head;
+	uint16_t clock_id;
+	uint8_t reserved[6];
+};
+
+/** Union of notification types for alarmq */
+union virtio_rtc_notif_alarmq {
+	struct virtio_rtc_notif_alarm alarm;
+};
+
+#endif /* _LINUX_VIRTIO_RTC_H */
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 083/106] virtio-rtc: Add basic virtio-rtc support
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (81 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 082/106] standard-headers: Add virtio_rtc.h from Linux 7.0-rc1 Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 084/106] hw/i386/pc: Add a proper owner for the ioport memory regions Michael S. Tsirkin
                   ` (23 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Kuan-Wei Chiu, Paolo Bonzini

From: Kuan-Wei Chiu <visitorckw@gmail.com>

Introduce the core device and PCI bindings for the virtio-rtc device
(VIRTIO_ID_CLOCK).

This implementation provides a read-only clock that returns the host's
time (QEMU_CLOCK_HOST) to the guest. It handles fundamental control
requests, reporting a single supported clock of type
VIRTIO_RTC_CLOCK_UTC, and responds to standard read requests.

- Virtio RTC Spec:
https://github.com/oasis-tcs/virtio-spec/tree/master/device-types/rtc
- Linux Virtio RTC driver:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/virtio/virtio_rtc_driver.c?h=v7.0-rc1

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: <20260228182246.700714-3-visitorckw@gmail.com>
---
 MAINTAINERS                    |   7 ++
 hw/virtio/Kconfig              |   5 +
 hw/virtio/meson.build          |   2 +
 hw/virtio/virtio-rtc-pci.c     |  65 +++++++++++
 hw/virtio/virtio-rtc.c         | 190 +++++++++++++++++++++++++++++++++
 include/hw/virtio/virtio-rtc.h |  22 ++++
 6 files changed, 291 insertions(+)
 create mode 100644 hw/virtio/virtio-rtc-pci.c
 create mode 100644 hw/virtio/virtio-rtc.c
 create mode 100644 include/hw/virtio/virtio-rtc.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 5a82aa3a05..df36496cfb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2527,6 +2527,13 @@ F: include/system/rng*.h
 F: backends/rng*.c
 F: tests/qtest/virtio-rng-test.c
 
+virtio-rtc
+M: Kuan-Wei Chiu <visitorckw@gmail.com>
+S: Maintained
+F: hw/virtio/virtio-rtc.c
+F: hw/virtio/virtio-rtc-pci.c
+F: include/hw/virtio/virtio-rtc.h
+
 virtio-nsm
 M: Alexander Graf <graf@amazon.com>
 M: Dorjoy Chowdhury <dorjoychy111@gmail.com>
diff --git a/hw/virtio/Kconfig b/hw/virtio/Kconfig
index 2ebdac16b3..91cf833407 100644
--- a/hw/virtio/Kconfig
+++ b/hw/virtio/Kconfig
@@ -76,6 +76,11 @@ config VIRTIO_MEM
     depends on VIRTIO_MEM_SUPPORTED
     select VIRTIO_MD
 
+config VIRTIO_RTC
+    bool
+    default y
+    depends on VIRTIO
+
 config VHOST_VSOCK_COMMON
     bool
     depends on VIRTIO
diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
index 3943e0d006..0e02323516 100644
--- a/hw/virtio/meson.build
+++ b/hw/virtio/meson.build
@@ -54,6 +54,7 @@ if have_vhost
 endif
 system_virtio_ss.add(when: 'CONFIG_VHOST_USER_VSOCK', if_true: files('vhost-user-vsock.c'))
 system_virtio_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true: files('virtio-rng.c'))
+system_virtio_ss.add(when: 'CONFIG_VIRTIO_RTC', if_true: files('virtio-rtc.c'))
 
 system_virtio_ss.add(when: 'CONFIG_VIRTIO_BALLOON', if_true: files('virtio-balloon.c'))
 system_virtio_ss.add(when: 'CONFIG_VHOST_USER_FS', if_true: files('vhost-user-fs.c'))
@@ -77,6 +78,7 @@ virtio_pci_ss.add(when: 'CONFIG_VIRTIO_CRYPTO', if_true: files('virtio-crypto-pc
 virtio_pci_ss.add(when: 'CONFIG_VIRTIO_INPUT_HOST', if_true: files('virtio-input-host-pci.c'))
 virtio_pci_ss.add(when: 'CONFIG_VIRTIO_INPUT', if_true: files('virtio-input-pci.c'))
 virtio_pci_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true: files('virtio-rng-pci.c'))
+virtio_pci_ss.add(when: 'CONFIG_VIRTIO_RTC', if_true: files('virtio-rtc-pci.c'))
 virtio_pci_ss.add(when: 'CONFIG_VIRTIO_NSM', if_true: [files('virtio-nsm-pci.c', 'cbor-helpers.c'), libcbor])
 virtio_pci_ss.add(when: 'CONFIG_VIRTIO_BALLOON', if_true: files('virtio-balloon-pci.c'))
 virtio_pci_ss.add(when: 'CONFIG_VIRTIO_9P', if_true: files('virtio-9p-pci.c'))
diff --git a/hw/virtio/virtio-rtc-pci.c b/hw/virtio/virtio-rtc-pci.c
new file mode 100644
index 0000000000..fe25f21fbc
--- /dev/null
+++ b/hw/virtio/virtio-rtc-pci.c
@@ -0,0 +1,65 @@
+/*
+ * Virtio RTC PCI Bindings
+ *
+ * Copyright (c) 2026 Kuan-Wei Chiu <visitorckw@gmail.com>
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/virtio/virtio-pci.h"
+#include "hw/virtio/virtio-rtc.h"
+#include "standard-headers/linux/virtio_ids.h"
+
+typedef struct VirtIORtcPCI {
+    VirtIOPCIProxy parent_obj;
+    VirtIORtc vdev;
+} VirtIORtcPCI;
+
+#define TYPE_VIRTIO_RTC_PCI "virtio-rtc-pci-base"
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIORtcPCI, VIRTIO_RTC_PCI)
+
+static void virtio_rtc_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
+{
+    VirtIORtcPCI *dev = VIRTIO_RTC_PCI(vpci_dev);
+    DeviceState *vdev = DEVICE(&dev->vdev);
+
+    qdev_realize(vdev, BUS(&vpci_dev->bus), errp);
+}
+
+static void virtio_rtc_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);
+
+    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+    k->realize = virtio_rtc_pci_realize;
+
+    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_10_BASE + VIRTIO_ID_CLOCK;
+    pcidev_k->revision = 0x00;
+    pcidev_k->class_id = PCI_CLASS_SYSTEM_RTC;
+}
+
+static void virtio_rtc_pci_instance_init(Object *obj)
+{
+    VirtIORtcPCI *dev = VIRTIO_RTC_PCI(obj);
+
+    virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
+                      TYPE_VIRTIO_RTC);
+}
+
+static const VirtioPCIDeviceTypeInfo virtio_rtc_pci_info = {
+    .base_name = TYPE_VIRTIO_RTC_PCI,
+    .non_transitional_name = "virtio-rtc-pci",
+    .instance_size = sizeof(VirtIORtcPCI),
+    .instance_init = virtio_rtc_pci_instance_init,
+    .class_init = virtio_rtc_pci_class_init,
+};
+
+static void virtio_rtc_pci_register(void)
+{
+    virtio_pci_types_register(&virtio_rtc_pci_info);
+}
+
+type_init(virtio_rtc_pci_register);
diff --git a/hw/virtio/virtio-rtc.c b/hw/virtio/virtio-rtc.c
new file mode 100644
index 0000000000..32de9c1650
--- /dev/null
+++ b/hw/virtio/virtio-rtc.c
@@ -0,0 +1,190 @@
+/*
+ * Virtio RTC device core
+ *
+ * Copyright (c) 2026 Kuan-Wei Chiu <visitorckw@gmail.com>
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/iov.h"
+#include "qemu/timer.h"
+#include "hw/virtio/virtio.h"
+#include "hw/virtio/virtio-rtc.h"
+#include "standard-headers/linux/virtio_ids.h"
+#include "standard-headers/linux/virtio_rtc.h"
+
+static void virtio_rtc_handle_request(VirtIODevice *vdev, VirtQueue *vq)
+{
+    VirtQueueElement *elem;
+    struct virtio_rtc_req_head req_head;
+    size_t written;
+
+    while ((elem = virtqueue_pop(vq, sizeof(VirtQueueElement)))) {
+        if (elem->out_num < 1 || elem->in_num < 1) {
+            virtio_error(vdev, "virtio-rtc: request missing in/out buffers");
+            virtqueue_detach_element(vq, elem, 0);
+            g_free(elem);
+            break;
+        }
+
+        if (iov_to_buf(elem->out_sg, elem->out_num, 0, &req_head,
+                       sizeof(req_head)) != sizeof(req_head)) {
+            virtio_error(vdev, "virtio-rtc: request header too short");
+            virtqueue_detach_element(vq, elem, 0);
+            g_free(elem);
+            break;
+        }
+
+        written = 0;
+
+        switch (le16_to_cpu(req_head.msg_type)) {
+        case VIRTIO_RTC_REQ_CFG: {
+            struct virtio_rtc_resp_cfg resp = {0};
+            resp.head.status = VIRTIO_RTC_S_OK;
+            resp.num_clocks = cpu_to_le16(1);
+            written = iov_from_buf(elem->in_sg, elem->in_num, 0, &resp,
+                                   sizeof(resp));
+            break;
+        }
+        case VIRTIO_RTC_REQ_CLOCK_CAP: {
+            struct virtio_rtc_req_clock_cap req;
+            struct virtio_rtc_resp_clock_cap resp = {0};
+
+            if (iov_to_buf(elem->out_sg, elem->out_num, 0, &req,
+                           sizeof(req)) != sizeof(req)) {
+                resp.head.status = VIRTIO_RTC_S_EINVAL;
+                written = iov_from_buf(elem->in_sg, elem->in_num, 0, &resp,
+                                       sizeof(resp.head));
+                break;
+            }
+
+            if (le16_to_cpu(req.clock_id) != 0) {
+                resp.head.status = VIRTIO_RTC_S_ENODEV;
+            } else {
+                resp.head.status = VIRTIO_RTC_S_OK;
+                resp.type = VIRTIO_RTC_CLOCK_UTC;
+            }
+            written = iov_from_buf(elem->in_sg, elem->in_num, 0, &resp,
+                                   sizeof(resp));
+            break;
+        }
+        case VIRTIO_RTC_REQ_CROSS_CAP: {
+            struct virtio_rtc_req_cross_cap req;
+            struct virtio_rtc_resp_cross_cap resp = {0};
+
+            if (iov_to_buf(elem->out_sg, elem->out_num, 0, &req,
+                     sizeof(req)) != sizeof(req)) {
+                resp.head.status = VIRTIO_RTC_S_EINVAL;
+                written = iov_from_buf(elem->in_sg, elem->in_num, 0, &resp,
+                                       sizeof(resp.head));
+                break;
+            }
+
+            if (le16_to_cpu(req.clock_id) != 0) {
+                resp.head.status = VIRTIO_RTC_S_ENODEV;
+            } else {
+                resp.head.status = VIRTIO_RTC_S_OK;
+            }
+            written = iov_from_buf(elem->in_sg, elem->in_num, 0, &resp,
+                                   sizeof(resp));
+            break;
+        }
+        case VIRTIO_RTC_REQ_READ: {
+            struct virtio_rtc_req_read req;
+            struct virtio_rtc_resp_read resp = {0};
+
+            if (iov_to_buf(elem->out_sg, elem->out_num, 0, &req,
+                           sizeof(req)) != sizeof(req)) {
+                resp.head.status = VIRTIO_RTC_S_EINVAL;
+                written = iov_from_buf(elem->in_sg, elem->in_num, 0, &resp,
+                                       sizeof(resp.head));
+                break;
+            }
+
+            if (le16_to_cpu(req.clock_id) != 0) {
+                resp.head.status = VIRTIO_RTC_S_ENODEV;
+                written = iov_from_buf(elem->in_sg, elem->in_num, 0, &resp,
+                                       sizeof(resp.head));
+            } else {
+                resp.head.status = VIRTIO_RTC_S_OK;
+                resp.clock_reading =
+                    cpu_to_le64(qemu_clock_get_ns(QEMU_CLOCK_HOST));
+                written = iov_from_buf(elem->in_sg, elem->in_num, 0, &resp,
+                                       sizeof(resp));
+            }
+            break;
+        }
+        default: {
+            struct virtio_rtc_resp_head resp = {0};
+            resp.status = VIRTIO_RTC_S_EOPNOTSUPP;
+            written = iov_from_buf(elem->in_sg, elem->in_num, 0, &resp,
+                                   sizeof(resp));
+            break;
+        }
+        }
+
+        virtqueue_push(vq, elem, written);
+        virtio_notify(vdev, vq);
+        g_free(elem);
+    }
+}
+
+static void virtio_rtc_device_realize(DeviceState *dev, Error **errp)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+    VirtIORtc *vrtc = VIRTIO_RTC(dev);
+
+    virtio_init(vdev, VIRTIO_ID_CLOCK, 0);
+    vrtc->vq = virtio_add_queue(vdev, 64, virtio_rtc_handle_request);
+}
+
+static void virtio_rtc_device_unrealize(DeviceState *dev)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+    VirtIORtc *vrtc = VIRTIO_RTC(dev);
+
+    virtio_delete_queue(vrtc->vq);
+    virtio_cleanup(vdev);
+}
+
+static uint64_t virtio_rtc_get_features(VirtIODevice *vdev, uint64_t f,
+                                        Error **errp)
+{
+    return f;
+}
+
+static const VMStateDescription vmstate_virtio_rtc = {
+    .name = "virtio-rtc",
+    .minimum_version_id = 1,
+    .version_id = 1,
+    .fields = (const VMStateField[]) {
+        VMSTATE_VIRTIO_DEVICE,
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static void virtio_rtc_class_init(ObjectClass *klass, const void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+
+    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+    vdc->realize = virtio_rtc_device_realize;
+    vdc->unrealize = virtio_rtc_device_unrealize;
+    vdc->get_features = virtio_rtc_get_features;
+    dc->vmsd = &vmstate_virtio_rtc;
+}
+
+static const TypeInfo virtio_rtc_info = {
+    .name = TYPE_VIRTIO_RTC,
+    .parent = TYPE_VIRTIO_DEVICE,
+    .instance_size = sizeof(VirtIORtc),
+    .class_init = virtio_rtc_class_init,
+};
+
+static void virtio_rtc_register_types(void)
+{
+    type_register_static(&virtio_rtc_info);
+}
+
+type_init(virtio_rtc_register_types)
diff --git a/include/hw/virtio/virtio-rtc.h b/include/hw/virtio/virtio-rtc.h
new file mode 100644
index 0000000000..51aa35201a
--- /dev/null
+++ b/include/hw/virtio/virtio-rtc.h
@@ -0,0 +1,22 @@
+/*
+ * Virtio RTC device
+ *
+ * Copyright (c) 2026 Kuan-Wei Chiu <visitorckw@gmail.com>
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef QEMU_VIRTIO_RTC_H
+#define QEMU_VIRTIO_RTC_H
+
+#include "hw/virtio/virtio.h"
+#include "qom/object.h"
+
+#define TYPE_VIRTIO_RTC "virtio-rtc-device"
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIORtc, VIRTIO_RTC)
+
+struct VirtIORtc {
+    VirtIODevice parent_obj;
+    VirtQueue *vq;
+};
+
+#endif
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 084/106] hw/i386/pc: Add a proper owner for the ioport memory regions
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (82 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 083/106] virtio-rtc: Add basic virtio-rtc support Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 085/106] acpi: add API to build WDAT instructions Michael S. Tsirkin
                   ` (22 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Thomas Huth, Paolo Bonzini, Richard Henderson

From: Thomas Huth <thuth@redhat.com>

Without a proper owner, the memory regions show up in /machine/unattached
in the QOM tree, which is something that should be avoided.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260217141827.534426-1-thuth@redhat.com>
---
 hw/i386/pc.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 2ecad3c503..a6958b4054 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1051,10 +1051,12 @@ void pc_basic_device_init(struct PCMachineState *pcms,
     MemoryRegion *ioportF0_io = g_new(MemoryRegion, 1);
     X86MachineState *x86ms = X86_MACHINE(pcms);
 
-    memory_region_init_io(ioport80_io, NULL, &ioport80_io_ops, NULL, "ioport80", 1);
+    memory_region_init_io(ioport80_io, OBJECT(pcms), &ioport80_io_ops, NULL,
+                          "ioport80", 1);
     memory_region_add_subregion(isa_bus->address_space_io, 0x80, ioport80_io);
 
-    memory_region_init_io(ioportF0_io, NULL, &ioportF0_io_ops, NULL, "ioportF0", 1);
+    memory_region_init_io(ioportF0_io, OBJECT(pcms), &ioportF0_io_ops, NULL,
+                          "ioportF0", 1);
     memory_region_add_subregion(isa_bus->address_space_io, 0xf0, ioportF0_io);
 
     /*
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 085/106] acpi: add API to build WDAT instructions
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (83 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 084/106] hw/i386/pc: Add a proper owner for the ioport memory regions Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 086/106] x86: q35: add 'wdat' property Michael S. Tsirkin
                   ` (21 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Igor Mammedov, Ani Sinha, Zhao Liu, Eric Auger

From: Igor Mammedov <imammedo@redhat.com>

Add definitions for WDAT[1] actions/instructions
and build_append_wdat_ins() API to build table entries.

1)
"Hardware Watchdog Timers Design Specification"
  https://uefi.org/acpi 'Watchdog Action Table (WDAT)'

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Ani Sinha <anisinha@redhat.com>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260303092532.2410177-2-imammedo@redhat.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/acpi/aml-build.c    |  14 +++++
 include/hw/acpi/wdat.h | 118 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 132 insertions(+)
 create mode 100644 include/hw/acpi/wdat.h

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 413d9b6240..9b3cdd3781 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -35,6 +35,7 @@
 #include "hw/acpi/acpi_aml_interface.h"
 #include "qemu/cutils.h"
 #include "hw/core/cpu.h"
+#include "hw/acpi/wdat.h"
 
 static GArray *build_alloc_array(void)
 {
@@ -2872,3 +2873,16 @@ void qbus_build_aml(BusState *bus, Aml *scope)
         call_dev_aml_func(DEVICE(kid->child), scope);
     }
 }
+
+void build_append_wdat_ins(GArray *table_data,
+                           WDATAction action, uint8_t flags,
+                           struct AcpiGenericAddress as,
+                           uint32_t val, uint32_t mask)
+{
+    build_append_int_noprefix(table_data, action, 1);    /* Watchdog Action */
+    build_append_int_noprefix(table_data, flags, 1);     /* Instruction Flags */
+    build_append_int_noprefix(table_data, 0, 2);         /* Reserved */
+    build_append_gas_from_struct(table_data, &as);       /* Register Region */
+    build_append_int_noprefix(table_data, val, 4);       /* Value */
+    build_append_int_noprefix(table_data, mask, 4);      /* Mask */
+}
diff --git a/include/hw/acpi/wdat.h b/include/hw/acpi/wdat.h
new file mode 100644
index 0000000000..89803eef4b
--- /dev/null
+++ b/include/hw/acpi/wdat.h
@@ -0,0 +1,118 @@
+/*
+ * Watchdog Action Table (WDAT) definitions
+ *
+ * Copyright Red Hat, Inc. 2026
+ * Author(s): Igor Mammedov <imammedo@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef QEMU_HW_ACPI_WDAT_H
+#define QEMU_HW_ACPI_WDAT_H
+
+#include "hw/acpi/acpi-defs.h"
+
+/*
+ * Watchdog actions as described in
+ *  "Hardware Watchdog Timers Design Specification"
+ * for link to spec see https://uefi.org/acpi
+ *     'Watchdog Action Table (WDAT)'
+ */
+typedef enum {
+    /*
+     * Restarts the watchdog timer's countdown. This action is
+     * required.
+     */
+    WDAT_ACTION_RESET = 0x1,
+    /*
+     * Returns the current countdown value of the watchdog hardware
+     * (in count intervals).
+     */
+    WDAT_ACTION_QUERY_CURRENT_COUNTDOWN_PERIOD = 0x4,
+    /*
+     * Returns the countdown value the watchdog hardware is
+     * configured to use when reset (in count intervals).
+     */
+    WDAT_ACTION_QUERY_COUNTDOWN_PERIOD = 0x5,
+    /*
+     * Sets the countdown value (in count intervals) to be used when
+     * the watchdog timer is reset. This action is required if
+     * WDAT_ACTION_RESET does not explicitly write a new
+     * countdown value to a register during a reset. Otherwise, this
+     * action is optional.
+     */
+    WDAT_ACTION_SET_COUNTDOWN_PERIOD = 0x6,
+    /*
+     * Determines if the watchdog hardware is currently in enabled/
+     * running state. The same result must occur when performed from
+     * both from enabled/stopped state and enabled/running state. If
+     * the watchdog hardware is disabled, results are indeterminate.
+     * This action is required.
+     */
+    WDAT_ACTION_QUERY_RUNNING_STATE = 0x8,
+    /*
+     * Starts the watchdog, if not already in running state. If the
+     * watchdog hardware is disabled, results are indeterminate.
+     * This action is required.
+     */
+    WDAT_ACTION_SET_RUNNING_STATE = 0x9,
+    /*
+     * Determines if the watchdog hardware is currently in enabled/
+     * stopped state. The same result must occur when performed from
+     * both the enabled/stopped state and enabled/running state. If
+     * the watchdog hardware is disabled, results are indeterminate.
+     * This action is required.
+     */
+    WDAT_ACTION_QUERY_STOPPED_STATE = 0xA,
+    /*
+     * Stops the watchdog, if not already in stopped state. If the
+     * watchdog hardware is disabled, results are indeterminate.
+     * This action is required.
+     */
+    WDAT_ACTION_SET_STOPPED_STATE = 0xB,
+    /*
+     * Determines if the watchdog hardware is configured to perform a
+     * reboot when the watchdog is fired.
+     */
+    WDAT_ACTION_QUERY_REBOOT = 0x10,
+    /*
+     * Configures the watchdog hardware to perform a reboot when it
+     * is fired.
+     */
+    WDAT_ACTION_SET_REBOOT = 0x11,
+    /*
+     * Determines if the watchdog hardware is configured to perform a
+     * system shutdown when fired.
+     */
+    WDAT_ACTION_QUERY_SHUTDOWN = 0x12,
+    /*
+     * Configures the watchdog hardware to perform a system shutdown
+     * when fired.
+     */
+    WDAT_ACTION_SET_SHUTDOWN = 0x13,
+    /*
+     * Determines if the current boot was caused by the watchdog
+     * firing. The boot status is required to be set if the watchdog
+     * fired and caused a reboot. It is recommended that the
+     * Watchdog Status be set if the watchdog fired and caused a
+     * shutdown. This action is required.
+     */
+    WDAT_ACTION_QUERY_WATCHDOG_STATUS = 0x20,
+    /*
+     * Sets the watchdog's boot status to the default value. This
+     * action is required.
+     */
+    WDAT_ACTION_SET_WATCHDOG_STATUS = 0x21,
+} WDATAction;
+
+#define WDAT_INS_READ_VALUE 0x0
+#define WDAT_INS_READ_COUNTDOWN 0x1
+#define WDAT_INS_WRITE_VALUE 0x2
+#define WDAT_INS_WRITE_COUNTDOWN 0x3
+#define WDAT_INS_PRESERVE_REGISTER 0x80
+
+void build_append_wdat_ins(GArray *table_data,
+                           WDATAction action, uint8_t flags,
+                           struct AcpiGenericAddress as,
+                           uint32_t val, uint32_t mask);
+
+#endif /* QEMU_HW_ACPI_WDAT_H */
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 086/106] x86: q35: add 'wdat' property
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (84 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 085/106] acpi: add API to build WDAT instructions Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 087/106] x86: q35: generate WDAT ACPI table Michael S. Tsirkin
                   ` (20 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Igor Mammedov, Zhao Liu, Ani Sinha, Paolo Bonzini,
	Richard Henderson

From: Igor Mammedov <imammedo@redhat.com>

Used for enabling WDAT based watchdog for builtin iTCO watchdog.
Usage:
    -M q35,wdat={on|off}
By default it is disabled.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Reviewed-by: Ani Sinha <anisinha@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260303092532.2410177-3-imammedo@redhat.com>
---
 hw/i386/pc_q35.c     | 18 ++++++++++++++++++
 include/hw/i386/pc.h |  1 +
 2 files changed, 19 insertions(+)

diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index d8fed698c7..6c1e4eff5f 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -331,6 +331,18 @@ static void pc_q35_init(MachineState *machine)
     }
 }
 
+static bool pc_q35_machine_get_wdat(Object *o, Error **errp)
+{
+    PCMachineState *pcms = PC_MACHINE(o);
+    return pcms->wdat_enabled;
+}
+
+static void pc_q35_machine_set_wdat(Object *o, bool value, Error **errp)
+{
+    PCMachineState *pcms = PC_MACHINE(o);
+    pcms->wdat_enabled = value;
+}
+
 #define DEFINE_Q35_MACHINE(major, minor) \
     DEFINE_PC_VER_MACHINE(pc_q35, "pc-q35", pc_q35_init, false, NULL, major, minor);
 
@@ -343,6 +355,7 @@ static void pc_q35_init(MachineState *machine)
 static void pc_q35_machine_options(MachineClass *m)
 {
     PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
+    ObjectClass *oc = OBJECT_CLASS(m);
     pcmc->pci_root_uid = 0;
     pcmc->default_cpu_version = 1;
 
@@ -361,6 +374,11 @@ static void pc_q35_machine_options(MachineClass *m)
     machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE);
     machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE);
     machine_class_allow_dynamic_sysbus_dev(m, TYPE_UEFI_VARS_X64);
+    object_class_property_add_bool(oc, "wdat",
+        pc_q35_machine_get_wdat, pc_q35_machine_set_wdat);
+    object_class_property_set_description(oc, "wdat",
+        "Enable WDAT watchdog support. Default: off");
+
     compat_props_add(m->compat_props,
                      pc_q35_compat_defaults, pc_q35_compat_defaults_len);
 }
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 85a74363b5..d4b6d3ed57 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -45,6 +45,7 @@ typedef struct PCMachineState {
     const char *south_bridge;
 
     bool acpi_build_enabled;
+    bool wdat_enabled;
     bool smbus_enabled;
     bool sata_enabled;
     bool hpet_enabled;
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 087/106] x86: q35: generate WDAT ACPI table
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (85 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 086/106] x86: q35: add 'wdat' property Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 088/106] tests: acpi: x86/q35: whitelist new WDAT table Michael S. Tsirkin
                   ` (19 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Igor Mammedov, Ani Sinha, Zhao Liu, Paolo Bonzini,
	Richard Henderson

From: Igor Mammedov <imammedo@redhat.com>

It will generate WDAT table [1] customized for TCO watchdog.
This allows Windows guests (Windows Server 2008/Vista+) to
use TCO watchdog using built-in generic driver, which
alleviates need to install vendor specific drivers.

Given that enabling it might change guest behaviour
(both Windows/Linux) the feature is disabled by default.

Users that need it can enable the feature with
following CLI option.
    -machine wdat=on

1)
   "Hardware Watchdog Timers Design Specification"
    https://uefi.org/acpi 'Watchdog Action Table (WDAT)'

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Ani Sinha <anisinha@redhat.com>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260303092532.2410177-4-imammedo@redhat.com>
---
 hw/acpi/meson.build         |  3 +-
 hw/acpi/wdat-ich9-stub.c    | 15 +++++++
 hw/acpi/wdat-ich9.c         | 90 +++++++++++++++++++++++++++++++++++++
 hw/i386/acpi-build.c        | 12 +++++
 include/hw/acpi/wdat-ich9.h | 15 +++++++
 5 files changed, 134 insertions(+), 1 deletion(-)
 create mode 100644 hw/acpi/wdat-ich9-stub.c
 create mode 100644 hw/acpi/wdat-ich9.c
 create mode 100644 include/hw/acpi/wdat-ich9.h

diff --git a/hw/acpi/meson.build b/hw/acpi/meson.build
index 1c5251909b..0c7bfb278a 100644
--- a/hw/acpi/meson.build
+++ b/hw/acpi/meson.build
@@ -25,7 +25,8 @@ acpi_ss.add(when: 'CONFIG_ACPI_PCI_BRIDGE', if_true: files('pci-bridge.c'))
 acpi_ss.add(when: 'CONFIG_ACPI_PCIHP', if_true: files('pcihp.c'))
 stub_ss.add(files('acpi-pci-hotplug-stub.c'))
 acpi_ss.add(when: 'CONFIG_ACPI_VIOT', if_true: files('viot.c'))
-acpi_ss.add(when: 'CONFIG_ACPI_ICH9', if_true: files('ich9.c', 'ich9_tco.c', 'ich9_timer.c'))
+acpi_ss.add(when: 'CONFIG_ACPI_ICH9', if_true: files('ich9.c', 'ich9_tco.c', 'ich9_timer.c', 'wdat-ich9.c'))
+stub_ss.add(files('wdat-ich9-stub.c'))
 acpi_ss.add(when: 'CONFIG_ACPI_ERST', if_true: files('erst.c'))
 acpi_ss.add(when: 'CONFIG_IPMI', if_true: files('ipmi.c'))
 stub_ss.add(files('ipmi-stub.c'))
diff --git a/hw/acpi/wdat-ich9-stub.c b/hw/acpi/wdat-ich9-stub.c
new file mode 100644
index 0000000000..7c30ef3558
--- /dev/null
+++ b/hw/acpi/wdat-ich9-stub.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright Red Hat, Inc. 2026
+ * Author(s): Igor Mammedov <imammedo@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/acpi/wdat-ich9.h"
+
+void build_ich9_wdat(GArray *table_data, BIOSLinker *linker, const char *oem_id,
+                const char *oem_table_id, uint64_t tco_base)
+{
+    g_assert_not_reached();
+}
diff --git a/hw/acpi/wdat-ich9.c b/hw/acpi/wdat-ich9.c
new file mode 100644
index 0000000000..259c45c62d
--- /dev/null
+++ b/hw/acpi/wdat-ich9.c
@@ -0,0 +1,90 @@
+/*
+ * TCO Watchdog Action Table (WDAT)
+ *
+ * Copyright Red Hat, Inc. 2026
+ * Author(s): Igor Mammedov <imammedo@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/acpi/wdat.h"
+#include "hw/acpi/wdat-ich9.h"
+#include "hw/southbridge/ich9.h"
+
+#define TCO_REG(base, reg_offset, reg_width) { .space_id = AML_AS_SYSTEM_IO, \
+            .address = base + reg_offset, .bit_width = reg_width, \
+            .access_width = AML_WORD_ACC, };
+
+/*
+ *   "Hardware Watchdog Timers Design Specification"
+ *       https://uefi.org/acpi 'Watchdog Action Table (WDAT)'
+ *
+ *   ICH9 specific implementation.
+ */
+void build_ich9_wdat(GArray *table_data, BIOSLinker *linker, const char *oem_id,
+                     const char *oem_table_id, uint64_t tco_base)
+{
+    AcpiTable table = { .sig = "WDAT", .rev = 1, .oem_id = oem_id,
+                        .oem_table_id = oem_table_id };
+    struct AcpiGenericAddress tco_rld =  TCO_REG(tco_base, 0x0, 16);
+    struct AcpiGenericAddress tco2_sts = TCO_REG(tco_base, 0x6, 16);
+    struct AcpiGenericAddress tco1_cnt = TCO_REG(tco_base, 0x8, 16);
+    struct AcpiGenericAddress tco_tmr =  TCO_REG(tco_base, 0x12, 16);
+
+    acpi_table_begin(&table, table_data);
+    build_append_int_noprefix(table_data, 0x20, 4); /* Watchdog Header Length */
+    build_append_int_noprefix(table_data, 0xff, 2); /* PCI Segment */
+    build_append_int_noprefix(table_data, 0xff, 1); /* PCI Bus Number */
+    build_append_int_noprefix(table_data, 0xff, 1); /* PCI Device Number */
+    build_append_int_noprefix(table_data, 0xff, 1); /* PCI Function Number */
+    build_append_int_noprefix(table_data, 0, 3);    /* Reserved */
+    /*
+     * limits/resolution are defined by ICH9 TCO spec
+     */
+    build_append_int_noprefix(table_data, 0x258, 4);/* Timer Period, ms */
+    build_append_int_noprefix(table_data, 0x3ff, 4);/* Maximum Count */
+    build_append_int_noprefix(table_data, 0x4, 4);  /* Minimum Count */
+    /*
+     * WATCHDOG_ENABLED & WATCHDOG_STOPPED_IN_SLEEP_STATE
+     */
+    build_append_int_noprefix(table_data, 0x81, 1); /* Watchdog Flags */
+    build_append_int_noprefix(table_data, 0, 3);    /* Reserved */
+    /*
+     * watchdog instruction entries
+     */
+    build_append_int_noprefix(table_data, 10 /* # of actions below */, 4);
+    /* Action table */
+    build_append_wdat_ins(table_data, WDAT_ACTION_RESET,
+        WDAT_INS_WRITE_VALUE,
+        tco_rld, 0x1, 0x1ff);
+    build_append_wdat_ins(table_data, WDAT_ACTION_QUERY_RUNNING_STATE,
+        WDAT_INS_READ_VALUE,
+        tco1_cnt, 0x0, 0x800);
+    build_append_wdat_ins(table_data, WDAT_ACTION_SET_RUNNING_STATE,
+        WDAT_INS_WRITE_VALUE | WDAT_INS_PRESERVE_REGISTER,
+        tco1_cnt, 0, 0x800);
+    build_append_wdat_ins(table_data, WDAT_ACTION_QUERY_STOPPED_STATE,
+        WDAT_INS_READ_VALUE,
+        tco1_cnt, 0x800, 0x800);
+    build_append_wdat_ins(table_data, WDAT_ACTION_SET_STOPPED_STATE,
+        WDAT_INS_WRITE_VALUE | WDAT_INS_PRESERVE_REGISTER,
+        tco1_cnt, 0x800, 0x800);
+    build_append_wdat_ins(table_data, WDAT_ACTION_SET_COUNTDOWN_PERIOD,
+        WDAT_INS_WRITE_COUNTDOWN,
+        tco_tmr, 0x0, 0x3FF);
+    build_append_wdat_ins(table_data, WDAT_ACTION_QUERY_COUNTDOWN_PERIOD,
+        WDAT_INS_READ_COUNTDOWN,
+        tco_tmr, 0x0, 0x3FF);
+    build_append_wdat_ins(table_data, WDAT_ACTION_QUERY_WATCHDOG_STATUS,
+        WDAT_INS_READ_VALUE,
+        tco2_sts, 0x2, 0x2);
+    build_append_wdat_ins(table_data, WDAT_ACTION_SET_WATCHDOG_STATUS,
+        WDAT_INS_WRITE_VALUE | WDAT_INS_PRESERVE_REGISTER,
+        tco2_sts, 0x2, 0x2);
+    build_append_wdat_ins(table_data, WDAT_ACTION_SET_WATCHDOG_STATUS,
+        WDAT_INS_WRITE_VALUE | WDAT_INS_PRESERVE_REGISTER,
+        tco2_sts, 0x4, 0x4);
+
+    acpi_table_end(linker, &table);
+}
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 0d7c83d5e9..2ee061558c 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -78,6 +78,7 @@
 
 #include "hw/acpi/hmat.h"
 #include "hw/acpi/viot.h"
+#include "hw/acpi/wdat-ich9.h"
 
 #include CONFIG_DEVICES
 
@@ -110,6 +111,7 @@ typedef struct AcpiPmInfo {
     uint16_t cpu_hp_io_base;
     uint16_t pcihp_io_base;
     uint16_t pcihp_io_len;
+    uint64_t tco_io_base;
 } AcpiPmInfo;
 
 typedef struct AcpiMiscInfo {
@@ -204,6 +206,7 @@ static void acpi_get_pm_info(MachineState *machine, AcpiPmInfo *pm)
     pm->pcihp_io_len = 0;
     pm->smi_on_cpuhp = false;
     pm->smi_on_cpu_unplug = false;
+    pm->tco_io_base = 0;
 
     assert(obj);
     init_common_fadt_data(machine, obj, &pm->fadt);
@@ -225,6 +228,8 @@ static void acpi_get_pm_info(MachineState *machine, AcpiPmInfo *pm)
             !!(smi_features & BIT_ULL(ICH9_LPC_SMI_F_CPU_HOTPLUG_BIT));
         pm->smi_on_cpu_unplug =
             !!(smi_features & BIT_ULL(ICH9_LPC_SMI_F_CPU_HOT_UNPLUG_BIT));
+        pm->tco_io_base = object_property_get_uint(obj, ACPI_PM_PROP_PM_IO_BASE,
+            NULL) + ICH9_PMIO_TCO_RLD;
     }
     pm->pcihp_io_base =
         object_property_get_uint(obj, ACPI_PCIHP_IO_BASE_PROP, NULL);
@@ -2078,6 +2083,13 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
     acpi_add_table(table_offsets, tables_blob);
     build_waet(tables_blob, tables->linker, x86ms->oem_id, x86ms->oem_table_id);
 
+    if (pcms->wdat_enabled == true) {
+        g_assert(pm.tco_io_base);
+        acpi_add_table(table_offsets, tables_blob);
+        build_ich9_wdat(tables_blob, tables->linker, x86ms->oem_id,
+                        x86ms->oem_table_id, pm.tco_io_base);
+    }
+
     /* Add tables supplied by user (if any) */
     for (u = acpi_table_first(); u; u = acpi_table_next(u)) {
         unsigned len = acpi_table_len(u);
diff --git a/include/hw/acpi/wdat-ich9.h b/include/hw/acpi/wdat-ich9.h
new file mode 100644
index 0000000000..60a2a6a112
--- /dev/null
+++ b/include/hw/acpi/wdat-ich9.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright Red Hat, Inc. 2026
+ * Author(s): Igor Mammedov <imammedo@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef QEMU_HW_ACPI_WDAT_ICH9_H
+#define QEMU_HW_ACPI_WDAT_ICH9_H
+
+#include "hw/acpi/aml-build.h"
+
+void build_ich9_wdat(GArray *table_data, BIOSLinker *linker, const char *oem_id,
+                     const char *oem_table_id, uint64_t tco_base);
+
+#endif /* QEMU_HW_ACPI_WDAT_ICH9_H */
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 088/106] tests: acpi: x86/q35: whitelist new WDAT table
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (86 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 087/106] x86: q35: generate WDAT ACPI table Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 089/106] tests: acpi: x86/q35: add WDAT table test case Michael S. Tsirkin
                   ` (18 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Igor Mammedov, Ani Sinha, Zhao Liu

From: Igor Mammedov <imammedo@redhat.com>

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Acked-by: Ani Sinha <anisinha@redhat.com>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260303092532.2410177-5-imammedo@redhat.com>
---
 tests/data/acpi/x86/q35/WDAT.wdat           | 0
 tests/qtest/bios-tables-test-allowed-diff.h | 1 +
 2 files changed, 1 insertion(+)
 create mode 100644 tests/data/acpi/x86/q35/WDAT.wdat

diff --git a/tests/data/acpi/x86/q35/WDAT.wdat b/tests/data/acpi/x86/q35/WDAT.wdat
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523c8b..14b680debe 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/WDAT.wdat",
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 089/106] tests: acpi: x86/q35: add WDAT table test case
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (87 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 088/106] tests: acpi: x86/q35: whitelist new WDAT table Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 090/106] tests: acpi: x86/q35: update expected WDAT blob Michael S. Tsirkin
                   ` (17 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Igor Mammedov, Ani Sinha, Zhao Liu

From: Igor Mammedov <imammedo@redhat.com>

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Ani Sinha <anisinha@redhat.com>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260303092532.2410177-6-imammedo@redhat.com>
---
 tests/qtest/bios-tables-test.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index 510751799e..af6d9b5136 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -2534,6 +2534,18 @@ static void test_acpi_isapc_smbios_legacy(void)
     free_test_data(&data);
 }
 
+static void test_acpi_q35_wdat(void)
+{
+    test_data data = {
+        .machine = MACHINE_Q35,
+        .arch    = "x86",
+        .variant = ".wdat",
+    };
+
+    test_acpi_one("-machine wdat=on", &data);
+    free_test_data(&data);
+}
+
 static void test_oem_fields(test_data *data)
 {
     int i;
@@ -2828,6 +2840,7 @@ int main(int argc, char *argv[])
             qtest_add_func("acpi/q35/cxl", test_acpi_q35_cxl);
 #endif
             qtest_add_func("acpi/q35/slic", test_acpi_q35_slic);
+            qtest_add_func("acpi/q35/wdat", test_acpi_q35_wdat);
         }
         if (qtest_has_machine("microvm")) {
             qtest_add_func("acpi/microvm", test_acpi_microvm_tcg);
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 090/106] tests: acpi: x86/q35: update expected WDAT blob
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (88 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 089/106] tests: acpi: x86/q35: add WDAT table test case Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 091/106] vhost-user: Add VirtIO Shared Memory map request Michael S. Tsirkin
                   ` (16 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Igor Mammedov, Ani Sinha, Zhao Liu

From: Igor Mammedov <imammedo@redhat.com>

replace blank table with a new one:

  +[000h 0000   4]                    Signature : "WDAT"    [Watchdog Action Table]
  +[004h 0004   4]                 Table Length : 00000134
  +[008h 0008   1]                     Revision : 01
  +[009h 0009   1]                     Checksum : 31
  +[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]                Header Length : 00000020
  +[028h 0040   2]                  PCI Segment : 00FF
  +[02Ah 0042   1]                      PCI Bus : FF
  +[02Bh 0043   1]                   PCI Device : FF
  +[02Ch 0044   1]                 PCI Function : FF
  +[02Dh 0045   3]                     Reserved : 000000
  +[030h 0048   4]                 Timer Period : 00000258
  +[034h 0052   4]                    Max Count : 000003FF
  +[038h 0056   4]                    Min Count : 00000004
  +[03Ch 0060   1]        Flags (decoded below) : 81
  +                                     Enabled : 1
  +                         Stopped When Asleep : 1
  +[03Dh 0061   3]                     Reserved : 000000
  +[040h 0064   4]         Watchdog Entry Count : 0000000A
  +
  +[044h 0068   1]              Watchdog Action : 01
  +[045h 0069   1]                  Instruction : 02
  +[046h 0070   2]                     Reserved : 0000
  +
  +[048h 0072  12]              Register Region : [Generic Address Structure]
  +[048h 0072   1]                     Space ID : 01 [SystemIO]
  +[049h 0073   1]                    Bit Width : 10
  +[04Ah 0074   1]                   Bit Offset : 00
  +[04Bh 0075   1]         Encoded Access Width : 02 [Word Access:16]
  +[04Ch 0076   8]                      Address : 0000000000000660
  +
  +[054h 0084   4]                        Value : 00000001
  +[058h 0088   4]                Register Mask : 000001FF
  +
  +[05Ch 0092   1]              Watchdog Action : 08
  +[05Dh 0093   1]                  Instruction : 00
  +[05Eh 0094   2]                     Reserved : 0000
  +
  +[060h 0096  12]              Register Region : [Generic Address Structure]
  +[060h 0096   1]                     Space ID : 01 [SystemIO]
  +[061h 0097   1]                    Bit Width : 10
  +[062h 0098   1]                   Bit Offset : 00
  +[063h 0099   1]         Encoded Access Width : 02 [Word Access:16]
  +[064h 0100   8]                      Address : 0000000000000668
  +
  +[06Ch 0108   4]                        Value : 00000000
  +[070h 0112   4]                Register Mask : 00000800
  +
  +[074h 0116   1]              Watchdog Action : 09
  +[075h 0117   1]                  Instruction : 82
  +[076h 0118   2]                     Reserved : 0000
  +
  +[078h 0120  12]              Register Region : [Generic Address Structure]
  +[078h 0120   1]                     Space ID : 01 [SystemIO]
  +[079h 0121   1]                    Bit Width : 10
  +[07Ah 0122   1]                   Bit Offset : 00
  +[07Bh 0123   1]         Encoded Access Width : 02 [Word Access:16]
  +[07Ch 0124   8]                      Address : 0000000000000668
  +
  +[084h 0132   4]                        Value : 00000000
  +[088h 0136   4]                Register Mask : 00000800
  +
  +[08Ch 0140   1]              Watchdog Action : 0A
  +[08Dh 0141   1]                  Instruction : 00
  +[08Eh 0142   2]                     Reserved : 0000
  +
  +[090h 0144  12]              Register Region : [Generic Address Structure]
  +[090h 0144   1]                     Space ID : 01 [SystemIO]
  +[091h 0145   1]                    Bit Width : 10
  +[092h 0146   1]                   Bit Offset : 00
  +[093h 0147   1]         Encoded Access Width : 02 [Word Access:16]
  +[094h 0148   8]                      Address : 0000000000000668
  +
  +[09Ch 0156   4]                        Value : 00000800
  +[0A0h 0160   4]                Register Mask : 00000800
  +
  +[0A4h 0164   1]              Watchdog Action : 0B
  +[0A5h 0165   1]                  Instruction : 82
  +[0A6h 0166   2]                     Reserved : 0000
  +
  +[0A8h 0168  12]              Register Region : [Generic Address Structure]
  +[0A8h 0168   1]                     Space ID : 01 [SystemIO]
  +[0A9h 0169   1]                    Bit Width : 10
  +[0AAh 0170   1]                   Bit Offset : 00
  +[0ABh 0171   1]         Encoded Access Width : 02 [Word Access:16]
  +[0ACh 0172   8]                      Address : 0000000000000668
  +
  +[0B4h 0180   4]                        Value : 00000800
  +[0B8h 0184   4]                Register Mask : 00000800
  +
  +[0BCh 0188   1]              Watchdog Action : 06
  +[0BDh 0189   1]                  Instruction : 03
  +[0BEh 0190   2]                     Reserved : 0000
  +
  +[0C0h 0192  12]              Register Region : [Generic Address Structure]
  +[0C0h 0192   1]                     Space ID : 01 [SystemIO]
  +[0C1h 0193   1]                    Bit Width : 10
  +[0C2h 0194   1]                   Bit Offset : 00
  +[0C3h 0195   1]         Encoded Access Width : 02 [Word Access:16]
  +[0C4h 0196   8]                      Address : 0000000000000672
  +
  +[0CCh 0204   4]                        Value : 00000000
  +[0D0h 0208   4]                Register Mask : 000003FF
  +
  +[0D4h 0212   1]              Watchdog Action : 05
  +[0D5h 0213   1]                  Instruction : 01
  +[0D6h 0214   2]                     Reserved : 0000
  +
  +[0D8h 0216  12]              Register Region : [Generic Address Structure]
  +[0D8h 0216   1]                     Space ID : 01 [SystemIO]
  +[0D9h 0217   1]                    Bit Width : 10
  +[0DAh 0218   1]                   Bit Offset : 00
  +[0DBh 0219   1]         Encoded Access Width : 02 [Word Access:16]
  +[0DCh 0220   8]                      Address : 0000000000000672
  +
  +[0E4h 0228   4]                        Value : 00000000
  +[0E8h 0232   4]                Register Mask : 000003FF
  +
  +[0ECh 0236   1]              Watchdog Action : 20
  +[0EDh 0237   1]                  Instruction : 00
  +[0EEh 0238   2]                     Reserved : 0000
  +
  +[0F0h 0240  12]              Register Region : [Generic Address Structure]
  +[0F0h 0240   1]                     Space ID : 01 [SystemIO]
  +[0F1h 0241   1]                    Bit Width : 10
  +[0F2h 0242   1]                   Bit Offset : 00
  +[0F3h 0243   1]         Encoded Access Width : 02 [Word Access:16]
  +[0F4h 0244   8]                      Address : 0000000000000666
  +
  +[0FCh 0252   4]                        Value : 00000002
  +[100h 0256   4]                Register Mask : 00000002
  +
  +[104h 0260   1]              Watchdog Action : 21
  +[105h 0261   1]                  Instruction : 82
  +[106h 0262   2]                     Reserved : 0000
  +
  +[108h 0264  12]              Register Region : [Generic Address Structure]
  +[108h 0264   1]                     Space ID : 01 [SystemIO]
  +[109h 0265   1]                    Bit Width : 10
  +[10Ah 0266   1]                   Bit Offset : 00
  +[10Bh 0267   1]         Encoded Access Width : 02 [Word Access:16]
  +[10Ch 0268   8]                      Address : 0000000000000666
  +
  +[114h 0276   4]                        Value : 00000002
  +[118h 0280   4]                Register Mask : 00000002
  +
  +[11Ch 0284   1]              Watchdog Action : 21
  +[11Dh 0285   1]                  Instruction : 82
  +[11Eh 0286   2]                     Reserved : 0000
  +
  +[120h 0288  12]              Register Region : [Generic Address Structure]
  +[120h 0288   1]                     Space ID : 01 [SystemIO]
  +[121h 0289   1]                    Bit Width : 10
  +[122h 0290   1]                   Bit Offset : 00
  +[123h 0291   1]         Encoded Access Width : 02 [Word Access:16]
  +[124h 0292   8]                      Address : 0000000000000666
  +
  +[12Ch 0300   4]                        Value : 00000004
  +[130h 0304   4]                Register Mask : 00000004

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Acked-by: Ani Sinha <anisinha@redhat.com>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260303092532.2410177-7-imammedo@redhat.com>
---
 tests/data/acpi/x86/q35/WDAT.wdat           | Bin 0 -> 308 bytes
 tests/qtest/bios-tables-test-allowed-diff.h |   1 -
 2 files changed, 1 deletion(-)

diff --git a/tests/data/acpi/x86/q35/WDAT.wdat b/tests/data/acpi/x86/q35/WDAT.wdat
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e1e056b390e51c49f11f7b0d35e4e7c55d8067b1 100644
GIT binary patch
literal 308
zcmaivF$w}f3`JkEx{TV)5#kX9FW|0)oq~c}T8Xtc(2GYhPO+$9AY^#?`OH6WH>b6L
zth#-_J6bm!dNVTt;vLff$K8QJ!5f$W4`2?6f@Jj4QYvm-AjK}Dx5`T;m_2{<;x*QX
lL4w7nzVfzt``kzV@waK@$$at15&T;93Z<9T{~wRc(JwJ97XbhO

literal 0
HcmV?d00001

diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
index 14b680debe..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/WDAT.wdat",
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 091/106] vhost-user: Add VirtIO Shared Memory map request
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (89 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 090/106] tests: acpi: x86/q35: update expected WDAT blob Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 092/106] vhost_user.rst: Align VhostUserMsg excerpt members Michael S. Tsirkin
                   ` (15 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Albert Esteve, Stefan Hajnoczi, Stefano Garzarella,
	Paolo Bonzini, Peter Xu, Philippe Mathieu-Daudé

From: Albert Esteve <aesteve@redhat.com>

Add SHMEM_MAP/UNMAP requests to vhost-user for dynamic management of
VIRTIO Shared Memory mappings.

This implementation introduces VirtioSharedMemoryMapping as a unified
QOM object that manages both the mapping metadata and MemoryRegion
lifecycle. This object provides reference-counted lifecycle management
with automatic cleanup of file descriptors and memory regions
through QOM finalization.

This request allows backends to dynamically map file descriptors into a
VIRTIO Shared Memory Region identified by their shmid. Maps are created
using memory_region_init_ram_from_fd() with configurable read/write
permissions, and the resulting MemoryRegions are added as subregions to
the shmem container region. The mapped memory is then advertised to the
guest VIRTIO drivers as a base address plus offset for reading and
writting according to the requested mmap flags.

The backend can unmap memory ranges within a given VIRTIO Shared Memory
Region to free resources. Upon receiving this message, the frontend
removes the MemoryRegion as a subregion and automatically unreferences
the VirtioSharedMemoryMapping object, triggering cleanup if no other
references exist.

Error handling has been improved to ensure consistent behavior across
handlers that manage their own vhost_user_send_resp() calls. Since
these handlers clear the VHOST_USER_NEED_REPLY_MASK flag, explicit
error checking ensures proper connection closure on failures,
maintaining the expected error flow.

Note the memory region commit for these operations needs to be delayed
until after we reply to the backend to avoid deadlocks. Otherwise,
the MemoryListener would send a VHOST_USER_SET_MEM_TABLE message
before the reply.

Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Stefano Garzarella <sgarzare@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: <20260304165223.2166175-2-aesteve@redhat.com>
---
 hw/virtio/vhost-user.c                    | 274 ++++++++++++++++++++++
 hw/virtio/virtio.c                        | 201 ++++++++++++++++
 include/hw/virtio/virtio.h                | 134 +++++++++++
 include/system/memory.h                   |   2 +-
 subprojects/libvhost-user/libvhost-user.c |  70 ++++++
 subprojects/libvhost-user/libvhost-user.h |  54 +++++
 system/memory.c                           |  14 ++
 7 files changed, 748 insertions(+), 1 deletion(-)

diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 15042c0f3c..d627351f45 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -100,6 +100,7 @@ typedef enum VhostUserRequest {
     VHOST_USER_GET_SHARED_OBJECT = 41,
     VHOST_USER_SET_DEVICE_STATE_FD = 42,
     VHOST_USER_CHECK_DEVICE_STATE = 43,
+    VHOST_USER_GET_SHMEM_CONFIG = 44,
     VHOST_USER_MAX
 } VhostUserRequest;
 
@@ -111,6 +112,8 @@ typedef enum VhostUserBackendRequest {
     VHOST_USER_BACKEND_SHARED_OBJECT_ADD = 6,
     VHOST_USER_BACKEND_SHARED_OBJECT_REMOVE = 7,
     VHOST_USER_BACKEND_SHARED_OBJECT_LOOKUP = 8,
+    VHOST_USER_BACKEND_SHMEM_MAP = 9,
+    VHOST_USER_BACKEND_SHMEM_UNMAP = 10,
     VHOST_USER_BACKEND_MAX
 }  VhostUserBackendRequest;
 
@@ -189,6 +192,12 @@ typedef struct VhostUserMemRegMsg {
     VhostUserMemoryRegion region;
 } VhostUserMemRegMsg;
 
+typedef struct VhostUserShMemConfig {
+    uint32_t nregions;
+    uint32_t padding;
+    uint64_t memory_sizes[VIRTIO_MAX_SHMEM_REGIONS];
+} VhostUserShMemConfig;
+
 typedef struct VhostUserLog {
     uint64_t mmap_size;
     uint64_t mmap_offset;
@@ -245,6 +254,23 @@ typedef struct VhostUserShared {
     unsigned char uuid[16];
 } VhostUserShared;
 
+/* For the flags field of VhostUserMMap */
+#define VHOST_USER_FLAG_MAP_RW (1u << 0)
+
+typedef struct {
+    /* VIRTIO Shared Memory Region ID */
+    uint8_t shmid;
+    uint8_t padding[7];
+    /* File offset */
+    uint64_t fd_offset;
+    /* Offset within the VIRTIO Shared Memory Region */
+    uint64_t shm_offset;
+    /* Size of the mapping */
+    uint64_t len;
+    /* Flags for the mmap operation, from VHOST_USER_FLAG_MAP_* */
+    uint64_t flags;
+} VhostUserMMap;
+
 typedef struct {
     VhostUserRequest request;
 
@@ -277,6 +303,8 @@ typedef union {
         VhostUserInflight inflight;
         VhostUserShared object;
         VhostUserTransferDeviceState transfer_state;
+        VhostUserMMap mmap;
+        VhostUserShMemConfig shmem;
 } VhostUserPayload;
 
 typedef struct VhostUserMsg {
@@ -1860,6 +1888,196 @@ vhost_user_backend_handle_shared_object_lookup(struct vhost_user *u,
     return 0;
 }
 
+/**
+ * vhost_user_backend_handle_shmem_map() - Handle SHMEM_MAP backend request
+ * @dev: vhost device
+ * @ioc: QIOChannel for communication
+ * @hdr: vhost-user message header
+ * @payload: message payload containing mapping details
+ * @fd: file descriptor for the shared memory region
+ *
+ * Handles VHOST_USER_BACKEND_SHMEM_MAP requests from the backend. Creates
+ * a VhostUserShmemObject to manage the shared memory mapping and adds it
+ * to the appropriate VirtIO shared memory region. The VhostUserShmemObject
+ * serves as an intermediate parent for the MemoryRegion, ensuring proper
+ * lifecycle management with reference counting.
+ *
+ * Returns: 0 on success, negative errno on failure
+ */
+static int
+vhost_user_backend_handle_shmem_map(struct vhost_dev *dev,
+                                    QIOChannel *ioc,
+                                    VhostUserHeader *hdr,
+                                    VhostUserPayload *payload,
+                                    int fd)
+{
+    VirtioSharedMemory *shmem;
+    VhostUserMMap *vu_mmap = &payload->mmap;
+    VirtioSharedMemoryMapping *existing;
+    Error *local_err = NULL;
+    int ret = 0;
+
+    if (fd < 0) {
+        error_report("Bad fd for map");
+        ret = -EBADF;
+        goto send_reply;
+    }
+
+    if (QSIMPLEQ_EMPTY(&dev->vdev->shmem_list)) {
+        error_report("Device has no VIRTIO Shared Memory Regions. "
+                     "Requested ID: %d", vu_mmap->shmid);
+        ret = -EFAULT;
+        goto send_reply;
+    }
+
+    shmem = virtio_find_shmem_region(dev->vdev, vu_mmap->shmid);
+    if (!shmem) {
+        error_report("VIRTIO Shared Memory Region at "
+                     "ID %d not found or uninitialized", vu_mmap->shmid);
+        ret = -EFAULT;
+        goto send_reply;
+    }
+
+    if ((vu_mmap->shm_offset + vu_mmap->len) < vu_mmap->len ||
+        (vu_mmap->shm_offset + vu_mmap->len) > memory_region_size(&shmem->mr)) {
+        error_report("Bad offset/len for mmap %" PRIx64 "+%" PRIx64,
+                     vu_mmap->shm_offset, vu_mmap->len);
+        ret = -EFAULT;
+        goto send_reply;
+    }
+
+    QTAILQ_FOREACH(existing, &shmem->mmaps, link) {
+        if (ranges_overlap(existing->offset, existing->len,
+                           vu_mmap->shm_offset, vu_mmap->len)) {
+            error_report("VIRTIO Shared Memory mapping overlap");
+            ret = -EFAULT;
+            goto send_reply;
+        }
+    }
+
+    memory_region_transaction_begin();
+
+    /* Create VirtioSharedMemoryMapping object */
+    VirtioSharedMemoryMapping *mapping = virtio_shared_memory_mapping_new(
+        vu_mmap->shmid, fd, vu_mmap->fd_offset, vu_mmap->shm_offset,
+        vu_mmap->len, vu_mmap->flags & VHOST_USER_FLAG_MAP_RW);
+
+    if (!mapping) {
+        ret = -EFAULT;
+        goto send_reply_commit;
+    }
+
+    /* Add the mapping to the shared memory region */
+    if (virtio_add_shmem_map(shmem, mapping) != 0) {
+        error_report("Failed to add shared memory mapping");
+        object_unref(OBJECT(mapping));
+        ret = -EFAULT;
+        goto send_reply_commit;
+    }
+
+send_reply_commit:
+    /* Send reply and commit after transaction started */
+    if (hdr->flags & VHOST_USER_NEED_REPLY_MASK) {
+        payload->u64 = !!ret;
+        hdr->size = sizeof(payload->u64);
+        if (!vhost_user_send_resp(ioc, hdr, payload, &local_err)) {
+            error_report_err(local_err);
+            memory_region_transaction_commit();
+            return -EFAULT;
+        }
+    }
+    memory_region_transaction_commit();
+    return 0;
+
+send_reply:
+    if (hdr->flags & VHOST_USER_NEED_REPLY_MASK) {
+        payload->u64 = !!ret;
+        hdr->size = sizeof(payload->u64);
+        if (!vhost_user_send_resp(ioc, hdr, payload, &local_err)) {
+            error_report_err(local_err);
+            return -EFAULT;
+        }
+    }
+    return 0;
+}
+
+/**
+ * vhost_user_backend_handle_shmem_unmap() - Handle SHMEM_UNMAP backend request
+ * @dev: vhost device
+ * @ioc: QIOChannel for communication
+ * @hdr: vhost-user message header
+ * @payload: message payload containing unmapping details
+ *
+ * Handles VHOST_USER_BACKEND_SHMEM_UNMAP requests from the backend. Removes
+ * the specified memory mapping from the VirtIO shared memory region. This
+ * automatically unreferences the associated VhostUserShmemObject, which may
+ * trigger its finalization and cleanup (munmap, close fd) if no other
+ * references exist.
+ *
+ * Returns: 0 on success, negative errno on failure
+ */
+static int
+vhost_user_backend_handle_shmem_unmap(struct vhost_dev *dev,
+                                      QIOChannel *ioc,
+                                      VhostUserHeader *hdr,
+                                      VhostUserPayload *payload)
+{
+    VirtioSharedMemory *shmem = NULL;
+    VirtioSharedMemoryMapping *mmap = NULL;
+    VhostUserMMap *vu_mmap = &payload->mmap;
+    Error *local_err = NULL;
+    int ret = 0;
+
+    if (QSIMPLEQ_EMPTY(&dev->vdev->shmem_list)) {
+        error_report("Device has no VIRTIO Shared Memory Regions. "
+                     "Requested ID: %d", vu_mmap->shmid);
+        ret = -EFAULT;
+        goto send_reply;
+    }
+
+    shmem = virtio_find_shmem_region(dev->vdev, vu_mmap->shmid);
+    if (!shmem) {
+        error_report("VIRTIO Shared Memory Region at "
+                     "ID %d not found or uninitialized", vu_mmap->shmid);
+        ret = -EFAULT;
+        goto send_reply;
+    }
+
+    if ((vu_mmap->shm_offset + vu_mmap->len) < vu_mmap->len ||
+        (vu_mmap->shm_offset + vu_mmap->len) > memory_region_size(&shmem->mr)) {
+        error_report("Bad offset/len for unmmap %" PRIx64 "+%" PRIx64,
+                     vu_mmap->shm_offset, vu_mmap->len);
+        ret = -EFAULT;
+        goto send_reply;
+    }
+
+    mmap = virtio_find_shmem_map(shmem, vu_mmap->shm_offset, vu_mmap->len);
+    if (!mmap) {
+        error_report("Shared memory mapping not found at offset %" PRIx64
+                     " with length %" PRIx64,
+                     vu_mmap->shm_offset, vu_mmap->len);
+        ret = -EFAULT;
+        goto send_reply;
+    }
+
+send_reply:
+    if (hdr->flags & VHOST_USER_NEED_REPLY_MASK) {
+        payload->u64 = !!ret;
+        hdr->size = sizeof(payload->u64);
+        if (!vhost_user_send_resp(ioc, hdr, payload, &local_err)) {
+            error_report_err(local_err);
+            return -EFAULT;
+        }
+    }
+
+    if (!ret && shmem && mmap) {
+        /* Free the MemoryRegion only after reply */
+        virtio_del_shmem_map(shmem, vu_mmap->shm_offset, vu_mmap->len);
+    }
+
+    return 0;
+}
+
 static void close_backend_channel(struct vhost_user *u)
 {
     g_source_destroy(u->backend_src);
@@ -1933,6 +2151,21 @@ static gboolean backend_read(QIOChannel *ioc, GIOCondition condition,
         ret = vhost_user_backend_handle_shared_object_lookup(dev->opaque,
                                                              &payload.object);
         break;
+    case VHOST_USER_BACKEND_SHMEM_MAP:
+        /* Handler manages its own response, check error and close connection */
+        reply_ack = false;
+        if (vhost_user_backend_handle_shmem_map(dev, ioc, &hdr, &payload,
+                                                fd ? fd[0] : -1) < 0) {
+            goto err;
+        }
+        break;
+    case VHOST_USER_BACKEND_SHMEM_UNMAP:
+        /* Handler manages its own response, check error and close connection */
+        reply_ack = false;
+        if (vhost_user_backend_handle_shmem_unmap(dev, ioc, &hdr, &payload) < 0) {
+            goto err;
+        }
+        break;
     default:
         error_report("Received unexpected msg type: %d.", hdr.request);
         ret = -EINVAL;
@@ -3123,6 +3356,46 @@ void vhost_user_qmp_status(struct vhost_dev *dev, VirtioStatus *status)
         qmp_decode_protocols(u->protocol_features);
 }
 
+static int vhost_user_get_shmem_config(struct vhost_dev *dev,
+                                       int *nregions,
+                                       uint64_t *memory_sizes,
+                                       Error **errp)
+{
+    int ret;
+    VhostUserMsg msg = {
+        .hdr.request = VHOST_USER_GET_SHMEM_CONFIG,
+        .hdr.flags = VHOST_USER_VERSION,
+    };
+
+    if (!vhost_user_has_protocol_feature(dev,
+                                         VHOST_USER_PROTOCOL_F_SHMEM)) {
+        *nregions = 0;
+        return 0;
+    }
+
+    ret = vhost_user_write(dev, &msg, NULL, 0);
+    if (ret < 0) {
+        return ret;
+    }
+
+    ret = vhost_user_read(dev, &msg);
+    if (ret < 0) {
+        return ret;
+    }
+
+    if (msg.payload.shmem.nregions > VIRTIO_MAX_SHMEM_REGIONS) {
+        error_setg(errp, "Received too many shared memory regions: %d",
+                   msg.payload.shmem.nregions);
+        return -EINVAL;
+    }
+
+    *nregions = msg.payload.shmem.nregions;
+    memcpy(memory_sizes,
+           &msg.payload.shmem.memory_sizes,
+           sizeof(uint64_t) * VIRTIO_MAX_SHMEM_REGIONS);
+    return 0;
+}
+
 const VhostOps user_ops = {
         .backend_type = VHOST_BACKEND_TYPE_USER,
         .vhost_init = vhost_user_backend_init,
@@ -3163,4 +3436,5 @@ const VhostOps user_ops = {
         .vhost_check_device_state = vhost_user_check_device_state,
         .vhost_phys_vring_addr = vhost_user_gpa_addresses,
         .vhost_phys_iotlb_msg = vhost_user_gpa_addresses,
+        .vhost_get_shmem_config = vhost_user_get_shmem_config,
 };
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index ed58c1af9f..f4d86a3655 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -3119,6 +3119,173 @@ int virtio_save(VirtIODevice *vdev, QEMUFile *f)
     return ret;
 }
 
+VirtioSharedMemory *virtio_new_shmem_region(VirtIODevice *vdev, uint8_t shmid, uint64_t size)
+{
+    VirtioSharedMemory *elem;
+    g_autofree char *name = NULL;
+
+    elem = g_new0(VirtioSharedMemory, 1);
+    elem->shmid = shmid;
+
+    /* Initialize embedded MemoryRegion as container for shmem mappings */
+    name = g_strdup_printf("virtio-shmem-%d", shmid);
+    memory_region_init(&elem->mr, OBJECT(vdev), name, size);
+    QTAILQ_INIT(&elem->mmaps);
+    QSIMPLEQ_INSERT_TAIL(&vdev->shmem_list, elem, entry);
+    return elem;
+}
+
+VirtioSharedMemory *virtio_find_shmem_region(VirtIODevice *vdev, uint8_t shmid)
+{
+    VirtioSharedMemory *shmem, *next;
+    QSIMPLEQ_FOREACH_SAFE(shmem, &vdev->shmem_list, entry, next) {
+        if (shmem->shmid == shmid) {
+            return shmem;
+        }
+    }
+    return NULL;
+}
+
+static void virtio_shared_memory_mapping_instance_init(Object *obj)
+{
+    VirtioSharedMemoryMapping *mapping = VIRTIO_SHARED_MEMORY_MAPPING(obj);
+
+    mapping->shmid = 0;
+    mapping->offset = 0;
+    mapping->len = 0;
+    mapping->mr = NULL;
+}
+
+static void virtio_shared_memory_mapping_instance_finalize(Object *obj)
+{
+    VirtioSharedMemoryMapping *mapping = VIRTIO_SHARED_MEMORY_MAPPING(obj);
+
+    /* Clean up MemoryRegion if it exists */
+    if (mapping->mr) {
+        /* Unparent the MemoryRegion to trigger cleanup */
+        object_unparent(OBJECT(mapping->mr));
+        mapping->mr = NULL;
+    }
+}
+
+VirtioSharedMemoryMapping *virtio_shared_memory_mapping_new(uint8_t shmid,
+                                                            int fd,
+                                                            uint64_t fd_offset,
+                                                            uint64_t shm_offset,
+                                                            uint64_t len,
+                                                            bool allow_write)
+{
+    VirtioSharedMemoryMapping *mapping;
+    MemoryRegion *mr;
+    g_autoptr(GString) mr_name = g_string_new(NULL);
+    uint32_t ram_flags;
+    Error *local_err = NULL;
+
+    if (len == 0) {
+        error_report("Shared memory mapping size cannot be zero");
+        return NULL;
+    }
+
+    fd = dup(fd);
+    if (fd < 0) {
+        error_report("Failed to duplicate fd: %s", strerror(errno));
+        return NULL;
+    }
+
+    /* Determine RAM flags */
+    ram_flags = RAM_SHARED;
+    if (!allow_write) {
+        ram_flags |= RAM_READONLY_FD;
+    }
+
+    /* Create the VirtioSharedMemoryMapping */
+    mapping = VIRTIO_SHARED_MEMORY_MAPPING(
+        object_new(TYPE_VIRTIO_SHARED_MEMORY_MAPPING));
+
+    /* Set up object properties */
+    mapping->shmid = shmid;
+    mapping->offset = shm_offset;
+    mapping->len = len;
+
+    /* Create MemoryRegion as a child of this object */
+    mr = g_new0(MemoryRegion, 1);
+    g_string_printf(mr_name, "virtio-shmem-%d-%" PRIx64, shmid, shm_offset);
+
+    /* Initialize MemoryRegion with file descriptor */
+    if (!memory_region_init_ram_from_fd(mr, OBJECT(mapping), mr_name->str,
+                                        len, ram_flags, fd, fd_offset,
+                                        &local_err)) {
+        error_report_err(local_err);
+        g_free(mr);
+        close(fd);
+        object_unref(OBJECT(mapping));
+        return NULL;
+    }
+
+    mapping->mr = mr;
+    return mapping;
+}
+
+int virtio_add_shmem_map(VirtioSharedMemory *shmem,
+                         VirtioSharedMemoryMapping *mapping)
+{
+    if (!mapping) {
+        error_report("VirtioSharedMemoryMapping cannot be NULL");
+        return -1;
+    }
+    if (!mapping->mr) {
+        error_report("VirtioSharedMemoryMapping has no MemoryRegion");
+        return -1;
+    }
+
+    /* Validate boundaries against the VIRTIO shared memory region */
+    if (mapping->offset + mapping->len > memory_region_size(&shmem->mr)) {
+        error_report("Memory exceeds the shared memory boundaries");
+        return -1;
+    }
+
+    /* Add as subregion to the VIRTIO shared memory */
+    memory_region_add_subregion(&shmem->mr, mapping->offset, mapping->mr);
+
+    /* Add to the mapped regions list */
+    QTAILQ_INSERT_TAIL(&shmem->mmaps, mapping, link);
+
+    return 0;
+}
+
+VirtioSharedMemoryMapping *virtio_find_shmem_map(VirtioSharedMemory *shmem,
+                                          hwaddr offset, uint64_t size)
+{
+    VirtioSharedMemoryMapping *mapping;
+    QTAILQ_FOREACH(mapping, &shmem->mmaps, link) {
+        if (mapping->offset == offset && mapping->len == size) {
+            return mapping;
+        }
+    }
+    return NULL;
+}
+
+void virtio_del_shmem_map(VirtioSharedMemory *shmem, hwaddr offset,
+                          uint64_t size)
+{
+    VirtioSharedMemoryMapping *mapping = virtio_find_shmem_map(shmem, offset, size);
+    if (mapping == NULL) {
+        return;
+    }
+
+    /*
+     * Remove from memory region first
+     */
+    memory_region_del_subregion(&shmem->mr, mapping->mr);
+
+    /*
+     * Remove from list and unref the mapping which will trigger automatic cleanup
+     * when the reference count reaches zero.
+     */
+    QTAILQ_REMOVE(&shmem->mmaps, mapping, link);
+    object_unref(OBJECT(mapping));
+}
+
 /* A wrapper for use as a VMState .put function */
 static int virtio_device_put(QEMUFile *f, void *opaque, size_t size,
                               const VMStateField *field, JSONWriter *vmdesc)
@@ -3244,6 +3411,7 @@ int virtio_set_features_ex(VirtIODevice *vdev, const uint64_t *features)
 void virtio_reset(VirtIODevice *vdev)
 {
     VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
+    VirtioSharedMemory *shmem;
     uint64_t features[VIRTIO_FEATURES_NU64S];
     int i;
 
@@ -3283,6 +3451,15 @@ void virtio_reset(VirtIODevice *vdev)
     for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
         __virtio_queue_reset(vdev, i);
     }
+
+    /* Mappings are removed to prevent stale fds from remaining open. */
+    QSIMPLEQ_FOREACH(shmem, &vdev->shmem_list, entry) {
+        while (!QTAILQ_EMPTY(&shmem->mmaps)) {
+            VirtioSharedMemoryMapping *mapping = QTAILQ_FIRST(&shmem->mmaps);
+            virtio_del_shmem_map(shmem, mapping->offset,
+                                 memory_region_size(mapping->mr));
+        }
+    }
 }
 
 static void virtio_device_check_notification_compatibility(VirtIODevice *vdev,
@@ -3606,6 +3783,7 @@ void virtio_init(VirtIODevice *vdev, uint16_t device_id, size_t config_size)
             NULL, virtio_vmstate_change, vdev);
     vdev->device_endian = virtio_default_endian();
     vdev->use_guest_notifier_mask = true;
+    QSIMPLEQ_INIT(&vdev->shmem_list);
 }
 
 /*
@@ -4117,11 +4295,25 @@ static void virtio_device_free_virtqueues(VirtIODevice *vdev)
 static void virtio_device_instance_finalize(Object *obj)
 {
     VirtIODevice *vdev = VIRTIO_DEVICE(obj);
+    VirtioSharedMemory *shmem;
 
     virtio_device_free_virtqueues(vdev);
 
     g_free(vdev->config);
     g_free(vdev->vector_queues);
+    while (!QSIMPLEQ_EMPTY(&vdev->shmem_list)) {
+        shmem = QSIMPLEQ_FIRST(&vdev->shmem_list);
+        while (!QTAILQ_EMPTY(&shmem->mmaps)) {
+            VirtioSharedMemoryMapping *mapping = QTAILQ_FIRST(&shmem->mmaps);
+            virtio_del_shmem_map(shmem, mapping->offset,
+                                 memory_region_size(mapping->mr));
+        }
+
+        /* Clean up the embedded MemoryRegion */
+        object_unparent(OBJECT(&shmem->mr));
+        QSIMPLEQ_REMOVE_HEAD(&vdev->shmem_list, entry);
+        g_free(shmem);
+    }
 }
 
 static const Property virtio_properties[] = {
@@ -4487,9 +4679,18 @@ static const TypeInfo virtio_device_info = {
     .class_size = sizeof(VirtioDeviceClass),
 };
 
+static const TypeInfo virtio_shared_memory_mapping_info = {
+    .name = TYPE_VIRTIO_SHARED_MEMORY_MAPPING,
+    .parent = TYPE_OBJECT,
+    .instance_size = sizeof(VirtioSharedMemoryMapping),
+    .instance_init = virtio_shared_memory_mapping_instance_init,
+    .instance_finalize = virtio_shared_memory_mapping_instance_finalize,
+};
+
 static void virtio_register_types(void)
 {
     type_register_static(&virtio_device_info);
+    type_register_static(&virtio_shared_memory_mapping_info);
 }
 
 type_init(virtio_register_types)
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index d9fde42558..3f745e3b67 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -99,6 +99,44 @@ enum virtio_device_endian {
     VIRTIO_DEVICE_ENDIAN_BIG,
 };
 
+#define TYPE_VIRTIO_SHARED_MEMORY_MAPPING "virtio-shared-memory-mapping"
+OBJECT_DECLARE_SIMPLE_TYPE(VirtioSharedMemoryMapping, VIRTIO_SHARED_MEMORY_MAPPING)
+
+/**
+ * VirtioSharedMemoryMapping:
+ * @parent: Parent QOM object
+ * @shmid: VIRTIO Shared Memory Region ID
+ * @offset: Offset within the VIRTIO Shared Memory Region
+ * @len: Size of the mapping
+ * @mr: MemoryRegion associated with this shared memory mapping
+ * @link: List entry for the shared memory region's mapping list
+ *
+ * A QOM object that represents an individual file descriptor-based shared
+ * memory mapping within a VIRTIO Shared Memory Region. It manages the
+ * MemoryRegion lifecycle and file descriptor cleanup through QOM reference
+ * counting. When the object is unreferenced and its reference count drops
+ * to zero, it automatically cleans up the MemoryRegion and closes the file
+ * descriptor.
+ */
+struct VirtioSharedMemoryMapping {
+    Object parent;
+
+    uint8_t shmid;
+    hwaddr offset;
+    uint64_t len;
+    MemoryRegion *mr;
+    QTAILQ_ENTRY(VirtioSharedMemoryMapping) link;
+};
+
+struct VirtioSharedMemory {
+    uint8_t shmid;
+    MemoryRegion mr;
+    QTAILQ_HEAD(, VirtioSharedMemoryMapping) mmaps;
+    QSIMPLEQ_ENTRY(VirtioSharedMemory) entry;
+};
+
+typedef struct VirtioSharedMemory VirtioSharedMemory;
+
 /**
  * struct VirtIODevice - common VirtIO structure
  * @name: name of the device
@@ -168,6 +206,8 @@ struct VirtIODevice
      */
     EventNotifier config_notifier;
     bool device_iotlb_enabled;
+    /* Shared memory region for mappings. */
+    QSIMPLEQ_HEAD(, VirtioSharedMemory) shmem_list;
 };
 
 struct VirtioDeviceClass {
@@ -298,6 +338,100 @@ void virtio_notify(VirtIODevice *vdev, VirtQueue *vq);
 
 int virtio_save(VirtIODevice *vdev, QEMUFile *f);
 
+/**
+ * virtio_new_shmem_region() - Create a new shared memory region
+ * @vdev: VirtIODevice
+ * @shmid: Shared memory ID
+ * @size: Size of the shared memory region
+ *
+ * Creates a new VirtioSharedMemory region for the given device and ID.
+ * The returned VirtioSharedMemory is owned by the VirtIODevice and will
+ * be automatically freed when the device is destroyed. The caller
+ * should not free the returned pointer.
+ *
+ * Returns: Pointer to the new VirtioSharedMemory region, or NULL on failure
+ */
+VirtioSharedMemory *virtio_new_shmem_region(VirtIODevice *vdev, uint8_t shmid, uint64_t size);
+
+/**
+ * virtio_find_shmem_region() - Find an existing shared memory region
+ * @vdev: VirtIODevice
+ * @shmid: Shared memory ID to find
+ *
+ * Finds an existing VirtioSharedMemory region by ID. The returned pointer
+ * is owned by the VirtIODevice and should not be freed by the caller.
+ *
+ * Returns: Pointer to the VirtioSharedMemory region, or NULL if not found
+ */
+VirtioSharedMemory *virtio_find_shmem_region(VirtIODevice *vdev, uint8_t shmid);
+
+/**
+ * virtio_shared_memory_mapping_new() - Create a new VirtioSharedMemoryMapping
+ * @shmid: VIRTIO Shared Memory Region ID
+ * @fd: File descriptor for the shared memory
+ * @fd_offset: Offset within the file descriptor
+ * @shm_offset: Offset within the VIRTIO Shared Memory Region
+ * @len: Size of the mapping
+ * @allow_write: Whether to allow write access to the mapping
+ *
+ * Creates a new VirtioSharedMemoryMapping that manages a shared memory mapping.
+ * The object will create a MemoryRegion using memory_region_init_ram_from_fd()
+ * as a child object. When the object is finalized, it will automatically
+ * clean up the MemoryRegion and close the file descriptor.
+ *
+ * Return: A new VirtioSharedMemoryMapping on success, NULL on error.
+ */
+VirtioSharedMemoryMapping *virtio_shared_memory_mapping_new(uint8_t shmid,
+                                                            int fd,
+                                                            uint64_t fd_offset,
+                                                            uint64_t shm_offset,
+                                                            uint64_t len,
+                                                            bool allow_write);
+
+/**
+ * virtio_add_shmem_map() - Add a memory mapping to a shared region
+ * @shmem: VirtioSharedMemory region
+ * @mapping: VirtioSharedMemoryMapping to add (transfers ownership)
+ *
+ * Adds a memory mapping to the shared memory region. The VirtioSharedMemoryMapping
+ * ownership is transferred to the shared memory region and will be automatically
+ * cleaned up through QOM reference counting when virtio_del_shmem_map() is
+ * called or when the shared memory region is destroyed.
+ *
+ * Returns: 0 on success, negative errno on failure
+ */
+int virtio_add_shmem_map(VirtioSharedMemory *shmem,
+                         VirtioSharedMemoryMapping *mapping);
+
+/**
+ * virtio_find_shmem_map() - Find a memory mapping in a shared region
+ * @shmem: VirtioSharedMemory region
+ * @offset: Offset within the shared memory region
+ * @size: Size of the mapping to find
+ *
+ * Finds an existing memory mapping that covers the specified range.
+ * The returned VirtioSharedMemoryMapping is owned by the VirtioSharedMemory
+ * region and should not be freed by the caller.
+ *
+ * Returns: Pointer to the VirtioSharedMemoryMapping, or NULL if not found
+ */
+VirtioSharedMemoryMapping *virtio_find_shmem_map(VirtioSharedMemory *shmem,
+                                          hwaddr offset, uint64_t size);
+
+/**
+ * virtio_del_shmem_map() - Remove a memory mapping from a shared region
+ * @shmem: VirtioSharedMemory region
+ * @offset: Offset of the mapping to remove
+ * @size: Size of the mapping to remove
+ *
+ * Removes a memory mapping from the shared memory region. This will
+ * automatically unref the associated VhostUserShmemObject, which may
+ * trigger its finalization and cleanup if no other references exist.
+ * The mapping's MemoryRegion will be properly unmapped and cleaned up.
+ */
+void virtio_del_shmem_map(VirtioSharedMemory *shmem, hwaddr offset,
+                          uint64_t size);
+
 extern const VMStateInfo virtio_vmstate_info;
 
 #define VMSTATE_VIRTIO_DEVICE \
diff --git a/include/system/memory.h b/include/system/memory.h
index 1edb38b07d..d5f8d8b349 100644
--- a/include/system/memory.h
+++ b/include/system/memory.h
@@ -1456,6 +1456,7 @@ bool memory_region_init_ram_from_file(MemoryRegion *mr,
                                       const char *path,
                                       ram_addr_t offset,
                                       Error **errp);
+#endif
 
 /**
  * memory_region_init_ram_from_fd:  Initialize RAM memory region with a
@@ -1485,7 +1486,6 @@ bool memory_region_init_ram_from_fd(MemoryRegion *mr,
                                     int fd,
                                     ram_addr_t offset,
                                     Error **errp);
-#endif
 
 /**
  * memory_region_init_ram_ptr:  Initialize RAM memory region from a
diff --git a/subprojects/libvhost-user/libvhost-user.c b/subprojects/libvhost-user/libvhost-user.c
index 014d210748..d2df50e3d0 100644
--- a/subprojects/libvhost-user/libvhost-user.c
+++ b/subprojects/libvhost-user/libvhost-user.c
@@ -1592,6 +1592,76 @@ vu_rm_shared_object(VuDev *dev, unsigned char uuid[UUID_LEN])
     return vu_send_message(dev, &msg);
 }
 
+bool
+vu_shmem_map(VuDev *dev, uint8_t shmid, uint64_t fd_offset,
+             uint64_t shm_offset, uint64_t len, uint64_t flags, int fd)
+{
+    VhostUserMsg vmsg = {
+        .request = VHOST_USER_BACKEND_SHMEM_MAP,
+        .size = sizeof(vmsg.payload.mmap),
+        .flags = VHOST_USER_VERSION,
+        .payload.mmap = {
+            .shmid = shmid,
+            .fd_offset = fd_offset,
+            .shm_offset = shm_offset,
+            .len = len,
+            .flags = flags,
+        },
+        .fd_num = 1,
+        .fds[0] = fd,
+    };
+
+    if (!vu_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_SHMEM)) {
+        return false;
+    }
+
+    if (vu_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_REPLY_ACK)) {
+        vmsg.flags |= VHOST_USER_NEED_REPLY_MASK;
+    }
+
+    pthread_mutex_lock(&dev->backend_mutex);
+    if (!vu_message_write(dev, dev->backend_fd, &vmsg)) {
+        pthread_mutex_unlock(&dev->backend_mutex);
+        return false;
+    }
+
+    /* Also unlocks the backend_mutex */
+    return vu_process_message_reply(dev, &vmsg);
+}
+
+bool
+vu_shmem_unmap(VuDev *dev, uint8_t shmid, uint64_t shm_offset, uint64_t len)
+{
+    VhostUserMsg vmsg = {
+        .request = VHOST_USER_BACKEND_SHMEM_UNMAP,
+        .size = sizeof(vmsg.payload.mmap),
+        .flags = VHOST_USER_VERSION,
+        .payload.mmap = {
+            .shmid = shmid,
+            .fd_offset = 0,
+            .shm_offset = shm_offset,
+            .len = len,
+        },
+    };
+
+    if (!vu_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_SHMEM)) {
+        return false;
+    }
+
+    if (vu_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_REPLY_ACK)) {
+        vmsg.flags |= VHOST_USER_NEED_REPLY_MASK;
+    }
+
+    pthread_mutex_lock(&dev->backend_mutex);
+    if (!vu_message_write(dev, dev->backend_fd, &vmsg)) {
+        pthread_mutex_unlock(&dev->backend_mutex);
+        return false;
+    }
+
+    /* Also unlocks the backend_mutex */
+    return vu_process_message_reply(dev, &vmsg);
+}
+
 static bool
 vu_set_vring_call_exec(VuDev *dev, VhostUserMsg *vmsg)
 {
diff --git a/subprojects/libvhost-user/libvhost-user.h b/subprojects/libvhost-user/libvhost-user.h
index 2ffc58c11b..6a2d0f9fae 100644
--- a/subprojects/libvhost-user/libvhost-user.h
+++ b/subprojects/libvhost-user/libvhost-user.h
@@ -69,6 +69,8 @@ enum VhostUserProtocolFeature {
     /* Feature 16 is reserved for VHOST_USER_PROTOCOL_F_STATUS. */
     /* Feature 17 reserved for VHOST_USER_PROTOCOL_F_XEN_MMAP. */
     VHOST_USER_PROTOCOL_F_SHARED_OBJECT = 18,
+    /* Feature 19 is reserved for VHOST_USER_PROTOCOL_F_DEVICE_STATE */
+    VHOST_USER_PROTOCOL_F_SHMEM = 20,
     VHOST_USER_PROTOCOL_F_MAX
 };
 
@@ -127,6 +129,8 @@ typedef enum VhostUserBackendRequest {
     VHOST_USER_BACKEND_SHARED_OBJECT_ADD = 6,
     VHOST_USER_BACKEND_SHARED_OBJECT_REMOVE = 7,
     VHOST_USER_BACKEND_SHARED_OBJECT_LOOKUP = 8,
+    VHOST_USER_BACKEND_SHMEM_MAP = 9,
+    VHOST_USER_BACKEND_SHMEM_UNMAP = 10,
     VHOST_USER_BACKEND_MAX
 }  VhostUserBackendRequest;
 
@@ -186,6 +190,23 @@ typedef struct VhostUserShared {
     unsigned char uuid[UUID_LEN];
 } VhostUserShared;
 
+/* For the flags field of VhostUserMMap */
+#define VHOST_USER_FLAG_MAP_RW (1u << 0)
+
+typedef struct {
+    /* VIRTIO Shared Memory Region ID */
+    uint8_t shmid;
+    uint8_t padding[7];
+    /* File offset */
+    uint64_t fd_offset;
+    /* Offset within the VIRTIO Shared Memory Region */
+    uint64_t shm_offset;
+    /* Size of the mapping */
+    uint64_t len;
+    /* Flags for the mmap operation, from VHOST_USER_FLAG_MAP_* */
+    uint64_t flags;
+} VhostUserMMap;
+
 #define VU_PACKED __attribute__((packed))
 
 typedef struct VhostUserMsg {
@@ -210,6 +231,7 @@ typedef struct VhostUserMsg {
         VhostUserVringArea area;
         VhostUserInflight inflight;
         VhostUserShared object;
+        VhostUserMMap mmap;
     } payload;
 
     int fds[VHOST_MEMORY_BASELINE_NREGIONS];
@@ -593,6 +615,38 @@ bool vu_add_shared_object(VuDev *dev, unsigned char uuid[UUID_LEN]);
  */
 bool vu_rm_shared_object(VuDev *dev, unsigned char uuid[UUID_LEN]);
 
+/**
+ * vu_shmem_map:
+ * @dev: a VuDev context
+ * @shmid: VIRTIO Shared Memory Region ID
+ * @fd_offset: File offset
+ * @shm_offset: Offset within the VIRTIO Shared Memory Region
+ * @len: Size of the mapping
+ * @flags: Flags for the mmap operation
+ * @fd: A file descriptor
+ *
+ * Advertises a new mapping to be made in a given VIRTIO Shared Memory Region.
+ *
+ * Returns: TRUE on success, FALSE on failure.
+ */
+bool vu_shmem_map(VuDev *dev, uint8_t shmid, uint64_t fd_offset,
+                  uint64_t shm_offset, uint64_t len, uint64_t flags, int fd);
+
+/**
+ * vu_shmem_unmap:
+ * @dev: a VuDev context
+ * @shmid: VIRTIO Shared Memory Region ID
+ * @fd_offset: File offset
+ * @len: Size of the mapping
+ *
+ * The front-end un-mmaps a given range in the VIRTIO Shared Memory Region
+ * with the requested `shmid`.
+ *
+ * Returns: TRUE on success, FALSE on failure.
+ */
+bool vu_shmem_unmap(VuDev *dev, uint8_t shmid, uint64_t shm_offset,
+                    uint64_t len);
+
 /**
  * vu_queue_set_notification:
  * @dev: a VuDev context
diff --git a/system/memory.c b/system/memory.c
index 739ba11da6..96c13664fe 100644
--- a/system/memory.c
+++ b/system/memory.c
@@ -1652,6 +1652,20 @@ bool memory_region_init_ram_from_fd(MemoryRegion *mr, Object *owner,
                                 false, errp);
     return memory_region_set_ram_block(mr, rb);
 }
+#else
+bool memory_region_init_ram_from_fd(MemoryRegion *mr,
+                                    Object *owner,
+                                    const char *name,
+                                    uint64_t size,
+                                    uint32_t ram_flags,
+                                    int fd,
+                                    ram_addr_t offset,
+                                    Error **errp)
+{
+    error_setg(errp,
+               "memory_region_init_ram_from_fd is not supported on this platform");
+    return false;
+}
 #endif
 
 static void memory_region_set_ram_ptr(MemoryRegion *mr, uint64_t size,
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 092/106] vhost_user.rst: Align VhostUserMsg excerpt members
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (90 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 091/106] vhost-user: Add VirtIO Shared Memory map request Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 093/106] vhost_user.rst: Add SHMEM_MAP/_UNMAP to spec Michael S. Tsirkin
                   ` (14 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Albert Esteve, Stefano Garzarella,
	David Hildenbrand, Stefan Hajnoczi, Pierrick Bouvier

From: Albert Esteve <aesteve@redhat.com>

Add missing members to the VhostUserMsg excerpt in
the vhost-user spec documentation.

Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@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: <20260304165223.2166175-3-aesteve@redhat.com>
---
 docs/interop/vhost-user.rst | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst
index e8554a3859..883b1e90a2 100644
--- a/docs/interop/vhost-user.rst
+++ b/docs/interop/vhost-user.rst
@@ -378,11 +378,15 @@ In QEMU the vhost-user message is implemented with the following struct:
           struct vhost_vring_state state;
           struct vhost_vring_addr addr;
           VhostUserMemory memory;
+          VhostUserMemRegMsg mem_reg;
           VhostUserLog log;
           struct vhost_iotlb_msg iotlb;
           VhostUserConfig config;
+          VhostUserCryptoSession session;
           VhostUserVringArea area;
           VhostUserInflight inflight;
+          VhostUserShared object;
+          VhostUserTransferDeviceState transfer_state;
       };
   } QEMU_PACKED VhostUserMsg;
 
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 093/106] vhost_user.rst: Add SHMEM_MAP/_UNMAP to spec
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (91 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 092/106] vhost_user.rst: Align VhostUserMsg excerpt members Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 094/106] vhost_user: Add frontend get_shmem_config command Michael S. Tsirkin
                   ` (13 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Albert Esteve, Stefano Garzarella, Alyssa Ross,
	Stefan Hajnoczi, Manos Pitsidianakis, Pierrick Bouvier

From: Albert Esteve <aesteve@redhat.com>

Add SHMEM_MAP/_UNMAP request to the vhost-user
spec documentation.

Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Reviewed-by: Alyssa Ross <hi@alyssa.is>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
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: <20260304165223.2166175-4-aesteve@redhat.com>
---
 docs/interop/vhost-user.rst | 64 +++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst
index 883b1e90a2..4182d721ca 100644
--- a/docs/interop/vhost-user.rst
+++ b/docs/interop/vhost-user.rst
@@ -362,6 +362,28 @@ Device state transfer parameters
   In the future, additional phases might be added e.g. to allow
   iterative migration while the device is running.
 
+MMAP request
+^^^^^^^^^^^^
+
++-------+---------+-----------+------------+-----+-------+
+| shmid | padding | fd_offset | shm_offset | len | flags |
++-------+---------+-----------+------------+-----+-------+
+
+:shmid: a 8-bit shared memory region identifier
+
+:fd_offset: a 64-bit offset of this area from the start
+            of the supplied file descriptor
+
+:shm_offset: a 64-bit offset from the start of the
+             pointed shared memory region
+
+:len: a 64-bit size of the memory to map
+
+:flags: a 64-bit value:
+
+  - 0: Pages are mapped read-only
+  - 1: Pages are mapped read-write
+
 C structure
 -----------
 
@@ -387,6 +409,7 @@ In QEMU the vhost-user message is implemented with the following struct:
           VhostUserInflight inflight;
           VhostUserShared object;
           VhostUserTransferDeviceState transfer_state;
+          VhostUserMMap mmap;
       };
   } QEMU_PACKED VhostUserMsg;
 
@@ -1083,6 +1106,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
 
 Front-end message types
 -----------------------
@@ -1904,6 +1928,46 @@ is sent by the front-end.
   when the operation is successful, or non-zero otherwise. Note that if the
   operation fails, no fd is sent to the backend.
 
+``VHOST_USER_BACKEND_SHMEM_MAP``
+  :id: 9
+  :equivalent ioctl: N/A
+  :request payload: fd and ``struct VhostUserMMap``
+  :reply payload: N/A
+
+  When the ``VHOST_USER_PROTOCOL_F_SHMEM`` protocol feature has been
+  successfully negotiated, this message can be submitted by the backends to
+  advertise a new mapping to be made in a given VIRTIO Shared Memory Region.
+  Upon receiving the message, the front-end will mmap the given fd into the
+  VIRTIO Shared Memory Region with the requested ``shmid``.
+
+  If ``VHOST_USER_PROTOCOL_F_REPLY_ACK`` is negotiated, and
+  back-end set the ``VHOST_USER_NEED_REPLY`` flag, the front-end
+  must respond with zero when operation is successfully completed,
+  or non-zero otherwise.
+
+  Mapping over an already existing map is not allowed and requests shall fail.
+  Therefore, the memory range in the request must correspond with a valid,
+  free region of the VIRTIO Shared Memory Region. Also, note that mappings
+  consume resources and that the request can fail when there are no resources
+  available. Lastly, mappings are automatically unmapped by the front-end
+  across device reset operation.
+
+``VHOST_USER_BACKEND_SHMEM_UNMAP``
+  :id: 10
+  :equivalent ioctl: N/A
+  :request payload: ``struct VhostUserMMap``
+  :reply payload: N/A
+
+  When the ``VHOST_USER_PROTOCOL_F_SHMEM`` protocol feature has been
+  successfully negotiated, this message can be submitted by the backends so
+  that the front-end un-mmaps a given range (``shm_offset``, ``len``) in the
+  VIRTIO Shared Memory Region with the requested ``shmid``. Note that the
+  given range shall correspond to the entirety of a valid mapped region.
+
+  If ``VHOST_USER_PROTOCOL_F_REPLY_ACK`` is negotiated, and the back-end
+  sets the ``VHOST_USER_NEED_REPLY`` flag, the front-end must respond with
+  zero when operation is successfully completed, or non-zero otherwise.
+
 .. _reply_ack:
 
 VHOST_USER_PROTOCOL_F_REPLY_ACK
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 094/106] vhost_user: Add frontend get_shmem_config command
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (92 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 093/106] vhost_user.rst: Add SHMEM_MAP/_UNMAP to spec Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 095/106] vhost_user.rst: Add GET_SHMEM_CONFIG message Michael S. Tsirkin
                   ` (12 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Albert Esteve, Stefano Garzarella, Stefan Hajnoczi

From: Albert Esteve <aesteve@redhat.com>

The frontend can use this command to retrieve
VirtIO Shared Memory Regions configuration from
the backend. The response contains the number of
shared memory regions, their size, and shmid.

This is useful when the frontend is unaware of
specific backend type and configuration,
for example, in the `vhost-user-device` case.

Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@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: <20260304165223.2166175-5-aesteve@redhat.com>
---
 include/hw/virtio/vhost-backend.h         | 10 ++++++++++
 include/hw/virtio/vhost-user.h            |  1 +
 include/hw/virtio/virtio.h                |  2 ++
 subprojects/libvhost-user/libvhost-user.h |  4 +++-
 4 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h
index 00881a0bd4..d878d7b733 100644
--- a/include/hw/virtio/vhost-backend.h
+++ b/include/hw/virtio/vhost-backend.h
@@ -162,6 +162,15 @@ typedef int (*vhost_set_device_state_fd_op)(struct vhost_dev *dev,
                                             int *reply_fd,
                                             Error **errp);
 typedef int (*vhost_check_device_state_op)(struct vhost_dev *dev, Error **errp);
+/*
+ * Max regions is VIRTIO_MAX_SHMEM_REGIONS, so that is the maximum
+ * number of memory_sizes that will be accepted.
+ */
+typedef int (*vhost_get_shmem_config_op)(struct vhost_dev *dev,
+                                         int *nregions,
+                                         uint64_t *memory_sizes,
+                                         Error **errp);
+
 
 typedef struct VhostOps {
     VhostBackendType backend_type;
@@ -220,6 +229,7 @@ typedef struct VhostOps {
     vhost_supports_device_state_op vhost_supports_device_state;
     vhost_set_device_state_fd_op vhost_set_device_state_fd;
     vhost_check_device_state_op vhost_check_device_state;
+    vhost_get_shmem_config_op vhost_get_shmem_config;
 } VhostOps;
 
 int vhost_user_gpu_set_socket(struct vhost_dev *dev, int fd);
diff --git a/include/hw/virtio/vhost-user.h b/include/hw/virtio/vhost-user.h
index 5ab70dab7e..06c360af18 100644
--- a/include/hw/virtio/vhost-user.h
+++ b/include/hw/virtio/vhost-user.h
@@ -35,6 +35,7 @@ enum VhostUserProtocolFeature {
     VHOST_USER_PROTOCOL_F_DEVICE_STATE = 19,
     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_MAX
 };
 
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 3f745e3b67..c99cb19d88 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -82,6 +82,8 @@ typedef struct VirtQueueElement
 
 #define VIRTIO_NO_VECTOR 0xffff
 
+#define VIRTIO_MAX_SHMEM_REGIONS 256
+
 /* special index value used internally for config irqs */
 #define VIRTIO_CONFIG_IRQ_IDX -1
 
diff --git a/subprojects/libvhost-user/libvhost-user.h b/subprojects/libvhost-user/libvhost-user.h
index 6a2d0f9fae..a534d70771 100644
--- a/subprojects/libvhost-user/libvhost-user.h
+++ b/subprojects/libvhost-user/libvhost-user.h
@@ -70,7 +70,9 @@ enum VhostUserProtocolFeature {
     /* Feature 17 reserved for VHOST_USER_PROTOCOL_F_XEN_MMAP. */
     VHOST_USER_PROTOCOL_F_SHARED_OBJECT = 18,
     /* Feature 19 is reserved for VHOST_USER_PROTOCOL_F_DEVICE_STATE */
-    VHOST_USER_PROTOCOL_F_SHMEM = 20,
+    /* Feature 20 is reserved for VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT */
+    /* Feature 21 is reserved for VHOST_USER_PROTOCOL_F_GPA_ADDRESSES */
+    VHOST_USER_PROTOCOL_F_SHMEM = 22,
     VHOST_USER_PROTOCOL_F_MAX
 };
 
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 095/106] vhost_user.rst: Add GET_SHMEM_CONFIG message
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (93 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 094/106] vhost_user: Add frontend get_shmem_config command Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 096/106] qmp: add shmem feature map Michael S. Tsirkin
                   ` (11 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Albert Esteve, Stefano Garzarella, Alyssa Ross,
	Stefan Hajnoczi, Pierrick Bouvier

From: Albert Esteve <aesteve@redhat.com>

Add GET_SHMEM_CONFIG vhost-user frontend
message to the spec documentation.

Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Reviewed-by: Alyssa Ross <hi@alyssa.is>
Reviewed-by: Stefan Hajnoczi <stefanha@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: <20260304165223.2166175-6-aesteve@redhat.com>
---
 docs/interop/vhost-user.rst | 39 +++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst
index 4182d721ca..c0ae4cba98 100644
--- a/docs/interop/vhost-user.rst
+++ b/docs/interop/vhost-user.rst
@@ -384,6 +384,22 @@ MMAP request
   - 0: Pages are mapped read-only
   - 1: Pages are mapped read-write
 
+VIRTIO Shared Memory Region configuration
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
++-------------+---------+------------+----+--------------+
+| num regions | padding | mem size 0 | .. | mem size 255 |
++-------------+---------+------------+----+--------------+
+
+:num regions: a 32-bit number of regions
+
+:padding: 32-bit
+
+:mem size: an array of 256 64-bit fields representing the size of each
+           VIRTIO Shared Memory Region. ``num regions`` specifies the
+           number of valid regions (non-zero size). The array index
+           corresponds to the shared memory ID (shmid).
+
 C structure
 -----------
 
@@ -410,6 +426,7 @@ In QEMU the vhost-user message is implemented with the following struct:
           VhostUserShared object;
           VhostUserTransferDeviceState transfer_state;
           VhostUserMMap mmap;
+          VhostUserShMemConfig shmem;
       };
   } QEMU_PACKED VhostUserMsg;
 
@@ -1794,6 +1811,28 @@ Front-end message types
   Using this function requires prior negotiation of the
   ``VHOST_USER_PROTOCOL_F_DEVICE_STATE`` feature.
 
+``VHOST_USER_GET_SHMEM_CONFIG``
+  :id: 44
+  :equivalent ioctl: N/A
+  :request payload: N/A
+  :reply payload: ``struct VhostUserShMemConfig``
+
+  When the ``VHOST_USER_PROTOCOL_F_SHMEM`` protocol feature has been
+  successfully negotiated, this message can be submitted by the front-end
+  to gather the VIRTIO Shared Memory Region configuration. The back-end will
+  respond with the number of VIRTIO Shared Memory Regions it requires, and
+  each shared memory region size in an array. The shared memory IDs are
+  represented by the array index. The information returned shall comply
+  with the following rules:
+
+  * The shared information will remain valid and unchanged for the entire
+    lifetime of the connection.
+
+  * The Shared Memory Region size must be a multiple of the page size
+    supported by mmap(2).
+
+  * The size may be 0 if the region is unused.
+
 Back-end message types
 ----------------------
 
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 096/106] qmp: add shmem feature map
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (94 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 095/106] vhost_user.rst: Add GET_SHMEM_CONFIG message Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 097/106] vhost-user-device: Add shared memory BAR Michael S. Tsirkin
                   ` (10 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Albert Esteve, Stefano Garzarella, Stefan Hajnoczi

From: Albert Esteve <aesteve@redhat.com>

Add new vhost-user protocol
VHOST_USER_PROTOCOL_F_SHMEM feature to
feature map.

Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@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: <20260304165223.2166175-7-aesteve@redhat.com>
---
 hw/virtio/virtio-qmp.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/hw/virtio/virtio-qmp.c b/hw/virtio/virtio-qmp.c
index ae9be0a00f..57cc03828c 100644
--- a/hw/virtio/virtio-qmp.c
+++ b/hw/virtio/virtio-qmp.c
@@ -123,6 +123,9 @@ static const qmp_virtio_feature_map_t vhost_user_protocol_map[] = {
     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_DEVICE_STATE, \
             "VHOST_USER_PROTOCOL_F_DEVICE_STATE: Backend device state transfer "
             "supported"),
+    FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_SHMEM, \
+                "VHOST_USER_PROTOCOL_F_SHMEM: Backend shared memory mapping "
+                "supported"),
     { -1, "" }
 };
 
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 097/106] vhost-user-device: Add shared memory BAR
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (95 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 096/106] qmp: add shmem feature map Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 098/106] vhost-user.rst: fix typo Michael S. Tsirkin
                   ` (9 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Albert Esteve, Stefano Garzarella, Stefan Hajnoczi,
	Alex Bennée

From: Albert Esteve <aesteve@redhat.com>

Add shared memory BAR support to vhost-user-device-pci
to enable direct file mapping for VIRTIO Shared
Memory Regions.

The implementation creates a consolidated shared
memory BAR that contains all VIRTIO Shared
Memory Regions as subregions. Each region is
configured with its proper shmid, size, and
offset within the BAR. The number and size of
regions are retrieved via VHOST_USER_GET_SHMEM_CONFIG
message sent by vhost-user-base during realization
after virtio_init().

Specifically, it uses BAR 4 to avoid conflicts, as
it is currently unused.

The shared memory BAR is only created when the
backend supports VHOST_USER_PROTOCOL_F_SHMEM and
has configured shared memory regions. This maintains
backward compatibility with backends that do not
support shared memory functionality.

Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@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: <20260304165223.2166175-8-aesteve@redhat.com>
---
 hw/virtio/vhost-user-base.c            | 46 ++++++++++++++++++++++++--
 hw/virtio/vhost-user-test-device-pci.c | 42 +++++++++++++++++++++--
 2 files changed, 83 insertions(+), 5 deletions(-)

diff --git a/hw/virtio/vhost-user-base.c b/hw/virtio/vhost-user-base.c
index 8b62c6c36e..39b5e637fc 100644
--- a/hw/virtio/vhost-user-base.c
+++ b/hw/virtio/vhost-user-base.c
@@ -16,6 +16,7 @@
 #include "hw/virtio/virtio-bus.h"
 #include "hw/virtio/vhost-user-base.h"
 #include "qemu/error-report.h"
+#include "migration/blocker.h"
 
 static void vub_start(VirtIODevice *vdev)
 {
@@ -281,7 +282,8 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
 {
     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
     VHostUserBase *vub = VHOST_USER_BASE(dev);
-    int ret;
+    uint64_t memory_sizes[VIRTIO_MAX_SHMEM_REGIONS];
+    int i, ret, nregions, regions_processed = 0;
 
     if (!vub->chardev.chr) {
         error_setg(errp, "vhost-user-base: missing chardev");
@@ -324,7 +326,7 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
 
     /* Allocate queues */
     vub->vqs = g_ptr_array_sized_new(vub->num_vqs);
-    for (int i = 0; i < vub->num_vqs; i++) {
+    for (i = 0; i < vub->num_vqs; i++) {
         g_ptr_array_add(vub->vqs,
                         virtio_add_queue(vdev, vub->vq_size,
                                          vub_handle_output));
@@ -338,11 +340,49 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
                          VHOST_BACKEND_TYPE_USER, 0, errp);
 
     if (ret < 0) {
-        do_vhost_user_cleanup(vdev, vub);
+        goto err;
+    }
+
+    ret = vub->vhost_dev.vhost_ops->vhost_get_shmem_config(&vub->vhost_dev,
+                                                           &nregions,
+                                                           memory_sizes,
+                                                           errp);
+
+    if (ret < 0) {
+        goto err;
+    }
+
+    for (i = 0; i < VIRTIO_MAX_SHMEM_REGIONS && regions_processed < nregions; i++) {
+        if (memory_sizes[i]) {
+            regions_processed++;
+            if (vub->vhost_dev.migration_blocker == NULL) {
+                error_setg(&vub->vhost_dev.migration_blocker,
+                       "Migration disabled: devices with VIRTIO Shared Memory "
+                       "Regions do not support migration yet.");
+                ret = migrate_add_blocker_normal(
+                    &vub->vhost_dev.migration_blocker,
+                    errp);
+
+                if (ret < 0) {
+                    goto err;
+                }
+            }
+
+            if (memory_sizes[i] % qemu_real_host_page_size() != 0) {
+                error_setg(errp, "Shared memory %d size must be a multiple of "
+                                 "the host page size", i);
+                goto err;
+            }
+
+            virtio_new_shmem_region(vdev, i, memory_sizes[i]);
+        }
     }
 
     qemu_chr_fe_set_handlers(&vub->chardev, NULL, NULL, vub_event, NULL,
                              dev, NULL, true);
+    return;
+err:
+    do_vhost_user_cleanup(vdev, vub);
 }
 
 static void vub_device_unrealize(DeviceState *dev)
diff --git a/hw/virtio/vhost-user-test-device-pci.c b/hw/virtio/vhost-user-test-device-pci.c
index 7f6d751690..2106557ed8 100644
--- a/hw/virtio/vhost-user-test-device-pci.c
+++ b/hw/virtio/vhost-user-test-device-pci.c
@@ -12,10 +12,13 @@
 #include "hw/virtio/vhost-user-base.h"
 #include "hw/virtio/virtio-pci.h"
 
+#define VIRTIO_DEVICE_PCI_SHMEM_BAR 4
+
 struct VHostUserDevicePCI {
     VirtIOPCIProxy parent_obj;
 
     VHostUserBase vub;
+    MemoryRegion shmembar;
 };
 
 #define TYPE_VHOST_USER_TEST_DEVICE_PCI "vhost-user-test-device-pci-base"
@@ -25,10 +28,45 @@ OBJECT_DECLARE_SIMPLE_TYPE(VHostUserDevicePCI, VHOST_USER_TEST_DEVICE_PCI)
 static void vhost_user_device_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
 {
     VHostUserDevicePCI *dev = VHOST_USER_TEST_DEVICE_PCI(vpci_dev);
-    DeviceState *vdev = DEVICE(&dev->vub);
+    DeviceState *dev_state = DEVICE(&dev->vub);
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev_state);
+    VirtioSharedMemory *shmem;
+    uint64_t offset = 0, shmem_size = 0;
 
+    /* Keep modern 64-bit BARs (2 slots) away from the shared memory BAR. */
+    vpci_dev->modern_mem_bar_idx = 2;
     vpci_dev->nvectors = 1;
-    qdev_realize(vdev, BUS(&vpci_dev->bus), errp);
+    if (!qdev_realize(dev_state, BUS(&vpci_dev->bus), errp)) {
+        return;
+    }
+
+    QSIMPLEQ_FOREACH(shmem, &vdev->shmem_list, entry) {
+        if (memory_region_size(&shmem->mr) > UINT64_MAX - shmem_size) {
+            error_setg(errp, "Total shared memory required overflow");
+            return;
+        }
+        shmem_size = shmem_size + memory_region_size(&shmem->mr);
+    }
+    if (shmem_size) {
+        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;
+        }
+        memory_region_init(&dev->shmembar, OBJECT(vpci_dev),
+                           "vhost-device-pci-shmembar", shmem_size);
+        QSIMPLEQ_FOREACH(shmem, &vdev->shmem_list, entry) {
+            memory_region_add_subregion(&dev->shmembar, offset, &shmem->mr);
+            virtio_pci_add_shm_cap(vpci_dev, VIRTIO_DEVICE_PCI_SHMEM_BAR,
+                                   offset, memory_region_size(&shmem->mr),
+                                   shmem->shmid);
+            offset = offset + memory_region_size(&shmem->mr);
+        }
+        pci_register_bar(&vpci_dev->pci_dev, VIRTIO_DEVICE_PCI_SHMEM_BAR,
+                        PCI_BASE_ADDRESS_SPACE_MEMORY |
+                        PCI_BASE_ADDRESS_MEM_PREFETCH |
+                        PCI_BASE_ADDRESS_MEM_TYPE_64,
+                        &dev->shmembar);
+    }
 }
 
 static void vhost_user_device_pci_class_init(ObjectClass *klass,
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 098/106] vhost-user.rst: fix typo
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (96 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 097/106] vhost-user-device: Add shared memory BAR Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 099/106] hw/cxl: Fix handling of component ID to not assume it is a string Michael S. Tsirkin
                   ` (8 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Alexandr Moshkov, Vladimir Sementsov-Ogievskiy,
	Stefan Hajnoczi, Raphael Norwitz, Stefano Garzarella,
	Pierrick Bouvier

From: Alexandr Moshkov <dtalexundeer@yandex-team.ru>

Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Alexandr Moshkov <dtalexundeer@yandex-team.ru>
Reviewed-by: Raphael Norwitz <rnorwitz@nvidia.com>
Message-Id: <20260330095226.158386-2-dtalexundeer@yandex-team.ru>
---
 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 c0ae4cba98..c83ae2accb 100644
--- a/docs/interop/vhost-user.rst
+++ b/docs/interop/vhost-user.rst
@@ -1329,7 +1329,7 @@ Front-end message types
   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 neogotiated if
+  protocol feature must only be negotiated if
   ``VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD`` is also negotiated.
 
 ``VHOST_USER_SET_VRING_KICK``
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 099/106] hw/cxl: Fix handling of component ID to not assume it is a string
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (97 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 098/106] vhost-user.rst: fix typo Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 100/106] hw/cxl: Add fixes in Post Package Repair (PPR) Michael S. Tsirkin
                   ` (7 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Shiju Jose, Jonathan Cameron, Jonathan Cameron,
	linux-cxl

From: Shiju Jose <shiju.jose@huawei.com>

Add following fixes,
1. Coverity reports a warning (CID 1645325) for use of strncpy() in
handling of component ID. In cxl_create_mem_sparing_event_records(),
fix handling of component ID to not assume it is a string by replacing
strncpy with memcpy to solve this warning and copy the entire component
ID data, which is 16 bytes.

2. In cxl_maintenance_insert(),
 - replace strncpy with memcpy to copy full data because component ID,
   which is 16 bytes data.
 - remove memset which is not required.

Closes ("https://lore.kernel.org/qemu-devel/CAFEAcA_CsVe4TUVm3o_-BA4hXvi2xAThGX5T97amgTQKW_kiYA@mail.gmail.com/")

Fixes: 5e5a86bab830("hw/cxl: Add support for Maintenance command and Post Package Repair (PPR)")
Reported-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Shiju Jose <shiju.jose@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260306101423.986-2-shiju.jose@huawei.com>
---
 hw/cxl/cxl-mailbox-utils.c | 4 ++--
 hw/mem/cxl_type3.c         | 4 +---
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
index d8ba7e8625..6b16cc206f 100644
--- a/hw/cxl/cxl-mailbox-utils.c
+++ b/hw/cxl/cxl-mailbox-utils.c
@@ -1994,8 +1994,8 @@ static void cxl_create_mem_sparing_event_records(CXLType3Dev *ct3d,
         stw_le_p(&event_rec.column, ent->column);
         event_rec.sub_channel = ent->sub_channel;
         if (ent->validity_flags & CXL_MSER_VALID_COMP_ID) {
-            strncpy((char *)event_rec.component_id, (char *)ent->component_id,
-                    sizeof(event_rec.component_id));
+            memcpy(event_rec.component_id, ent->component_id,
+                   sizeof(event_rec.component_id));
         }
     } else if (sparing_pi) {
         event_rec.flags = CXL_MSER_FLAGS_QUERY_RESOURCES;
diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index 4739239da3..3cb1096e16 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.c
@@ -1767,7 +1767,6 @@ static void cxl_maintenance_insert(CXLType3Dev *ct3d, uint64_t dpa,
         }
     }
     m = g_new0(CXLMaintenance, 1);
-    memset(m, 0, sizeof(*m));
     m->dpa = dpa;
     m->validity_flags = 0;
 
@@ -1804,8 +1803,7 @@ static void cxl_maintenance_insert(CXLType3Dev *ct3d, uint64_t dpa,
         m->validity_flags |= CXL_MSER_VALID_SUB_CHANNEL;
     }
     if (component_id) {
-        strncpy((char *)m->component_id, component_id,
-                sizeof(m->component_id) - 1);
+        memcpy(m->component_id, component_id, sizeof(m->component_id));
         m->validity_flags |= CXL_MSER_VALID_COMP_ID;
         if (has_comp_id_pldm && is_comp_id_pldm) {
             m->validity_flags |= CXL_MSER_VALID_COMP_ID_FORMAT;
-- 
MST


^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 100/106] hw/cxl: Add fixes in Post Package Repair (PPR)
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (98 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 099/106] hw/cxl: Fix handling of component ID to not assume it is a string Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 101/106] hw/cxl/events: Fix handling of component ID in event records generation to not assume it is a string Michael S. Tsirkin
                   ` (6 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Shiju Jose, Jonathan Cameron, Jonathan Cameron,
	linux-cxl

From: Shiju Jose <shiju.jose@huawei.com>

Add following fixes to the commit: hw/cxl: Add support for Maintenance
command and Post Package Repair (PPR).

In cxl_perform_ppr(), remove and free the maintenance entry from QLIST
if match is found and PPR operation is performed.

Fixes: 5e5a86bab830("hw/cxl: Add support for Maintenance command and Post Package Repair (PPR)")
Signed-off-by: Shiju Jose <shiju.jose@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260306101423.986-3-shiju.jose@huawei.com>
---
 hw/cxl/cxl-mailbox-utils.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
index 6b16cc206f..20e0b7e476 100644
--- a/hw/cxl/cxl-mailbox-utils.c
+++ b/hw/cxl/cxl-mailbox-utils.c
@@ -2068,6 +2068,8 @@ static void cxl_perform_ppr(CXLType3Dev *ct3d, uint64_t dpa)
                                 CXL_MEMDEV_MAINT_SUBCLASS_CACHELINE_SPARING,
                                 ent, NULL);
             }
+            QLIST_REMOVE(ent, node);
+            g_free(ent);
             break;
         }
     }
-- 
MST


^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 101/106] hw/cxl/events: Fix handling of component ID in event records generation to not assume it is a string
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (99 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 100/106] hw/cxl: Add fixes in Post Package Repair (PPR) Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 102/106] hw/cxl: Allow cxl_cfmws_find_device() to filter on whether interleaved paths are accepted Michael S. Tsirkin
                   ` (5 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Shiju Jose, Jonathan Cameron, Jonathan Cameron,
	linux-cxl

From: Shiju Jose <shiju.jose@huawei.com>

Fix handling of component ID in event records generation to not assume it
is a string. Component ID in CXL events is 16 bytes data, but event record
generation copy 15 bytes only from the qmp "component-id" field using
strncpy. Replace strncpy with memcpy and copy the entire component ID
data.

Fixes: ea9b6d647f2f("hw/cxl/events: Add injection of General Media Events")
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Signed-off-by: Shiju Jose <shiju.jose@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260306101423.986-4-shiju.jose@huawei.com>
---
 hw/mem/cxl_type3.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index 3cb1096e16..03a5d1751f 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.c
@@ -1895,8 +1895,7 @@ void qmp_cxl_inject_general_media_event(const char *path, CxlEventLog log,
     }
 
     if (component_id) {
-        strncpy((char *)gem.component_id, component_id,
-                sizeof(gem.component_id) - 1);
+        memcpy(gem.component_id, component_id, sizeof(gem.component_id));
         valid_flags |= CXL_GMER_VALID_COMPONENT;
         if (has_comp_id_pldm && is_comp_id_pldm) {
             valid_flags |= CXL_GMER_VALID_COMPONENT_ID_FORMAT;
@@ -2066,8 +2065,7 @@ void qmp_cxl_inject_dram_event(const char *path, CxlEventLog log,
     }
 
     if (component_id) {
-        strncpy((char *)dram.component_id, component_id,
-                sizeof(dram.component_id) - 1);
+        memcpy(dram.component_id, component_id, sizeof(dram.component_id));
         valid_flags |= CXL_DRAM_VALID_COMPONENT;
         if (has_comp_id_pldm && is_comp_id_pldm) {
             valid_flags |= CXL_DRAM_VALID_COMPONENT_ID_FORMAT;
@@ -2185,8 +2183,7 @@ void qmp_cxl_inject_memory_module_event(const char *path, CxlEventLog log,
              corrected_persist_error_count);
 
     if (component_id) {
-        strncpy((char *)module.component_id, component_id,
-                sizeof(module.component_id) - 1);
+        memcpy(module.component_id, component_id, sizeof(module.component_id));
         valid_flags |= CXL_MMER_VALID_COMPONENT;
         if (has_comp_id_pldm && is_comp_id_pldm) {
             valid_flags |= CXL_MMER_VALID_COMPONENT_ID_FORMAT;
-- 
MST


^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 102/106] hw/cxl: Allow cxl_cfmws_find_device() to filter on whether interleaved paths are accepted
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (100 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 101/106] hw/cxl/events: Fix handling of component ID in event records generation to not assume it is a string Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:09 ` [PULL 103/106] hw/cxl: Add a performant (and correct) path for the non interleaved cases Michael S. Tsirkin
                   ` (4 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Li Zhijian, Jonathan Cameron, Gregory Price,
	Alireza Sanaee, Jonathan Cameron, linux-cxl

From: Alireza Sanaee via qemu development <qemu-devel@nongnu.org>

Extend cxl_cfmws_find_device() with a parameter that filters on whether the
address lies in an interleaved range. For now all callers accept
interleave configurations so no functional changes.

Reviewed-by: Li Zhijian <lizhijian@fujitsu.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Reviewed-by: Gregory Price <gourry@gourry.net>
Tested-by: Gregory Price <gourry@gourry.net>
Signed-off-by: Alireza Sanaee <alireza.sanaee@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260318171918.146-3-alireza.sanaee@huawei.com>
---
 hw/cxl/cxl-host.c | 33 ++++++++++++++++++++++++++-------
 1 file changed, 26 insertions(+), 7 deletions(-)

diff --git a/hw/cxl/cxl-host.c b/hw/cxl/cxl-host.c
index a94b893e99..2dc9f77007 100644
--- a/hw/cxl/cxl-host.c
+++ b/hw/cxl/cxl-host.c
@@ -104,7 +104,7 @@ void cxl_fmws_link_targets(Error **errp)
 }
 
 static bool cxl_hdm_find_target(uint32_t *cache_mem, hwaddr addr,
-                                uint8_t *target)
+                                uint8_t *target, bool *interleaved)
 {
     int hdm_inc = R_CXL_HDM_DECODER1_BASE_LO - R_CXL_HDM_DECODER0_BASE_LO;
     unsigned int hdm_count;
@@ -138,6 +138,11 @@ static bool cxl_hdm_find_target(uint32_t *cache_mem, hwaddr addr,
         found = true;
         ig_enc = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, IG);
         iw_enc = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, IW);
+
+        if (interleaved) {
+            *interleaved = iw_enc != 0;
+        }
+
         target_idx = (addr / cxl_decode_ig(ig_enc)) % (1 << iw_enc);
 
         if (target_idx < 4) {
@@ -157,7 +162,8 @@ static bool cxl_hdm_find_target(uint32_t *cache_mem, hwaddr addr,
     return found;
 }
 
-static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr)
+static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr,
+                                        bool allow_interleave)
 {
     CXLComponentState *hb_cstate, *usp_cstate;
     PCIHostState *hb;
@@ -165,9 +171,13 @@ static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr)
     int rb_index;
     uint32_t *cache_mem;
     uint8_t target;
-    bool target_found;
+    bool target_found, interleaved;
     PCIDevice *rp, *d;
 
+    if ((fw->num_targets > 1) && !allow_interleave) {
+        return NULL;
+    }
+
     rb_index = (addr / cxl_decode_ig(fw->enc_int_gran)) % fw->num_targets;
     hb = PCI_HOST_BRIDGE(fw->target_hbs[rb_index]->cxl_host_bridge);
     if (!hb || !hb->bus || !pci_bus_is_cxl(hb->bus)) {
@@ -187,11 +197,16 @@ static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr)
 
         cache_mem = hb_cstate->crb.cache_mem_registers;
 
-        target_found = cxl_hdm_find_target(cache_mem, addr, &target);
+        target_found = cxl_hdm_find_target(cache_mem, addr, &target,
+                                           &interleaved);
         if (!target_found) {
             return NULL;
         }
 
+        if (interleaved && !allow_interleave) {
+            return NULL;
+        }
+
         rp = pcie_find_port_by_pn(hb->bus, target);
         if (!rp) {
             return NULL;
@@ -223,11 +238,15 @@ static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr)
 
     cache_mem = usp_cstate->crb.cache_mem_registers;
 
-    target_found = cxl_hdm_find_target(cache_mem, addr, &target);
+    target_found = cxl_hdm_find_target(cache_mem, addr, &target, &interleaved);
     if (!target_found) {
         return NULL;
     }
 
+    if (interleaved && !allow_interleave) {
+        return NULL;
+    }
+
     d = pcie_find_port_by_pn(&PCI_BRIDGE(d)->sec_bus, target);
     if (!d) {
         return NULL;
@@ -251,7 +270,7 @@ static MemTxResult cxl_read_cfmws(void *opaque, hwaddr addr, uint64_t *data,
     CXLFixedWindow *fw = opaque;
     PCIDevice *d;
 
-    d = cxl_cfmws_find_device(fw, addr + fw->base);
+    d = cxl_cfmws_find_device(fw, addr + fw->base, true);
     if (d == NULL) {
         *data = 0;
         /* Reads to invalid address return poison */
@@ -268,7 +287,7 @@ static MemTxResult cxl_write_cfmws(void *opaque, hwaddr addr,
     CXLFixedWindow *fw = opaque;
     PCIDevice *d;
 
-    d = cxl_cfmws_find_device(fw, addr + fw->base);
+    d = cxl_cfmws_find_device(fw, addr + fw->base, true);
     if (d == NULL) {
         /* Writes to invalid address are silent */
         return MEMTX_OK;
-- 
MST


^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 103/106] hw/cxl: Add a performant (and correct) path for the non interleaved cases
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (101 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 102/106] hw/cxl: Allow cxl_cfmws_find_device() to filter on whether interleaved paths are accepted Michael S. Tsirkin
@ 2026-06-14 19:09 ` Michael S. Tsirkin
  2026-06-14 19:10 ` [PULL 104/106] intel_iommu: fix guest-triggerable abort on oversized MMIO access Michael S. Tsirkin
                   ` (3 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Li Zhijian, Jonathan Cameron, Gregory Price,
	Alireza Sanaee, Jonathan Cameron, linux-cxl

From: Alireza Sanaee via qemu development <qemu-devel@nongnu.org>

The CXL address to device decoding logic is complex because of the need to
correctly decode fine grained interleave. The current implementation
prevents use with KVM where executed instructions may reside in that memory
and gives very slow performance even in TCG.

In many real cases non interleaved memory configurations are useful and for
those we can use a more conventional memory region alias allowing similar
performance to other memory in the system.

Whether this fast path is applicable can be established once the full set
of HDM decoders has been committed (in whatever order the guest decides to
commit them). As such a check is performed on each commit/uncommit of HDM
decoder to establish if the alias should be added or removed.

Reviewed-by: Li Zhijian <lizhijian@fujitsu.com>
Co-developed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Signed-off-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Reviewed-by: Gregory Price <gourry@gourry.net>
Tested-by: Gregory Price <gourry@gourry.net>
Signed-off-by: Alireza Sanaee <alireza.sanaee@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260318171918.146-4-alireza.sanaee@huawei.com>
---
 hw/cxl/cxl-component-utils.c |   6 ++
 hw/cxl/cxl-host.c            | 201 +++++++++++++++++++++++++++++++++++
 hw/mem/cxl_type3.c           |   4 +
 include/hw/cxl/cxl.h         |   1 +
 include/hw/cxl/cxl_device.h  |   4 +
 5 files changed, 216 insertions(+)

diff --git a/hw/cxl/cxl-component-utils.c b/hw/cxl/cxl-component-utils.c
index 07aabe331c..a624357978 100644
--- a/hw/cxl/cxl-component-utils.c
+++ b/hw/cxl/cxl-component-utils.c
@@ -143,6 +143,12 @@ static void dumb_hdm_handler(CXLComponentState *cxl_cstate, hwaddr offset,
         value = FIELD_DP32(value, CXL_HDM_DECODER0_CTRL, COMMITTED, 0);
     }
     stl_le_p((uint8_t *)cache_mem + offset, value);
+
+    if (should_commit) {
+        cfmws_update_non_interleaved(true);
+    } else if (should_uncommit) {
+        cfmws_update_non_interleaved(false);
+    }
 }
 
 static void bi_handler(CXLComponentState *cxl_cstate, hwaddr offset,
diff --git a/hw/cxl/cxl-host.c b/hw/cxl/cxl-host.c
index 2dc9f77007..7e744312f1 100644
--- a/hw/cxl/cxl-host.c
+++ b/hw/cxl/cxl-host.c
@@ -264,6 +264,207 @@ static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr,
     return d;
 }
 
+typedef struct CXLDirectPTState {
+    CXLType3Dev *ct3d;
+    hwaddr decoder_base;
+    hwaddr decoder_size;
+    hwaddr dpa_base;
+    unsigned int hdm_decoder_idx;
+} CXLDirectPTState;
+
+static void cxl_fmws_direct_passthrough_setup(CXLDirectPTState *state,
+                                              CXLFixedWindow *fw)
+{
+    CXLType3Dev *ct3d = state->ct3d;
+    MemoryRegion *mr = NULL;
+    uint64_t vmr_size = 0, pmr_size = 0, offset = 0;
+    MemoryRegion *direct_mr;
+    g_autofree char *direct_mr_name;
+    unsigned int idx = state->hdm_decoder_idx;
+
+    if (ct3d->hostvmem) {
+        MemoryRegion *vmr = host_memory_backend_get_memory(ct3d->hostvmem);
+
+        vmr_size = memory_region_size(vmr);
+        if (state->dpa_base < vmr_size) {
+            mr = vmr;
+            offset = state->dpa_base;
+        }
+    }
+    if (!mr && ct3d->hostpmem) {
+        MemoryRegion *pmr = host_memory_backend_get_memory(ct3d->hostpmem);
+
+        pmr_size = memory_region_size(pmr);
+        if (state->dpa_base - vmr_size < pmr_size) {
+            mr = pmr;
+            offset = state->dpa_base - vmr_size;
+        }
+    }
+    if (!mr) {
+        return;
+    }
+
+    if (ct3d->direct_mr_fw[idx]) {
+        return;
+    }
+
+    direct_mr = &ct3d->direct_mr[idx];
+    direct_mr_name = g_strdup_printf("cxl-direct-mapping-alias-%u", idx);
+    if (!direct_mr_name) {
+        return;
+    }
+
+    memory_region_init_alias(direct_mr, OBJECT(ct3d), direct_mr_name, mr,
+                             offset, state->decoder_size);
+    memory_region_transaction_begin();
+    memory_region_add_subregion(&fw->mr,
+                                state->decoder_base - fw->base, direct_mr);
+    memory_region_transaction_commit();
+    ct3d->direct_mr_fw[idx] = fw;
+}
+
+static void cxl_fmws_direct_passthrough_remove(CXLType3Dev *ct3d,
+                                               uint64_t decoder_base,
+                                               unsigned int idx)
+{
+    CXLFixedWindow *owner_fw = ct3d->direct_mr_fw[idx];
+    MemoryRegion *direct_mr = &ct3d->direct_mr[idx];
+
+    if (!owner_fw) {
+        return;
+    }
+
+    if (!memory_region_is_mapped(direct_mr)) {
+        return;
+    }
+
+    if (cxl_cfmws_find_device(owner_fw, decoder_base, false)) {
+        return;
+    }
+
+    memory_region_transaction_begin();
+    memory_region_del_subregion(&owner_fw->mr, direct_mr);
+    object_unparent(OBJECT(direct_mr));
+    memory_region_transaction_commit();
+    ct3d->direct_mr_fw[idx] = NULL;
+}
+
+static int cxl_fmws_direct_passthrough(Object *obj, void *opaque)
+{
+    CXLDirectPTState *state = opaque;
+    CXLFixedWindow *fw;
+
+    if (!object_dynamic_cast(obj, TYPE_CXL_FMW)) {
+        return 0;
+    }
+
+    fw = CXL_FMW(obj);
+
+    /* Verify not interleaved */
+    if (!cxl_cfmws_find_device(fw, state->decoder_base, false)) {
+        return 0;
+    }
+
+    cxl_fmws_direct_passthrough_setup(state, fw);
+
+    return 0;
+}
+
+static int update_non_interleaved(Object *obj, void *opaque)
+{
+    const int hdm_inc = R_CXL_HDM_DECODER1_BASE_LO - R_CXL_HDM_DECODER0_BASE_LO;
+    bool commit = *(bool *)opaque;
+    CXLType3Dev *ct3d;
+    uint32_t *cache_mem;
+    unsigned int hdm_count, i;
+    int interleave_ways_dec;
+    uint32_t cap;
+    uint64_t dpa_base = 0;
+
+    if (!object_dynamic_cast(obj, TYPE_CXL_TYPE3)) {
+        return 0;
+    }
+
+    ct3d = CXL_TYPE3(obj);
+    cache_mem = ct3d->cxl_cstate.crb.cache_mem_registers;
+    cap = ldl_le_p(cache_mem + R_CXL_HDM_DECODER_CAPABILITY);
+    hdm_count = cxl_decoder_count_dec(FIELD_EX32(cap,
+                                                 CXL_HDM_DECODER_CAPABILITY,
+                                                 DECODER_COUNT));
+    for (i = 0; i < hdm_count; i++) {
+        uint64_t decoder_base, decoder_size, skip;
+        uint32_t hdm_ctrl, low, high;
+        int iw, committed;
+
+        hdm_ctrl = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + i * hdm_inc);
+        committed = FIELD_EX32(hdm_ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED);
+
+        /*
+         * Optimization: Looking for a fully committed path; if the type 3 HDM
+         * decoder is not commmitted, it cannot lie on such a path.
+         */
+        if (commit && !committed) {
+            return 0;
+        }
+
+        low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_DPA_SKIP_LO +
+                       i * hdm_inc);
+        high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_DPA_SKIP_HI +
+                        i * hdm_inc);
+        skip = ((uint64_t)high << 32) | (low & 0xf0000000);
+        dpa_base += skip;
+
+        low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_SIZE_LO + i * hdm_inc);
+        high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_SIZE_HI + i * hdm_inc);
+        decoder_size = ((uint64_t)high << 32) | (low & 0xf0000000);
+
+        low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_BASE_LO + i * hdm_inc);
+        high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_BASE_HI + i * hdm_inc);
+        decoder_base = ((uint64_t)high << 32) | (low & 0xf0000000);
+
+        iw = FIELD_EX32(hdm_ctrl, CXL_HDM_DECODER0_CTRL, IW);
+
+        if (iw == 0) {
+            if (!commit) {
+                cxl_fmws_direct_passthrough_remove(ct3d, decoder_base, i);
+            } else {
+                CXLDirectPTState state = {
+                    .ct3d = ct3d,
+                    .decoder_base = decoder_base,
+                    .decoder_size = decoder_size,
+                    .dpa_base = dpa_base,
+                    .hdm_decoder_idx = i,
+                };
+
+                object_child_foreach_recursive(object_get_root(),
+                                               cxl_fmws_direct_passthrough,
+                                               &state);
+            }
+        }
+
+        interleave_ways_dec = cxl_interleave_ways_dec(iw, &error_fatal);
+        if (interleave_ways_dec == 0) {
+            return 0;
+        }
+
+        dpa_base += decoder_size / interleave_ways_dec;
+    }
+
+    return 0;
+}
+
+void cfmws_update_non_interleaved(bool commit)
+{
+    /*
+     * Walk endpoints to find both committed and uncommitted decoders,
+     * then check if they are not interleaved (but the path is fully set up).
+     */
+    object_child_foreach_recursive(object_get_root(),
+                                   update_non_interleaved, &commit);
+
+    return;
+}
+
 static MemTxResult cxl_read_cfmws(void *opaque, hwaddr addr, uint64_t *data,
                                   unsigned size, MemTxAttrs attrs)
 {
diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index 03a5d1751f..cba05ec57d 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.c
@@ -427,6 +427,8 @@ static void hdm_decoder_commit(CXLType3Dev *ct3d, int which)
     ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED, 1);
 
     stl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + which * hdm_inc, ctrl);
+
+    cfmws_update_non_interleaved(true);
 }
 
 static void hdm_decoder_uncommit(CXLType3Dev *ct3d, int which)
@@ -442,6 +444,8 @@ static void hdm_decoder_uncommit(CXLType3Dev *ct3d, int which)
     ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED, 0);
 
     stl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + which * hdm_inc, ctrl);
+
+    cfmws_update_non_interleaved(false);
 }
 
 static int ct3d_qmp_uncor_err_to_cxl(CxlUncorErrorType qmp_err)
diff --git a/include/hw/cxl/cxl.h b/include/hw/cxl/cxl.h
index 998f495a98..d8cd8359d2 100644
--- a/include/hw/cxl/cxl.h
+++ b/include/hw/cxl/cxl.h
@@ -71,4 +71,5 @@ CXLComponentState *cxl_usp_to_cstate(CXLUpstreamPort *usp);
 typedef struct CXLDownstreamPort CXLDownstreamPort;
 DECLARE_INSTANCE_CHECKER(CXLDownstreamPort, CXL_DSP, TYPE_CXL_DSP)
 
+void cfmws_update_non_interleaved(bool commit);
 #endif
diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
index 393f312217..ba551fa5f9 100644
--- a/include/hw/cxl/cxl_device.h
+++ b/include/hw/cxl/cxl_device.h
@@ -685,6 +685,8 @@ typedef struct CXLSetFeatureInfo {
     size_t data_size;
 } CXLSetFeatureInfo;
 
+typedef struct CXLFixedWindow CXLFixedWindow;
+
 struct CXLSanitizeInfo;
 
 typedef struct CXLAlertConfig {
@@ -712,6 +714,8 @@ struct CXLType3Dev {
     uint64_t sn;
 
     /* State */
+    MemoryRegion direct_mr[CXL_HDM_DECODER_COUNT];
+    CXLFixedWindow *direct_mr_fw[CXL_HDM_DECODER_COUNT];
     AddressSpace hostvmem_as;
     AddressSpace hostpmem_as;
     CXLComponentState cxl_cstate;
-- 
MST


^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 104/106] intel_iommu: fix guest-triggerable abort on oversized MMIO access
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (102 preceding siblings ...)
  2026-06-14 19:09 ` [PULL 103/106] hw/cxl: Add a performant (and correct) path for the non interleaved cases Michael S. Tsirkin
@ 2026-06-14 19:10 ` Michael S. Tsirkin
  2026-06-14 19:10 ` [PULL 105/106] tests/qtest: add 8-byte MMIO access sweep for intel-iommu Michael S. Tsirkin
                   ` (2 subsequent siblings)
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:10 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Junjie Cao, Zhenzhong Duan, Yi Liu, Jason Wang,
	Clément Mathieu--Drif, Paolo Bonzini, Richard Henderson

From: Junjie Cao <junjie.cao@intel.com>

An 8-byte guest access to a 32-bit-only VT-d register hit
assert(size == 4) and aborted QEMU.  Remove all 25 asserts.

All 3 read-side and 18 of 22 write-side asserts are at
non-8-aligned offsets (unreachable, rejected by
memory_region_access_valid()) -- simply deleted.

The remaining 4, all writes at 8-aligned offsets, are
reachable: FECTL 0x38, IECTL 0xa0, IEADDR 0xa8, PECTL 0xe0.
Truncating the high half via vtd_set_long() matches prior
behavior; log under -d guest_errors since the VT-d spec is
silent on oversized accesses to 32-bit registers, and add a
comment so future maintainers don't delete the check as
"harmless".  min_access_size stays 4, so all size-based
branches on 64-bit register pairs are preserved.

Found by generic-fuzz (24 distinct crash seeds, all fixed).

Suggested-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Signed-off-by: Junjie Cao <junjie.cao@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Yi Liu <yi.l.liu@intel.com>
Reviewed-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260514180703.85686-2-junjie.cao@intel.com>
---
 hw/i386/intel_iommu.c | 74 ++++++++++++++++++++++++++++---------------
 1 file changed, 49 insertions(+), 25 deletions(-)

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 8bb2a1e339..744cdfd2e6 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -21,6 +21,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu/error-report.h"
+#include "qemu/log.h"
 #include "qemu/main-loop.h"
 #include "qapi/error.h"
 #include "hw/core/sysbus.h"
@@ -3659,7 +3660,6 @@ static uint64_t vtd_mem_read(void *opaque, hwaddr addr, unsigned size)
         break;
 
     case DMAR_RTADDR_REG_HI:
-        assert(size == 4);
         val = vtd_get_quad_raw(s, DMAR_RTADDR_REG) >> 32;
         break;
 
@@ -3674,12 +3674,10 @@ static uint64_t vtd_mem_read(void *opaque, hwaddr addr, unsigned size)
         break;
 
     case DMAR_IQA_REG_HI:
-        assert(size == 4);
         val = s->iq >> 32;
         break;
 
     case DMAR_PEUADDR_REG:
-        assert(size == 4);
         val = vtd_get_long_raw(s, DMAR_PEUADDR_REG);
         break;
 
@@ -3725,7 +3723,6 @@ static void vtd_mem_write(void *opaque, hwaddr addr,
         break;
 
     case DMAR_CCMD_REG_HI:
-        assert(size == 4);
         vtd_set_long(s, addr, val);
         vtd_handle_ccmd_write(s);
         break;
@@ -3741,13 +3738,11 @@ static void vtd_mem_write(void *opaque, hwaddr addr,
         break;
 
     case DMAR_IOTLB_REG_HI:
-        assert(size == 4);
         vtd_set_long(s, addr, val);
         vtd_handle_iotlb_write(s);
         break;
 
     case DMAR_PEUADDR_REG:
-        assert(size == 4);
         vtd_set_long(s, addr, val);
         break;
 
@@ -3761,27 +3756,35 @@ static void vtd_mem_write(void *opaque, hwaddr addr,
         break;
 
     case DMAR_IVA_REG_HI:
-        assert(size == 4);
         vtd_set_long(s, addr, val);
         break;
 
     /* Fault Status Register, 32-bit */
     case DMAR_FSTS_REG:
-        assert(size == 4);
         vtd_set_long(s, addr, val);
         vtd_handle_fsts_write(s);
         break;
 
     /* Fault Event Control Register, 32-bit */
     case DMAR_FECTL_REG:
-        assert(size == 4);
+        /*
+         * 32-bit register at an 8-byte-aligned offset: a well-formed
+         * 8-byte guest access reaches this handler.  vtd_set_long()
+         * takes uint32_t and truncates the high half -- undefined per
+         * the VT-d spec but harmless here.  Flag it under
+         * -d guest_errors so the guest-side bug surfaces.
+         */
+        if (size != 4) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: invalid %u-byte access to 32-bit reg "
+                          "addr=0x%" PRIx64 "\n", __func__, size, addr);
+        }
         vtd_set_long(s, addr, val);
         vtd_handle_fectl_write(s);
         break;
 
     /* Fault Event Data Register, 32-bit */
     case DMAR_FEDATA_REG:
-        assert(size == 4);
         vtd_set_long(s, addr, val);
         break;
 
@@ -3800,13 +3803,11 @@ static void vtd_mem_write(void *opaque, hwaddr addr,
 
     /* Fault Event Upper Address Register, 32-bit */
     case DMAR_FEUADDR_REG:
-        assert(size == 4);
         vtd_set_long(s, addr, val);
         break;
 
     /* Protected Memory Enable Register, 32-bit */
     case DMAR_PMEN_REG:
-        assert(size == 4);
         vtd_set_long(s, addr, val);
         break;
 
@@ -3820,7 +3821,6 @@ static void vtd_mem_write(void *opaque, hwaddr addr,
         break;
 
     case DMAR_RTADDR_REG_HI:
-        assert(size == 4);
         vtd_set_long(s, addr, val);
         break;
 
@@ -3835,7 +3835,6 @@ static void vtd_mem_write(void *opaque, hwaddr addr,
         break;
 
     case DMAR_IQT_REG_HI:
-        assert(size == 4);
         vtd_set_long(s, addr, val);
         /* 19:63 of IQT_REG is RsvdZ, do nothing here */
         break;
@@ -3851,39 +3850,57 @@ static void vtd_mem_write(void *opaque, hwaddr addr,
         break;
 
     case DMAR_IQA_REG_HI:
-        assert(size == 4);
         vtd_set_long(s, addr, val);
         break;
 
     /* Invalidation Completion Status Register, 32-bit */
     case DMAR_ICS_REG:
-        assert(size == 4);
         vtd_set_long(s, addr, val);
         vtd_handle_ics_write(s);
         break;
 
     /* Invalidation Event Control Register, 32-bit */
     case DMAR_IECTL_REG:
-        assert(size == 4);
+        /*
+         * 32-bit register at an 8-byte-aligned offset: a well-formed
+         * 8-byte guest access reaches this handler.  vtd_set_long()
+         * takes uint32_t and truncates the high half -- undefined per
+         * the VT-d spec but harmless here.  Flag it under
+         * -d guest_errors so the guest-side bug surfaces.
+         */
+        if (size != 4) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: invalid %u-byte access to 32-bit reg "
+                          "addr=0x%" PRIx64 "\n", __func__, size, addr);
+        }
         vtd_set_long(s, addr, val);
         vtd_handle_iectl_write(s);
         break;
 
     /* Invalidation Event Data Register, 32-bit */
     case DMAR_IEDATA_REG:
-        assert(size == 4);
         vtd_set_long(s, addr, val);
         break;
 
     /* Invalidation Event Address Register, 32-bit */
     case DMAR_IEADDR_REG:
-        assert(size == 4);
+        /*
+         * 32-bit register at an 8-byte-aligned offset: a well-formed
+         * 8-byte guest access reaches this handler.  vtd_set_long()
+         * takes uint32_t and truncates the high half -- undefined per
+         * the VT-d spec but harmless here.  Flag it under
+         * -d guest_errors so the guest-side bug surfaces.
+         */
+        if (size != 4) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: invalid %u-byte access to 32-bit reg "
+                          "addr=0x%" PRIx64 "\n", __func__, size, addr);
+        }
         vtd_set_long(s, addr, val);
         break;
 
     /* Invalidation Event Upper Address Register, 32-bit */
     case DMAR_IEUADDR_REG:
-        assert(size == 4);
         vtd_set_long(s, addr, val);
         break;
 
@@ -3897,7 +3914,6 @@ static void vtd_mem_write(void *opaque, hwaddr addr,
         break;
 
     case DMAR_FRCD_REG_0_1:
-        assert(size == 4);
         vtd_set_long(s, addr, val);
         break;
 
@@ -3912,7 +3928,6 @@ static void vtd_mem_write(void *opaque, hwaddr addr,
         break;
 
     case DMAR_FRCD_REG_0_3:
-        assert(size == 4);
         vtd_set_long(s, addr, val);
         /* May clear bit 127 (Fault), update PPF */
         vtd_update_fsts_ppf(s);
@@ -3927,18 +3942,27 @@ static void vtd_mem_write(void *opaque, hwaddr addr,
         break;
 
     case DMAR_IRTA_REG_HI:
-        assert(size == 4);
         vtd_set_long(s, addr, val);
         break;
 
     case DMAR_PRS_REG:
-        assert(size == 4);
         vtd_set_long(s, addr, val);
         vtd_handle_prs_write(s);
         break;
 
     case DMAR_PECTL_REG:
-        assert(size == 4);
+        /*
+         * 32-bit register at an 8-byte-aligned offset: a well-formed
+         * 8-byte guest access reaches this handler.  vtd_set_long()
+         * takes uint32_t and truncates the high half -- undefined per
+         * the VT-d spec but harmless here.  Flag it under
+         * -d guest_errors so the guest-side bug surfaces.
+         */
+        if (size != 4) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: invalid %u-byte access to 32-bit reg "
+                          "addr=0x%" PRIx64 "\n", __func__, size, addr);
+        }
         vtd_set_long(s, addr, val);
         vtd_handle_pectl_write(s);
         break;
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 105/106] tests/qtest: add 8-byte MMIO access sweep for intel-iommu
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (103 preceding siblings ...)
  2026-06-14 19:10 ` [PULL 104/106] intel_iommu: fix guest-triggerable abort on oversized MMIO access Michael S. Tsirkin
@ 2026-06-14 19:10 ` Michael S. Tsirkin
  2026-06-14 19:10 ` [PULL 106/106] hw/scsi/vhost-scsi: fix build with older kernel headers Michael S. Tsirkin
  2026-06-15 15:06 ` [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Stefan Hajnoczi
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:10 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Junjie Cao, Philippe Mathieu-Daudé, Yi Liu,
	Zhenzhong Duan, Jason Wang, Clément Mathieu--Drif,
	Fabiano Rosas, Laurent Vivier, Paolo Bonzini

From: Junjie Cao <junjie.cao@intel.com>

Sweep every 4-byte-aligned offset in the VT-d MMIO register space
with 8-byte reads and writes to verify that no register handler
aborts on an oversized access.

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Junjie Cao <junjie.cao@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Yi Liu <yi.l.liu@intel.com>
Reviewed-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260514180703.85686-3-junjie.cao@intel.com>
---
 tests/qtest/intel-iommu-test.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/tests/qtest/intel-iommu-test.c b/tests/qtest/intel-iommu-test.c
index 30ee6524df..ef6e6eb8b6 100644
--- a/tests/qtest/intel-iommu-test.c
+++ b/tests/qtest/intel-iommu-test.c
@@ -17,11 +17,39 @@
 #define ECAP_STAGE_1_FIXED1   (VTD_ECAP_QI |  VTD_ECAP_IR | VTD_ECAP_IRO | \
                               VTD_ECAP_MHMV | VTD_ECAP_SMTS | VTD_ECAP_FSTS)
 
+static inline uint32_t vtd_reg_readl(QTestState *s, uint64_t offset)
+{
+    return qtest_readl(s, Q35_HOST_BRIDGE_IOMMU_ADDR + offset);
+}
+
 static inline uint64_t vtd_reg_readq(QTestState *s, uint64_t offset)
 {
     return qtest_readq(s, Q35_HOST_BRIDGE_IOMMU_ADDR + offset);
 }
 
+static inline void vtd_reg_writeq(QTestState *s, uint64_t offset,
+                                  uint64_t value)
+{
+    qtest_writeq(s, Q35_HOST_BRIDGE_IOMMU_ADDR + offset, value);
+}
+
+static void test_intel_iommu_8byte_access(void)
+{
+    QTestState *s;
+    uint64_t off;
+
+    s = qtest_init("-M q35 -device intel-iommu");
+
+    for (off = 0; off < DMAR_REG_SIZE; off += 4) {
+        vtd_reg_readq(s, off);
+        vtd_reg_writeq(s, off, 0);
+    }
+
+    g_assert_cmpuint(vtd_reg_readl(s, DMAR_VER_REG), !=, 0);
+
+    qtest_quit(s);
+}
+
 static void test_intel_iommu_stage_1(void)
 {
     uint8_t init_csr[DMAR_REG_SIZE];     /* register values */
@@ -58,6 +86,8 @@ static void test_intel_iommu_stage_1(void)
 int main(int argc, char **argv)
 {
     g_test_init(&argc, &argv, NULL);
+    qtest_add_func("/q35/intel-iommu/8byte-access",
+                   test_intel_iommu_8byte_access);
     qtest_add_func("/q35/intel-iommu/stage-1", test_intel_iommu_stage_1);
 
     return g_test_run();
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 106/106] hw/scsi/vhost-scsi: fix build with older kernel headers
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (104 preceding siblings ...)
  2026-06-14 19:10 ` [PULL 105/106] tests/qtest: add 8-byte MMIO access sweep for intel-iommu Michael S. Tsirkin
@ 2026-06-14 19:10 ` Michael S. Tsirkin
  2026-06-15 15:06 ` [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Stefan Hajnoczi
  106 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:10 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Quan Sun, Philippe Mathieu-Daudé,
	Paolo Bonzini, Fam Zheng, Stefano Garzarella

From: Quan Sun <Quan.Sun@windriver.com>

On build hosts with kernel headers older than 6.0, the system's
<linux/vhost_types.h> does not define struct vhost_vring_worker or
struct vhost_worker_state, causing compilation of vhost-scsi.c to
fail:

  error: storage size of 'vq_worker' isn't known

Fix by including standard-headers/linux/vhost_types.h before the
system's <linux/vhost.h>, matching the existing pattern used in
hw/virtio/vhost-backend.c. QEMU's bundled header provides the
struct definitions, and its include guard prevents redefinition
when the system header pulls in its own vhost_types.h.

Signed-off-by: Quan Sun <Quan.Sun@windriver.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260525182730.4098543-1-Quan.Sun@windriver.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/scsi/vhost-scsi.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index 859888fdba..657403cad0 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -15,6 +15,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "standard-headers/linux/vhost_types.h"
 #include <linux/vhost.h>
 #include <sys/ioctl.h>
 #include "qapi/error.h"
-- 
MST



^ permalink raw reply related	[flat|nested] 109+ messages in thread

* [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups
@ 2026-06-14 19:10 Michael S. Tsirkin
  2026-06-14 19:05 ` [PULL 001/106] amd_iommu: restrict command buffer head/tail ranges to ring size Michael S. Tsirkin
                   ` (106 more replies)
  0 siblings, 107 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-14 19:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell

Resolved a bunch of conflicts.
If you see anything wrong here, pls holler.


The following changes since commit f5a2438405d4ae8b62de7c9b39fac0b2155ee544:

  Merge tag 'pull-qapi-2026-05-21' of https://repo.or.cz/qemu/armbru into staging (2026-05-21 09:00:22 -0400)

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 31dbba011d0f3a21432d0629fae0b4885f2eed25:

  hw/scsi/vhost-scsi: fix build with older kernel headers (2026-06-03 08:36:42 -0400)

----------------------------------------------------------------
pci, vhost, virtio, iommu: features, fixes, cleanups

intel_iommu:
    PASID support for passthrough
    some properties renamed
virtio-rtc:
    new device
acpi:
    watchdog (x86 q35)
    COM irqs are now shared
vhost-user:
    vhost-user passes GPA not HVA now
    vhost SHMEM_MAP/UNMAP support
vhost-vdpa:
    svq IN_ORDER support
amd_iommu:
    IOMMU XT interrupt support
    command buffer fixes
cxl:
    PPR support
    performant path for non-interleaved cases
vhost-scsi:
    build fix for older kernel headers
fixes, cleanups all over the place

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

----------------------------------------------------------------
Aditya Gupta (2):
      ppc/pnv_phb3: Error out on invalid config access
      hw/pci: Replace assert with bounds check and return

Albert Esteve (7):
      vhost-user: Add VirtIO Shared Memory map request
      vhost_user.rst: Align VhostUserMsg excerpt members
      vhost_user.rst: Add SHMEM_MAP/_UNMAP to spec
      vhost_user: Add frontend get_shmem_config command
      vhost_user.rst: Add GET_SHMEM_CONFIG message
      qmp: add shmem feature map
      vhost-user-device: Add shared memory BAR

Alejandro Jimenez (3):
      amd_iommu: Update command buffer head ptr in MMIO region after wraparound
      amd_iommu: Follow root pointer before page walk and use 1-based levels
      amd_iommu: Reject non-decreasing NextLevel in fetch_pte()

Alexandr Moshkov (1):
      vhost-user.rst: fix typo

Alexey Gerasimenko (1):
      q35: Fix incorrect values for PCIEXBAR masks

Alireza Sanaee via qemu development (2):
      hw/cxl: Allow cxl_cfmws_find_device() to filter on whether interleaved paths are accepted
      hw/cxl: Add a performant (and correct) path for the non interleaved cases

Costas Argyris (1):
      tests/qtest: Add amd-iommu command buffer head wrap test

Eugenio Pérez (8):
      net/vhost-vdpa: enable vqs before DRIVER_OK if no cvq
      virtio: Allow to fill a whole virtqueue in order
      vhost: move svq next desc array to descs state struct
      vhost: factor out the descriptor next fetching
      vhost: factor out the get of last used desc in SVQ
      vhost: factor out the detach buf logic in SVQ
      vhost: add in_order feature to shadow virtqueue
      vhost: accept in order feature flag

Igor Mammedov (6):
      acpi: add API to build WDAT instructions
      x86: q35: add 'wdat' property
      x86: q35: generate WDAT ACPI table
      tests: acpi: x86/q35: whitelist new WDAT table
      tests: acpi: x86/q35: add WDAT table test case
      tests: acpi: x86/q35: update expected WDAT blob

Jonathan Cameron (1):
      MAINTAINERS: Update CXL maintainers entry including adding linux-cxl list

Jorge E. Moreira (1):
      vhost-user.rst: Explicitly allow front-end to write to kick FDs

Junjie Cao (2):
      intel_iommu: fix guest-triggerable abort on oversized MMIO access
      tests/qtest: add 8-byte MMIO access sweep for intel-iommu

Kuan-Wei Chiu (3):
      vhost-user: Fix stale error logs and return values in teardown paths
      standard-headers: Add virtio_rtc.h from Linux 7.0-rc1
      virtio-rtc: Add basic virtio-rtc support

Mark Cave-Ayland (4):
      hw/acpi/aml-build.c: add aml_irq() representing the 3-byte IRQ descriptor
      tests/acpi: allow DSDT acpi table changes
      hw/char/serial-isa.c: declare IRQ as shared in ACPI IRQ descriptor
      tests: data: update x86 ACPI tables

Max Makarov (2):
      vhost-user-blk-server: do not advertise VIRTIO_BLK_F_SIZE_MAX with size_max=0
      vhost-user-blk: do not force VIRTIO_BLK_F_SIZE_MAX

Paolo Bonzini (1):
      amd_iommu: restrict command buffer head/tail ranges to ring size

Quan Sun (1):
      hw/scsi/vhost-scsi: fix build with older kernel headers

Sairaj Kodilkar (3):
      amd_iommu: Use switch case to determine mmio register name
      amd_iommu: Turn on XT support only when guest has enabled it
      amd_iommu: Generate XT interrupts when xt support is enabled

Shiju Jose (3):
      hw/cxl: Fix handling of component ID to not assume it is a string
      hw/cxl: Add fixes in Post Package Repair (PPR)
      hw/cxl/events: Fix handling of component ID in event records generation to not assume it is a string

Stefano Garzarella (2):
      libvhost-user: fix buffer overflow in virtqueue_read_indirect_desc()
      libvduse: fix buffer overflow in vduse_queue_read_indirect_desc()

Thomas Huth (1):
      hw/i386/pc: Add a proper owner for the ioport memory regions

Vladimir Sementsov-Ogievskiy (32):
      vhost-user: rework enabling vrings
      vhost: drop backend_features field
      vhost-user: introduce vhost_user_has_protocol_feature() helper
      vhost: move protocol_features to vhost_user
      vhost-user-gpu: drop code duplication
      vhost: make vhost_dev.features private
      virtio: move common part of _set_guest_notifier to generic code
      virtio: drop *_set_guest_notifier_fd_handler() helpers
      vhost-user: keep QIOChannelSocket for backend channel
      vhost: vhost_virtqueue_start(): fix failure path
      vhost: make vhost_memory_unmap() null-safe
      vhost: simplify calls to vhost_memory_unmap()
      vhost: move vrings mapping to the top of vhost_virtqueue_start()
      vhost: vhost_virtqueue_start(): drop extra local variables
      vhost: final refactoring of vhost vrings map/unmap
      vhost: simplify vhost_dev_init() error-path
      vhost: move busyloop timeout initialization to vhost_virtqueue_init()
      vhost: vhost_dev_init(): simplify features initialization
      hw/virtio/virtio-bus: refactor virtio_bus_set_host_notifier()
      vhost-user: make trace events more readable
      vhost-user-blk: add some useful trace-points
      vhost: add some useful trace-points
      vhost: move IOTLB functions from vhost-backend.c to vhost.c
      vhost: use consistent naming for backend handlers
      vhost: rename vhost-backend.c to vhost-kernel.c
      vhost: replace .vhost_vq_get_addr() with .vhost_phys_vring_addr()
      vhost: simplify vhost_memory_map() and vhost_memory_unmap()
      qapi: remove user addresses from x-query-virtio-vhost-queue-status
      vhost: stop reusing vq->desc (and friends) to store physical address
      vhost: rename vring pointer fields to reflect user addresses
      vhost: add .vhost_phys_iotlb_msg() handler
      vhost-user: add VHOST_USER_PROTOCOL_F_GPA_ADDRESSES

Zhenzhong Duan (19):
      intel_iommu: Remove 'x-' prefix from 'x-scalable-mode' and 'x-flts' properties
      intel_iommu: Change 'flts' property naming to 'fsts'
      vfio/iommufd: Extend attach/detach_hwpt callback implementations with pasid
      iommufd: Extend attach/detach_hwpt callbacks to support pasid
      vfio/iommufd: Create nesting parent hwpt with IOMMU_HWPT_ALLOC_PASID flag
      intel_iommu: Create the nested hwpt with IOMMU_HWPT_ALLOC_PASID flag
      intel_iommu: Rename pasid property to "pasid-bits" and define it as type uint8
      intel_iommu: make vtd_dev_get_pe_from_pasid() more generic
      intel_iommu: Export some functions
      intel_iommu: Fix PASID validity check in fault reporting
      intel_iommu: Use IOMMU_NO_PASID and delete PASID_0
      intel_iommu: Refactor PASID processing to use IOMMU_NO_PASID internally
      intel_iommu_accel: Handle PASID entry addition for pc_inv_dsc request
      intel_iommu_accel: Handle PASID entry removal for pc_inv_dsc request
      intel_iommu_accel: Bypass PASID entry addition for just deleted entry
      intel_iommu_accel: Handle PASID entry removal for system reset
      intel_iommu_accel: Switch to VTDAccelPASIDCacheEntry for PASID bind/unbind and PIOTLB invalidation
      intel_iommu_accel: Add pasid bits size check
      intel_iommu: Expose flag VIOMMU_FLAG_PASID_SUPPORTED and VIOMMU_FLAG_WANT_PASID_ATTACH

 MAINTAINERS                                       |  12 +-
 backends/cryptodev-vhost.c                        |   9 +-
 backends/iommufd.c                                |  23 +-
 backends/vhost-user.c                             |   8 +-
 block/export/vhost-user-blk-server.c              |   2 +-
 docs/devel/vfio-iommufd.rst                       |  10 +-
 docs/interop/vhost-user.rst                       | 135 +++++-
 hw/acpi/aml-build-stub.c                          |   6 +
 hw/acpi/aml-build.c                               |  41 ++
 hw/acpi/meson.build                               |   3 +-
 hw/acpi/wdat-ich9-stub.c                          |  15 +
 hw/acpi/wdat-ich9.c                               |  90 ++++
 hw/arm/smmuv3-accel.c                             |  12 +-
 hw/block/trace-events                             |  10 +
 hw/block/vhost-user-blk.c                         |  36 +-
 hw/char/serial-isa.c                              |   3 +-
 hw/cxl/cxl-component-utils.c                      |   6 +
 hw/cxl/cxl-host.c                                 | 234 ++++++++-
 hw/cxl/cxl-mailbox-utils.c                        |   6 +-
 hw/display/vhost-user-gpu.c                       |  11 +-
 hw/i386/acpi-build.c                              |  12 +
 hw/i386/amd_iommu.c                               | 288 +++++++----
 hw/i386/amd_iommu.h                               |  36 +-
 hw/i386/intel_iommu.c                             | 352 +++++++-------
 hw/i386/intel_iommu_accel.c                       | 401 ++++++++++++---
 hw/i386/intel_iommu_accel.h                       |  20 +-
 hw/i386/intel_iommu_internal.h                    |  44 +-
 hw/i386/pc.c                                      |   6 +-
 hw/i386/pc_q35.c                                  |  18 +
 hw/i386/trace-events                              |   1 +
 hw/mem/cxl_type3.c                                |  17 +-
 hw/net/vhost_net.c                                |  35 +-
 hw/pci-host/pnv_phb3.c                            |  10 +
 hw/pci-host/q35.c                                 |   6 +-
 hw/pci/pci_host.c                                 |  14 +-
 hw/s390x/virtio-ccw.c                             |  35 +-
 hw/scsi/vhost-scsi-common.c                       |   2 +-
 hw/scsi/vhost-scsi.c                              |   2 +-
 hw/scsi/vhost-user-scsi.c                         |   1 -
 hw/vfio/device.c                                  |  11 +
 hw/vfio/iommufd.c                                 |  68 ++-
 hw/vfio/trace-events                              |   4 +-
 hw/virtio/Kconfig                                 |   5 +
 hw/virtio/meson.build                             |   5 +-
 hw/virtio/trace-events                            |  16 +-
 hw/virtio/vdpa-dev.c                              |   3 +-
 hw/virtio/{vhost-backend.c => vhost-kernel.c}     |  90 +---
 hw/virtio/vhost-shadow-virtqueue.c                | 215 ++++++--
 hw/virtio/vhost-shadow-virtqueue.h                |  38 +-
 hw/virtio/vhost-user-base.c                       |  63 ++-
 hw/virtio/vhost-user-fs.c                         |   9 +-
 hw/virtio/vhost-user-scmi.c                       |   9 +-
 hw/virtio/vhost-user-stub.c                       |   6 +
 hw/virtio/vhost-user-test-device-pci.c            |  42 +-
 hw/virtio/vhost-user.c                            | 566 ++++++++++++++++++----
 hw/virtio/vhost-vdpa.c                            |  19 +-
 hw/virtio/vhost-vsock-common.c                    |   9 +-
 hw/virtio/vhost.c                                 | 384 +++++++++------
 hw/virtio/virtio-bus.c                            |  18 +-
 hw/virtio/virtio-hmp-cmds.c                       |   5 -
 hw/virtio/virtio-mmio.c                           |  41 +-
 hw/virtio/virtio-pci.c                            |  34 +-
 hw/virtio/virtio-qmp.c                            |  18 +-
 hw/virtio/virtio-rtc-pci.c                        |  65 +++
 hw/virtio/virtio-rtc.c                            | 190 ++++++++
 hw/virtio/virtio.c                                | 251 +++++++++-
 include/hw/acpi/aml-build.h                       |   2 +
 include/hw/acpi/wdat-ich9.h                       |  15 +
 include/hw/acpi/wdat.h                            | 118 +++++
 include/hw/core/iommu.h                           |  14 +
 include/hw/cxl/cxl.h                              |   1 +
 include/hw/cxl/cxl_device.h                       |   4 +
 include/hw/i386/intel_iommu.h                     |   4 +-
 include/hw/i386/pc.h                              |   1 +
 include/hw/pci-host/q35.h                         |   4 +-
 include/hw/vfio/vfio-device.h                     |   1 +
 include/hw/virtio/vhost-backend.h                 |  47 +-
 include/hw/virtio/vhost-user.h                    |   6 +
 include/hw/virtio/vhost.h                         |  71 ++-
 include/hw/virtio/virtio-pci.h                    |   3 -
 include/hw/virtio/virtio-rtc.h                    |  22 +
 include/hw/virtio/virtio.h                        | 151 +++++-
 include/standard-headers/linux/virtio_rtc.h       | 237 +++++++++
 include/system/iommufd.h                          |  18 +-
 include/system/memory.h                           |   4 +-
 net/vhost-vdpa.c                                  |  37 +-
 qapi/virtio.json                                  |  18 -
 subprojects/libvduse/libvduse.c                   |   7 +-
 subprojects/libvhost-user/libvhost-user.c         |  77 ++-
 subprojects/libvhost-user/libvhost-user.h         |  56 +++
 system/memory.c                                   |  14 +
 tests/data/acpi/x86/microvm/DSDT                  | Bin 365 -> 366 bytes
 tests/data/acpi/x86/microvm/DSDT.ioapic2          | Bin 365 -> 366 bytes
 tests/data/acpi/x86/microvm/DSDT.pcie             | Bin 2985 -> 2986 bytes
 tests/data/acpi/x86/microvm/DSDT.rtc              | Bin 404 -> 405 bytes
 tests/data/acpi/x86/microvm/DSDT.usb              | Bin 414 -> 415 bytes
 tests/data/acpi/x86/pc/DSDT                       | Bin 8598 -> 8599 bytes
 tests/data/acpi/x86/pc/DSDT.acpierst              | Bin 8509 -> 8510 bytes
 tests/data/acpi/x86/pc/DSDT.acpihmat              | Bin 9923 -> 9924 bytes
 tests/data/acpi/x86/pc/DSDT.bridge                | Bin 15469 -> 15470 bytes
 tests/data/acpi/x86/pc/DSDT.cphp                  | Bin 9062 -> 9063 bytes
 tests/data/acpi/x86/pc/DSDT.dimmpxm               | Bin 10252 -> 10253 bytes
 tests/data/acpi/x86/pc/DSDT.hpbridge              | Bin 8549 -> 8550 bytes
 tests/data/acpi/x86/pc/DSDT.hpbrroot              | Bin 5087 -> 5088 bytes
 tests/data/acpi/x86/pc/DSDT.ipmikcs               | Bin 8670 -> 8671 bytes
 tests/data/acpi/x86/pc/DSDT.memhp                 | Bin 9957 -> 9958 bytes
 tests/data/acpi/x86/pc/DSDT.nohpet                | Bin 8456 -> 8457 bytes
 tests/data/acpi/x86/pc/DSDT.numamem               | Bin 8604 -> 8605 bytes
 tests/data/acpi/x86/pc/DSDT.roothp                | Bin 12391 -> 12392 bytes
 tests/data/acpi/x86/q35/DSDT                      | Bin 8427 -> 8428 bytes
 tests/data/acpi/x86/q35/DSDT.acpierst             | Bin 8444 -> 8445 bytes
 tests/data/acpi/x86/q35/DSDT.acpihmat             | Bin 9752 -> 9753 bytes
 tests/data/acpi/x86/q35/DSDT.acpihmat-generic-x   | Bin 12637 -> 12638 bytes
 tests/data/acpi/x86/q35/DSDT.acpihmat-noinitiator | Bin 8706 -> 8707 bytes
 tests/data/acpi/x86/q35/DSDT.applesmc             | Bin 8473 -> 8474 bytes
 tests/data/acpi/x86/q35/DSDT.bridge               | Bin 12040 -> 12041 bytes
 tests/data/acpi/x86/q35/DSDT.core-count           | Bin 12985 -> 12986 bytes
 tests/data/acpi/x86/q35/DSDT.core-count2          | Bin 33842 -> 33843 bytes
 tests/data/acpi/x86/q35/DSDT.cphp                 | Bin 8891 -> 8892 bytes
 tests/data/acpi/x86/q35/DSDT.cxl                  | Bin 13218 -> 13219 bytes
 tests/data/acpi/x86/q35/DSDT.dimmpxm              | Bin 10081 -> 10082 bytes
 tests/data/acpi/x86/q35/DSDT.ipmibt               | Bin 8502 -> 8503 bytes
 tests/data/acpi/x86/q35/DSDT.ipmismbus            | Bin 8515 -> 8516 bytes
 tests/data/acpi/x86/q35/DSDT.ivrs                 | Bin 8444 -> 8445 bytes
 tests/data/acpi/x86/q35/DSDT.memhp                | Bin 9786 -> 9787 bytes
 tests/data/acpi/x86/q35/DSDT.mmio64               | Bin 9557 -> 9558 bytes
 tests/data/acpi/x86/q35/DSDT.multi-bridge         | Bin 13280 -> 13281 bytes
 tests/data/acpi/x86/q35/DSDT.noacpihp             | Bin 8289 -> 8290 bytes
 tests/data/acpi/x86/q35/DSDT.nohpet               | Bin 8285 -> 8286 bytes
 tests/data/acpi/x86/q35/DSDT.numamem              | Bin 8433 -> 8434 bytes
 tests/data/acpi/x86/q35/DSDT.pvpanic-isa          | Bin 8528 -> 8529 bytes
 tests/data/acpi/x86/q35/DSDT.thread-count         | Bin 12985 -> 12986 bytes
 tests/data/acpi/x86/q35/DSDT.thread-count2        | Bin 33842 -> 33843 bytes
 tests/data/acpi/x86/q35/DSDT.tis.tpm12            | Bin 9033 -> 9034 bytes
 tests/data/acpi/x86/q35/DSDT.tis.tpm2             | Bin 9059 -> 9060 bytes
 tests/data/acpi/x86/q35/DSDT.type4-count          | Bin 18661 -> 18662 bytes
 tests/data/acpi/x86/q35/DSDT.viot                 | Bin 14684 -> 14685 bytes
 tests/data/acpi/x86/q35/DSDT.xapic                | Bin 35790 -> 35791 bytes
 tests/data/acpi/x86/q35/WDAT.wdat                 | Bin 0 -> 308 bytes
 tests/qtest/amd-iommu-test.c                      |  76 +++
 tests/qtest/bios-tables-test.c                    |  13 +
 tests/qtest/intel-iommu-test.c                    |  32 +-
 tests/qtest/iommu-intel-test.c                    |   4 +-
 tests/qtest/meson.build                           |   1 +
 144 files changed, 4056 insertions(+), 1158 deletions(-)
 create mode 100644 hw/acpi/wdat-ich9-stub.c
 create mode 100644 hw/acpi/wdat-ich9.c
 rename hw/virtio/{vhost-backend.c => vhost-kernel.c} (83%)
 create mode 100644 hw/virtio/vhost-user-stub.c
 create mode 100644 hw/virtio/virtio-rtc-pci.c
 create mode 100644 hw/virtio/virtio-rtc.c
 create mode 100644 include/hw/acpi/wdat-ich9.h
 create mode 100644 include/hw/acpi/wdat.h
 create mode 100644 include/hw/virtio/virtio-rtc.h
 create mode 100644 include/standard-headers/linux/virtio_rtc.h
 create mode 100644 tests/data/acpi/x86/q35/WDAT.wdat
 create mode 100644 tests/qtest/amd-iommu-test.c



^ permalink raw reply	[flat|nested] 109+ messages in thread

* Re: [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups
  2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
                   ` (105 preceding siblings ...)
  2026-06-14 19:10 ` [PULL 106/106] hw/scsi/vhost-scsi: fix build with older kernel headers Michael S. Tsirkin
@ 2026-06-15 15:06 ` Stefan Hajnoczi
  2026-06-15 20:05   ` Michael S. Tsirkin
  106 siblings, 1 reply; 109+ messages in thread
From: Stefan Hajnoczi @ 2026-06-15 15:06 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel, Peter Maydell

On Sun, Jun 14, 2026 at 3:10 PM Michael S. Tsirkin <mst@redhat.com> wrote:
>
> Resolved a bunch of conflicts.
> If you see anything wrong here, pls holler.

Hi Michael,
The check for mangled mailing list author emails is failing. Please
`git commit --amend --author=...` with their real email and resend
your pull request:

Alireza Sanaee via qemu development (2):
      hw/cxl: Allow cxl_cfmws_find_device() to filter on whether
interleaved paths are accepted
      hw/cxl: Add a performant (and correct) path for the non interleaved cases
ERROR: pull request includes commits attributed to list

Thanks!

Stefan

>
>
> The following changes since commit f5a2438405d4ae8b62de7c9b39fac0b2155ee544:
>
>   Merge tag 'pull-qapi-2026-05-21' of https://repo.or.cz/qemu/armbru into staging (2026-05-21 09:00:22 -0400)
>
> 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 31dbba011d0f3a21432d0629fae0b4885f2eed25:
>
>   hw/scsi/vhost-scsi: fix build with older kernel headers (2026-06-03 08:36:42 -0400)
>
> ----------------------------------------------------------------
> pci, vhost, virtio, iommu: features, fixes, cleanups
>
> intel_iommu:
>     PASID support for passthrough
>     some properties renamed
> virtio-rtc:
>     new device
> acpi:
>     watchdog (x86 q35)
>     COM irqs are now shared
> vhost-user:
>     vhost-user passes GPA not HVA now
>     vhost SHMEM_MAP/UNMAP support
> vhost-vdpa:
>     svq IN_ORDER support
> amd_iommu:
>     IOMMU XT interrupt support
>     command buffer fixes
> cxl:
>     PPR support
>     performant path for non-interleaved cases
> vhost-scsi:
>     build fix for older kernel headers
> fixes, cleanups all over the place
>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
>
> ----------------------------------------------------------------
> Aditya Gupta (2):
>       ppc/pnv_phb3: Error out on invalid config access
>       hw/pci: Replace assert with bounds check and return
>
> Albert Esteve (7):
>       vhost-user: Add VirtIO Shared Memory map request
>       vhost_user.rst: Align VhostUserMsg excerpt members
>       vhost_user.rst: Add SHMEM_MAP/_UNMAP to spec
>       vhost_user: Add frontend get_shmem_config command
>       vhost_user.rst: Add GET_SHMEM_CONFIG message
>       qmp: add shmem feature map
>       vhost-user-device: Add shared memory BAR
>
> Alejandro Jimenez (3):
>       amd_iommu: Update command buffer head ptr in MMIO region after wraparound
>       amd_iommu: Follow root pointer before page walk and use 1-based levels
>       amd_iommu: Reject non-decreasing NextLevel in fetch_pte()
>
> Alexandr Moshkov (1):
>       vhost-user.rst: fix typo
>
> Alexey Gerasimenko (1):
>       q35: Fix incorrect values for PCIEXBAR masks
>
> Alireza Sanaee via qemu development (2):
>       hw/cxl: Allow cxl_cfmws_find_device() to filter on whether interleaved paths are accepted
>       hw/cxl: Add a performant (and correct) path for the non interleaved cases
>
> Costas Argyris (1):
>       tests/qtest: Add amd-iommu command buffer head wrap test
>
> Eugenio Pérez (8):
>       net/vhost-vdpa: enable vqs before DRIVER_OK if no cvq
>       virtio: Allow to fill a whole virtqueue in order
>       vhost: move svq next desc array to descs state struct
>       vhost: factor out the descriptor next fetching
>       vhost: factor out the get of last used desc in SVQ
>       vhost: factor out the detach buf logic in SVQ
>       vhost: add in_order feature to shadow virtqueue
>       vhost: accept in order feature flag
>
> Igor Mammedov (6):
>       acpi: add API to build WDAT instructions
>       x86: q35: add 'wdat' property
>       x86: q35: generate WDAT ACPI table
>       tests: acpi: x86/q35: whitelist new WDAT table
>       tests: acpi: x86/q35: add WDAT table test case
>       tests: acpi: x86/q35: update expected WDAT blob
>
> Jonathan Cameron (1):
>       MAINTAINERS: Update CXL maintainers entry including adding linux-cxl list
>
> Jorge E. Moreira (1):
>       vhost-user.rst: Explicitly allow front-end to write to kick FDs
>
> Junjie Cao (2):
>       intel_iommu: fix guest-triggerable abort on oversized MMIO access
>       tests/qtest: add 8-byte MMIO access sweep for intel-iommu
>
> Kuan-Wei Chiu (3):
>       vhost-user: Fix stale error logs and return values in teardown paths
>       standard-headers: Add virtio_rtc.h from Linux 7.0-rc1
>       virtio-rtc: Add basic virtio-rtc support
>
> Mark Cave-Ayland (4):
>       hw/acpi/aml-build.c: add aml_irq() representing the 3-byte IRQ descriptor
>       tests/acpi: allow DSDT acpi table changes
>       hw/char/serial-isa.c: declare IRQ as shared in ACPI IRQ descriptor
>       tests: data: update x86 ACPI tables
>
> Max Makarov (2):
>       vhost-user-blk-server: do not advertise VIRTIO_BLK_F_SIZE_MAX with size_max=0
>       vhost-user-blk: do not force VIRTIO_BLK_F_SIZE_MAX
>
> Paolo Bonzini (1):
>       amd_iommu: restrict command buffer head/tail ranges to ring size
>
> Quan Sun (1):
>       hw/scsi/vhost-scsi: fix build with older kernel headers
>
> Sairaj Kodilkar (3):
>       amd_iommu: Use switch case to determine mmio register name
>       amd_iommu: Turn on XT support only when guest has enabled it
>       amd_iommu: Generate XT interrupts when xt support is enabled
>
> Shiju Jose (3):
>       hw/cxl: Fix handling of component ID to not assume it is a string
>       hw/cxl: Add fixes in Post Package Repair (PPR)
>       hw/cxl/events: Fix handling of component ID in event records generation to not assume it is a string
>
> Stefano Garzarella (2):
>       libvhost-user: fix buffer overflow in virtqueue_read_indirect_desc()
>       libvduse: fix buffer overflow in vduse_queue_read_indirect_desc()
>
> Thomas Huth (1):
>       hw/i386/pc: Add a proper owner for the ioport memory regions
>
> Vladimir Sementsov-Ogievskiy (32):
>       vhost-user: rework enabling vrings
>       vhost: drop backend_features field
>       vhost-user: introduce vhost_user_has_protocol_feature() helper
>       vhost: move protocol_features to vhost_user
>       vhost-user-gpu: drop code duplication
>       vhost: make vhost_dev.features private
>       virtio: move common part of _set_guest_notifier to generic code
>       virtio: drop *_set_guest_notifier_fd_handler() helpers
>       vhost-user: keep QIOChannelSocket for backend channel
>       vhost: vhost_virtqueue_start(): fix failure path
>       vhost: make vhost_memory_unmap() null-safe
>       vhost: simplify calls to vhost_memory_unmap()
>       vhost: move vrings mapping to the top of vhost_virtqueue_start()
>       vhost: vhost_virtqueue_start(): drop extra local variables
>       vhost: final refactoring of vhost vrings map/unmap
>       vhost: simplify vhost_dev_init() error-path
>       vhost: move busyloop timeout initialization to vhost_virtqueue_init()
>       vhost: vhost_dev_init(): simplify features initialization
>       hw/virtio/virtio-bus: refactor virtio_bus_set_host_notifier()
>       vhost-user: make trace events more readable
>       vhost-user-blk: add some useful trace-points
>       vhost: add some useful trace-points
>       vhost: move IOTLB functions from vhost-backend.c to vhost.c
>       vhost: use consistent naming for backend handlers
>       vhost: rename vhost-backend.c to vhost-kernel.c
>       vhost: replace .vhost_vq_get_addr() with .vhost_phys_vring_addr()
>       vhost: simplify vhost_memory_map() and vhost_memory_unmap()
>       qapi: remove user addresses from x-query-virtio-vhost-queue-status
>       vhost: stop reusing vq->desc (and friends) to store physical address
>       vhost: rename vring pointer fields to reflect user addresses
>       vhost: add .vhost_phys_iotlb_msg() handler
>       vhost-user: add VHOST_USER_PROTOCOL_F_GPA_ADDRESSES
>
> Zhenzhong Duan (19):
>       intel_iommu: Remove 'x-' prefix from 'x-scalable-mode' and 'x-flts' properties
>       intel_iommu: Change 'flts' property naming to 'fsts'
>       vfio/iommufd: Extend attach/detach_hwpt callback implementations with pasid
>       iommufd: Extend attach/detach_hwpt callbacks to support pasid
>       vfio/iommufd: Create nesting parent hwpt with IOMMU_HWPT_ALLOC_PASID flag
>       intel_iommu: Create the nested hwpt with IOMMU_HWPT_ALLOC_PASID flag
>       intel_iommu: Rename pasid property to "pasid-bits" and define it as type uint8
>       intel_iommu: make vtd_dev_get_pe_from_pasid() more generic
>       intel_iommu: Export some functions
>       intel_iommu: Fix PASID validity check in fault reporting
>       intel_iommu: Use IOMMU_NO_PASID and delete PASID_0
>       intel_iommu: Refactor PASID processing to use IOMMU_NO_PASID internally
>       intel_iommu_accel: Handle PASID entry addition for pc_inv_dsc request
>       intel_iommu_accel: Handle PASID entry removal for pc_inv_dsc request
>       intel_iommu_accel: Bypass PASID entry addition for just deleted entry
>       intel_iommu_accel: Handle PASID entry removal for system reset
>       intel_iommu_accel: Switch to VTDAccelPASIDCacheEntry for PASID bind/unbind and PIOTLB invalidation
>       intel_iommu_accel: Add pasid bits size check
>       intel_iommu: Expose flag VIOMMU_FLAG_PASID_SUPPORTED and VIOMMU_FLAG_WANT_PASID_ATTACH
>
>  MAINTAINERS                                       |  12 +-
>  backends/cryptodev-vhost.c                        |   9 +-
>  backends/iommufd.c                                |  23 +-
>  backends/vhost-user.c                             |   8 +-
>  block/export/vhost-user-blk-server.c              |   2 +-
>  docs/devel/vfio-iommufd.rst                       |  10 +-
>  docs/interop/vhost-user.rst                       | 135 +++++-
>  hw/acpi/aml-build-stub.c                          |   6 +
>  hw/acpi/aml-build.c                               |  41 ++
>  hw/acpi/meson.build                               |   3 +-
>  hw/acpi/wdat-ich9-stub.c                          |  15 +
>  hw/acpi/wdat-ich9.c                               |  90 ++++
>  hw/arm/smmuv3-accel.c                             |  12 +-
>  hw/block/trace-events                             |  10 +
>  hw/block/vhost-user-blk.c                         |  36 +-
>  hw/char/serial-isa.c                              |   3 +-
>  hw/cxl/cxl-component-utils.c                      |   6 +
>  hw/cxl/cxl-host.c                                 | 234 ++++++++-
>  hw/cxl/cxl-mailbox-utils.c                        |   6 +-
>  hw/display/vhost-user-gpu.c                       |  11 +-
>  hw/i386/acpi-build.c                              |  12 +
>  hw/i386/amd_iommu.c                               | 288 +++++++----
>  hw/i386/amd_iommu.h                               |  36 +-
>  hw/i386/intel_iommu.c                             | 352 +++++++-------
>  hw/i386/intel_iommu_accel.c                       | 401 ++++++++++++---
>  hw/i386/intel_iommu_accel.h                       |  20 +-
>  hw/i386/intel_iommu_internal.h                    |  44 +-
>  hw/i386/pc.c                                      |   6 +-
>  hw/i386/pc_q35.c                                  |  18 +
>  hw/i386/trace-events                              |   1 +
>  hw/mem/cxl_type3.c                                |  17 +-
>  hw/net/vhost_net.c                                |  35 +-
>  hw/pci-host/pnv_phb3.c                            |  10 +
>  hw/pci-host/q35.c                                 |   6 +-
>  hw/pci/pci_host.c                                 |  14 +-
>  hw/s390x/virtio-ccw.c                             |  35 +-
>  hw/scsi/vhost-scsi-common.c                       |   2 +-
>  hw/scsi/vhost-scsi.c                              |   2 +-
>  hw/scsi/vhost-user-scsi.c                         |   1 -
>  hw/vfio/device.c                                  |  11 +
>  hw/vfio/iommufd.c                                 |  68 ++-
>  hw/vfio/trace-events                              |   4 +-
>  hw/virtio/Kconfig                                 |   5 +
>  hw/virtio/meson.build                             |   5 +-
>  hw/virtio/trace-events                            |  16 +-
>  hw/virtio/vdpa-dev.c                              |   3 +-
>  hw/virtio/{vhost-backend.c => vhost-kernel.c}     |  90 +---
>  hw/virtio/vhost-shadow-virtqueue.c                | 215 ++++++--
>  hw/virtio/vhost-shadow-virtqueue.h                |  38 +-
>  hw/virtio/vhost-user-base.c                       |  63 ++-
>  hw/virtio/vhost-user-fs.c                         |   9 +-
>  hw/virtio/vhost-user-scmi.c                       |   9 +-
>  hw/virtio/vhost-user-stub.c                       |   6 +
>  hw/virtio/vhost-user-test-device-pci.c            |  42 +-
>  hw/virtio/vhost-user.c                            | 566 ++++++++++++++++++----
>  hw/virtio/vhost-vdpa.c                            |  19 +-
>  hw/virtio/vhost-vsock-common.c                    |   9 +-
>  hw/virtio/vhost.c                                 | 384 +++++++++------
>  hw/virtio/virtio-bus.c                            |  18 +-
>  hw/virtio/virtio-hmp-cmds.c                       |   5 -
>  hw/virtio/virtio-mmio.c                           |  41 +-
>  hw/virtio/virtio-pci.c                            |  34 +-
>  hw/virtio/virtio-qmp.c                            |  18 +-
>  hw/virtio/virtio-rtc-pci.c                        |  65 +++
>  hw/virtio/virtio-rtc.c                            | 190 ++++++++
>  hw/virtio/virtio.c                                | 251 +++++++++-
>  include/hw/acpi/aml-build.h                       |   2 +
>  include/hw/acpi/wdat-ich9.h                       |  15 +
>  include/hw/acpi/wdat.h                            | 118 +++++
>  include/hw/core/iommu.h                           |  14 +
>  include/hw/cxl/cxl.h                              |   1 +
>  include/hw/cxl/cxl_device.h                       |   4 +
>  include/hw/i386/intel_iommu.h                     |   4 +-
>  include/hw/i386/pc.h                              |   1 +
>  include/hw/pci-host/q35.h                         |   4 +-
>  include/hw/vfio/vfio-device.h                     |   1 +
>  include/hw/virtio/vhost-backend.h                 |  47 +-
>  include/hw/virtio/vhost-user.h                    |   6 +
>  include/hw/virtio/vhost.h                         |  71 ++-
>  include/hw/virtio/virtio-pci.h                    |   3 -
>  include/hw/virtio/virtio-rtc.h                    |  22 +
>  include/hw/virtio/virtio.h                        | 151 +++++-
>  include/standard-headers/linux/virtio_rtc.h       | 237 +++++++++
>  include/system/iommufd.h                          |  18 +-
>  include/system/memory.h                           |   4 +-
>  net/vhost-vdpa.c                                  |  37 +-
>  qapi/virtio.json                                  |  18 -
>  subprojects/libvduse/libvduse.c                   |   7 +-
>  subprojects/libvhost-user/libvhost-user.c         |  77 ++-
>  subprojects/libvhost-user/libvhost-user.h         |  56 +++
>  system/memory.c                                   |  14 +
>  tests/data/acpi/x86/microvm/DSDT                  | Bin 365 -> 366 bytes
>  tests/data/acpi/x86/microvm/DSDT.ioapic2          | Bin 365 -> 366 bytes
>  tests/data/acpi/x86/microvm/DSDT.pcie             | Bin 2985 -> 2986 bytes
>  tests/data/acpi/x86/microvm/DSDT.rtc              | Bin 404 -> 405 bytes
>  tests/data/acpi/x86/microvm/DSDT.usb              | Bin 414 -> 415 bytes
>  tests/data/acpi/x86/pc/DSDT                       | Bin 8598 -> 8599 bytes
>  tests/data/acpi/x86/pc/DSDT.acpierst              | Bin 8509 -> 8510 bytes
>  tests/data/acpi/x86/pc/DSDT.acpihmat              | Bin 9923 -> 9924 bytes
>  tests/data/acpi/x86/pc/DSDT.bridge                | Bin 15469 -> 15470 bytes
>  tests/data/acpi/x86/pc/DSDT.cphp                  | Bin 9062 -> 9063 bytes
>  tests/data/acpi/x86/pc/DSDT.dimmpxm               | Bin 10252 -> 10253 bytes
>  tests/data/acpi/x86/pc/DSDT.hpbridge              | Bin 8549 -> 8550 bytes
>  tests/data/acpi/x86/pc/DSDT.hpbrroot              | Bin 5087 -> 5088 bytes
>  tests/data/acpi/x86/pc/DSDT.ipmikcs               | Bin 8670 -> 8671 bytes
>  tests/data/acpi/x86/pc/DSDT.memhp                 | Bin 9957 -> 9958 bytes
>  tests/data/acpi/x86/pc/DSDT.nohpet                | Bin 8456 -> 8457 bytes
>  tests/data/acpi/x86/pc/DSDT.numamem               | Bin 8604 -> 8605 bytes
>  tests/data/acpi/x86/pc/DSDT.roothp                | Bin 12391 -> 12392 bytes
>  tests/data/acpi/x86/q35/DSDT                      | Bin 8427 -> 8428 bytes
>  tests/data/acpi/x86/q35/DSDT.acpierst             | Bin 8444 -> 8445 bytes
>  tests/data/acpi/x86/q35/DSDT.acpihmat             | Bin 9752 -> 9753 bytes
>  tests/data/acpi/x86/q35/DSDT.acpihmat-generic-x   | Bin 12637 -> 12638 bytes
>  tests/data/acpi/x86/q35/DSDT.acpihmat-noinitiator | Bin 8706 -> 8707 bytes
>  tests/data/acpi/x86/q35/DSDT.applesmc             | Bin 8473 -> 8474 bytes
>  tests/data/acpi/x86/q35/DSDT.bridge               | Bin 12040 -> 12041 bytes
>  tests/data/acpi/x86/q35/DSDT.core-count           | Bin 12985 -> 12986 bytes
>  tests/data/acpi/x86/q35/DSDT.core-count2          | Bin 33842 -> 33843 bytes
>  tests/data/acpi/x86/q35/DSDT.cphp                 | Bin 8891 -> 8892 bytes
>  tests/data/acpi/x86/q35/DSDT.cxl                  | Bin 13218 -> 13219 bytes
>  tests/data/acpi/x86/q35/DSDT.dimmpxm              | Bin 10081 -> 10082 bytes
>  tests/data/acpi/x86/q35/DSDT.ipmibt               | Bin 8502 -> 8503 bytes
>  tests/data/acpi/x86/q35/DSDT.ipmismbus            | Bin 8515 -> 8516 bytes
>  tests/data/acpi/x86/q35/DSDT.ivrs                 | Bin 8444 -> 8445 bytes
>  tests/data/acpi/x86/q35/DSDT.memhp                | Bin 9786 -> 9787 bytes
>  tests/data/acpi/x86/q35/DSDT.mmio64               | Bin 9557 -> 9558 bytes
>  tests/data/acpi/x86/q35/DSDT.multi-bridge         | Bin 13280 -> 13281 bytes
>  tests/data/acpi/x86/q35/DSDT.noacpihp             | Bin 8289 -> 8290 bytes
>  tests/data/acpi/x86/q35/DSDT.nohpet               | Bin 8285 -> 8286 bytes
>  tests/data/acpi/x86/q35/DSDT.numamem              | Bin 8433 -> 8434 bytes
>  tests/data/acpi/x86/q35/DSDT.pvpanic-isa          | Bin 8528 -> 8529 bytes
>  tests/data/acpi/x86/q35/DSDT.thread-count         | Bin 12985 -> 12986 bytes
>  tests/data/acpi/x86/q35/DSDT.thread-count2        | Bin 33842 -> 33843 bytes
>  tests/data/acpi/x86/q35/DSDT.tis.tpm12            | Bin 9033 -> 9034 bytes
>  tests/data/acpi/x86/q35/DSDT.tis.tpm2             | Bin 9059 -> 9060 bytes
>  tests/data/acpi/x86/q35/DSDT.type4-count          | Bin 18661 -> 18662 bytes
>  tests/data/acpi/x86/q35/DSDT.viot                 | Bin 14684 -> 14685 bytes
>  tests/data/acpi/x86/q35/DSDT.xapic                | Bin 35790 -> 35791 bytes
>  tests/data/acpi/x86/q35/WDAT.wdat                 | Bin 0 -> 308 bytes
>  tests/qtest/amd-iommu-test.c                      |  76 +++
>  tests/qtest/bios-tables-test.c                    |  13 +
>  tests/qtest/intel-iommu-test.c                    |  32 +-
>  tests/qtest/iommu-intel-test.c                    |   4 +-
>  tests/qtest/meson.build                           |   1 +
>  144 files changed, 4056 insertions(+), 1158 deletions(-)
>  create mode 100644 hw/acpi/wdat-ich9-stub.c
>  create mode 100644 hw/acpi/wdat-ich9.c
>  rename hw/virtio/{vhost-backend.c => vhost-kernel.c} (83%)
>  create mode 100644 hw/virtio/vhost-user-stub.c
>  create mode 100644 hw/virtio/virtio-rtc-pci.c
>  create mode 100644 hw/virtio/virtio-rtc.c
>  create mode 100644 include/hw/acpi/wdat-ich9.h
>  create mode 100644 include/hw/acpi/wdat.h
>  create mode 100644 include/hw/virtio/virtio-rtc.h
>  create mode 100644 include/standard-headers/linux/virtio_rtc.h
>  create mode 100644 tests/data/acpi/x86/q35/WDAT.wdat
>  create mode 100644 tests/qtest/amd-iommu-test.c
>
>


^ permalink raw reply	[flat|nested] 109+ messages in thread

* Re: [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups
  2026-06-15 15:06 ` [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Stefan Hajnoczi
@ 2026-06-15 20:05   ` Michael S. Tsirkin
  0 siblings, 0 replies; 109+ messages in thread
From: Michael S. Tsirkin @ 2026-06-15 20:05 UTC (permalink / raw)
  To: Stefan Hajnoczi; +Cc: qemu-devel, Peter Maydell

On Mon, Jun 15, 2026 at 11:06:17AM -0400, Stefan Hajnoczi wrote:
> On Sun, Jun 14, 2026 at 3:10 PM Michael S. Tsirkin <mst@redhat.com> wrote:
> >
> > Resolved a bunch of conflicts.
> > If you see anything wrong here, pls holler.
> 
> Hi Michael,
> The check for mangled mailing list author emails is failing. Please
> `git commit --amend --author=...` with their real email and resend
> your pull request:
> 
> Alireza Sanaee via qemu development (2):
>       hw/cxl: Allow cxl_cfmws_find_device() to filter on whether
> interleaved paths are accepted
>       hw/cxl: Add a performant (and correct) path for the non interleaved cases
> ERROR: pull request includes commits attributed to list
> 
> Thanks!
> 
> Stefan


Fixed now, thanks!

new hash 062c1b7d033e675ea622939
 

> >
> >
> > The following changes since commit f5a2438405d4ae8b62de7c9b39fac0b2155ee544:
> >
> >   Merge tag 'pull-qapi-2026-05-21' of https://repo.or.cz/qemu/armbru into staging (2026-05-21 09:00:22 -0400)
> >
> > 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 31dbba011d0f3a21432d0629fae0b4885f2eed25:
> >
> >   hw/scsi/vhost-scsi: fix build with older kernel headers (2026-06-03 08:36:42 -0400)
> >
> > ----------------------------------------------------------------
> > pci, vhost, virtio, iommu: features, fixes, cleanups
> >
> > intel_iommu:
> >     PASID support for passthrough
> >     some properties renamed
> > virtio-rtc:
> >     new device
> > acpi:
> >     watchdog (x86 q35)
> >     COM irqs are now shared
> > vhost-user:
> >     vhost-user passes GPA not HVA now
> >     vhost SHMEM_MAP/UNMAP support
> > vhost-vdpa:
> >     svq IN_ORDER support
> > amd_iommu:
> >     IOMMU XT interrupt support
> >     command buffer fixes
> > cxl:
> >     PPR support
> >     performant path for non-interleaved cases
> > vhost-scsi:
> >     build fix for older kernel headers
> > fixes, cleanups all over the place
> >
> > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> >
> > ----------------------------------------------------------------
> > Aditya Gupta (2):
> >       ppc/pnv_phb3: Error out on invalid config access
> >       hw/pci: Replace assert with bounds check and return
> >
> > Albert Esteve (7):
> >       vhost-user: Add VirtIO Shared Memory map request
> >       vhost_user.rst: Align VhostUserMsg excerpt members
> >       vhost_user.rst: Add SHMEM_MAP/_UNMAP to spec
> >       vhost_user: Add frontend get_shmem_config command
> >       vhost_user.rst: Add GET_SHMEM_CONFIG message
> >       qmp: add shmem feature map
> >       vhost-user-device: Add shared memory BAR
> >
> > Alejandro Jimenez (3):
> >       amd_iommu: Update command buffer head ptr in MMIO region after wraparound
> >       amd_iommu: Follow root pointer before page walk and use 1-based levels
> >       amd_iommu: Reject non-decreasing NextLevel in fetch_pte()
> >
> > Alexandr Moshkov (1):
> >       vhost-user.rst: fix typo
> >
> > Alexey Gerasimenko (1):
> >       q35: Fix incorrect values for PCIEXBAR masks
> >
> > Alireza Sanaee via qemu development (2):
> >       hw/cxl: Allow cxl_cfmws_find_device() to filter on whether interleaved paths are accepted
> >       hw/cxl: Add a performant (and correct) path for the non interleaved cases
> >
> > Costas Argyris (1):
> >       tests/qtest: Add amd-iommu command buffer head wrap test
> >
> > Eugenio Pérez (8):
> >       net/vhost-vdpa: enable vqs before DRIVER_OK if no cvq
> >       virtio: Allow to fill a whole virtqueue in order
> >       vhost: move svq next desc array to descs state struct
> >       vhost: factor out the descriptor next fetching
> >       vhost: factor out the get of last used desc in SVQ
> >       vhost: factor out the detach buf logic in SVQ
> >       vhost: add in_order feature to shadow virtqueue
> >       vhost: accept in order feature flag
> >
> > Igor Mammedov (6):
> >       acpi: add API to build WDAT instructions
> >       x86: q35: add 'wdat' property
> >       x86: q35: generate WDAT ACPI table
> >       tests: acpi: x86/q35: whitelist new WDAT table
> >       tests: acpi: x86/q35: add WDAT table test case
> >       tests: acpi: x86/q35: update expected WDAT blob
> >
> > Jonathan Cameron (1):
> >       MAINTAINERS: Update CXL maintainers entry including adding linux-cxl list
> >
> > Jorge E. Moreira (1):
> >       vhost-user.rst: Explicitly allow front-end to write to kick FDs
> >
> > Junjie Cao (2):
> >       intel_iommu: fix guest-triggerable abort on oversized MMIO access
> >       tests/qtest: add 8-byte MMIO access sweep for intel-iommu
> >
> > Kuan-Wei Chiu (3):
> >       vhost-user: Fix stale error logs and return values in teardown paths
> >       standard-headers: Add virtio_rtc.h from Linux 7.0-rc1
> >       virtio-rtc: Add basic virtio-rtc support
> >
> > Mark Cave-Ayland (4):
> >       hw/acpi/aml-build.c: add aml_irq() representing the 3-byte IRQ descriptor
> >       tests/acpi: allow DSDT acpi table changes
> >       hw/char/serial-isa.c: declare IRQ as shared in ACPI IRQ descriptor
> >       tests: data: update x86 ACPI tables
> >
> > Max Makarov (2):
> >       vhost-user-blk-server: do not advertise VIRTIO_BLK_F_SIZE_MAX with size_max=0
> >       vhost-user-blk: do not force VIRTIO_BLK_F_SIZE_MAX
> >
> > Paolo Bonzini (1):
> >       amd_iommu: restrict command buffer head/tail ranges to ring size
> >
> > Quan Sun (1):
> >       hw/scsi/vhost-scsi: fix build with older kernel headers
> >
> > Sairaj Kodilkar (3):
> >       amd_iommu: Use switch case to determine mmio register name
> >       amd_iommu: Turn on XT support only when guest has enabled it
> >       amd_iommu: Generate XT interrupts when xt support is enabled
> >
> > Shiju Jose (3):
> >       hw/cxl: Fix handling of component ID to not assume it is a string
> >       hw/cxl: Add fixes in Post Package Repair (PPR)
> >       hw/cxl/events: Fix handling of component ID in event records generation to not assume it is a string
> >
> > Stefano Garzarella (2):
> >       libvhost-user: fix buffer overflow in virtqueue_read_indirect_desc()
> >       libvduse: fix buffer overflow in vduse_queue_read_indirect_desc()
> >
> > Thomas Huth (1):
> >       hw/i386/pc: Add a proper owner for the ioport memory regions
> >
> > Vladimir Sementsov-Ogievskiy (32):
> >       vhost-user: rework enabling vrings
> >       vhost: drop backend_features field
> >       vhost-user: introduce vhost_user_has_protocol_feature() helper
> >       vhost: move protocol_features to vhost_user
> >       vhost-user-gpu: drop code duplication
> >       vhost: make vhost_dev.features private
> >       virtio: move common part of _set_guest_notifier to generic code
> >       virtio: drop *_set_guest_notifier_fd_handler() helpers
> >       vhost-user: keep QIOChannelSocket for backend channel
> >       vhost: vhost_virtqueue_start(): fix failure path
> >       vhost: make vhost_memory_unmap() null-safe
> >       vhost: simplify calls to vhost_memory_unmap()
> >       vhost: move vrings mapping to the top of vhost_virtqueue_start()
> >       vhost: vhost_virtqueue_start(): drop extra local variables
> >       vhost: final refactoring of vhost vrings map/unmap
> >       vhost: simplify vhost_dev_init() error-path
> >       vhost: move busyloop timeout initialization to vhost_virtqueue_init()
> >       vhost: vhost_dev_init(): simplify features initialization
> >       hw/virtio/virtio-bus: refactor virtio_bus_set_host_notifier()
> >       vhost-user: make trace events more readable
> >       vhost-user-blk: add some useful trace-points
> >       vhost: add some useful trace-points
> >       vhost: move IOTLB functions from vhost-backend.c to vhost.c
> >       vhost: use consistent naming for backend handlers
> >       vhost: rename vhost-backend.c to vhost-kernel.c
> >       vhost: replace .vhost_vq_get_addr() with .vhost_phys_vring_addr()
> >       vhost: simplify vhost_memory_map() and vhost_memory_unmap()
> >       qapi: remove user addresses from x-query-virtio-vhost-queue-status
> >       vhost: stop reusing vq->desc (and friends) to store physical address
> >       vhost: rename vring pointer fields to reflect user addresses
> >       vhost: add .vhost_phys_iotlb_msg() handler
> >       vhost-user: add VHOST_USER_PROTOCOL_F_GPA_ADDRESSES
> >
> > Zhenzhong Duan (19):
> >       intel_iommu: Remove 'x-' prefix from 'x-scalable-mode' and 'x-flts' properties
> >       intel_iommu: Change 'flts' property naming to 'fsts'
> >       vfio/iommufd: Extend attach/detach_hwpt callback implementations with pasid
> >       iommufd: Extend attach/detach_hwpt callbacks to support pasid
> >       vfio/iommufd: Create nesting parent hwpt with IOMMU_HWPT_ALLOC_PASID flag
> >       intel_iommu: Create the nested hwpt with IOMMU_HWPT_ALLOC_PASID flag
> >       intel_iommu: Rename pasid property to "pasid-bits" and define it as type uint8
> >       intel_iommu: make vtd_dev_get_pe_from_pasid() more generic
> >       intel_iommu: Export some functions
> >       intel_iommu: Fix PASID validity check in fault reporting
> >       intel_iommu: Use IOMMU_NO_PASID and delete PASID_0
> >       intel_iommu: Refactor PASID processing to use IOMMU_NO_PASID internally
> >       intel_iommu_accel: Handle PASID entry addition for pc_inv_dsc request
> >       intel_iommu_accel: Handle PASID entry removal for pc_inv_dsc request
> >       intel_iommu_accel: Bypass PASID entry addition for just deleted entry
> >       intel_iommu_accel: Handle PASID entry removal for system reset
> >       intel_iommu_accel: Switch to VTDAccelPASIDCacheEntry for PASID bind/unbind and PIOTLB invalidation
> >       intel_iommu_accel: Add pasid bits size check
> >       intel_iommu: Expose flag VIOMMU_FLAG_PASID_SUPPORTED and VIOMMU_FLAG_WANT_PASID_ATTACH
> >
> >  MAINTAINERS                                       |  12 +-
> >  backends/cryptodev-vhost.c                        |   9 +-
> >  backends/iommufd.c                                |  23 +-
> >  backends/vhost-user.c                             |   8 +-
> >  block/export/vhost-user-blk-server.c              |   2 +-
> >  docs/devel/vfio-iommufd.rst                       |  10 +-
> >  docs/interop/vhost-user.rst                       | 135 +++++-
> >  hw/acpi/aml-build-stub.c                          |   6 +
> >  hw/acpi/aml-build.c                               |  41 ++
> >  hw/acpi/meson.build                               |   3 +-
> >  hw/acpi/wdat-ich9-stub.c                          |  15 +
> >  hw/acpi/wdat-ich9.c                               |  90 ++++
> >  hw/arm/smmuv3-accel.c                             |  12 +-
> >  hw/block/trace-events                             |  10 +
> >  hw/block/vhost-user-blk.c                         |  36 +-
> >  hw/char/serial-isa.c                              |   3 +-
> >  hw/cxl/cxl-component-utils.c                      |   6 +
> >  hw/cxl/cxl-host.c                                 | 234 ++++++++-
> >  hw/cxl/cxl-mailbox-utils.c                        |   6 +-
> >  hw/display/vhost-user-gpu.c                       |  11 +-
> >  hw/i386/acpi-build.c                              |  12 +
> >  hw/i386/amd_iommu.c                               | 288 +++++++----
> >  hw/i386/amd_iommu.h                               |  36 +-
> >  hw/i386/intel_iommu.c                             | 352 +++++++-------
> >  hw/i386/intel_iommu_accel.c                       | 401 ++++++++++++---
> >  hw/i386/intel_iommu_accel.h                       |  20 +-
> >  hw/i386/intel_iommu_internal.h                    |  44 +-
> >  hw/i386/pc.c                                      |   6 +-
> >  hw/i386/pc_q35.c                                  |  18 +
> >  hw/i386/trace-events                              |   1 +
> >  hw/mem/cxl_type3.c                                |  17 +-
> >  hw/net/vhost_net.c                                |  35 +-
> >  hw/pci-host/pnv_phb3.c                            |  10 +
> >  hw/pci-host/q35.c                                 |   6 +-
> >  hw/pci/pci_host.c                                 |  14 +-
> >  hw/s390x/virtio-ccw.c                             |  35 +-
> >  hw/scsi/vhost-scsi-common.c                       |   2 +-
> >  hw/scsi/vhost-scsi.c                              |   2 +-
> >  hw/scsi/vhost-user-scsi.c                         |   1 -
> >  hw/vfio/device.c                                  |  11 +
> >  hw/vfio/iommufd.c                                 |  68 ++-
> >  hw/vfio/trace-events                              |   4 +-
> >  hw/virtio/Kconfig                                 |   5 +
> >  hw/virtio/meson.build                             |   5 +-
> >  hw/virtio/trace-events                            |  16 +-
> >  hw/virtio/vdpa-dev.c                              |   3 +-
> >  hw/virtio/{vhost-backend.c => vhost-kernel.c}     |  90 +---
> >  hw/virtio/vhost-shadow-virtqueue.c                | 215 ++++++--
> >  hw/virtio/vhost-shadow-virtqueue.h                |  38 +-
> >  hw/virtio/vhost-user-base.c                       |  63 ++-
> >  hw/virtio/vhost-user-fs.c                         |   9 +-
> >  hw/virtio/vhost-user-scmi.c                       |   9 +-
> >  hw/virtio/vhost-user-stub.c                       |   6 +
> >  hw/virtio/vhost-user-test-device-pci.c            |  42 +-
> >  hw/virtio/vhost-user.c                            | 566 ++++++++++++++++++----
> >  hw/virtio/vhost-vdpa.c                            |  19 +-
> >  hw/virtio/vhost-vsock-common.c                    |   9 +-
> >  hw/virtio/vhost.c                                 | 384 +++++++++------
> >  hw/virtio/virtio-bus.c                            |  18 +-
> >  hw/virtio/virtio-hmp-cmds.c                       |   5 -
> >  hw/virtio/virtio-mmio.c                           |  41 +-
> >  hw/virtio/virtio-pci.c                            |  34 +-
> >  hw/virtio/virtio-qmp.c                            |  18 +-
> >  hw/virtio/virtio-rtc-pci.c                        |  65 +++
> >  hw/virtio/virtio-rtc.c                            | 190 ++++++++
> >  hw/virtio/virtio.c                                | 251 +++++++++-
> >  include/hw/acpi/aml-build.h                       |   2 +
> >  include/hw/acpi/wdat-ich9.h                       |  15 +
> >  include/hw/acpi/wdat.h                            | 118 +++++
> >  include/hw/core/iommu.h                           |  14 +
> >  include/hw/cxl/cxl.h                              |   1 +
> >  include/hw/cxl/cxl_device.h                       |   4 +
> >  include/hw/i386/intel_iommu.h                     |   4 +-
> >  include/hw/i386/pc.h                              |   1 +
> >  include/hw/pci-host/q35.h                         |   4 +-
> >  include/hw/vfio/vfio-device.h                     |   1 +
> >  include/hw/virtio/vhost-backend.h                 |  47 +-
> >  include/hw/virtio/vhost-user.h                    |   6 +
> >  include/hw/virtio/vhost.h                         |  71 ++-
> >  include/hw/virtio/virtio-pci.h                    |   3 -
> >  include/hw/virtio/virtio-rtc.h                    |  22 +
> >  include/hw/virtio/virtio.h                        | 151 +++++-
> >  include/standard-headers/linux/virtio_rtc.h       | 237 +++++++++
> >  include/system/iommufd.h                          |  18 +-
> >  include/system/memory.h                           |   4 +-
> >  net/vhost-vdpa.c                                  |  37 +-
> >  qapi/virtio.json                                  |  18 -
> >  subprojects/libvduse/libvduse.c                   |   7 +-
> >  subprojects/libvhost-user/libvhost-user.c         |  77 ++-
> >  subprojects/libvhost-user/libvhost-user.h         |  56 +++
> >  system/memory.c                                   |  14 +
> >  tests/data/acpi/x86/microvm/DSDT                  | Bin 365 -> 366 bytes
> >  tests/data/acpi/x86/microvm/DSDT.ioapic2          | Bin 365 -> 366 bytes
> >  tests/data/acpi/x86/microvm/DSDT.pcie             | Bin 2985 -> 2986 bytes
> >  tests/data/acpi/x86/microvm/DSDT.rtc              | Bin 404 -> 405 bytes
> >  tests/data/acpi/x86/microvm/DSDT.usb              | Bin 414 -> 415 bytes
> >  tests/data/acpi/x86/pc/DSDT                       | Bin 8598 -> 8599 bytes
> >  tests/data/acpi/x86/pc/DSDT.acpierst              | Bin 8509 -> 8510 bytes
> >  tests/data/acpi/x86/pc/DSDT.acpihmat              | Bin 9923 -> 9924 bytes
> >  tests/data/acpi/x86/pc/DSDT.bridge                | Bin 15469 -> 15470 bytes
> >  tests/data/acpi/x86/pc/DSDT.cphp                  | Bin 9062 -> 9063 bytes
> >  tests/data/acpi/x86/pc/DSDT.dimmpxm               | Bin 10252 -> 10253 bytes
> >  tests/data/acpi/x86/pc/DSDT.hpbridge              | Bin 8549 -> 8550 bytes
> >  tests/data/acpi/x86/pc/DSDT.hpbrroot              | Bin 5087 -> 5088 bytes
> >  tests/data/acpi/x86/pc/DSDT.ipmikcs               | Bin 8670 -> 8671 bytes
> >  tests/data/acpi/x86/pc/DSDT.memhp                 | Bin 9957 -> 9958 bytes
> >  tests/data/acpi/x86/pc/DSDT.nohpet                | Bin 8456 -> 8457 bytes
> >  tests/data/acpi/x86/pc/DSDT.numamem               | Bin 8604 -> 8605 bytes
> >  tests/data/acpi/x86/pc/DSDT.roothp                | Bin 12391 -> 12392 bytes
> >  tests/data/acpi/x86/q35/DSDT                      | Bin 8427 -> 8428 bytes
> >  tests/data/acpi/x86/q35/DSDT.acpierst             | Bin 8444 -> 8445 bytes
> >  tests/data/acpi/x86/q35/DSDT.acpihmat             | Bin 9752 -> 9753 bytes
> >  tests/data/acpi/x86/q35/DSDT.acpihmat-generic-x   | Bin 12637 -> 12638 bytes
> >  tests/data/acpi/x86/q35/DSDT.acpihmat-noinitiator | Bin 8706 -> 8707 bytes
> >  tests/data/acpi/x86/q35/DSDT.applesmc             | Bin 8473 -> 8474 bytes
> >  tests/data/acpi/x86/q35/DSDT.bridge               | Bin 12040 -> 12041 bytes
> >  tests/data/acpi/x86/q35/DSDT.core-count           | Bin 12985 -> 12986 bytes
> >  tests/data/acpi/x86/q35/DSDT.core-count2          | Bin 33842 -> 33843 bytes
> >  tests/data/acpi/x86/q35/DSDT.cphp                 | Bin 8891 -> 8892 bytes
> >  tests/data/acpi/x86/q35/DSDT.cxl                  | Bin 13218 -> 13219 bytes
> >  tests/data/acpi/x86/q35/DSDT.dimmpxm              | Bin 10081 -> 10082 bytes
> >  tests/data/acpi/x86/q35/DSDT.ipmibt               | Bin 8502 -> 8503 bytes
> >  tests/data/acpi/x86/q35/DSDT.ipmismbus            | Bin 8515 -> 8516 bytes
> >  tests/data/acpi/x86/q35/DSDT.ivrs                 | Bin 8444 -> 8445 bytes
> >  tests/data/acpi/x86/q35/DSDT.memhp                | Bin 9786 -> 9787 bytes
> >  tests/data/acpi/x86/q35/DSDT.mmio64               | Bin 9557 -> 9558 bytes
> >  tests/data/acpi/x86/q35/DSDT.multi-bridge         | Bin 13280 -> 13281 bytes
> >  tests/data/acpi/x86/q35/DSDT.noacpihp             | Bin 8289 -> 8290 bytes
> >  tests/data/acpi/x86/q35/DSDT.nohpet               | Bin 8285 -> 8286 bytes
> >  tests/data/acpi/x86/q35/DSDT.numamem              | Bin 8433 -> 8434 bytes
> >  tests/data/acpi/x86/q35/DSDT.pvpanic-isa          | Bin 8528 -> 8529 bytes
> >  tests/data/acpi/x86/q35/DSDT.thread-count         | Bin 12985 -> 12986 bytes
> >  tests/data/acpi/x86/q35/DSDT.thread-count2        | Bin 33842 -> 33843 bytes
> >  tests/data/acpi/x86/q35/DSDT.tis.tpm12            | Bin 9033 -> 9034 bytes
> >  tests/data/acpi/x86/q35/DSDT.tis.tpm2             | Bin 9059 -> 9060 bytes
> >  tests/data/acpi/x86/q35/DSDT.type4-count          | Bin 18661 -> 18662 bytes
> >  tests/data/acpi/x86/q35/DSDT.viot                 | Bin 14684 -> 14685 bytes
> >  tests/data/acpi/x86/q35/DSDT.xapic                | Bin 35790 -> 35791 bytes
> >  tests/data/acpi/x86/q35/WDAT.wdat                 | Bin 0 -> 308 bytes
> >  tests/qtest/amd-iommu-test.c                      |  76 +++
> >  tests/qtest/bios-tables-test.c                    |  13 +
> >  tests/qtest/intel-iommu-test.c                    |  32 +-
> >  tests/qtest/iommu-intel-test.c                    |   4 +-
> >  tests/qtest/meson.build                           |   1 +
> >  144 files changed, 4056 insertions(+), 1158 deletions(-)
> >  create mode 100644 hw/acpi/wdat-ich9-stub.c
> >  create mode 100644 hw/acpi/wdat-ich9.c
> >  rename hw/virtio/{vhost-backend.c => vhost-kernel.c} (83%)
> >  create mode 100644 hw/virtio/vhost-user-stub.c
> >  create mode 100644 hw/virtio/virtio-rtc-pci.c
> >  create mode 100644 hw/virtio/virtio-rtc.c
> >  create mode 100644 include/hw/acpi/wdat-ich9.h
> >  create mode 100644 include/hw/acpi/wdat.h
> >  create mode 100644 include/hw/virtio/virtio-rtc.h
> >  create mode 100644 include/standard-headers/linux/virtio_rtc.h
> >  create mode 100644 tests/data/acpi/x86/q35/WDAT.wdat
> >  create mode 100644 tests/qtest/amd-iommu-test.c
> >
> >



^ permalink raw reply	[flat|nested] 109+ messages in thread

end of thread, other threads:[~2026-06-15 20:06 UTC | newest]

Thread overview: 109+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-14 19:10 [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Michael S. Tsirkin
2026-06-14 19:05 ` [PULL 001/106] amd_iommu: restrict command buffer head/tail ranges to ring size Michael S. Tsirkin
2026-06-14 19:05 ` [PULL 002/106] amd_iommu: Update command buffer head ptr in MMIO region after wraparound Michael S. Tsirkin
2026-06-14 19:05 ` [PULL 003/106] tests/qtest: Add amd-iommu command buffer head wrap test Michael S. Tsirkin
2026-06-14 19:05 ` [PULL 004/106] intel_iommu: Remove 'x-' prefix from 'x-scalable-mode' and 'x-flts' properties Michael S. Tsirkin
2026-06-14 19:05 ` [PULL 005/106] intel_iommu: Change 'flts' property naming to 'fsts' Michael S. Tsirkin
2026-06-14 19:05 ` [PULL 006/106] vfio/iommufd: Extend attach/detach_hwpt callback implementations with pasid Michael S. Tsirkin
2026-06-14 19:05 ` [PULL 007/106] iommufd: Extend attach/detach_hwpt callbacks to support pasid Michael S. Tsirkin
2026-06-14 19:06 ` [PULL 008/106] vfio/iommufd: Create nesting parent hwpt with IOMMU_HWPT_ALLOC_PASID flag Michael S. Tsirkin
2026-06-14 19:06 ` [PULL 009/106] intel_iommu: Create the nested " Michael S. Tsirkin
2026-06-14 19:06 ` [PULL 010/106] intel_iommu: Rename pasid property to "pasid-bits" and define it as type uint8 Michael S. Tsirkin
2026-06-14 19:06 ` [PULL 011/106] intel_iommu: make vtd_dev_get_pe_from_pasid() more generic Michael S. Tsirkin
2026-06-14 19:06 ` [PULL 012/106] intel_iommu: Export some functions Michael S. Tsirkin
2026-06-14 19:06 ` [PULL 013/106] intel_iommu: Fix PASID validity check in fault reporting Michael S. Tsirkin
2026-06-14 19:06 ` [PULL 014/106] intel_iommu: Use IOMMU_NO_PASID and delete PASID_0 Michael S. Tsirkin
2026-06-14 19:06 ` [PULL 015/106] intel_iommu: Refactor PASID processing to use IOMMU_NO_PASID internally Michael S. Tsirkin
2026-06-14 19:06 ` [PULL 016/106] intel_iommu_accel: Handle PASID entry addition for pc_inv_dsc request Michael S. Tsirkin
2026-06-14 19:06 ` [PULL 017/106] intel_iommu_accel: Handle PASID entry removal " Michael S. Tsirkin
2026-06-14 19:06 ` [PULL 018/106] intel_iommu_accel: Bypass PASID entry addition for just deleted entry Michael S. Tsirkin
2026-06-14 19:06 ` [PULL 019/106] intel_iommu_accel: Handle PASID entry removal for system reset Michael S. Tsirkin
2026-06-14 19:06 ` [PULL 020/106] intel_iommu_accel: Switch to VTDAccelPASIDCacheEntry for PASID bind/unbind and PIOTLB invalidation Michael S. Tsirkin
2026-06-14 19:06 ` [PULL 021/106] intel_iommu_accel: Add pasid bits size check Michael S. Tsirkin
2026-06-14 19:06 ` [PULL 022/106] intel_iommu: Expose flag VIOMMU_FLAG_PASID_SUPPORTED and VIOMMU_FLAG_WANT_PASID_ATTACH Michael S. Tsirkin
2026-06-14 19:06 ` [PULL 023/106] hw/acpi/aml-build.c: add aml_irq() representing the 3-byte IRQ descriptor Michael S. Tsirkin
2026-06-14 19:06 ` [PULL 024/106] tests/acpi: allow DSDT acpi table changes Michael S. Tsirkin
2026-06-14 19:06 ` [PULL 025/106] hw/char/serial-isa.c: declare IRQ as shared in ACPI IRQ descriptor Michael S. Tsirkin
2026-06-14 19:06 ` [PULL 026/106] tests: data: update x86 ACPI tables Michael S. Tsirkin
2026-06-14 19:06 ` [PULL 027/106] vhost-user: rework enabling vrings Michael S. Tsirkin
2026-06-14 19:06 ` [PULL 028/106] vhost: drop backend_features field Michael S. Tsirkin
2026-06-14 19:06 ` [PULL 029/106] vhost-user: introduce vhost_user_has_protocol_feature() helper Michael S. Tsirkin
2026-06-14 19:07 ` [PULL 030/106] vhost: move protocol_features to vhost_user Michael S. Tsirkin
2026-06-14 19:07 ` [PULL 031/106] vhost-user-gpu: drop code duplication Michael S. Tsirkin
2026-06-14 19:07 ` [PULL 032/106] vhost: make vhost_dev.features private Michael S. Tsirkin
2026-06-14 19:07 ` [PULL 033/106] virtio: move common part of _set_guest_notifier to generic code Michael S. Tsirkin
2026-06-14 19:07 ` [PULL 034/106] virtio: drop *_set_guest_notifier_fd_handler() helpers Michael S. Tsirkin
2026-06-14 19:07 ` [PULL 035/106] vhost-user: keep QIOChannelSocket for backend channel Michael S. Tsirkin
2026-06-14 19:07 ` [PULL 036/106] vhost: vhost_virtqueue_start(): fix failure path Michael S. Tsirkin
2026-06-14 19:07 ` [PULL 037/106] vhost: make vhost_memory_unmap() null-safe Michael S. Tsirkin
2026-06-14 19:07 ` [PULL 038/106] vhost: simplify calls to vhost_memory_unmap() Michael S. Tsirkin
2026-06-14 19:07 ` [PULL 039/106] vhost: move vrings mapping to the top of vhost_virtqueue_start() Michael S. Tsirkin
2026-06-14 19:07 ` [PULL 040/106] vhost: vhost_virtqueue_start(): drop extra local variables Michael S. Tsirkin
2026-06-14 19:07 ` [PULL 041/106] vhost: final refactoring of vhost vrings map/unmap Michael S. Tsirkin
2026-06-14 19:07 ` [PULL 042/106] vhost: simplify vhost_dev_init() error-path Michael S. Tsirkin
2026-06-14 19:07 ` [PULL 043/106] vhost: move busyloop timeout initialization to vhost_virtqueue_init() Michael S. Tsirkin
2026-06-14 19:07 ` [PULL 044/106] vhost: vhost_dev_init(): simplify features initialization Michael S. Tsirkin
2026-06-14 19:07 ` [PULL 045/106] hw/virtio/virtio-bus: refactor virtio_bus_set_host_notifier() Michael S. Tsirkin
2026-06-14 19:07 ` [PULL 046/106] vhost-user: make trace events more readable Michael S. Tsirkin
2026-06-14 19:07 ` [PULL 047/106] vhost-user-blk: add some useful trace-points Michael S. Tsirkin
2026-06-14 19:07 ` [PULL 048/106] vhost: " Michael S. Tsirkin
2026-06-14 19:07 ` [PULL 049/106] vhost: move IOTLB functions from vhost-backend.c to vhost.c Michael S. Tsirkin
2026-06-14 19:07 ` [PULL 050/106] vhost: use consistent naming for backend handlers Michael S. Tsirkin
2026-06-14 19:07 ` [PULL 051/106] vhost: rename vhost-backend.c to vhost-kernel.c Michael S. Tsirkin
2026-06-14 19:07 ` [PULL 052/106] vhost: replace .vhost_vq_get_addr() with .vhost_phys_vring_addr() Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 053/106] vhost: simplify vhost_memory_map() and vhost_memory_unmap() Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 054/106] qapi: remove user addresses from x-query-virtio-vhost-queue-status Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 055/106] vhost: stop reusing vq->desc (and friends) to store physical address Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 056/106] vhost: rename vring pointer fields to reflect user addresses Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 057/106] vhost: add .vhost_phys_iotlb_msg() handler Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 058/106] vhost-user: add VHOST_USER_PROTOCOL_F_GPA_ADDRESSES Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 059/106] libvhost-user: fix buffer overflow in virtqueue_read_indirect_desc() Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 060/106] libvduse: fix buffer overflow in vduse_queue_read_indirect_desc() Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 061/106] MAINTAINERS: Update CXL maintainers entry including adding linux-cxl list Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 062/106] vhost-user.rst: Explicitly allow front-end to write to kick FDs Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 063/106] amd_iommu: Follow root pointer before page walk and use 1-based levels Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 064/106] amd_iommu: Reject non-decreasing NextLevel in fetch_pte() Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 065/106] vhost-user-blk-server: do not advertise VIRTIO_BLK_F_SIZE_MAX with size_max=0 Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 066/106] vhost-user-blk: do not force VIRTIO_BLK_F_SIZE_MAX Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 067/106] ppc/pnv_phb3: Error out on invalid config access Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 068/106] hw/pci: Replace assert with bounds check and return Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 069/106] vhost-user: Fix stale error logs and return values in teardown paths Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 070/106] q35: Fix incorrect values for PCIEXBAR masks Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 071/106] net/vhost-vdpa: enable vqs before DRIVER_OK if no cvq Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 072/106] virtio: Allow to fill a whole virtqueue in order Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 073/106] vhost: move svq next desc array to descs state struct Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 074/106] vhost: factor out the descriptor next fetching Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 075/106] vhost: factor out the get of last used desc in SVQ Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 076/106] vhost: factor out the detach buf logic " Michael S. Tsirkin
2026-06-14 19:08 ` [PULL 077/106] vhost: add in_order feature to shadow virtqueue Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 078/106] vhost: accept in order feature flag Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 079/106] amd_iommu: Use switch case to determine mmio register name Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 080/106] amd_iommu: Turn on XT support only when guest has enabled it Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 081/106] amd_iommu: Generate XT interrupts when xt support is enabled Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 082/106] standard-headers: Add virtio_rtc.h from Linux 7.0-rc1 Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 083/106] virtio-rtc: Add basic virtio-rtc support Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 084/106] hw/i386/pc: Add a proper owner for the ioport memory regions Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 085/106] acpi: add API to build WDAT instructions Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 086/106] x86: q35: add 'wdat' property Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 087/106] x86: q35: generate WDAT ACPI table Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 088/106] tests: acpi: x86/q35: whitelist new WDAT table Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 089/106] tests: acpi: x86/q35: add WDAT table test case Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 090/106] tests: acpi: x86/q35: update expected WDAT blob Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 091/106] vhost-user: Add VirtIO Shared Memory map request Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 092/106] vhost_user.rst: Align VhostUserMsg excerpt members Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 093/106] vhost_user.rst: Add SHMEM_MAP/_UNMAP to spec Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 094/106] vhost_user: Add frontend get_shmem_config command Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 095/106] vhost_user.rst: Add GET_SHMEM_CONFIG message Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 096/106] qmp: add shmem feature map Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 097/106] vhost-user-device: Add shared memory BAR Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 098/106] vhost-user.rst: fix typo Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 099/106] hw/cxl: Fix handling of component ID to not assume it is a string Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 100/106] hw/cxl: Add fixes in Post Package Repair (PPR) Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 101/106] hw/cxl/events: Fix handling of component ID in event records generation to not assume it is a string Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 102/106] hw/cxl: Allow cxl_cfmws_find_device() to filter on whether interleaved paths are accepted Michael S. Tsirkin
2026-06-14 19:09 ` [PULL 103/106] hw/cxl: Add a performant (and correct) path for the non interleaved cases Michael S. Tsirkin
2026-06-14 19:10 ` [PULL 104/106] intel_iommu: fix guest-triggerable abort on oversized MMIO access Michael S. Tsirkin
2026-06-14 19:10 ` [PULL 105/106] tests/qtest: add 8-byte MMIO access sweep for intel-iommu Michael S. Tsirkin
2026-06-14 19:10 ` [PULL 106/106] hw/scsi/vhost-scsi: fix build with older kernel headers Michael S. Tsirkin
2026-06-15 15:06 ` [PULL 000/106] pci, vhost, virtio, iommu: features, fixes, cleanups Stefan Hajnoczi
2026-06-15 20:05   ` Michael S. Tsirkin

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.