[PATCH] hw/riscv/riscv-iommu-sys.c: record fault on IOMMU-generated MSI write

Daniel Henrique Barboza posted 1 patch 3 weeks, 5 days ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20260629165954.1018123-1-daniel.barboza@oss.qualcomm.com
Maintainers: Palmer Dabbelt <palmer@dabbelt.com>, Alistair Francis <alistair.francis@wdc.com>, Weiwei Li <liwei1518@gmail.com>, Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>, Liu Zhiwei <zhiwei_liu@linux.alibaba.com>, Chao Liu <chao.liu.zevorn@gmail.com>
hw/riscv/riscv-iommu-sys.c | 16 +++++++++++++++-
hw/riscv/riscv-iommu.c     |  3 +--
hw/riscv/riscv-iommu.h     |  1 +
3 files changed, 17 insertions(+), 3 deletions(-)
[PATCH] hw/riscv/riscv-iommu-sys.c: record fault on IOMMU-generated MSI write
Posted by Daniel Henrique Barboza 3 weeks, 5 days ago
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>
---
 hw/riscv/riscv-iommu-sys.c | 16 +++++++++++++++-
 hw/riscv/riscv-iommu.c     |  3 +--
 hw/riscv/riscv-iommu.h     |  1 +
 3 files changed, 17 insertions(+), 3 deletions(-)

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 c9687e01a8..a962926688 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. */
-- 
2.43.0
Re: [PATCH] hw/riscv/riscv-iommu-sys.c: record fault on IOMMU-generated MSI write
Posted by Alistair Francis 3 weeks, 2 days ago
On Tue, Jun 30, 2026 at 3:02 AM Daniel Henrique Barboza
<daniel.barboza@oss.qualcomm.com> wrote:
>
> 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>

Thanks!

Applied to riscv-to-apply.next

Alistair

> ---
>  hw/riscv/riscv-iommu-sys.c | 16 +++++++++++++++-
>  hw/riscv/riscv-iommu.c     |  3 +--
>  hw/riscv/riscv-iommu.h     |  1 +
>  3 files changed, 17 insertions(+), 3 deletions(-)
>
> 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 c9687e01a8..a962926688 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. */
> --
> 2.43.0
>
>
Re: [PATCH] hw/riscv/riscv-iommu-sys.c: record fault on IOMMU-generated MSI write
Posted by Nutty.Liu 3 weeks, 5 days ago
On 6/30/2026 12:59 AM, Daniel Henrique Barboza wrote:
> 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>

Thanks,
Nutty
> ---
>   hw/riscv/riscv-iommu-sys.c | 16 +++++++++++++++-
>   hw/riscv/riscv-iommu.c     |  3 +--
>   hw/riscv/riscv-iommu.h     |  1 +
>   3 files changed, 17 insertions(+), 3 deletions(-)
>
> 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 c9687e01a8..a962926688 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. */