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; 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. */