Linux-RISC-V Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: fangyu.yu@linux.alibaba.com
To: tjeznach@rivosinc.com, joro@8bytes.org, will@kernel.org,
	robin.murphy@arm.com, pjw@kernel.org, palmer@dabbelt.com,
	aou@eecs.berkeley.edu, alex@ghiti.fr,
	andrew.jones@oss.qualcomm.com
Cc: guoren@kernel.org, iommu@lists.linux.dev,
	linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org,
	Fangyu Yu <fangyu.yu@linux.alibaba.com>
Subject: [PATCH 2/2] iommu/riscv: Add non-leaf invalidation support
Date: Sun,  8 Feb 2026 22:42:13 +0800	[thread overview]
Message-ID: <20260208144213.94856-3-fangyu.yu@linux.alibaba.com> (raw)
In-Reply-To: <20260208144213.94856-1-fangyu.yu@linux.alibaba.com>

From: Fangyu Yu <fangyu.yu@linux.alibaba.com>

The RISC-V IOMMU v1.0.1 spec adds the Non-leaf PTE Invalidation extension
(capabilities.NL) which allows IOTINVAL.VMA to invalidate cached non-leaf
PTE information when performing address-specific invalidations.

Add the NL capability bit definition and the IOTINVAL.VMA NL operand bit,
and provide a helper to set NL in an invalidation command.

Extend the internal IOTLB invalidation helpers to optionally request non-
leaf invalidation and, when mapping replaces non-leaf page-table entries
(freelist is not empty), invalidate the affected IOVA range with non-leaf
semantics instead of falling back to invalidate-all.

This reduces the scope of invalidations while keeping compatibility with
implementations that do not support the NL extension.

Signed-off-by: Fangyu Yu <fangyu.yu@linux.alibaba.com>
---
 drivers/iommu/riscv/iommu-bits.h |  7 +++++++
 drivers/iommu/riscv/iommu.c      | 29 +++++++++++++++++++++++------
 2 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/drivers/iommu/riscv/iommu-bits.h b/drivers/iommu/riscv/iommu-bits.h
index 0d1f8813ae31..35bb9eaa5214 100644
--- a/drivers/iommu/riscv/iommu-bits.h
+++ b/drivers/iommu/riscv/iommu-bits.h
@@ -62,6 +62,7 @@
 #define RISCV_IOMMU_CAPABILITIES_PD8		BIT_ULL(38)
 #define RISCV_IOMMU_CAPABILITIES_PD17		BIT_ULL(39)
 #define RISCV_IOMMU_CAPABILITIES_PD20		BIT_ULL(40)
+#define RISCV_IOMMU_CAPABILITIES_NL		BIT_ULL(42)
 #define RISCV_IOMMU_CAPABILITIES_S		BIT_ULL(43)
 
 /**
@@ -473,6 +474,7 @@ struct riscv_iommu_command {
 #define RISCV_IOMMU_CMD_IOTINVAL_PSCV		BIT_ULL(32)
 #define RISCV_IOMMU_CMD_IOTINVAL_GV		BIT_ULL(33)
 #define RISCV_IOMMU_CMD_IOTINVAL_GSCID		GENMASK_ULL(59, 44)
+#define RISCV_IOMMU_CMD_IOTINVAL_NL		BIT_ULL(34)
 #define RISCV_IOMMU_CMD_IOTINVAL_S		BIT_ULL(9)
 /* dword1[61:10] is the 4K-aligned page address */
 #define RISCV_IOMMU_CMD_IOTINVAL_ADDR		GENMASK_ULL(61, 10)
@@ -732,6 +734,11 @@ static inline void riscv_iommu_cmd_inval_set_addr(struct riscv_iommu_command *cm
 	cmd->dword0 |= RISCV_IOMMU_CMD_IOTINVAL_AV;
 }
 
+static inline void riscv_iommu_cmd_inval_set_nonleaf(struct riscv_iommu_command *cmd)
+{
+	cmd->dword0 |= RISCV_IOMMU_CMD_IOTINVAL_NL;
+}
+
 static inline void riscv_iommu_cmd_inval_set_pscid(struct riscv_iommu_command *cmd,
 						   int pscid)
 {
diff --git a/drivers/iommu/riscv/iommu.c b/drivers/iommu/riscv/iommu.c
index ae48409a052a..acc82c8626ce 100644
--- a/drivers/iommu/riscv/iommu.c
+++ b/drivers/iommu/riscv/iommu.c
@@ -933,7 +933,8 @@ static unsigned long range_encode(unsigned long start, unsigned long size)
 }
 static void riscv_iommu_iotlb_inval_range(struct riscv_iommu_domain *domain,
 					  struct riscv_iommu_device *iommu,
-					  unsigned long start, unsigned long end)
+					  unsigned long start, unsigned long end,
+					  bool non_leaf)
 {
 	struct riscv_iommu_command cmd;
 	unsigned long len = end - start + 1;
@@ -962,6 +963,16 @@ static void riscv_iommu_iotlb_inval_range(struct riscv_iommu_domain *domain,
 	limit = PAGE_ALIGN(end + 1);
 	cur = page_start;
 
+	if (non_leaf) {
+		if (!!(iommu->caps & RISCV_IOMMU_CAPABILITIES_NL)) {
+			riscv_iommu_cmd_inval_set_nonleaf(&cmd);
+		} else {
+			/* Falls back to whole address space invalidation */
+			riscv_iommu_cmd_send(iommu, &cmd);
+			return;
+		}
+	}
+
 	while (cur < limit) {
 		max_range = 0;
 
@@ -1004,7 +1015,8 @@ static void riscv_iommu_iotlb_inval_range(struct riscv_iommu_domain *domain,
 #define RISCV_IOMMU_IOTLB_INVAL_LIMIT	(2 << 20)
 
 static void riscv_iommu_iotlb_inval(struct riscv_iommu_domain *domain,
-				    unsigned long start, unsigned long end)
+				    unsigned long start, unsigned long end,
+				    bool non_leaf)
 {
 	struct riscv_iommu_bond *bond;
 	struct riscv_iommu_device *iommu, *prev;
@@ -1052,8 +1064,11 @@ static void riscv_iommu_iotlb_inval(struct riscv_iommu_domain *domain,
 			continue;
 
 		if (!!(iommu->caps & RISCV_IOMMU_CAPABILITIES_S)) {
-			riscv_iommu_iotlb_inval_range(domain, iommu, start, end);
+			riscv_iommu_iotlb_inval_range(domain, iommu, start, end, non_leaf);
 			continue;
+		} else if (non_leaf) {
+			/* Falls back to whole address space invalidation */
+			len = ULONG_MAX;
 		}
 
 		riscv_iommu_cmd_inval_vma(&cmd);
@@ -1155,7 +1170,7 @@ static void riscv_iommu_iotlb_flush_all(struct iommu_domain *iommu_domain)
 {
 	struct riscv_iommu_domain *domain = iommu_domain_to_riscv(iommu_domain);
 
-	riscv_iommu_iotlb_inval(domain, 0, ULONG_MAX);
+	riscv_iommu_iotlb_inval(domain, 0, ULONG_MAX, false);
 }
 
 static void riscv_iommu_iotlb_sync(struct iommu_domain *iommu_domain,
@@ -1163,7 +1178,7 @@ static void riscv_iommu_iotlb_sync(struct iommu_domain *iommu_domain,
 {
 	struct riscv_iommu_domain *domain = iommu_domain_to_riscv(iommu_domain);
 
-	riscv_iommu_iotlb_inval(domain, gather->start, gather->end);
+	riscv_iommu_iotlb_inval(domain, gather->start, gather->end, false);
 }
 
 #define PT_SHIFT (PAGE_SHIFT - ilog2(sizeof(pte_t)))
@@ -1284,6 +1299,7 @@ static int riscv_iommu_map_pages(struct iommu_domain *iommu_domain,
 	unsigned long pte, old, pte_prot;
 	int rc = 0;
 	struct iommu_pages_list freelist = IOMMU_PAGES_LIST_INIT(freelist);
+	unsigned long inval_start = iova;
 
 	if (!(prot & IOMMU_WRITE))
 		pte_prot = _PAGE_BASE | _PAGE_READ;
@@ -1322,7 +1338,8 @@ static int riscv_iommu_map_pages(struct iommu_domain *iommu_domain,
 		 * This will be updated with hardware support for
 		 * capability.NL (non-leaf) IOTINVAL command.
 		 */
-		riscv_iommu_iotlb_inval(domain, 0, ULONG_MAX);
+		riscv_iommu_iotlb_inval(domain, inval_start,
+					inval_start + size - 1, true);
 		iommu_put_pages_list(&freelist);
 	}
 
-- 
2.50.1


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

  parent reply	other threads:[~2026-02-08 14:43 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-08 14:42 [PATCH 0/2] iommu/riscv: support range and non-leaf IOTLB invalidation fangyu.yu
2026-02-08 14:42 ` [PATCH 1/2] iommu/riscv: Add NAPOT range invalidation support for IOTINVAL fangyu.yu
2026-02-08 14:42 ` fangyu.yu [this message]
2026-02-10 13:02 ` [PATCH 0/2] iommu/riscv: support range and non-leaf IOTLB invalidation Jason Gunthorpe
2026-02-11 12:07   ` fangyu.yu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260208144213.94856-3-fangyu.yu@linux.alibaba.com \
    --to=fangyu.yu@linux.alibaba.com \
    --cc=alex@ghiti.fr \
    --cc=andrew.jones@oss.qualcomm.com \
    --cc=aou@eecs.berkeley.edu \
    --cc=guoren@kernel.org \
    --cc=iommu@lists.linux.dev \
    --cc=joro@8bytes.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-riscv@lists.infradead.org \
    --cc=palmer@dabbelt.com \
    --cc=pjw@kernel.org \
    --cc=robin.murphy@arm.com \
    --cc=tjeznach@rivosinc.com \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox