[PATCH v6 10/10] iommu/riscv: Add IOTINVAL.GVMA invalidations

From: fangyu . yu

Date: Sat Oct 31 2026 - 04:34:58 EST


From: Fangyu Yu <fangyu.yu@xxxxxxxxxxxxxxxxx>

Previously, only IOTINVAL.VMA was issued, which is insufficient for
second-stage address translation consistency.

Signed-off-by: Fangyu Yu <fangyu.yu@xxxxxxxxxxxxxxxxx>
Reviewed-by: Nutty Liu <nutty.liu@xxxxxxxxxxx>
---
drivers/iommu/riscv/iommu.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/riscv/iommu.c b/drivers/iommu/riscv/iommu.c
index 9f572baeca74..899b9872ca56 100644
--- a/drivers/iommu/riscv/iommu.c
+++ b/drivers/iommu/riscv/iommu.c
@@ -831,6 +831,15 @@ static int riscv_iommu_iodir_set_mode(struct riscv_iommu_device *iommu,
riscv_iommu_cmd_inval_vma(&cmd);
riscv_iommu_cmd_send(iommu, &cmd);

+ /*
+ * Per the RISC-V IOMMU spec (sec. 5.5), the IOMMU may retain
+ * cached translations across mode switches. IOTINVAL.VMA only
+ * covers first-stage leaf PTEs, so use a global IOTINVAL.GVMA
+ * to flush stale second-stage translations.
+ */
+ riscv_iommu_cmd_inval_gvma(&cmd);
+ riscv_iommu_cmd_send(iommu, &cmd);
+
/* IOFENCE.C */
riscv_iommu_cmd_sync(iommu, RISCV_IOMMU_IOTINVAL_TIMEOUT);

@@ -1176,12 +1185,15 @@ static void riscv_iommu_iodir_iotinval(struct riscv_iommu_device *iommu,
/*
* else: IOTINVAL.VMA with GV=1,AV=PSCV=0,and
* GSCID=DC.iohgatp.GSCID
- *
+ */
+ riscv_iommu_cmd_send(iommu, &cmd);
+ /*
* IOTINVAL.GVMA with GV=1,AV=0,and
* GSCID=DC.iohgatp.GSCID
- * TODO: For now, the Second-Stage feature have not yet been merged,
- * also issue IOTINVAL.GVMA once second-stage support is merged.
*/
+ riscv_iommu_cmd_inval_gvma(&cmd);
+ riscv_iommu_cmd_inval_set_gscid(&cmd,
+ FIELD_GET(RISCV_IOMMU_DC_IOHGATP_GSCID, iohgatp));
}
riscv_iommu_cmd_send(iommu, &cmd);
}
--
2.50.1