From: Daniel Henrique Barboza <[email protected]>
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 <[email protected]>
Reviewed-by: Nutty Liu <[email protected]>
Message-ID: <[email protected]>
Signed-off-by: Alistair Francis <[email protected]>
---
hw/riscv/riscv-iommu.h | 1 +
hw/riscv/riscv-iommu-sys.c | 16 +++++++++++++++-
hw/riscv/riscv-iommu.c | 3 +--
3 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/hw/riscv/riscv-iommu.h b/hw/riscv/riscv-iommu.h
index a778e86fb7..da70e8bfa8 100644
--- a/hw/riscv/riscv-iommu.h
+++ b/hw/riscv/riscv-iommu.h
@@ -103,6 +103,7 @@ void riscv_iommu_pci_setup_iommu(RISCVIOMMUState *iommu,
PCIBus *bus,
void riscv_iommu_set_cap_igs(RISCVIOMMUState *s, riscv_iommu_igs_mode mode);
void riscv_iommu_reset(RISCVIOMMUState *s);
void riscv_iommu_notify(RISCVIOMMUState *s, int vec_type);
+void riscv_iommu_fault(RISCVIOMMUState *s, struct riscv_iommu_fq_record *ev);
typedef struct RISCVIOMMUContext RISCVIOMMUContext;
/* Device translation context state. */
diff --git a/hw/riscv/riscv-iommu-sys.c b/hw/riscv/riscv-iommu-sys.c
index bf87b0b4ea..3314adeed2 100644
--- a/hw/riscv/riscv-iommu-sys.c
+++ b/hw/riscv/riscv-iommu-sys.c
@@ -26,6 +26,7 @@
#include "qemu/host-utils.h"
#include "qemu/module.h"
#include "qom/object.h"
+#include "target/riscv/cpu_bits.h"
#include "trace.h"
#include "riscv-iommu.h"
@@ -143,7 +144,20 @@ static void riscv_iommu_sysdev_send_MSI(RISCVIOMMUStateSys
*s,
address_space_stl_le(&address_space_memory, msi_addr,
msi_data, MEMTXATTRS_UNSPECIFIED, &result);
- trace_riscv_iommu_sys_msi_sent(vector, msi_addr, msi_data, result);
+
+ if (result == MEMTX_OK) {
+ trace_riscv_iommu_sys_msi_sent(vector, msi_addr, msi_data, result);
+ } else {
+ /* Record an access fault error in the fault queue */
+ struct riscv_iommu_fq_record ev = { 0 };
+ RISCVIOMMUState *iommu = &s->iommu;
+
+ ev.hdr = set_field(ev.hdr, RISCV_IOMMU_FQ_HDR_CAUSE,
+ RISCV_IOMMU_FQ_CAUSE_MSI_WR_FAULT);
+ ev.hdr = set_field(ev.hdr, RISCV_IOMMU_FQ_HDR_TTYPE,
+ RISCV_IOMMU_FQ_TTYPE_UADDR_WR);
+ riscv_iommu_fault(iommu, &ev);
+ }
}
static void riscv_iommu_sysdev_notify(RISCVIOMMUState *iommu,
diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
index c3f9f052ae..12f20fa4bd 100644
--- a/hw/riscv/riscv-iommu.c
+++ b/hw/riscv/riscv-iommu.c
@@ -118,8 +118,7 @@ void riscv_iommu_notify(RISCVIOMMUState *s, int vec_type)
}
}
-static void riscv_iommu_fault(RISCVIOMMUState *s,
- struct riscv_iommu_fq_record *ev)
+void riscv_iommu_fault(RISCVIOMMUState *s, struct riscv_iommu_fq_record *ev)
{
uint32_t ctrl = riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_FQCSR);
uint32_t head = riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_FQH) & s->fq_mask;
--
2.54.0