@samitouri / QOSamiQemu / commits / 83ec1c7fcb

amd_iommu: Decode XT interrupt control register without bitfields

The XT IOMMU General Interrupt Control Register is a guest-visible MMIO register. Decoding it with bitfields depends on host bitfield layout and is not portable to big-endian hosts. Fix this by removing union mmio_xt_intr and explicitly extracting fields with FIELD_EX64() from the full register value returned by amdvi_readq(), which has already been converted to host endianness. Using a designated initializer for X86IOMMUIrq also ensures fields not provided by the XT register (e.g. msi_addr_last_bits) are initialized before x86_iommu_irq_to_msi_message() uses them. CID: 1660056 Fixes: cf0210df65aa ("amd_iommu: Generate XT interrupts when xt support is enabled") Reported-by: Peter Maydell <peter.maydell@linaro.org> Suggested-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Alejandro Jimenez <alejandro.j.jimenez@oracle.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20260630220806.1758748-4-alejandro.j.jimenez@oracle.com>

Alejandro Jimenez committed Jun 30, 2026 at 22:08 UTC 83ec1c7fcb243c232186df790f5847808cc26982
2 files changed +18 -24
hw/i386/amd_iommu.c
+18 -10
@@ -34,6 +34,7 @@
34 #include "hw/core/qdev-properties.h"
35 #include "kvm/kvm_i386.h"
36 #include "qemu/iova-tree.h"
37 +#include "hw/core/registerfields.h"
38
39 struct AMDVIAddressSpace {
40 PCIBus *bus; /* PCIBus (for bus number) */
@@ -88,6 +89,13 @@ typedef struct AMDVIIOTLBKey {
89 uint16_t devid;
90 } AMDVIIOTLBKey;
91
92 +/* XT IOMMU General Interrupt Control Register layout */
93 +FIELD(AMDVI_XT_GEN_INTR, DEST_MODE, 2, 1)
94 +FIELD(AMDVI_XT_GEN_INTR, DEST_LO, 8, 24)
95 +FIELD(AMDVI_XT_GEN_INTR, VECTOR, 32, 8)
96 +FIELD(AMDVI_XT_GEN_INTR, DELIVERY_MODE, 40, 1)
97 +FIELD(AMDVI_XT_GEN_INTR, DEST_HI, 56, 8)
98 +
99 uint64_t amdvi_extended_feature_register(AMDVIState *s)
100 {
101 uint64_t feature = AMDVI_DEFAULT_EXT_FEATURES;
@@ -194,17 +202,17 @@ static void amdvi_assign_andq(AMDVIState *s, hwaddr addr, uint64_t val)
202
203 static void amdvi_build_xt_msi_msg(AMDVIState *s, MSIMessage *msg)
204 {
197 - union mmio_xt_intr xt_reg;
198 - struct X86IOMMUIrq irq;
199 -
200 - xt_reg.val = amdvi_readq(s, AMDVI_MMIO_XT_GEN_INTR);
205 + uint64_t xt_reg = amdvi_readq(s, AMDVI_MMIO_XT_GEN_INTR);
206
202 - irq.vector = xt_reg.vector;
203 - irq.delivery_mode = xt_reg.delivery_mode;
204 - irq.dest_mode = xt_reg.destination_mode;
205 - irq.dest = (xt_reg.destination_hi << 24) | xt_reg.destination_lo;
206 - irq.trigger_mode = 0;
207 - irq.redir_hint = 0;
207 + X86IOMMUIrq irq = {
208 + .vector = FIELD_EX64(xt_reg, AMDVI_XT_GEN_INTR, VECTOR),
209 + .delivery_mode = FIELD_EX64(xt_reg, AMDVI_XT_GEN_INTR, DELIVERY_MODE),
210 + .dest_mode = FIELD_EX64(xt_reg, AMDVI_XT_GEN_INTR, DEST_MODE),
211 + .dest = (FIELD_EX64(xt_reg, AMDVI_XT_GEN_INTR, DEST_HI) << 24) |
212 + FIELD_EX64(xt_reg, AMDVI_XT_GEN_INTR, DEST_LO),
213 + .trigger_mode = 0,
214 + .redir_hint = 0,
215 + };
216
217 x86_iommu_irq_to_msi_message(&irq, msg);
218 }
hw/i386/amd_iommu.h
-14
@@ -340,20 +340,6 @@ struct irte_ga {
340 union irte_ga_hi hi;
341 };
342
343 -union mmio_xt_intr {
344 - uint64_t val;
345 - struct {
346 - uint64_t rsvd_1:2,
347 - destination_mode:1,
348 - rsvd_2:5,
349 - destination_lo:24,
350 - vector:8,
351 - delivery_mode:1,
352 - rsvd_3:15,
353 - destination_hi:8;
354 - };
355 -};
356 -
343 #define TYPE_AMD_IOMMU_DEVICE "amd-iommu"
344 OBJECT_DECLARE_SIMPLE_TYPE(AMDVIState, AMD_IOMMU_DEVICE)
345