From: Alejandro Jimenez <[email protected]>
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 <[email protected]>
Suggested-by: Peter Maydell <[email protected]>
Signed-off-by: Alejandro Jimenez <[email protected]>
Reviewed-by: Philippe Mathieu-Daudé <[email protected]>
Reviewed-by: Peter Maydell <[email protected]>
Reviewed-by: Michael S. Tsirkin <[email protected]>
Signed-off-by: Michael S. Tsirkin <[email protected]>
Message-ID: <[email protected]>
---
hw/i386/amd_iommu.h | 14 --------------
hw/i386/amd_iommu.c | 28 ++++++++++++++++++----------
2 files changed, 18 insertions(+), 24 deletions(-)
diff --git a/hw/i386/amd_iommu.h b/hw/i386/amd_iommu.h
index 3cab04a6d4..ca4440a4c1 100644
--- a/hw/i386/amd_iommu.h
+++ b/hw/i386/amd_iommu.h
@@ -340,20 +340,6 @@ 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)
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
index a0835a20d7..291cb368a9 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -34,6 +34,7 @@
#include "hw/core/qdev-properties.h"
#include "kvm/kvm_i386.h"
#include "qemu/iova-tree.h"
+#include "hw/core/registerfields.h"
struct AMDVIAddressSpace {
PCIBus *bus; /* PCIBus (for bus number) */
@@ -88,6 +89,13 @@ typedef struct AMDVIIOTLBKey {
uint16_t devid;
} AMDVIIOTLBKey;
+/* XT IOMMU General Interrupt Control Register layout */
+FIELD(AMDVI_XT_GEN_INTR, DEST_MODE, 2, 1)
+FIELD(AMDVI_XT_GEN_INTR, DEST_LO, 8, 24)
+FIELD(AMDVI_XT_GEN_INTR, VECTOR, 32, 8)
+FIELD(AMDVI_XT_GEN_INTR, DELIVERY_MODE, 40, 1)
+FIELD(AMDVI_XT_GEN_INTR, DEST_HI, 56, 8)
+
uint64_t amdvi_extended_feature_register(AMDVIState *s)
{
uint64_t feature = AMDVI_DEFAULT_EXT_FEATURES;
@@ -194,17 +202,17 @@ static void amdvi_assign_andq(AMDVIState *s, hwaddr addr,
uint64_t val)
static void amdvi_build_xt_msi_msg(AMDVIState *s, MSIMessage *msg)
{
- union mmio_xt_intr xt_reg;
- struct X86IOMMUIrq irq;
+ uint64_t xt_reg = amdvi_readq(s, AMDVI_MMIO_XT_GEN_INTR);
- 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;
+ X86IOMMUIrq irq = {
+ .vector = FIELD_EX64(xt_reg, AMDVI_XT_GEN_INTR, VECTOR),
+ .delivery_mode = FIELD_EX64(xt_reg, AMDVI_XT_GEN_INTR, DELIVERY_MODE),
+ .dest_mode = FIELD_EX64(xt_reg, AMDVI_XT_GEN_INTR, DEST_MODE),
+ .dest = (FIELD_EX64(xt_reg, AMDVI_XT_GEN_INTR, DEST_HI) << 24) |
+ FIELD_EX64(xt_reg, AMDVI_XT_GEN_INTR, DEST_LO),
+ .trigger_mode = 0,
+ .redir_hint = 0,
+ };
x86_iommu_irq_to_msi_message(&irq, msg);
}
--
MST