<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Thu, Jan 8, 2026 at 9:49 PM <<a href="mailto:fangyu.yu@linux.alibaba.com">fangyu.yu@linux.alibaba.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">From: Fangyu Yu <<a href="mailto:fangyu.yu@linux.alibaba.com" target="_blank">fangyu.yu@linux.alibaba.com</a>><br>
<br>
Add riscv_iommu_iodir_iotinval() to perform required TLB and context cache<br>
invalidations after updating DDT or PDT entries, as mandated by the RISC-V<br>
IOMMU specification (Section 6.3.1 and 6.3.2).<br>
<br>
Signed-off-by: Fangyu Yu <<a href="mailto:fangyu.yu@linux.alibaba.com" target="_blank">fangyu.yu@linux.alibaba.com</a>><br>
---<br>
 drivers/iommu/riscv/iommu.c | 85 +++++++++++++++++++++++++++++++++++++<br>
 1 file changed, 85 insertions(+)<br>
<br>
diff --git a/drivers/iommu/riscv/iommu.c b/drivers/iommu/riscv/iommu.c<br>
index d9429097a2b5..2900170133fc 100644<br>
--- a/drivers/iommu/riscv/iommu.c<br>
+++ b/drivers/iommu/riscv/iommu.c<br>
@@ -996,7 +996,82 @@ static void riscv_iommu_iotlb_inval(struct riscv_iommu_domain *domain,<br>
 }<br>
<br>
 #define RISCV_IOMMU_FSC_BARE 0<br>
+/*<br>
+ * This function sends IOTINVAL commands as required by the RISC-V<br>
+ * IOMMU specification (Section 6.3.1 and 6.3.2 in 1.0 spec version)<br>
+ * after modifying DDT or PDT entries<br>
+ */<br>
+static void riscv_iommu_iodir_iotinval(struct riscv_iommu_device *iommu,<br>
+                                   bool inval_pdt, unsigned long iohgatp,<br>
+                                   struct riscv_iommu_dc *dc, struct riscv_iommu_pc *pc)<br>
+{<br>
+       struct riscv_iommu_command cmd;<br>
<br>
+       if (FIELD_GET(RISCV_IOMMU_DC_IOHGATP_MODE, iohgatp) ==<br>
+               RISCV_IOMMU_DC_IOHGATP_MODE_BARE) {<br>
+               if (inval_pdt) {<br>
+                       /*<br>
+                        * IOTINVAL.VMA with GV=AV=0, and PSCV=1, and<br>
+                        * PSCID=PC.PSCID<br>
+                        */<br>
+                       riscv_iommu_cmd_inval_vma(&cmd);<br>
+                       riscv_iommu_cmd_inval_set_pscid(&cmd,<br>
+                               FIELD_GET(RISCV_IOMMU_PC_TA_PSCID, pc->ta));<br>
+               } else {<br>
+                       if (FIELD_GET(RISCV_IOMMU_DC_TC_PDTV, dc->tc) || (<br>
+                                   FIELD_GET(RISCV_IOMMU_DC_FSC_MODE, dc->fsc) ==<br>
+                                   RISCV_IOMMU_DC_FSC_MODE_BARE)) {<br>
+                               /* IOTINVAL.VMA with GV=AV=PSCV=0 */<br>
+                               riscv_iommu_cmd_inval_vma(&cmd);<br>
+                       } else {<br>
+                               /*<br>
+                                * IOTINVAL.VMA with GV=AV=0, and PSCV=1, and<br>
+                                * PSCID=DC.ta.PSCID<br>
+                                */<br>
+                               riscv_iommu_cmd_inval_vma(&cmd);<br>
+                               riscv_iommu_cmd_inval_set_pscid(&cmd,<br>
+                                       FIELD_GET(RISCV_IOMMU_DC_TA_PSCID, dc->ta));<br>
+                       }<br>
+               }<br>
+       } else {<br>
+               if (inval_pdt) {<br>
+                       /*<br>
+                        * IOTINVAL.VMA with GV=1, AV=0, and PSCV=1, and<br>
+                        * GSCID=DC.iohgatp.GSCID, PSCID=PC.PSCID<br>
+                        */<br>
+                       riscv_iommu_cmd_inval_vma(&cmd);</blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+                       riscv_iommu_cmd_inval_set_gscid(&cmd,<br>
+                               FIELD_GET(RISCV_IOMMU_DC_IOHGATP_GSCID, iohgatp));<br>
+                       riscv_iommu_cmd_inval_set_pscid(&cmd,<br>
+                               FIELD_GET(RISCV_IOMMU_PC_TA_PSCID, pc->ta));<br></blockquote><div>The riscv_iommu_cmd_inval_set_pscid() and riscv_iommu_cmd_inval_vma() could be moved out to prevent duplicate code.<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+               } else {<br>
+                       /*<br>
+                        * IOTINVAL.VMA with GV=1,AV=PSCV=0,and<br>
+                        * GSCID=DC.iohgatp.GSCID<br>
+                        */<br>
+                       riscv_iommu_cmd_inval_vma(&cmd);<br>
+                       riscv_iommu_cmd_inval_set_gscid(&cmd,<br>
+                               FIELD_GET(RISCV_IOMMU_DC_IOHGATP_GSCID, iohgatp));<br>
+<br>
+                       /*<br>
+                        * IOTINVAL.GVMA with GV=1,AV=0,and<br>
+                        * GSCID=DC.iohgatp.GSCID<br>
+                        */<br>
+                       /*<br>
+                        * For now, the Second-Stage feature have not yet been merged, so<br>
+                        * let's comment out the code first.<br>
+                        */<br>
+#if 0 </blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+                       riscv_iommu_cmd_send(iommu, &cmd);<br>
+                       memset(&cmd, 0, sizeof(cmd));<br>
+                       riscv_iommu_cmd_inval_gvma(&cmd);<br>
+                       riscv_iommu_cmd_inval_set_gscid(&cmd,<br>
+                               FIELD_GET(RISCV_IOMMU_DC_IOHGATP_GSCID, iohgatp));<br>
+#endif<br></blockquote><div>All the above should be removed from the patch; we don't need draft code.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+               }<br>
+       }<br>
+       riscv_iommu_cmd_send(iommu, &cmd);<br>
+}<br>
 /*<br>
  * Update IODIR for the device.<br>
  *<br>
@@ -1031,6 +1106,11 @@ static void riscv_iommu_iodir_update(struct riscv_iommu_device *iommu,<br>
                riscv_iommu_cmd_iodir_inval_ddt(&cmd);<br>
                riscv_iommu_cmd_iodir_set_did(&cmd, fwspec->ids[i]);<br>
                riscv_iommu_cmd_send(iommu, &cmd);<br>
+               /*<br>
+                * For now, the SVA and PASID features have not yet been merged, the<br>
+                * default configuration is inval_pdt=false and pc=NULL.<br>
+                */<br>
+               riscv_iommu_iodir_iotinval(iommu, false, dc->iohgatp, dc, NULL);<br></blockquote><div> The riscv_iommu_iodir_iotinval() is the same level as riscv_iommu_iodir_update(). Could we move it out and put it after riscv_iommu_iodir_update()?</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
                sync_required = true;<br>
        }<br>
<br>
@@ -1055,6 +1135,11 @@ static void riscv_iommu_iodir_update(struct riscv_iommu_device *iommu,<br></blockquote><div>Why do you have two riscv_iommu_iodir_update() function definitions?<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
                /* Invalidate device context after update */<br>
                riscv_iommu_cmd_iodir_inval_ddt(&cmd);<br>
                riscv_iommu_cmd_iodir_set_did(&cmd, fwspec->ids[i]);<br>
+               /*<br>
+                * For now, the SVA and PASID features have not yet been merged, the<br>
+                * default configuration is inval_pdt=false and pc=NULL.<br>
+                */<br>
+               riscv_iommu_iodir_iotinval(iommu, false, dc->iohgatp, dc, NULL);<br>
                riscv_iommu_cmd_send(iommu, &cmd);<br></blockquote><div>If IOTLB invalidation occurs before DDT_CACHE invalidation, the IOTLB may use DDT_CACHE's stall info, which may cause IOTLB invalidation to fail.<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
        }<br>
<br>
-- <br>
2.50.1<br>
<br>
</blockquote></div><div><br clear="all"></div><div><br></div><span class="gmail_signature_prefix">-- </span><br><div dir="ltr" class="gmail_signature"><div dir="ltr">Best Regards<br> Guo Ren<br></div></div></div>