hw/riscv/riscv-iommu-sys.c: record fault on IOMMU-generated MSI write
The riscv-iommu spec requires that the IOMMU records its own generated MSI write faults. Fixes: 01c1caa9d1 ("hw/riscv/virt.c, riscv-iommu-sys.c: add MSIx support") Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3572 Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Nutty Liu <nutty.liu@hotmail.com> Message-ID: <20260629165954.1018123-1-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Daniel Henrique Barboza committed
Jun 29, 2026 at 13:59 UTC
58e801f74e6a4ebd3a0cf3ab1a96e1676b263efd
3 files changed
+17
-3
hw/riscv/riscv-iommu-sys.c
+15
-1
@@ -26,6 +26,7 @@
26
#include "qemu/host-utils.h"
27
#include "qemu/module.h"
28
#include "qom/object.h"
29
+#include "target/riscv/cpu_bits.h"
30
#include "trace.h"
31
32
#include "riscv-iommu.h"
@@ -143,7 +144,20 @@ static void riscv_iommu_sysdev_send_MSI(RISCVIOMMUStateSys *s,
144
145
address_space_stl_le(&address_space_memory, msi_addr,
146
msi_data, MEMTXATTRS_UNSPECIFIED, &result);
146
- trace_riscv_iommu_sys_msi_sent(vector, msi_addr, msi_data, result);
147
+
148
+ if (result == MEMTX_OK) {
149
+ trace_riscv_iommu_sys_msi_sent(vector, msi_addr, msi_data, result);
150
+ } else {
151
+ /* Record an access fault error in the fault queue */
152
+ struct riscv_iommu_fq_record ev = { 0 };
153
+ RISCVIOMMUState *iommu = &s->iommu;
154
+
155
+ ev.hdr = set_field(ev.hdr, RISCV_IOMMU_FQ_HDR_CAUSE,
156
+ RISCV_IOMMU_FQ_CAUSE_MSI_WR_FAULT);
157
+ ev.hdr = set_field(ev.hdr, RISCV_IOMMU_FQ_HDR_TTYPE,
158
+ RISCV_IOMMU_FQ_TTYPE_UADDR_WR);
159
+ riscv_iommu_fault(iommu, &ev);
160
+ }
161
}
162
163
static void riscv_iommu_sysdev_notify(RISCVIOMMUState *iommu,
hw/riscv/riscv-iommu.c
+1
-2
@@ -118,8 +118,7 @@ void riscv_iommu_notify(RISCVIOMMUState *s, int vec_type)
118
}
119
}
120
121
-static void riscv_iommu_fault(RISCVIOMMUState *s,
122
- struct riscv_iommu_fq_record *ev)
121
+void riscv_iommu_fault(RISCVIOMMUState *s, struct riscv_iommu_fq_record *ev)
122
{
123
uint32_t ctrl = riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_FQCSR);
124
uint32_t head = riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_FQH) & s->fq_mask;
hw/riscv/riscv-iommu.h
+1
@@ -103,6 +103,7 @@ void riscv_iommu_pci_setup_iommu(RISCVIOMMUState *iommu, PCIBus *bus,
103
void riscv_iommu_set_cap_igs(RISCVIOMMUState *s, riscv_iommu_igs_mode mode);
104
void riscv_iommu_reset(RISCVIOMMUState *s);
105
void riscv_iommu_notify(RISCVIOMMUState *s, int vec_type);
106
+void riscv_iommu_fault(RISCVIOMMUState *s, struct riscv_iommu_fq_record *ev);
107
108
typedef struct RISCVIOMMUContext RISCVIOMMUContext;
109
/* Device translation context state. */