* [PULL 01/17] pcie_sriov: Rework the assert statements checking region numbers
2026-11-03 11:50 [PULL 00/17] pci: fixes Michael S. Tsirkin
@ 2026-11-03 11:50 ` Michael S. Tsirkin
2026-11-03 11:50 ` [PULL 02/17] pcie_sriov: Adapt bar type array size to the number of regions Michael S. Tsirkin
` (16 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2026-11-03 11:50 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Clément MATHIEU--DRIF
From: Clément MATHIEU--DRIF <clement.mathieu--drif@bull.com>
pcie_sriov_pf_init_vf_bar: PCI_ROM_SLOT is already out of the SR-IOV
regions.
pcie_sriov_pf_init_from_user_created_vfs: ROM region must never have a
non-zero size.
Signed-off-by: Clement Mathieu--Drif <clement.mathieu--drif@bull.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20261028144539.691098-1-clement.mathieu--drif@bull.com>
---
hw/pci/pcie_sriov.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/hw/pci/pcie_sriov.c b/hw/pci/pcie_sriov.c
index 6a748c3626..e6891436d3 100644
--- a/hw/pci/pcie_sriov.c
+++ b/hw/pci/pcie_sriov.c
@@ -230,7 +230,6 @@ void pcie_sriov_pf_init_vf_bar(PCIDevice *dev, int region_num,
assert(sriov_cap > 0);
assert(region_num >= 0);
assert(region_num < PCI_SRIOV_NUM_BARS);
- assert(region_num != PCI_ROM_SLOT);
wmask = ~(size - 1);
addr = sriov_cap + PCI_SRIOV_BAR + region_num * 4;
@@ -344,6 +343,8 @@ int16_t pcie_sriov_pf_init_from_user_created_vfs(PCIDevice *dev,
dev->exp.sriov_pf.vf = vfs;
dev->exp.sriov_pf.vf_user_created = true;
+ assert(vfs[0]->io_regions[PCI_ROM_SLOT].size == 0);
+
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
PCIIORegion *region = &vfs[0]->io_regions[i];
--
MST
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PULL 02/17] pcie_sriov: Adapt bar type array size to the number of regions
2026-11-03 11:50 [PULL 00/17] pci: fixes Michael S. Tsirkin
2026-11-03 11:50 ` [PULL 01/17] pcie_sriov: Rework the assert statements checking region numbers Michael S. Tsirkin
@ 2026-11-03 11:50 ` Michael S. Tsirkin
2026-11-03 11:50 ` [PULL 03/17] pci id: clarify pci subsystem id usage Michael S. Tsirkin
` (15 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2026-11-03 11:50 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Clément MATHIEU--DRIF
From: Clément MATHIEU--DRIF <clement.mathieu--drif@bull.com>
Signed-off-by: Clement Mathieu--Drif <clement.mathieu--drif@bull.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20261028144539.691098-2-clement.mathieu--drif@bull.com>
---
include/hw/pci/pcie_sriov.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/hw/pci/pcie_sriov.h b/include/hw/pci/pcie_sriov.h
index b0ea6a62c7..5f81e3b1bb 100644
--- a/include/hw/pci/pcie_sriov.h
+++ b/include/hw/pci/pcie_sriov.h
@@ -16,7 +16,7 @@
#include "hw/pci/pci.h"
typedef struct PCIESriovPF {
- uint8_t vf_bar_type[PCI_NUM_REGIONS]; /* Store type for each VF bar */
+ uint8_t vf_bar_type[PCI_SRIOV_NUM_BARS]; /* Store type for each VF bar */
PCIDevice **vf; /* Pointer to an array of num_vfs VF devices */
bool vf_user_created; /* If VFs are created by user */
} PCIESriovPF;
--
MST
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PULL 03/17] pci id: clarify pci subsystem id usage
2026-11-03 11:50 [PULL 00/17] pci: fixes Michael S. Tsirkin
2026-11-03 11:50 ` [PULL 01/17] pcie_sriov: Rework the assert statements checking region numbers Michael S. Tsirkin
2026-11-03 11:50 ` [PULL 02/17] pcie_sriov: Adapt bar type array size to the number of regions Michael S. Tsirkin
@ 2026-11-03 11:50 ` Michael S. Tsirkin
2026-11-03 11:50 ` [PULL 04/17] pci id: assign pci subsystem id for osmates Michael S. Tsirkin
` (14 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2026-11-03 11:50 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Gerd Hoffmann, Pierrick Bouvier
From: Gerd Hoffmann <kraxel@redhat.com>
Qemu uses the pci subsystem id not only for emulated devices, but also
for virtio devices and generic pci class devices such as pci bridges,
xhci + nvme controllers etc. Update the documentation accordingly.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20261030115455.1121808-2-kraxel@redhat.com>
---
docs/specs/pci-ids.rst | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/docs/specs/pci-ids.rst b/docs/specs/pci-ids.rst
index 60cb0f7db6..53dd571de2 100644
--- a/docs/specs/pci-ids.rst
+++ b/docs/specs/pci-ids.rst
@@ -46,8 +46,9 @@ maintained as part of the virtio specification.
upstream merge or shipping a distro/product) to avoid conflicts.
1af4:1100
- Used as PCI Subsystem ID for existing hardware devices emulated
- by QEMU.
+ Used as PCI Subsystem ID for existing hardware devices emulated by
+ QEMU, such as the intel chipset devices. Also used for virtio
+ devices and generic pci class devices (1b36:00xx, see below).
1af4:1110
ivshmem device (:doc:`ivshmem-spec`)
--
MST
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PULL 04/17] pci id: assign pci subsystem id for osmates
2026-11-03 11:50 [PULL 00/17] pci: fixes Michael S. Tsirkin
` (2 preceding siblings ...)
2026-11-03 11:50 ` [PULL 03/17] pci id: clarify pci subsystem id usage Michael S. Tsirkin
@ 2026-11-03 11:50 ` Michael S. Tsirkin
2026-11-03 11:50 ` [PULL 05/17] pci: fix null pointer dereference on pci device registration failure Michael S. Tsirkin
` (13 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2026-11-03 11:50 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Gerd Hoffmann, Đạt Ngô Quốc,
Pierrick Bouvier
From: Gerd Hoffmann <kraxel@redhat.com>
Allows the guest driver to identify the host implementation,
useful to be more specific when applying quirks etc.
OSMates is an open source VMM for macOS under MIT license.
It will be released in near future and will be available from
github.com/osmates.
Cc: Đạt Ngô Quốc <datlechin@gmail.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20261030115455.1121808-3-kraxel@redhat.com>
---
docs/specs/pci-ids.rst | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/docs/specs/pci-ids.rst b/docs/specs/pci-ids.rst
index 53dd571de2..74460bb19e 100644
--- a/docs/specs/pci-ids.rst
+++ b/docs/specs/pci-ids.rst
@@ -50,6 +50,10 @@ maintained as part of the virtio specification.
QEMU, such as the intel chipset devices. Also used for virtio
devices and generic pci class devices (1b36:00xx, see below).
+1af4:1101
+ PCI Subsystem ID for OSMates (github.com/osmates), will be used
+ for virtio devices and pci class devices (xhci, nvme).
+
1af4:1110
ivshmem device (:doc:`ivshmem-spec`)
--
MST
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PULL 05/17] pci: fix null pointer dereference on pci device registration failure
2026-11-03 11:50 [PULL 00/17] pci: fixes Michael S. Tsirkin
` (3 preceding siblings ...)
2026-11-03 11:50 ` [PULL 04/17] pci id: assign pci subsystem id for osmates Michael S. Tsirkin
@ 2026-11-03 11:50 ` Michael S. Tsirkin
2026-11-03 11:50 ` [PULL 06/17] pcie_sriov: perform additional checks after pci device realization Michael S. Tsirkin
` (12 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2026-11-03 11:50 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Daniel Paziyski, qemu-stable
From: Daniel Paziyski <danielpaziyski@gmail.com>
When a PCI device fails to be registered using do_pci_register_device, which
takes the PCI device as one of its arguments, and returns the PCI device itself
on success or null on failure, the acpi index is forcefully released using
pci_unregister_acpi_index.
However, this causes a null pointer to be passed always on failure to
pci_unregister_acpi_index. Instead, do not reassign pci_dev from the return
value of do_pci_register_device, just check it.
Cc: qemu-stable@nongnu.org
Resolves: Coverity CID 1689947
Fixes: 432ea8cc7d27 ("pcie_sriov: register user created virtual function before realizing it")
Signed-off-by: Daniel Paziyski <danielpaziyski@gmail.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20261101162132.147838-2-danielpaziyski@gmail.com>
---
hw/pci/pci.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 2d2fe02c68..1ea388be37 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -2327,10 +2327,8 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp)
pci_dev->cap_present |= QEMU_PCIE_CAP_CXL;
}
- pci_dev = do_pci_register_device(pci_dev,
- object_get_typename(OBJECT(qdev)),
- pci_dev->devfn, errp);
- if (pci_dev == NULL) {
+ if (!do_pci_register_device(pci_dev, object_get_typename(OBJECT(qdev)),
+ pci_dev->devfn, errp)) {
pci_unregister_acpi_index(pci_dev);
return;
}
--
MST
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PULL 06/17] pcie_sriov: perform additional checks after pci device realization
2026-11-03 11:50 [PULL 00/17] pci: fixes Michael S. Tsirkin
` (4 preceding siblings ...)
2026-11-03 11:50 ` [PULL 05/17] pci: fix null pointer dereference on pci device registration failure Michael S. Tsirkin
@ 2026-11-03 11:50 ` Michael S. Tsirkin
2026-11-03 11:50 ` [PULL 07/17] pcie_sriov: fix null pointer dereference when initializing PFs in a system with user and device created VFs Michael S. Tsirkin
` (11 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2026-11-03 11:50 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Daniel Paziyski, qemu-stable
From: Daniel Paziyski <danielpaziyski@gmail.com>
Handle two cases after realization, which were implicitly handled back when PCI
SR-IOV device registration was done after PCI realization before commit
432ea8cc7d27 ("pcie_sriov: register user created virtual function before realizing it")
- If a device is a PF of user created VFs, make sure that it has initialized its
list of VFs. This check seems to be superfluous, because the only way it can
fail is:
- if PCI device realization forgets to initialize the user created virtual
functions via pcie_sriov_pf_init_from_user_created_vfs, despite having set
sriov_vf_user_creatable in the device class;
- if the pcie_sriov_pf_init_from_user_created_vfs function fails, but forgets
to set errp (which does not happen), and the device specific realization
code forgets to check and/or propagate if an error has happened.
However, this check was present, so let's include it again for good measure.
- If a device is a user created VF, make sure that the device is still a
PCI Express device. This edge case occurs on devices that before realization
have the PCIe capability set, but then during realization they clear it for
some reason. This only seems to happen to modern virtio-net-pci devices, which
have their PCIe capability on, as any other modern virtio device, on object
instantiation, but is then cleared in its realize function when it is located
at the root complex or not in a PCIe bus.
Cc: qemu-stable@nongnu.org
Fixes: 432ea8cc7d27 ("pcie_sriov: register user created virtual function before realizing it")
Signed-off-by: Daniel Paziyski <danielpaziyski@gmail.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20261101162132.147838-3-danielpaziyski@gmail.com>
---
include/hw/pci/pcie_sriov.h | 2 ++
hw/pci/pci.c | 5 +++++
hw/pci/pcie_sriov.c | 19 +++++++++++++++++++
3 files changed, 26 insertions(+)
diff --git a/include/hw/pci/pcie_sriov.h b/include/hw/pci/pcie_sriov.h
index 5f81e3b1bb..41ccba8a71 100644
--- a/include/hw/pci/pcie_sriov.h
+++ b/include/hw/pci/pcie_sriov.h
@@ -57,6 +57,8 @@ int16_t pcie_sriov_pf_init_from_user_created_vfs(PCIDevice *dev,
bool pcie_sriov_register_device(PCIDevice *dev, Error **errp);
void pcie_sriov_unregister_device(PCIDevice *dev);
+bool pcie_sriov_check_after_realize(PCIDevice *dev, Error **errp);
+
/*
* Default (minimal) page size support values
* as required by the SR/IOV standard:
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 1ea388be37..e85b34d06d 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -2347,6 +2347,11 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp)
}
}
+ if (!pcie_sriov_check_after_realize(pci_dev, errp)) {
+ pci_qdev_unrealize(DEVICE(pci_dev));
+ return;
+ }
+
/*
* A PCIe Downstream Port that do not have ARI Forwarding enabled must
* associate only Device 0 with the device attached to the bus
diff --git a/hw/pci/pcie_sriov.c b/hw/pci/pcie_sriov.c
index e6891436d3..63d19ea488 100644
--- a/hw/pci/pcie_sriov.c
+++ b/hw/pci/pcie_sriov.c
@@ -393,6 +393,25 @@ bool pcie_sriov_register_device(PCIDevice *dev, Error **errp)
return true;
}
+bool pcie_sriov_check_after_realize(PCIDevice *dev, Error **errp)
+{
+ if (!dev->exp.sriov_pf.vf && dev->qdev.id &&
+ pfs && g_hash_table_contains(pfs, dev->qdev.id)) {
+ error_setg(errp, "attaching user-created SR-IOV VF unsupported");
+ return false;
+ }
+
+ if (dev->sriov_pf) {
+ /* some devices might clear their PCIe capability during realization */
+ if (!pci_is_express(dev)) {
+ error_setg(errp, "PCI Express is required for SR-IOV VF");
+ return false;
+ }
+ }
+
+ return true;
+}
+
void pcie_sriov_unregister_device(PCIDevice *dev)
{
if (dev->sriov_pf && pfs) {
--
MST
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PULL 07/17] pcie_sriov: fix null pointer dereference when initializing PFs in a system with user and device created VFs
2026-11-03 11:50 [PULL 00/17] pci: fixes Michael S. Tsirkin
` (5 preceding siblings ...)
2026-11-03 11:50 ` [PULL 06/17] pcie_sriov: perform additional checks after pci device realization Michael S. Tsirkin
@ 2026-11-03 11:50 ` Michael S. Tsirkin
2026-11-03 11:50 ` [PULL 08/17] tests/qtest: Enforce zero for the "un-fired" msix message value Michael S. Tsirkin
` (10 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2026-11-03 11:50 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, Daniel Paziyski, qemu-stable
From: Daniel Paziyski <danielpaziyski@gmail.com>
pcie_sriov_pf_init is only used to initialize PFs for device created VFs, and
as such, it is checked that the PF has not been referenced by a user created VF
by means of the sriov-pf parameter.
This check crashes if it is performed for a PF that does not have an ID, and
there are already user created VFs in the system.
Example:
qemu-system-x86_64 -M q35 \
-device pcie-root-port,id=rp1,chassis=1,slot=1 \
-device virtio-net-pci,sriov-pf=f,addr=0.1,bus=rp1 \
-device virtio-net-pci,id=f,addr=0.0,bus=rp1 \
-device pcie-root-port,id=rp2,chassis=1,slot=2 \
-device nvme-subsys,id=subsys0 \
-device nvme,sriov_max_vfs=1,serial=s,sriov_vq_flexible=2,sriov_vi_flexible=1,bus=rp2,subsys=subsys0
ASAN message:
The signal is caused by a READ memory access.
Hint: address points to the zero page.
#0 in g_str_hash (/usr/lib/libglib-2.0.so.0+0x49954)
#1 in g_hash_table_contains (/usr/lib/libglib-2.0.so.0+0x4ad3b)
#2 in pcie_sriov_pf_init ../hw/pci/pcie_sriov.c:161
#3 in nvme_init_sriov ../hw/nvme/ctrl.c:9088
#4 in nvme_init_pci ../hw/nvme/ctrl.c:9218
#5 in nvme_realize ../hw/nvme/ctrl.c:9696
Cc: qemu-stable@nongnu.org
Fixes: 19e55471d4e8 ("pcie_sriov: Allow user to create SR-IOV device")
Signed-off-by: Daniel Paziyski <danielpaziyski@gmail.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20261101162132.147838-4-danielpaziyski@gmail.com>
---
hw/pci/pcie_sriov.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/pci/pcie_sriov.c b/hw/pci/pcie_sriov.c
index 63d19ea488..9ba14d46c4 100644
--- a/hw/pci/pcie_sriov.c
+++ b/hw/pci/pcie_sriov.c
@@ -158,7 +158,7 @@ bool pcie_sriov_pf_init(PCIDevice *dev, uint16_t offset,
BusState *bus = qdev_get_parent_bus(&dev->qdev);
int32_t devfn = dev->devfn + vf_offset;
- if (pfs && g_hash_table_contains(pfs, dev->qdev.id)) {
+ if (pfs && dev->qdev.id && g_hash_table_contains(pfs, dev->qdev.id)) {
error_setg(errp, "attaching user-created SR-IOV VF unsupported");
return false;
}
--
MST
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PULL 08/17] tests/qtest: Enforce zero for the "un-fired" msix message value
2026-11-03 11:50 [PULL 00/17] pci: fixes Michael S. Tsirkin
` (6 preceding siblings ...)
2026-11-03 11:50 ` [PULL 07/17] pcie_sriov: fix null pointer dereference when initializing PFs in a system with user and device created VFs Michael S. Tsirkin
@ 2026-11-03 11:50 ` Michael S. Tsirkin
2026-11-03 11:50 ` [PULL 09/17] tests/qtest: Fix virtio msix message endianness Michael S. Tsirkin
` (9 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2026-11-03 11:50 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Nicholas Piggin, Philippe Mathieu-Daudé,
Fabiano Rosas, Jishnu Warrier, Utkarsh Verma, Laurent Vivier,
Paolo Bonzini
From: Nicholas Piggin <npiggin@gmail.com>
virtio-pci detects an unmasked msix interrupt has fired by looking
for the data payload value at the target address. If a value of zero
is enforced for the memory value when an interrupt has not fired,
then an assertion can be added to catch the case where something
changed the memory to an unexpected value.
This catches an endian conversion bug in the message value when
running these tests on a big endian target. Previously the test
just times out waiting for interrupt, after this it fails nicely.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Fabiano Rosas <farosas@suse.de>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Jishnu Warrier <jishnuvw@linux.ibm.com>
Signed-off-by: Utkarsh Verma <uverma@linux.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20261102035306.2291147-2-uverma@linux.ibm.com>
---
tests/qtest/libqos/virtio-pci-modern.c | 9 +++++----
tests/qtest/libqos/virtio-pci.c | 20 ++++++++++++--------
2 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/tests/qtest/libqos/virtio-pci-modern.c b/tests/qtest/libqos/virtio-pci-modern.c
index 4e67fcbd5d..f31b3be656 100644
--- a/tests/qtest/libqos/virtio-pci-modern.c
+++ b/tests/qtest/libqos/virtio-pci-modern.c
@@ -137,12 +137,13 @@ static bool get_msix_status(QVirtioPCIDevice *dev, uint32_t msix_entry,
}
data = qtest_readl(dev->pdev->bus->qts, msix_addr);
- if (data == msix_data) {
- qtest_writel(dev->pdev->bus->qts, msix_addr, 0);
- return true;
- } else {
+ if (data == 0) {
return false;
}
+ /* got a message, ensure it matches expected value then clear it. */
+ g_assert_cmphex(data, ==, msix_data);
+ qtest_writel(dev->pdev->bus->qts, msix_addr, 0);
+ return true;
}
static bool get_queue_isr_status(QVirtioDevice *d, QVirtQueue *vq)
diff --git a/tests/qtest/libqos/virtio-pci.c b/tests/qtest/libqos/virtio-pci.c
index 002bf8b8c2..102e45b524 100644
--- a/tests/qtest/libqos/virtio-pci.c
+++ b/tests/qtest/libqos/virtio-pci.c
@@ -132,12 +132,13 @@ static bool qvirtio_pci_get_queue_isr_status(QVirtioDevice *d, QVirtQueue *vq)
return qpci_msix_pending(dev->pdev, vqpci->msix_entry);
} else {
data = qtest_readl(dev->pdev->bus->qts, vqpci->msix_addr);
- if (data == vqpci->msix_data) {
- qtest_writel(dev->pdev->bus->qts, vqpci->msix_addr, 0);
- return true;
- } else {
+ if (data == 0) {
return false;
}
+ /* got a message, ensure it matches expected value then clear it. */
+ g_assert_cmphex(data, ==, vqpci->msix_data);
+ qtest_writel(dev->pdev->bus->qts, vqpci->msix_addr, 0);
+ return true;
}
} else {
return qpci_io_readb(dev->pdev, dev->bar, VIRTIO_PCI_ISR) & 1;
@@ -156,12 +157,13 @@ static bool qvirtio_pci_get_config_isr_status(QVirtioDevice *d)
return qpci_msix_pending(dev->pdev, dev->config_msix_entry);
} else {
data = qtest_readl(dev->pdev->bus->qts, dev->config_msix_addr);
- if (data == dev->config_msix_data) {
- qtest_writel(dev->pdev->bus->qts, dev->config_msix_addr, 0);
- return true;
- } else {
+ if (data == 0) {
return false;
}
+ /* got a message, ensure it matches expected value then clear it. */
+ g_assert_cmphex(data, ==, dev->config_msix_data);
+ qtest_writel(dev->pdev->bus->qts, dev->config_msix_addr, 0);
+ return true;
}
} else {
return qpci_io_readb(dev->pdev, dev->bar, VIRTIO_PCI_ISR) & 2;
@@ -323,6 +325,7 @@ void qvirtqueue_pci_msix_setup(QVirtioPCIDevice *d, QVirtQueuePCI *vqpci,
vqpci->msix_entry = entry;
vqpci->msix_addr = guest_alloc(alloc, 4);
+ qtest_memset(d->pdev->bus->qts, vqpci->msix_addr, 0, 4);
qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
off + PCI_MSIX_ENTRY_LOWER_ADDR, vqpci->msix_addr & ~0UL);
qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
@@ -355,6 +358,7 @@ void qvirtio_pci_set_msix_configuration_vector(QVirtioPCIDevice *d,
d->config_msix_data = 0x12345678;
d->config_msix_addr = guest_alloc(alloc, 4);
+ qtest_memset(d->pdev->bus->qts, d->config_msix_addr, 0, 4);
qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
off + PCI_MSIX_ENTRY_LOWER_ADDR, d->config_msix_addr & ~0UL);
--
MST
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PULL 09/17] tests/qtest: Fix virtio msix message endianness
2026-11-03 11:50 [PULL 00/17] pci: fixes Michael S. Tsirkin
` (7 preceding siblings ...)
2026-11-03 11:50 ` [PULL 08/17] tests/qtest: Enforce zero for the "un-fired" msix message value Michael S. Tsirkin
@ 2026-11-03 11:50 ` Michael S. Tsirkin
2026-11-03 11:50 ` [PULL 10/17] tests/qtest: Add libqos function for testing MSI-X interrupt status Michael S. Tsirkin
` (8 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2026-11-03 11:50 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Nicholas Piggin, Philippe Mathieu-Daudé,
Fabiano Rosas, Jishnu Warrier, Utkarsh Verma, Laurent Vivier,
Paolo Bonzini
From: Nicholas Piggin <npiggin@gmail.com>
msix messages are written to memory in little-endian order, so they
should not be byteswapped depending on target endianness, but read
as le and converted to host endian by the qtest.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Fabiano Rosas <farosas@suse.de>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Jishnu Warrier <jishnuvw@linux.ibm.com>
Signed-off-by: Utkarsh Verma <uverma@linux.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20261102035306.2291147-3-uverma@linux.ibm.com>
---
tests/qtest/libqos/virtio-pci-modern.c | 4 +++-
tests/qtest/libqos/virtio-pci.c | 8 ++++++--
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/tests/qtest/libqos/virtio-pci-modern.c b/tests/qtest/libqos/virtio-pci-modern.c
index f31b3be656..097b548f95 100644
--- a/tests/qtest/libqos/virtio-pci-modern.c
+++ b/tests/qtest/libqos/virtio-pci-modern.c
@@ -8,6 +8,7 @@
*/
#include "qemu/osdep.h"
+#include "qemu/bswap.h"
#include "standard-headers/linux/pci_regs.h"
#include "standard-headers/linux/virtio_pci.h"
#include "standard-headers/linux/virtio_config.h"
@@ -136,7 +137,8 @@ static bool get_msix_status(QVirtioPCIDevice *dev, uint32_t msix_entry,
return qpci_msix_pending(dev->pdev, msix_entry);
}
- data = qtest_readl(dev->pdev->bus->qts, msix_addr);
+ qtest_memread(dev->pdev->bus->qts, msix_addr, &data, sizeof(data));
+ data = le32_to_cpu(data);
if (data == 0) {
return false;
}
diff --git a/tests/qtest/libqos/virtio-pci.c b/tests/qtest/libqos/virtio-pci.c
index 102e45b524..d2b978d4b1 100644
--- a/tests/qtest/libqos/virtio-pci.c
+++ b/tests/qtest/libqos/virtio-pci.c
@@ -131,7 +131,9 @@ static bool qvirtio_pci_get_queue_isr_status(QVirtioDevice *d, QVirtQueue *vq)
/* No ISR checking should be done if masked, but read anyway */
return qpci_msix_pending(dev->pdev, vqpci->msix_entry);
} else {
- data = qtest_readl(dev->pdev->bus->qts, vqpci->msix_addr);
+ qtest_memread(dev->pdev->bus->qts, vqpci->msix_addr,
+ &data, sizeof(data));
+ data = le32_to_cpu(data);
if (data == 0) {
return false;
}
@@ -156,7 +158,9 @@ static bool qvirtio_pci_get_config_isr_status(QVirtioDevice *d)
/* No ISR checking should be done if masked, but read anyway */
return qpci_msix_pending(dev->pdev, dev->config_msix_entry);
} else {
- data = qtest_readl(dev->pdev->bus->qts, dev->config_msix_addr);
+ qtest_memread(dev->pdev->bus->qts, dev->config_msix_addr,
+ &data, sizeof(data));
+ data = le32_to_cpu(data);
if (data == 0) {
return false;
}
--
MST
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PULL 10/17] tests/qtest: Add libqos function for testing MSI-X interrupt status
2026-11-03 11:50 [PULL 00/17] pci: fixes Michael S. Tsirkin
` (8 preceding siblings ...)
2026-11-03 11:50 ` [PULL 09/17] tests/qtest: Fix virtio msix message endianness Michael S. Tsirkin
@ 2026-11-03 11:50 ` Michael S. Tsirkin
2026-11-03 11:50 ` [PULL 11/17] tests/qtest/nvme-test: fix NVMe struct field endianness Michael S. Tsirkin
` (7 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2026-11-03 11:50 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Nicholas Piggin, Philippe Mathieu-Daudé,
Jishnu Warrier, Utkarsh Verma, Fabiano Rosas, Laurent Vivier,
Paolo Bonzini
From: Nicholas Piggin <npiggin@gmail.com>
This function is duplicated 3 times, with more potential future users.
Factor it into libqos, using qtest_memset instead of qtest_writel to
clear the message just because that looks nicer with the qtest_memread
used to read it.
Make msix_entry to uint16_t to match other MSI-X helpers and validate it
against qpci_msix_table_size() to correctly catch uninitialized or
out of bounds vectors instead of checking != -1.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Jishnu Warrier <jishnuvw@linux.ibm.com>
Signed-off-by: Utkarsh Verma <uverma@linux.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20261102035306.2291147-4-uverma@linux.ibm.com>
---
tests/qtest/libqos/pci.h | 2 +
tests/qtest/libqos/pci.c | 53 ++++++++++++++++++++++++++
tests/qtest/libqos/virtio-pci-modern.c | 31 +++------------
tests/qtest/libqos/virtio-pci.c | 42 ++++----------------
4 files changed, 67 insertions(+), 61 deletions(-)
diff --git a/tests/qtest/libqos/pci.h b/tests/qtest/libqos/pci.h
index 8389614523..d51bf240ee 100644
--- a/tests/qtest/libqos/pci.h
+++ b/tests/qtest/libqos/pci.h
@@ -92,6 +92,8 @@ void qpci_msix_enable(QPCIDevice *dev);
void qpci_msix_disable(QPCIDevice *dev);
bool qpci_msix_pending(QPCIDevice *dev, uint16_t entry);
bool qpci_msix_masked(QPCIDevice *dev, uint16_t entry);
+bool qpci_msix_test_interrupt(QPCIDevice *dev, uint16_t msix_entry,
+ uint64_t msix_addr, uint32_t msix_data);
uint16_t qpci_msix_table_size(QPCIDevice *dev);
uint8_t qpci_config_readb(QPCIDevice *dev, uint8_t offset);
diff --git a/tests/qtest/libqos/pci.c b/tests/qtest/libqos/pci.c
index a59197b992..f6db133f6a 100644
--- a/tests/qtest/libqos/pci.c
+++ b/tests/qtest/libqos/pci.c
@@ -351,6 +351,59 @@ bool qpci_msix_masked(QPCIDevice *dev, uint16_t entry)
}
}
+/**
+ * qpci_msix_test_interrupt - test whether MSI-X interrupt has been raised
+ * @dev: PCI device
+ * @msix_entry: MSI-X entry to test
+ * @msix_addr: address of MSI-X message
+ * @msix_data: expected MSI-X message payload
+ *
+ * This tests whether the device has raised an MSI-X interrupt. If the MSI-X
+ * entry is masked, it tests the pending bit array for a pending message
+ * and @msix_addr and @msix_data need not be supplied. If the entry is not
+ * masked, it tests the address for corresponding data to see if the interrupt
+ * fired.
+ *
+ * Note that this does not lower the interrupt, however it does clear the
+ * MSI-X message address to 0 if it is found set. This must be called with
+ * the MSI-X address memory containing either 0 or the value of data, otherwise
+ * it will assert on incorrect message.
+ */
+bool qpci_msix_test_interrupt(QPCIDevice *dev, uint16_t msix_entry,
+ uint64_t msix_addr, uint32_t msix_data)
+{
+ uint32_t data;
+
+ g_assert(dev->msix_enabled);
+ g_assert_cmpint(msix_entry, <, qpci_msix_table_size(dev));
+
+ if (qpci_msix_masked(dev, msix_entry)) {
+ /* No ISR checking should be done if masked, but read anyway */
+ return qpci_msix_pending(dev, msix_entry);
+ }
+
+ /*
+ * 0 is used as the "not fired" sentinel — callers must program a
+ * non-zero MSI-X data value so the pre-zeroed target memory can be
+ * polled reliably.
+ */
+ g_assert_cmpint(msix_addr, !=, 0);
+ g_assert_cmpint(msix_data, !=, 0);
+
+ /* MSI-X payload is written in little-endian format */
+ qtest_memread(dev->bus->qts, msix_addr, &data, sizeof(data));
+ data = le32_to_cpu(data);
+ if (data == 0) {
+ return false;
+ }
+
+ /* got a message, ensure it matches expected value then clear it. */
+ g_assert_cmphex(data, ==, msix_data);
+ qtest_memset(dev->bus->qts, msix_addr, 0, sizeof(data));
+
+ return true;
+}
+
uint16_t qpci_msix_table_size(QPCIDevice *dev)
{
uint8_t addr;
diff --git a/tests/qtest/libqos/virtio-pci-modern.c b/tests/qtest/libqos/virtio-pci-modern.c
index 097b548f95..0d7d89bbcb 100644
--- a/tests/qtest/libqos/virtio-pci-modern.c
+++ b/tests/qtest/libqos/virtio-pci-modern.c
@@ -126,28 +126,6 @@ static void set_status(QVirtioDevice *d, uint8_t status)
status);
}
-static bool get_msix_status(QVirtioPCIDevice *dev, uint32_t msix_entry,
- uint32_t msix_addr, uint32_t msix_data)
-{
- uint32_t data;
-
- g_assert_cmpint(msix_entry, !=, -1);
- if (qpci_msix_masked(dev->pdev, msix_entry)) {
- /* No ISR checking should be done if masked, but read anyway */
- return qpci_msix_pending(dev->pdev, msix_entry);
- }
-
- qtest_memread(dev->pdev->bus->qts, msix_addr, &data, sizeof(data));
- data = le32_to_cpu(data);
- if (data == 0) {
- return false;
- }
- /* got a message, ensure it matches expected value then clear it. */
- g_assert_cmphex(data, ==, msix_data);
- qtest_writel(dev->pdev->bus->qts, msix_addr, 0);
- return true;
-}
-
static bool get_queue_isr_status(QVirtioDevice *d, QVirtQueue *vq)
{
QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev);
@@ -155,8 +133,8 @@ static bool get_queue_isr_status(QVirtioDevice *d, QVirtQueue *vq)
if (dev->pdev->msix_enabled) {
QVirtQueuePCI *vqpci = container_of(vq, QVirtQueuePCI, vq);
- return get_msix_status(dev, vqpci->msix_entry, vqpci->msix_addr,
- vqpci->msix_data);
+ return qpci_msix_test_interrupt(dev->pdev, vqpci->msix_entry,
+ vqpci->msix_addr, vqpci->msix_data);
}
return qpci_io_readb(dev->pdev, dev->bar, dev->isr_cfg_offset) & 1;
@@ -167,8 +145,9 @@ static bool get_config_isr_status(QVirtioDevice *d)
QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev);
if (dev->pdev->msix_enabled) {
- return get_msix_status(dev, dev->config_msix_entry,
- dev->config_msix_addr, dev->config_msix_data);
+ return qpci_msix_test_interrupt(dev->pdev, dev->config_msix_entry,
+ dev->config_msix_addr,
+ dev->config_msix_data);
}
return qpci_io_readb(dev->pdev, dev->bar, dev->isr_cfg_offset) & 2;
diff --git a/tests/qtest/libqos/virtio-pci.c b/tests/qtest/libqos/virtio-pci.c
index d2b978d4b1..ea8114e243 100644
--- a/tests/qtest/libqos/virtio-pci.c
+++ b/tests/qtest/libqos/virtio-pci.c
@@ -122,26 +122,12 @@ static void qvirtio_pci_set_status(QVirtioDevice *d, uint8_t status)
static bool qvirtio_pci_get_queue_isr_status(QVirtioDevice *d, QVirtQueue *vq)
{
QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev);
- QVirtQueuePCI *vqpci = (QVirtQueuePCI *)vq;
- uint32_t data;
if (dev->pdev->msix_enabled) {
- g_assert_cmpint(vqpci->msix_entry, !=, -1);
- if (qpci_msix_masked(dev->pdev, vqpci->msix_entry)) {
- /* No ISR checking should be done if masked, but read anyway */
- return qpci_msix_pending(dev->pdev, vqpci->msix_entry);
- } else {
- qtest_memread(dev->pdev->bus->qts, vqpci->msix_addr,
- &data, sizeof(data));
- data = le32_to_cpu(data);
- if (data == 0) {
- return false;
- }
- /* got a message, ensure it matches expected value then clear it. */
- g_assert_cmphex(data, ==, vqpci->msix_data);
- qtest_writel(dev->pdev->bus->qts, vqpci->msix_addr, 0);
- return true;
- }
+ QVirtQueuePCI *vqpci = (QVirtQueuePCI *)vq;
+
+ return qpci_msix_test_interrupt(dev->pdev, vqpci->msix_entry,
+ vqpci->msix_addr, vqpci->msix_data);
} else {
return qpci_io_readb(dev->pdev, dev->bar, VIRTIO_PCI_ISR) & 1;
}
@@ -150,25 +136,11 @@ static bool qvirtio_pci_get_queue_isr_status(QVirtioDevice *d, QVirtQueue *vq)
static bool qvirtio_pci_get_config_isr_status(QVirtioDevice *d)
{
QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev);
- uint32_t data;
if (dev->pdev->msix_enabled) {
- g_assert_cmpint(dev->config_msix_entry, !=, -1);
- if (qpci_msix_masked(dev->pdev, dev->config_msix_entry)) {
- /* No ISR checking should be done if masked, but read anyway */
- return qpci_msix_pending(dev->pdev, dev->config_msix_entry);
- } else {
- qtest_memread(dev->pdev->bus->qts, dev->config_msix_addr,
- &data, sizeof(data));
- data = le32_to_cpu(data);
- if (data == 0) {
- return false;
- }
- /* got a message, ensure it matches expected value then clear it. */
- g_assert_cmphex(data, ==, dev->config_msix_data);
- qtest_writel(dev->pdev->bus->qts, dev->config_msix_addr, 0);
- return true;
- }
+ return qpci_msix_test_interrupt(dev->pdev, dev->config_msix_entry,
+ dev->config_msix_addr,
+ dev->config_msix_data);
} else {
return qpci_io_readb(dev->pdev, dev->bar, VIRTIO_PCI_ISR) & 2;
}
--
MST
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PULL 11/17] tests/qtest/nvme-test: fix NVMe struct field endianness
2026-11-03 11:50 [PULL 00/17] pci: fixes Michael S. Tsirkin
` (9 preceding siblings ...)
2026-11-03 11:50 ` [PULL 10/17] tests/qtest: Add libqos function for testing MSI-X interrupt status Michael S. Tsirkin
@ 2026-11-03 11:50 ` Michael S. Tsirkin
2026-11-03 11:50 ` [PULL 12/17] tests/qtest: Enable spapr dma with linear iommu Michael S. Tsirkin
` (6 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2026-11-03 11:50 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Utkarsh Verma, Keith Busch, Klaus Jensen,
Jesper Devantier, Fabiano Rosas, Laurent Vivier, Paolo Bonzini,
qemu-block
From: Utkarsh Verma <uverma@linux.ibm.com>
NVMe queue structures in guest memory are written and read in little
endian byte order, so they must not be byte swapped depending on target
endianness. Instead, read using qtest_memread/memwrite with explicit
le*-to-cpu / cpu-to-le* conversions.
Also, fix the qtest_writel call with qtest_writeb for NvmeIdentify.cns
(uint8_t) access.
Signed-off-by: Utkarsh Verma <uverma@linux.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20261102035306.2291147-5-uverma@linux.ibm.com>
---
tests/qtest/nvme-test.c | 31 ++++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)
diff --git a/tests/qtest/nvme-test.c b/tests/qtest/nvme-test.c
index f9395cc252..edf982a111 100644
--- a/tests/qtest/nvme-test.c
+++ b/tests/qtest/nvme-test.c
@@ -223,10 +223,12 @@ static void nvme_init_cq(nvme_ctrl *ctrl, nvme_cq *cq, uint16_t db_idx,
static int nvme_cqe_pending(nvme_cq *cq)
{
- uint16_t status = qtest_readw(
- cq->common.ctrl->pdev->bus->qts,
- PHYS_ADDR_OF(NvmeCqe, cq->phys_cqe, [cq->head].status));
- return (status & 1) == cq->phase;
+ uint16_t status;
+
+ qtest_memread(cq->common.ctrl->pdev->bus->qts,
+ PHYS_ADDR_OF(NvmeCqe, cq->phys_cqe, [cq->head].status),
+ &status, sizeof(status));
+ return (le16_to_cpu(status) & 1) == cq->phase;
}
static int nvme_is_cqe_success(NvmeCqe *cqe)
@@ -253,8 +255,8 @@ static NvmeCqe nvme_handle_cqe(nvme_sq *sq)
}
cq->head = cq_next_head;
- if (cqe.sq_head != sq->head) {
- sq->head = cqe.sq_head;
+ if (le16_to_cpu(cqe.sq_head) != sq->head) {
+ sq->head = le16_to_cpu(cqe.sq_head);
g_test_message("sq %p head = %u", sq, sq->head);
}
@@ -298,15 +300,14 @@ static uint64_t nvme_get_next_sqe(nvme_sq *sq, uint8_t opcode,
qtest_memset(sq->common.ctrl->pdev->bus->qts,
phys_sqe, 0, sizeof(NvmeCmd));
- #define GUEST_MEM_WRITE(fn, phys_addr, val) \
- fn(sq->common.ctrl->pdev->bus->qts, phys_addr, (val))
+ #define GUEST_MEM_WRITE(phys_addr, val) \
+ qtest_memwrite(sq->common.ctrl->pdev->bus->qts, phys_addr, &val, sizeof(val))
- GUEST_MEM_WRITE(qtest_writeb,
- PHYS_ADDR_OF_FIELD(NvmeCmd, phys_sqe, opcode), opcode);
- GUEST_MEM_WRITE(qtest_writew,
- PHYS_ADDR_OF_FIELD(NvmeCmd, phys_sqe, cid), cid);
- GUEST_MEM_WRITE(qtest_writeq,
- PHYS_ADDR_OF_FIELD(NvmeCmd, phys_sqe, dptr.prp1), prp1);
+ GUEST_MEM_WRITE(PHYS_ADDR_OF_FIELD(NvmeCmd, phys_sqe, opcode), opcode);
+ cid = cpu_to_le16(cid);
+ GUEST_MEM_WRITE(PHYS_ADDR_OF_FIELD(NvmeCmd, phys_sqe, cid), cid);
+ prp1 = cpu_to_le64(prp1);
+ GUEST_MEM_WRITE(PHYS_ADDR_OF_FIELD(NvmeCmd, phys_sqe, dptr.prp1), prp1);
#undef GUEST_MEM_WRITE
@@ -344,7 +345,7 @@ static uint64_t nvme_admin_identify_ctrl(nvme_ctrl *ctrl,
GUEST_MEM_WRITE(qtest_writel,
PHYS_ADDR_OF_FIELD(NvmeCmd, phys_cmd_identify, nsid), 0);
- GUEST_MEM_WRITE(qtest_writel,
+ GUEST_MEM_WRITE(qtest_writeb,
PHYS_ADDR_OF_FIELD(NvmeIdentify, phys_cmd_identify, cns),
NVME_ID_CNS_CTRL);
--
MST
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PULL 12/17] tests/qtest: Enable spapr dma with linear iommu
2026-11-03 11:50 [PULL 00/17] pci: fixes Michael S. Tsirkin
` (10 preceding siblings ...)
2026-11-03 11:50 ` [PULL 11/17] tests/qtest/nvme-test: fix NVMe struct field endianness Michael S. Tsirkin
@ 2026-11-03 11:50 ` Michael S. Tsirkin
2026-11-03 11:51 ` [PULL 13/17] tests/qtest/ahci: unmap pci bar before reusing device Michael S. Tsirkin
` (5 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2026-11-03 11:50 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Nicholas Piggin, Fabiano Rosas, Jishnu Warrier,
Utkarsh Verma, Harsh Prateek Bora, Amit Machhiwal,
Dmitry Fleytman, Akihiko Odaki, Laurent Vivier, Paolo Bonzini,
Sriram Yagnaraman, Keith Busch, Klaus Jensen, Jesper Devantier,
Stefan Hajnoczi, qemu-ppc, qemu-block
From: Nicholas Piggin <npiggin@gmail.com>
qtests spapr dma was broken because the iommu was not set up.
spapr requires hypercalls to set up the iommu (TCE tables), but
there is no support for that or a side-channel to the iommu in
qtests at the moment, so add a quick workaround in QEMU to have
the spapr iommu provide a linear map to memory when running
qtests.
The buggy msix checks can all be removed since the tests all work
now.
Reviewed-by: Fabiano Rosas <farosas@suse.de>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Jishnu Warrier <jishnuvw@linux.ibm.com>
Signed-off-by: Utkarsh Verma <uverma@linux.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20261102035306.2291147-6-uverma@linux.ibm.com>
---
tests/qtest/libqos/pci.h | 4 ----
hw/ppc/spapr_iommu.c | 10 +++++++++-
tests/qtest/e1000e-test.c | 21 ---------------------
tests/qtest/igb-test.c | 21 ---------------------
tests/qtest/libqos/generic-pcihost.c | 1 -
tests/qtest/libqos/pci-pc.c | 3 ---
tests/qtest/libqos/pci-spapr.c | 7 ++++---
tests/qtest/libqos/pci.c | 14 --------------
tests/qtest/nvme-test.c | 4 ----
tests/qtest/vhost-user-blk-test.c | 6 ------
tests/qtest/virtio-blk-test.c | 12 ------------
11 files changed, 13 insertions(+), 90 deletions(-)
diff --git a/tests/qtest/libqos/pci.h b/tests/qtest/libqos/pci.h
index d51bf240ee..c3a0f85fef 100644
--- a/tests/qtest/libqos/pci.h
+++ b/tests/qtest/libqos/pci.h
@@ -51,7 +51,6 @@ struct QPCIBus {
QTestState *qts;
uint64_t pio_alloc_ptr, pio_limit;
uint64_t mmio_alloc_ptr, mmio_limit;
- bool has_buggy_msi; /* TRUE for spapr, FALSE for pci */
bool not_hotpluggable; /* TRUE if devices cannot be hotplugged */
};
@@ -83,9 +82,6 @@ QPCIDevice *qpci_device_find(QPCIBus *bus, int devfn);
void qpci_device_init(QPCIDevice *dev, QPCIBus *bus, QPCIAddress *addr);
int qpci_secondary_buses_init(QPCIBus *bus);
-bool qpci_has_buggy_msi(QPCIDevice *dev);
-bool qpci_check_buggy_msi(QPCIDevice *dev);
-
void qpci_device_enable(QPCIDevice *dev);
uint8_t qpci_find_capability(QPCIDevice *dev, uint8_t id, uint8_t start_addr);
void qpci_msix_enable(QPCIDevice *dev);
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index e6264b0785..5470602ef1 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -22,6 +22,8 @@
#include "qemu/log.h"
#include "qemu/module.h"
#include "system/kvm.h"
+#include "system/qtest.h"
+#include "exec/target_page.h"
#include "kvm_ppc.h"
#include "migration/vmstate.h"
#include "system/dma.h"
@@ -125,7 +127,13 @@ static IOMMUTLBEntry spapr_tce_translate_iommu(IOMMUMemoryRegion *iommu,
.perm = IOMMU_NONE,
};
- if ((addr >> tcet->page_shift) < tcet->nb_table) {
+ if (qtest_enabled()) {
+ /* spapr qtests does not set up the IOMMU, shortcut a linear map */
+ ret.iova = addr & TARGET_PAGE_MASK;
+ ret.translated_addr = addr & TARGET_PAGE_MASK;
+ ret.addr_mask = ~TARGET_PAGE_MASK;
+ ret.perm = IOMMU_RW;
+ } else if ((addr >> tcet->page_shift) < tcet->nb_table) {
/* Check if we are in bound */
hwaddr page_mask = IOMMU_PAGE_MASK(tcet->page_shift);
diff --git a/tests/qtest/e1000e-test.c b/tests/qtest/e1000e-test.c
index de9738fdb7..8300bf5a5b 100644
--- a/tests/qtest/e1000e-test.c
+++ b/tests/qtest/e1000e-test.c
@@ -139,13 +139,6 @@ static void test_e1000e_tx(void *obj, void *data, QGuestAllocator * alloc)
{
QE1000E_PCI *e1000e = obj;
QE1000E *d = &e1000e->e1000e;
- QOSGraphObject *e_object = obj;
- QPCIDevice *dev = e_object->get_driver(e_object, "pci-device");
-
- /* FIXME: add spapr support */
- if (qpci_check_buggy_msi(dev)) {
- return;
- }
e1000e_send_verify(d, data, alloc);
}
@@ -154,13 +147,6 @@ static void test_e1000e_rx(void *obj, void *data, QGuestAllocator * alloc)
{
QE1000E_PCI *e1000e = obj;
QE1000E *d = &e1000e->e1000e;
- QOSGraphObject *e_object = obj;
- QPCIDevice *dev = e_object->get_driver(e_object, "pci-device");
-
- /* FIXME: add spapr support */
- if (qpci_check_buggy_msi(dev)) {
- return;
- }
e1000e_receive_verify(d, data, alloc);
}
@@ -173,13 +159,6 @@ static void test_e1000e_multiple_transfers(void *obj, void *data,
QE1000E_PCI *e1000e = obj;
QE1000E *d = &e1000e->e1000e;
- QOSGraphObject *e_object = obj;
- QPCIDevice *dev = e_object->get_driver(e_object, "pci-device");
-
- /* FIXME: add spapr support */
- if (qpci_check_buggy_msi(dev)) {
- return;
- }
for (i = 0; i < iterations; i++) {
e1000e_send_verify(d, data, alloc);
diff --git a/tests/qtest/igb-test.c b/tests/qtest/igb-test.c
index 3d397ea697..1b3b5aa6c7 100644
--- a/tests/qtest/igb-test.c
+++ b/tests/qtest/igb-test.c
@@ -142,13 +142,6 @@ static void test_igb_tx(void *obj, void *data, QGuestAllocator * alloc)
{
QE1000E_PCI *e1000e = obj;
QE1000E *d = &e1000e->e1000e;
- QOSGraphObject *e_object = obj;
- QPCIDevice *dev = e_object->get_driver(e_object, "pci-device");
-
- /* FIXME: add spapr support */
- if (qpci_check_buggy_msi(dev)) {
- return;
- }
igb_send_verify(d, data, alloc);
}
@@ -157,13 +150,6 @@ static void test_igb_rx(void *obj, void *data, QGuestAllocator * alloc)
{
QE1000E_PCI *e1000e = obj;
QE1000E *d = &e1000e->e1000e;
- QOSGraphObject *e_object = obj;
- QPCIDevice *dev = e_object->get_driver(e_object, "pci-device");
-
- /* FIXME: add spapr support */
- if (qpci_check_buggy_msi(dev)) {
- return;
- }
igb_receive_verify(d, data, alloc);
}
@@ -176,13 +162,6 @@ static void test_igb_multiple_transfers(void *obj, void *data,
QE1000E_PCI *e1000e = obj;
QE1000E *d = &e1000e->e1000e;
- QOSGraphObject *e_object = obj;
- QPCIDevice *dev = e_object->get_driver(e_object, "pci-device");
-
- /* FIXME: add spapr support */
- if (qpci_check_buggy_msi(dev)) {
- return;
- }
for (i = 0; i < iterations; i++) {
igb_send_verify(d, data, alloc);
diff --git a/tests/qtest/libqos/generic-pcihost.c b/tests/qtest/libqos/generic-pcihost.c
index b77617524c..93cc3b8561 100644
--- a/tests/qtest/libqos/generic-pcihost.c
+++ b/tests/qtest/libqos/generic-pcihost.c
@@ -182,7 +182,6 @@ void qpci_init_generic(QGenericPCIBus *qpci, QTestState *qts,
qpci->gpex_pio_base = 0x3eff0000;
qpci->bus.not_hotpluggable = !hotpluggable;
- qpci->bus.has_buggy_msi = false;
qpci->bus.pio_readb = qpci_generic_pio_readb;
qpci->bus.pio_readw = qpci_generic_pio_readw;
diff --git a/tests/qtest/libqos/pci-pc.c b/tests/qtest/libqos/pci-pc.c
index 147009f4f4..8b79d858bd 100644
--- a/tests/qtest/libqos/pci-pc.c
+++ b/tests/qtest/libqos/pci-pc.c
@@ -124,9 +124,6 @@ void qpci_init_pc(QPCIBusPC *qpci, QTestState *qts, QGuestAllocator *alloc)
{
assert(qts);
- /* tests can use pci-bus */
- qpci->bus.has_buggy_msi = false;
-
qpci->bus.pio_readb = qpci_pc_pio_readb;
qpci->bus.pio_readw = qpci_pc_pio_readw;
qpci->bus.pio_readl = qpci_pc_pio_readl;
diff --git a/tests/qtest/libqos/pci-spapr.c b/tests/qtest/libqos/pci-spapr.c
index 3723cbb38d..b58cc1b59f 100644
--- a/tests/qtest/libqos/pci-spapr.c
+++ b/tests/qtest/libqos/pci-spapr.c
@@ -20,6 +20,10 @@
* PCI devices are always little-endian
* SPAPR by default is big-endian
* so PCI accessors need to swap data endianness
+ *
+ * The spapr iommu model has a qtest_enabled() check that short-cuts
+ * the TCE table and provides a linear map for DMA, since qtests does
+ * not have a way to make hcalls to set up the TCE table.
*/
static uint8_t qpci_spapr_pio_readb(QPCIBus *bus, uint32_t addr)
@@ -155,9 +159,6 @@ void qpci_init_spapr(QPCIBusSPAPR *qpci, QTestState *qts,
{
assert(qts);
- /* tests cannot use spapr, needs to be fixed first */
- qpci->bus.has_buggy_msi = true;
-
qpci->alloc = alloc;
qpci->bus.pio_readb = qpci_spapr_pio_readb;
diff --git a/tests/qtest/libqos/pci.c b/tests/qtest/libqos/pci.c
index f6db133f6a..e9233c81e9 100644
--- a/tests/qtest/libqos/pci.c
+++ b/tests/qtest/libqos/pci.c
@@ -53,20 +53,6 @@ void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id,
}
}
-bool qpci_has_buggy_msi(QPCIDevice *dev)
-{
- return dev->bus->has_buggy_msi;
-}
-
-bool qpci_check_buggy_msi(QPCIDevice *dev)
-{
- if (qpci_has_buggy_msi(dev)) {
- g_test_skip("Skipping due to incomplete support for MSI");
- return true;
- }
- return false;
-}
-
static void qpci_device_set(QPCIDevice *dev, QPCIBus *bus, int devfn)
{
g_assert(dev);
diff --git a/tests/qtest/nvme-test.c b/tests/qtest/nvme-test.c
index edf982a111..09972b50ff 100644
--- a/tests/qtest/nvme-test.c
+++ b/tests/qtest/nvme-test.c
@@ -493,10 +493,6 @@ static void test_migrate(void *obj, void *data, QGuestAllocator *alloc)
{ 333, false }
};
- if (qpci_check_buggy_msi(pdev)) {
- return;
- }
-
/* create temporary dir and prepare unix socket path for migration */
tmpfs = g_dir_make_tmp("nvme-test-XXXXXX", &err);
if (!tmpfs) {
diff --git a/tests/qtest/vhost-user-blk-test.c b/tests/qtest/vhost-user-blk-test.c
index ea90d41232..3e71fdb9d7 100644
--- a/tests/qtest/vhost-user-blk-test.c
+++ b/tests/qtest/vhost-user-blk-test.c
@@ -554,14 +554,8 @@ static void idx(void *obj, void *u_data, QGuestAllocator *t_alloc)
uint32_t desc_idx;
uint8_t status;
char *data;
- QOSGraphObject *blk_object = obj;
- QPCIDevice *pci_dev = blk_object->get_driver(blk_object, "pci-device");
QTestState *qts = global_qtest;
- if (qpci_check_buggy_msi(pci_dev)) {
- return;
- }
-
qpci_msix_enable(pdev->pdev);
qvirtio_pci_set_msix_configuration_vector(pdev, t_alloc, 0);
diff --git a/tests/qtest/virtio-blk-test.c b/tests/qtest/virtio-blk-test.c
index 722bd0711f..a7e864ee81 100644
--- a/tests/qtest/virtio-blk-test.c
+++ b/tests/qtest/virtio-blk-test.c
@@ -476,14 +476,8 @@ static void msix(void *obj, void *u_data, QGuestAllocator *t_alloc)
uint32_t free_head;
uint8_t status;
char *data;
- QOSGraphObject *blk_object = obj;
- QPCIDevice *pci_dev = blk_object->get_driver(blk_object, "pci-device");
QTestState *qts = global_qtest;
- if (qpci_check_buggy_msi(pci_dev)) {
- return;
- }
-
qpci_msix_enable(pdev->pdev);
qvirtio_pci_set_msix_configuration_vector(pdev, t_alloc, 0);
@@ -586,14 +580,8 @@ static void idx(void *obj, void *u_data, QGuestAllocator *t_alloc)
uint32_t desc_idx;
uint8_t status;
char *data;
- QOSGraphObject *blk_object = obj;
- QPCIDevice *pci_dev = blk_object->get_driver(blk_object, "pci-device");
QTestState *qts = global_qtest;
- if (qpci_check_buggy_msi(pci_dev)) {
- return;
- }
-
qpci_msix_enable(pdev->pdev);
qvirtio_pci_set_msix_configuration_vector(pdev, t_alloc, 0);
--
MST
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PULL 13/17] tests/qtest/ahci: unmap pci bar before reusing device
2026-11-03 11:50 [PULL 00/17] pci: fixes Michael S. Tsirkin
` (11 preceding siblings ...)
2026-11-03 11:50 ` [PULL 12/17] tests/qtest: Enable spapr dma with linear iommu Michael S. Tsirkin
@ 2026-11-03 11:51 ` Michael S. Tsirkin
2026-11-03 11:51 ` [PULL 14/17] tests/qtest/libquos/pci: Add migration fixup helper for pci devices Michael S. Tsirkin
` (4 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2026-11-03 11:51 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Nicholas Piggin, Marcel Apfelbaum, Akihiko Odaki,
Fabiano Rosas, Jishnu Warrier, Utkarsh Verma, John Snow,
Denis V. Lunev, Laurent Vivier, Paolo Bonzini, qemu-block
From: Nicholas Piggin <npiggin@gmail.com>
ahci-test double-maps the hba bar in the pending_callback test.
Unmap it first, to keep iomaps balanced.
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
Cc: Akihiko Odaki <akihiko.odaki@daynix.com>
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Reviewed-by: Fabiano Rosas <farosas@suse.de>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Jishnu Warrier <jishnuvw@linux.ibm.com>
Signed-off-by: Utkarsh Verma <uverma@linux.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20261102035306.2291147-7-uverma@linux.ibm.com>
---
tests/qtest/libqos/ahci.h | 2 ++
tests/qtest/ahci-test.c | 6 ++++++
tests/qtest/libqos/ahci.c | 11 +++++++++++
3 files changed, 19 insertions(+)
diff --git a/tests/qtest/libqos/ahci.h b/tests/qtest/libqos/ahci.h
index 6d861c79ee..f098c91b47 100644
--- a/tests/qtest/libqos/ahci.h
+++ b/tests/qtest/libqos/ahci.h
@@ -580,7 +580,9 @@ void ahci_clean_mem(AHCIQState *ahci);
QPCIDevice *get_ahci_device(QTestState *qts, uint32_t *fingerprint);
void free_ahci_device(QPCIDevice *dev);
void ahci_pci_enable(AHCIQState *ahci);
+void ahci_pci_disable(AHCIQState *ahci);
void start_ahci_device(AHCIQState *ahci);
+void stop_ahci_device(AHCIQState *ahci);
void ahci_hba_enable(AHCIQState *ahci);
/* Port Management */
diff --git a/tests/qtest/ahci-test.c b/tests/qtest/ahci-test.c
index c49aa61862..043a916fdd 100644
--- a/tests/qtest/ahci-test.c
+++ b/tests/qtest/ahci-test.c
@@ -85,6 +85,8 @@ static void verify_state(AHCIQState *ahci, uint64_t hba_old)
uint64_t hba_base;
AHCICommandHeader cmd;
+ g_assert_cmphex(ahci->hba_bar.addr, ==, hba_old);
+
ahci_fingerprint = qpci_config_readl(ahci->dev, PCI_VENDOR_ID);
g_assert_cmphex(ahci_fingerprint, ==, ahci->fingerprint);
@@ -198,6 +200,7 @@ static void ahci_shutdown(AHCIQState *ahci)
{
QOSState *qs = ahci->parent;
+ ahci_pci_disable(ahci);
ahci_clean_mem(ahci);
free_ahci_device(ahci->dev);
g_free(ahci);
@@ -1457,7 +1460,9 @@ static void test_reset(void)
CMD_READ_DMA_EXT,
CMD_WRITE_DMA_EXT);
ahci_set(ahci, AHCI_GHC, AHCI_GHC_HR);
+ stop_ahci_device(ahci);
ahci_clean_mem(ahci);
+ start_ahci_device(ahci);
}
ahci_shutdown(ahci);
@@ -1523,6 +1528,7 @@ static void test_reset_pending_callback(void)
sleep(1);
/* Start again. */
+ stop_ahci_device(ahci);
ahci_clean_mem(ahci);
ahci_pci_enable(ahci);
ahci_hba_enable(ahci);
diff --git a/tests/qtest/libqos/ahci.c b/tests/qtest/libqos/ahci.c
index 50b63239c2..a709558aac 100644
--- a/tests/qtest/libqos/ahci.c
+++ b/tests/qtest/libqos/ahci.c
@@ -206,6 +206,11 @@ void ahci_pci_enable(AHCIQState *ahci)
}
+void ahci_pci_disable(AHCIQState *ahci)
+{
+ stop_ahci_device(ahci);
+}
+
/**
* Map BAR5/ABAR, and engage the PCI device.
*/
@@ -218,6 +223,12 @@ void start_ahci_device(AHCIQState *ahci)
qpci_device_enable(ahci->dev);
}
+void stop_ahci_device(AHCIQState *ahci)
+{
+ /* Unmap AHCI's ABAR */
+ qpci_iounmap(ahci->dev, ahci->hba_bar);
+}
+
/**
* Test and initialize the AHCI's HBA memory areas.
* Initialize and start any ports with devices attached.
--
MST
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PULL 14/17] tests/qtest/libquos/pci: Add migration fixup helper for pci devices
2026-11-03 11:50 [PULL 00/17] pci: fixes Michael S. Tsirkin
` (12 preceding siblings ...)
2026-11-03 11:51 ` [PULL 13/17] tests/qtest/ahci: unmap pci bar before reusing device Michael S. Tsirkin
@ 2026-11-03 11:51 ` Michael S. Tsirkin
2026-11-03 11:51 ` [PULL 15/17] qtest/libqos/pci: Enforce balanced iomap/unmap Michael S. Tsirkin
` (3 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2026-11-03 11:51 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Nicholas Piggin, Akihiko Odaki, Jishnu Warrier,
Utkarsh Verma, John Snow, Denis V. Lunev, Fabiano Rosas,
Laurent Vivier, Paolo Bonzini, Keith Busch, Klaus Jensen,
Jesper Devantier, qemu-block
From: Nicholas Piggin <npiggin@gmail.com>
Migration tests can create new QPCI devices for the destination
machine which may need to take on some state of the source machine
after destination is complete.
Add a migration fixup helper and call it from ahci and nvme migration
tests.
This is currently a noop and will be used subsequently.
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Jishnu Warrier <jishnuvw@linux.ibm.com>
Signed-off-by: Utkarsh Verma <uverma@linux.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20261102035306.2291147-8-uverma@linux.ibm.com>
---
tests/qtest/libqos/pci.h | 1 +
tests/qtest/ahci-test.c | 1 +
tests/qtest/libqos/pci.c | 4 ++++
tests/qtest/nvme-test.c | 4 +---
4 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/tests/qtest/libqos/pci.h b/tests/qtest/libqos/pci.h
index c3a0f85fef..cfb7c17dd3 100644
--- a/tests/qtest/libqos/pci.h
+++ b/tests/qtest/libqos/pci.h
@@ -120,6 +120,7 @@ void qpci_memwrite(QPCIDevice *bus, QPCIBar token, uint64_t off,
const void *buf, size_t len);
QPCIBar qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr);
void qpci_iounmap(QPCIDevice *dev, QPCIBar addr);
+void qpci_migrate_fixup(QPCIDevice *to, QPCIDevice *from);
QPCIBar qpci_legacy_iomap(QPCIDevice *dev, uint16_t addr);
void qpci_unplug_acpi_device_test(QTestState *qs, const char *id, uint8_t slot);
diff --git a/tests/qtest/ahci-test.c b/tests/qtest/ahci-test.c
index 043a916fdd..291f29e762 100644
--- a/tests/qtest/ahci-test.c
+++ b/tests/qtest/ahci-test.c
@@ -137,6 +137,7 @@ static void ahci_migrate(AHCIQState *from, AHCIQState *to, const char *uri)
memcpy(to, from, sizeof(AHCIQState));
to->parent = tmp;
to->dev = dev;
+ qpci_migrate_fixup(to->dev, from->dev);
tmp = from->parent;
dev = from->dev;
diff --git a/tests/qtest/libqos/pci.c b/tests/qtest/libqos/pci.c
index e9233c81e9..e78dd4d4c7 100644
--- a/tests/qtest/libqos/pci.c
+++ b/tests/qtest/libqos/pci.c
@@ -625,6 +625,10 @@ QPCIBar qpci_legacy_iomap(QPCIDevice *dev, uint16_t addr)
return bar;
}
+void qpci_migrate_fixup(QPCIDevice *to, QPCIDevice *from)
+{
+}
+
void add_qpci_address(QOSGraphEdgeOptions *opts, QPCIAddress *addr)
{
g_assert(addr);
diff --git a/tests/qtest/nvme-test.c b/tests/qtest/nvme-test.c
index 09972b50ff..dfa59cfbce 100644
--- a/tests/qtest/nvme-test.c
+++ b/tests/qtest/nvme-test.c
@@ -517,8 +517,6 @@ static void test_migrate(void *obj, void *data, QGuestAllocator *alloc)
test_migrate_setup_nvme_ctrl(ctrl);
test_migrate_send_nvme_reqs(ctrl, test_reqs, ARRAY_SIZE(test_reqs));
- qpci_iounmap(ctrl->pdev, ctrl->bar);
-
dest_cmdline = g_string_new(qos_get_current_command_line());
g_string_append_printf(dest_cmdline, " -incoming %s", uri);
@@ -528,8 +526,8 @@ static void test_migrate(void *obj, void *data, QGuestAllocator *alloc)
/* Get access to PCI device from destination VM */
nvme = qos_allocate_objects(to, &ctrl->alloc);
pdev = &nvme->dev;
+ qpci_migrate_fixup(pdev, ctrl->pdev);
ctrl->pdev = pdev;
- ctrl->bar = qpci_iomap(ctrl->pdev, 0, NULL);
g_assert(pdev->bus->qts == to);
/* Migrate VM */
--
MST
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PULL 15/17] qtest/libqos/pci: Enforce balanced iomap/unmap
2026-11-03 11:50 [PULL 00/17] pci: fixes Michael S. Tsirkin
` (13 preceding siblings ...)
2026-11-03 11:51 ` [PULL 14/17] tests/qtest/libquos/pci: Add migration fixup helper for pci devices Michael S. Tsirkin
@ 2026-11-03 11:51 ` Michael S. Tsirkin
2026-11-03 11:51 ` [PULL 16/17] qtest/libqos/pci: Fix qpci_msix_enable sharing bar0 Michael S. Tsirkin
` (2 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2026-11-03 11:51 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Nicholas Piggin, Marcel Apfelbaum, Akihiko Odaki,
Fabiano Rosas, Jishnu Warrier, Utkarsh Verma, John Snow,
Denis V. Lunev, Laurent Vivier, Paolo Bonzini, qemu-block
From: Nicholas Piggin <npiggin@gmail.com>
Add assertions to ensure a BAR is not mapped twice, and that only
previously mapped BARs are unmapped. This can help catch bugs and
fragile coding.
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Reviewed-by: Fabiano Rosas <farosas@suse.de>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Jishnu Warrier <jishnuvw@linux.ibm.com>
Signed-off-by: Utkarsh Verma <uverma@linux.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20261102035306.2291147-9-uverma@linux.ibm.com>
---
tests/qtest/libqos/pci.h | 10 +++++++
tests/qtest/libqos/ahci.c | 3 ++-
tests/qtest/libqos/pci.c | 57 +++++++++++++++++++++++++++++++++++----
3 files changed, 64 insertions(+), 6 deletions(-)
diff --git a/tests/qtest/libqos/pci.h b/tests/qtest/libqos/pci.h
index cfb7c17dd3..2f9555ae4e 100644
--- a/tests/qtest/libqos/pci.h
+++ b/tests/qtest/libqos/pci.h
@@ -58,12 +58,22 @@ struct QPCIBus {
struct QPCIBar {
uint64_t addr;
bool is_io;
+ bool mapped;
};
+/*
+ * hw/pci permits 7 (PCI_NUM_REGIONS) regions, the last for PCI_ROM_SLOT.
+ * libqos does not implement PCI_ROM_SLOT at the moment, and as such it
+ * permits 6.
+ */
+#define QPCI_NUM_REGIONS 6
+
struct QPCIDevice
{
QPCIBus *bus;
int devfn;
+ bool bars_mapped[QPCI_NUM_REGIONS];
+ QPCIBar bars[QPCI_NUM_REGIONS];
bool msix_enabled;
QPCIBar msix_table_bar, msix_pba_bar;
uint64_t msix_table_off, msix_pba_off;
diff --git a/tests/qtest/libqos/ahci.c b/tests/qtest/libqos/ahci.c
index a709558aac..53a98bd6cb 100644
--- a/tests/qtest/libqos/ahci.c
+++ b/tests/qtest/libqos/ahci.c
@@ -225,7 +225,7 @@ void start_ahci_device(AHCIQState *ahci)
void stop_ahci_device(AHCIQState *ahci)
{
- /* Unmap AHCI's ABAR */
+ /* Unmap AHCI's ABAR (no-op if not mapped) */
qpci_iounmap(ahci->dev, ahci->hba_bar);
}
@@ -250,6 +250,7 @@ void ahci_hba_enable(AHCIQState *ahci)
uint8_t num_cmd_slots;
g_assert(ahci != NULL);
+ g_assert(ahci->hba_bar.mapped);
/* Set GHC.AE to 1 */
ahci_set(ahci, AHCI_GHC, AHCI_GHC_AE);
diff --git a/tests/qtest/libqos/pci.c b/tests/qtest/libqos/pci.c
index e78dd4d4c7..365fde1fb9 100644
--- a/tests/qtest/libqos/pci.c
+++ b/tests/qtest/libqos/pci.c
@@ -79,12 +79,17 @@ QPCIDevice *qpci_device_find(QPCIBus *bus, int devfn)
void qpci_device_init(QPCIDevice *dev, QPCIBus *bus, QPCIAddress *addr)
{
uint16_t vendor_id, device_id;
+ int i;
qpci_device_set(dev, bus, addr->devfn);
vendor_id = qpci_config_readw(dev, PCI_VENDOR_ID);
device_id = qpci_config_readw(dev, PCI_DEVICE_ID);
g_assert(!addr->vendor_id || vendor_id == addr->vendor_id);
g_assert(!addr->device_id || device_id == addr->device_id);
+
+ for (i = 0; i < QPCI_NUM_REGIONS; i++) {
+ g_assert(!dev->bars_mapped[i]);
+ }
}
static uint8_t qpci_find_resource_reserve_capability(QPCIDevice *dev)
@@ -554,21 +559,31 @@ void qpci_memwrite(QPCIDevice *dev, QPCIBar token, uint64_t off,
dev->bus->memwrite(dev->bus, token.addr + off, buf, len);
}
-QPCIBar qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
+static uint8_t qpci_bar_reg(int barno)
{
- QPCIBus *bus = dev->bus;
static const int bar_reg_map[] = {
PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
};
+
+ g_assert(barno >= 0 && barno < QPCI_NUM_REGIONS);
+
+ return bar_reg_map[barno];
+}
+
+QPCIBar qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
+{
+ QPCIBus *bus = dev->bus;
QPCIBar bar;
int bar_reg;
uint32_t addr, size;
uint32_t io_type;
uint64_t loc;
- g_assert(barno >= 0 && barno <= 5);
- bar_reg = bar_reg_map[barno];
+ g_assert(barno >= 0 && barno < QPCI_NUM_REGIONS);
+ g_assert(!dev->bars_mapped[barno]);
+
+ bar_reg = qpci_bar_reg(barno);
qpci_config_writel(dev, bar_reg, 0xFFFFFFFF);
addr = qpci_config_readl(dev, bar_reg);
@@ -611,12 +626,40 @@ QPCIBar qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
}
bar.addr = loc;
+ bar.mapped = true;
+
+ dev->bars_mapped[barno] = true;
+ dev->bars[barno] = bar;
+
return bar;
}
void qpci_iounmap(QPCIDevice *dev, QPCIBar bar)
{
- /* FIXME */
+ int bar_reg;
+ int i;
+
+ if (!bar.mapped) {
+ return; /* bar was never mapped; no-op */
+ }
+
+ for (i = 0; i < QPCI_NUM_REGIONS; i++) {
+ if (!dev->bars_mapped[i]) {
+ continue;
+ }
+ if (dev->bars[i].addr == bar.addr) {
+ dev->bars_mapped[i] = false;
+ dev->bars[i].mapped = false;
+ bar_reg = qpci_bar_reg(i);
+ qpci_config_writel(dev, bar_reg, 0xFFFFFFFF);
+ /* FIXME: the address space is leaked */
+ return;
+ }
+ }
+ /*
+ * bar was not iomap()ed; treat as no-op for callers that may
+ * call iounmap unconditionally during cleanup paths.
+ */
}
QPCIBar qpci_legacy_iomap(QPCIDevice *dev, uint16_t addr)
@@ -627,6 +670,10 @@ QPCIBar qpci_legacy_iomap(QPCIDevice *dev, uint16_t addr)
void qpci_migrate_fixup(QPCIDevice *to, QPCIDevice *from)
{
+ memcpy(to->bars_mapped, from->bars_mapped, sizeof(from->bars_mapped));
+ memset(from->bars_mapped, 0, sizeof(from->bars_mapped));
+ memcpy(to->bars, from->bars, sizeof(from->bars));
+ memset(from->bars, 0, sizeof(from->bars));
}
void add_qpci_address(QOSGraphEdgeOptions *opts, QPCIAddress *addr)
--
MST
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PULL 16/17] qtest/libqos/pci: Fix qpci_msix_enable sharing bar0
2026-11-03 11:50 [PULL 00/17] pci: fixes Michael S. Tsirkin
` (14 preceding siblings ...)
2026-11-03 11:51 ` [PULL 15/17] qtest/libqos/pci: Enforce balanced iomap/unmap Michael S. Tsirkin
@ 2026-11-03 11:51 ` Michael S. Tsirkin
2026-11-03 11:51 ` [PULL 17/17] qtest/libqos/pci: Factor msix entry helpers into pci common code Michael S. Tsirkin
2026-11-03 22:42 ` [PULL 00/17] pci: fixes Richard Henderson
17 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2026-11-03 11:51 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Nicholas Piggin, Marcel Apfelbaum, Akihiko Odaki,
Fabiano Rosas, Jishnu Warrier, Utkarsh Verma, Laurent Vivier,
Paolo Bonzini
From: Nicholas Piggin <npiggin@gmail.com>
Devices where the MSI-X addresses are shared with other MMIO on BAR0
can not use msi_enable because it unmaps and remaps BAR0, which
interferes with device MMIO mappings. xhci-nec is one such device we
would like to test with msix.
Use the BAR iomap tracking structure introduced in the previous change
to have qpci_misx_enable() use existing iomaps if msix bars are
already mapped.
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Reviewed-by: Fabiano Rosas <farosas@suse.de>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Jishnu Warrier <jishnuvw@linux.ibm.com>
Signed-off-by: Utkarsh Verma <uverma@linux.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20261102035306.2291147-10-uverma@linux.ibm.com>
---
tests/qtest/libqos/pci.h | 1 +
tests/qtest/libqos/pci.c | 40 ++++++++++++++++++++++++++++++++++------
2 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/tests/qtest/libqos/pci.h b/tests/qtest/libqos/pci.h
index 2f9555ae4e..2fcddd19a8 100644
--- a/tests/qtest/libqos/pci.h
+++ b/tests/qtest/libqos/pci.h
@@ -75,6 +75,7 @@ struct QPCIDevice
bool bars_mapped[QPCI_NUM_REGIONS];
QPCIBar bars[QPCI_NUM_REGIONS];
bool msix_enabled;
+ bool msix_table_bar_iomap, msix_pba_bar_iomap;
QPCIBar msix_table_bar, msix_pba_bar;
uint64_t msix_table_off, msix_pba_off;
};
diff --git a/tests/qtest/libqos/pci.c b/tests/qtest/libqos/pci.c
index 365fde1fb9..41f9673022 100644
--- a/tests/qtest/libqos/pci.c
+++ b/tests/qtest/libqos/pci.c
@@ -274,15 +274,21 @@ void qpci_msix_enable(QPCIDevice *dev)
table = qpci_config_readl(dev, addr + PCI_MSIX_TABLE);
bir_table = table & PCI_MSIX_FLAGS_BIRMASK;
- dev->msix_table_bar = qpci_iomap(dev, bir_table, NULL);
+ if (dev->bars_mapped[bir_table]) {
+ dev->msix_table_bar = dev->bars[bir_table];
+ } else {
+ dev->msix_table_bar_iomap = true;
+ dev->msix_table_bar = qpci_iomap(dev, bir_table, NULL);
+ }
dev->msix_table_off = table & ~PCI_MSIX_FLAGS_BIRMASK;
table = qpci_config_readl(dev, addr + PCI_MSIX_PBA);
bir_pba = table & PCI_MSIX_FLAGS_BIRMASK;
- if (bir_pba != bir_table) {
- dev->msix_pba_bar = qpci_iomap(dev, bir_pba, NULL);
+ if (dev->bars_mapped[bir_pba]) {
+ dev->msix_pba_bar = dev->bars[bir_pba];
} else {
- dev->msix_pba_bar = dev->msix_table_bar;
+ dev->msix_pba_bar_iomap = true;
+ dev->msix_pba_bar = qpci_iomap(dev, bir_pba, NULL);
}
dev->msix_pba_off = table & ~PCI_MSIX_FLAGS_BIRMASK;
@@ -293,6 +299,7 @@ void qpci_msix_disable(QPCIDevice *dev)
{
uint8_t addr;
uint16_t val;
+ uint32_t table;
g_assert(dev->msix_enabled);
addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX, 0);
@@ -301,10 +308,31 @@ void qpci_msix_disable(QPCIDevice *dev)
qpci_config_writew(dev, addr + PCI_MSIX_FLAGS,
val & ~PCI_MSIX_FLAGS_ENABLE);
- if (dev->msix_pba_bar.addr != dev->msix_table_bar.addr) {
+ if (dev->msix_pba_bar_iomap) {
+ dev->msix_pba_bar_iomap = false;
qpci_iounmap(dev, dev->msix_pba_bar);
+ } else {
+ /*
+ * If we had reused an existing iomap, ensure it is still mapped
+ * otherwise it would be a bug if it were unmapped before msix is
+ * disabled. A refcounting iomap implementation could avoid this
+ * issue entirely, but let's wait until that's needed.
+ */
+ uint8_t bir_pba;
+ table = qpci_config_readl(dev, addr + PCI_MSIX_PBA);
+ bir_pba = table & PCI_MSIX_FLAGS_BIRMASK;
+ g_assert(dev->bars_mapped[bir_pba]);
+ }
+
+ if (dev->msix_table_bar_iomap) {
+ dev->msix_table_bar_iomap = false;
+ qpci_iounmap(dev, dev->msix_table_bar);
+ } else {
+ uint8_t bir_table;
+ table = qpci_config_readl(dev, addr + PCI_MSIX_TABLE);
+ bir_table = table & PCI_MSIX_FLAGS_BIRMASK;
+ g_assert(dev->bars_mapped[bir_table]);
}
- qpci_iounmap(dev, dev->msix_table_bar);
dev->msix_enabled = 0;
dev->msix_table_off = 0;
--
MST
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PULL 17/17] qtest/libqos/pci: Factor msix entry helpers into pci common code
2026-11-03 11:50 [PULL 00/17] pci: fixes Michael S. Tsirkin
` (15 preceding siblings ...)
2026-11-03 11:51 ` [PULL 16/17] qtest/libqos/pci: Fix qpci_msix_enable sharing bar0 Michael S. Tsirkin
@ 2026-11-03 11:51 ` Michael S. Tsirkin
2026-11-03 22:42 ` [PULL 00/17] pci: fixes Richard Henderson
17 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2026-11-03 11:51 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Nicholas Piggin, Akihiko Odaki, Jishnu Warrier,
Utkarsh Verma, Fabiano Rosas, Laurent Vivier, Paolo Bonzini
From: Nicholas Piggin <npiggin@gmail.com>
Setting msix entry address and data and masking is moved into
common code helpers from virtio tests.
For now that remains the only user, but there are changes under
development to enable msix vectors for msix, e1000e, and xhci
tests, which can make use of them.
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Jishnu Warrier <jishnuvw@linux.ibm.com>
Signed-off-by: Utkarsh Verma <uverma@linux.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20261102035306.2291147-11-uverma@linux.ibm.com>
---
tests/qtest/libqos/pci.h | 3 ++
tests/qtest/libqos/pci.c | 49 +++++++++++++++++++++++++++++++++
tests/qtest/libqos/virtio-pci.c | 48 ++++----------------------------
3 files changed, 57 insertions(+), 43 deletions(-)
diff --git a/tests/qtest/libqos/pci.h b/tests/qtest/libqos/pci.h
index 2fcddd19a8..986cc53c3a 100644
--- a/tests/qtest/libqos/pci.h
+++ b/tests/qtest/libqos/pci.h
@@ -97,8 +97,11 @@ void qpci_device_enable(QPCIDevice *dev);
uint8_t qpci_find_capability(QPCIDevice *dev, uint8_t id, uint8_t start_addr);
void qpci_msix_enable(QPCIDevice *dev);
void qpci_msix_disable(QPCIDevice *dev);
+void qpci_msix_set_entry(QPCIDevice *dev, uint16_t entry,
+ uint64_t guest_addr, uint32_t data);
bool qpci_msix_pending(QPCIDevice *dev, uint16_t entry);
bool qpci_msix_masked(QPCIDevice *dev, uint16_t entry);
+void qpci_msix_set_masked(QPCIDevice *dev, uint16_t entry, bool masked);
bool qpci_msix_test_interrupt(QPCIDevice *dev, uint16_t msix_entry,
uint64_t msix_addr, uint32_t msix_data);
uint16_t qpci_msix_table_size(QPCIDevice *dev);
diff --git a/tests/qtest/libqos/pci.c b/tests/qtest/libqos/pci.c
index 41f9673022..253c5df3e4 100644
--- a/tests/qtest/libqos/pci.c
+++ b/tests/qtest/libqos/pci.c
@@ -339,6 +339,24 @@ void qpci_msix_disable(QPCIDevice *dev)
dev->msix_pba_off = 0;
}
+void qpci_msix_set_entry(QPCIDevice *dev, uint16_t entry,
+ uint64_t guest_addr, uint32_t data)
+{
+ uint64_t vector_off = dev->msix_table_off + entry * PCI_MSIX_ENTRY_SIZE;
+
+ g_assert(dev->msix_enabled);
+ g_assert_cmpint(entry, <, qpci_msix_table_size(dev));
+
+ qpci_io_writel(dev, dev->msix_table_bar,
+ vector_off + PCI_MSIX_ENTRY_LOWER_ADDR, guest_addr & ~0UL);
+ qpci_io_writel(dev, dev->msix_table_bar,
+ vector_off + PCI_MSIX_ENTRY_UPPER_ADDR,
+ (guest_addr >> 32) & ~0UL);
+
+ qpci_io_writel(dev, dev->msix_table_bar,
+ vector_off + PCI_MSIX_ENTRY_DATA, data);
+}
+
bool qpci_msix_pending(QPCIDevice *dev, uint16_t entry)
{
uint32_t pba_entry;
@@ -346,6 +364,8 @@ bool qpci_msix_pending(QPCIDevice *dev, uint16_t entry)
uint64_t off = (entry / 32) * PCI_MSIX_ENTRY_SIZE / 4;
g_assert(dev->msix_enabled);
+ g_assert_cmpint(entry, <, qpci_msix_table_size(dev));
+
pba_entry = qpci_io_readl(dev, dev->msix_pba_bar, dev->msix_pba_off + off);
return (pba_entry & (1 << bit_n)) != 0;
}
@@ -357,6 +377,8 @@ bool qpci_msix_masked(QPCIDevice *dev, uint16_t entry)
uint64_t vector_off = dev->msix_table_off + entry * PCI_MSIX_ENTRY_SIZE;
g_assert(dev->msix_enabled);
+ g_assert_cmpint(entry, <, qpci_msix_table_size(dev));
+
addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX, 0);
g_assert_cmphex(addr, !=, 0);
val = qpci_config_readw(dev, addr + PCI_MSIX_FLAGS);
@@ -370,6 +392,33 @@ bool qpci_msix_masked(QPCIDevice *dev, uint16_t entry)
}
}
+void qpci_msix_set_masked(QPCIDevice *dev, uint16_t entry, bool masked)
+{
+ uint8_t addr;
+ uint16_t val;
+ uint64_t vector_off = dev->msix_table_off + entry * PCI_MSIX_ENTRY_SIZE;
+
+ g_assert(dev->msix_enabled);
+ g_assert_cmpint(entry, <, qpci_msix_table_size(dev));
+
+ addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX, 0);
+ g_assert_cmphex(addr, !=, 0);
+ val = qpci_config_readw(dev, addr + PCI_MSIX_FLAGS);
+ g_assert(!(val & PCI_MSIX_FLAGS_MASKALL));
+
+ val = qpci_io_readl(dev, dev->msix_table_bar,
+ vector_off + PCI_MSIX_ENTRY_VECTOR_CTRL);
+ if (masked && !(val & PCI_MSIX_ENTRY_CTRL_MASKBIT)) {
+ qpci_io_writel(dev, dev->msix_table_bar,
+ vector_off + PCI_MSIX_ENTRY_VECTOR_CTRL,
+ val | PCI_MSIX_ENTRY_CTRL_MASKBIT);
+ } else if (!masked && (val & PCI_MSIX_ENTRY_CTRL_MASKBIT)) {
+ qpci_io_writel(dev, dev->msix_table_bar,
+ vector_off + PCI_MSIX_ENTRY_VECTOR_CTRL,
+ val & ~PCI_MSIX_ENTRY_CTRL_MASKBIT);
+ }
+}
+
/**
* qpci_msix_test_interrupt - test whether MSI-X interrupt has been raised
* @dev: PCI device
diff --git a/tests/qtest/libqos/virtio-pci.c b/tests/qtest/libqos/virtio-pci.c
index ea8114e243..16e0220920 100644
--- a/tests/qtest/libqos/virtio-pci.c
+++ b/tests/qtest/libqos/virtio-pci.c
@@ -290,66 +290,28 @@ void qvirtio_pci_device_disable(QVirtioPCIDevice *d)
void qvirtqueue_pci_msix_setup(QVirtioPCIDevice *d, QVirtQueuePCI *vqpci,
QGuestAllocator *alloc, uint16_t entry)
{
- uint32_t control;
- uint64_t off;
-
g_assert(d->pdev->msix_enabled);
- off = d->pdev->msix_table_off + (entry * 16);
-
- g_assert_cmpint(entry, >=, 0);
- g_assert_cmpint(entry, <, qpci_msix_table_size(d->pdev));
vqpci->msix_entry = entry;
-
vqpci->msix_addr = guest_alloc(alloc, 4);
qtest_memset(d->pdev->bus->qts, vqpci->msix_addr, 0, 4);
- qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
- off + PCI_MSIX_ENTRY_LOWER_ADDR, vqpci->msix_addr & ~0UL);
- qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
- off + PCI_MSIX_ENTRY_UPPER_ADDR,
- (vqpci->msix_addr >> 32) & ~0UL);
- qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
- off + PCI_MSIX_ENTRY_DATA, vqpci->msix_data);
-
- control = qpci_io_readl(d->pdev, d->pdev->msix_table_bar,
- off + PCI_MSIX_ENTRY_VECTOR_CTRL);
- qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
- off + PCI_MSIX_ENTRY_VECTOR_CTRL,
- control & ~PCI_MSIX_ENTRY_CTRL_MASKBIT);
+ qpci_msix_set_entry(d->pdev, entry, vqpci->msix_addr, vqpci->msix_data);
+ qpci_msix_set_masked(d->pdev, entry, false);
d->msix_ops->set_queue_vector(d, vqpci->vq.index, entry);
}
void qvirtio_pci_set_msix_configuration_vector(QVirtioPCIDevice *d,
QGuestAllocator *alloc, uint16_t entry)
{
- uint32_t control;
- uint64_t off;
-
g_assert(d->pdev->msix_enabled);
- off = d->pdev->msix_table_off + (entry * 16);
-
- g_assert_cmpint(entry, >=, 0);
- g_assert_cmpint(entry, <, qpci_msix_table_size(d->pdev));
d->config_msix_entry = entry;
-
d->config_msix_data = 0x12345678;
d->config_msix_addr = guest_alloc(alloc, 4);
qtest_memset(d->pdev->bus->qts, d->config_msix_addr, 0, 4);
- qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
- off + PCI_MSIX_ENTRY_LOWER_ADDR, d->config_msix_addr & ~0UL);
- qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
- off + PCI_MSIX_ENTRY_UPPER_ADDR,
- (d->config_msix_addr >> 32) & ~0UL);
- qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
- off + PCI_MSIX_ENTRY_DATA, d->config_msix_data);
-
- control = qpci_io_readl(d->pdev, d->pdev->msix_table_bar,
- off + PCI_MSIX_ENTRY_VECTOR_CTRL);
- qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
- off + PCI_MSIX_ENTRY_VECTOR_CTRL,
- control & ~PCI_MSIX_ENTRY_CTRL_MASKBIT);
-
+ qpci_msix_set_entry(d->pdev, entry, d->config_msix_addr,
+ d->config_msix_data);
+ qpci_msix_set_masked(d->pdev, entry, false);
d->msix_ops->set_config_vector(d, entry);
}
--
MST
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PULL 00/17] pci: fixes
2026-11-03 11:50 [PULL 00/17] pci: fixes Michael S. Tsirkin
` (16 preceding siblings ...)
2026-11-03 11:51 ` [PULL 17/17] qtest/libqos/pci: Factor msix entry helpers into pci common code Michael S. Tsirkin
@ 2026-11-03 22:42 ` Richard Henderson
17 siblings, 0 replies; 19+ messages in thread
From: Richard Henderson @ 2026-11-03 22:42 UTC (permalink / raw)
To: Michael S. Tsirkin, qemu-devel; +Cc: Peter Maydell
On 11/3/26 03:50, Michael S. Tsirkin wrote:
> The following changes since commit 4075aa42daecf701cd3869da8b3271dc3c04a4b1:
>
> Merge tag 'block-pull-request' ofhttps://gitlab.com/stefanha/qemu into staging (2026-10-30 15:26:36 -0500)
>
> 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 cc82fad46af62a3f5488538b6261eb7d54837294:
>
> qtest/libqos/pci: Factor msix entry helpers into pci common code (2026-11-02 03:52:53 -0500)
>
> ----------------------------------------------------------------
> pci: fixes
>
> pcie_sriov: fix for user-creation of VFs replaced by v2
> pcie sriov: a couple more robustness improvements
> pci: id docs clarified
> pci: a bunch of test fixes, robustness
Applied, thanks.
r~
^ permalink raw reply [flat|nested] 19+ messages in thread