aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw@amazon.co.uk>2025-07-14 09:00:47 +0100
committerMichael S. Tsirkin <mst@redhat.com>2025-08-01 10:23:50 -0400
commite8145dcd311b58921f3a45121792cbfab38fd2f6 (patch)
treeba8b897e086d44b662abee69bbf7b5a3ccf68788
parentcd16f08ad4bda8191e4de986d17184c9da5466cd (diff)
downloadqemu-e8145dcd311b58921f3a45121792cbfab38fd2f6.zip
qemu-e8145dcd311b58921f3a45121792cbfab38fd2f6.tar.gz
qemu-e8145dcd311b58921f3a45121792cbfab38fd2f6.tar.bz2
intel_iommu: Allow both Status Write and Interrupt Flag in QI wait
FreeBSD does both, and this appears to be perfectly valid. The VT-d spec even talks about the ordering (the status write should be done first, unsurprisingly). We certainly shouldn't assert() and abort QEMU if the guest asks for both. Fixes: ed7b8fbcfb88 ("intel-iommu: add supports for queued invalidation interface") Closes: https://gitlab.com/qemu-project/qemu/-/issues/3028 Signed-off-by: David Woodhouse <dwmw@amazon.co.uk> Message-Id: <0122cbabc0adcc3cf878f5fd7834d8f258c7a2f2.camel@infradead.org> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-rw-r--r--hw/i386/intel_iommu.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index fe9a5f2..83c5e44 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -2828,6 +2828,7 @@ static bool vtd_process_wait_desc(IntelIOMMUState *s, VTDInvDesc *inv_desc)
{
uint64_t mask[4] = {VTD_INV_DESC_WAIT_RSVD_LO, VTD_INV_DESC_WAIT_RSVD_HI,
VTD_INV_DESC_ALL_ONE, VTD_INV_DESC_ALL_ONE};
+ bool ret = true;
if (!vtd_inv_desc_reserved_check(s, inv_desc, mask, false,
__func__, "wait")) {
@@ -2839,8 +2840,6 @@ static bool vtd_process_wait_desc(IntelIOMMUState *s, VTDInvDesc *inv_desc)
uint32_t status_data = (uint32_t)(inv_desc->lo >>
VTD_INV_DESC_WAIT_DATA_SHIFT);
- assert(!(inv_desc->lo & VTD_INV_DESC_WAIT_IF));
-
/* FIXME: need to be masked with HAW? */
dma_addr_t status_addr = inv_desc->hi;
trace_vtd_inv_desc_wait_sw(status_addr, status_data);
@@ -2849,18 +2848,22 @@ static bool vtd_process_wait_desc(IntelIOMMUState *s, VTDInvDesc *inv_desc)
&status_data, sizeof(status_data),
MEMTXATTRS_UNSPECIFIED)) {
trace_vtd_inv_desc_wait_write_fail(inv_desc->hi, inv_desc->lo);
- return false;
+ ret = false;
}
- } else if (inv_desc->lo & VTD_INV_DESC_WAIT_IF) {
+ }
+
+ if (inv_desc->lo & VTD_INV_DESC_WAIT_IF) {
/* Interrupt flag */
vtd_generate_completion_event(s);
- } else {
+ }
+
+ if (!(inv_desc->lo & (VTD_INV_DESC_WAIT_IF | VTD_INV_DESC_WAIT_SW))) {
error_report_once("%s: invalid wait desc: hi=%"PRIx64", lo=%"PRIx64
" (unknown type)", __func__, inv_desc->hi,
inv_desc->lo);
return false;
}
- return true;
+ return ret;
}
static bool vtd_process_context_cache_desc(IntelIOMMUState *s,