From: fangyu.yu@linux.alibaba.com
To: tomasz.jeznach@linux.dev, joro@8bytes.org, will@kernel.org,
robin.murphy@arm.com, pjw@kernel.org, palmer@dabbelt.com,
aou@eecs.berkeley.edu, alex@ghiti.fr, baolu.lu@linux.intel.com,
jroedel@suse.de, zong.li@sifive.com,
andrew.jones@oss.qualcomm.com, anup@brainfault.org,
jgg@nvidia.com, jgg@ziepe.ca, kevin.tian@intel.com,
atish.patra@linux.dev, skhawaja@google.com, vasant.hegde@amd.com
Cc: fangyu.yu@linux.alibaba.com, guoren@kernel.org,
iommu@lists.linux.dev, linux-kernel@vger.kernel.org,
linux-riscv@lists.infradead.org
Subject: [RFC PATCH v3 05/10] iommu/riscv: support GSCID and GVMA invalidation command
Date: Fri, 21 Aug 2026 21:27:45 +0800 [thread overview]
Message-ID: <20260821132749.82070-6-fangyu.yu@linux.alibaba.com> (raw)
In-Reply-To: <20260821132749.82070-1-fangyu.yu@linux.alibaba.com>
From: Zong Li <zong.li@sifive.com>
This patch adds a ID Allocator for GSCID and a wrap for setting up
GSCID in IOTLB invalidation command.
Set up iohgatp to enable second stage table and flush stage-2 table if
the GSCID is set.
The GSCID of domain should be freed when release domain. GSCID will be
allocated for parent domain in nested IOMMU process.
Signed-off-by: Zong Li <zong.li@sifive.com>
Signed-off-by: Fangyu Yu <fangyu.yu@linux.alibaba.com>
---
drivers/iommu/riscv/iommu-bits.h | 7 ++++
drivers/iommu/riscv/iommu.c | 62 ++++++++++++++++++++++++++------
2 files changed, 58 insertions(+), 11 deletions(-)
diff --git a/drivers/iommu/riscv/iommu-bits.h b/drivers/iommu/riscv/iommu-bits.h
index f2ef9bd3cde9..65d1f2250011 100644
--- a/drivers/iommu/riscv/iommu-bits.h
+++ b/drivers/iommu/riscv/iommu-bits.h
@@ -720,6 +720,13 @@ static inline void riscv_iommu_cmd_inval_vma(struct riscv_iommu_command *cmd)
cmd->dword1 = 0;
}
+static inline void riscv_iommu_cmd_inval_gvma(struct riscv_iommu_command *cmd)
+{
+ cmd->dword0 = FIELD_PREP(RISCV_IOMMU_CMD0_OPCODE, RISCV_IOMMU_CMD_IOTINVAL_OPCODE) |
+ FIELD_PREP(RISCV_IOMMU_CMD0_FUNC, RISCV_IOMMU_CMD_IOTINVAL_FUNC_GVMA);
+ cmd->dword1 = 0;
+}
+
static inline void riscv_iommu_cmd_inval_set_addr(struct riscv_iommu_command *cmd,
u64 addr)
{
diff --git a/drivers/iommu/riscv/iommu.c b/drivers/iommu/riscv/iommu.c
index c5b6214ee672..99f05f1db35b 100644
--- a/drivers/iommu/riscv/iommu.c
+++ b/drivers/iommu/riscv/iommu.c
@@ -48,6 +48,10 @@
static DEFINE_IDA(riscv_iommu_pscids);
#define RISCV_IOMMU_MAX_PSCID (BIT(20) - 1)
+/* IOMMU GSCID allocation namespace. */
+static DEFINE_IDA(riscv_iommu_gscids);
+#define RISCV_IOMMU_MAX_GSCID (BIT(16) - 1)
+
/* Device resource-managed allocations */
struct riscv_iommu_devres {
void *addr;
@@ -819,6 +823,7 @@ struct riscv_iommu_domain {
struct list_head bonds;
spinlock_t lock; /* protect bonds list updates. */
int pscid;
+ int gscid;
};
PT_IOMMU_CHECK_DOMAIN(struct riscv_iommu_domain, riscvpt.iommu, domain);
@@ -981,7 +986,7 @@ static void riscv_iommu_tlbi_calc(struct riscv_iommu_tlbi *tlbi,
}
static void riscv_iommu_iotlb_inval_iommu(struct riscv_iommu_device *iommu,
- int pscid,
+ int pscid, int gscid,
struct riscv_iommu_tlbi *tlbi)
{
bool use_nl = tlbi->non_leaf &&
@@ -989,8 +994,13 @@ static void riscv_iommu_iotlb_inval_iommu(struct riscv_iommu_device *iommu,
struct riscv_iommu_command cmd;
unsigned int i;
- riscv_iommu_cmd_inval_vma(&cmd);
- riscv_iommu_cmd_inval_set_pscid(&cmd, pscid);
+ if (gscid) {
+ riscv_iommu_cmd_inval_gvma(&cmd);
+ riscv_iommu_cmd_inval_set_gscid(&cmd, gscid);
+ } else {
+ riscv_iommu_cmd_inval_vma(&cmd);
+ riscv_iommu_cmd_inval_set_pscid(&cmd, pscid);
+ }
/*
* If non-leaf entries were changed and the IOMMU doesn't
@@ -1074,7 +1084,7 @@ static void riscv_iommu_iotlb_inval(struct riscv_iommu_domain *domain,
if (iommu == prev)
continue;
- riscv_iommu_iotlb_inval_iommu(iommu, domain->pscid, &tlbi);
+ riscv_iommu_iotlb_inval_iommu(iommu, domain->pscid, domain->gscid, &tlbi);
prev = iommu;
}
@@ -1208,6 +1218,7 @@ static void riscv_iommu_iodir_update(struct riscv_iommu_device *iommu,
WRITE_ONCE(dc->fsc, new_dc->fsc);
WRITE_ONCE(dc->ta, new_dc->ta & RISCV_IOMMU_PC_TA_PSCID);
+ WRITE_ONCE(dc->iohgatp, new_dc->iohgatp);
/* Update device context, write TC.V as the last step. */
dma_wmb();
WRITE_ONCE(dc->tc, tc);
@@ -1258,16 +1269,19 @@ static void riscv_iommu_free_paging_domain(struct iommu_domain *iommu_domain)
WARN_ON(!list_empty(&domain->bonds));
- if ((int)domain->pscid > 0)
+ if (domain->pscid > 0)
ida_free(&riscv_iommu_pscids, domain->pscid);
+ if (domain->gscid > 0)
+ ida_free(&riscv_iommu_gscids, domain->gscid);
pt_iommu_deinit(&domain->riscvpt.iommu);
kfree(domain);
}
-static bool riscv_iommu_pt_supported(struct riscv_iommu_device *iommu, int pgd_mode)
+static bool riscv_iommu_fsc_supported(struct riscv_iommu_device *iommu,
+ int mode)
{
- switch (pgd_mode) {
+ switch (mode) {
case RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV39:
return iommu->caps & RISCV_IOMMU_CAPABILITIES_SV39;
@@ -1280,6 +1294,22 @@ static bool riscv_iommu_pt_supported(struct riscv_iommu_device *iommu, int pgd_m
return false;
}
+static bool riscv_iommu_iohgatp_supported(struct riscv_iommu_device *iommu,
+ int mode)
+{
+ switch (mode) {
+ case RISCV_IOMMU_DC_IOHGATP_MODE_SV39X4:
+ return iommu->caps & RISCV_IOMMU_CAPABILITIES_SV39X4;
+
+ case RISCV_IOMMU_DC_IOHGATP_MODE_SV48X4:
+ return iommu->caps & RISCV_IOMMU_CAPABILITIES_SV48X4;
+
+ case RISCV_IOMMU_DC_IOHGATP_MODE_SV57X4:
+ return iommu->caps & RISCV_IOMMU_CAPABILITIES_SV57X4;
+ }
+ return false;
+}
+
static int riscv_iommu_attach_paging_domain(struct iommu_domain *iommu_domain,
struct device *dev,
struct iommu_domain *old)
@@ -1292,11 +1322,21 @@ static int riscv_iommu_attach_paging_domain(struct iommu_domain *iommu_domain,
pt_iommu_riscv_64_hw_info(&domain->riscvpt, &pt_info);
- if (!riscv_iommu_pt_supported(iommu, pt_info.fsc_iosatp_mode))
- return -ENODEV;
+ if (domain->gscid) {
+ if (!riscv_iommu_iohgatp_supported(iommu, pt_info.iohgatp_mode))
+ return -ENODEV;
+
+ dc.iohgatp =
+ FIELD_PREP(RISCV_IOMMU_DC_IOHGATP_MODE, pt_info.iohgatp_mode) |
+ FIELD_PREP(RISCV_IOMMU_DC_IOHGATP_GSCID, domain->gscid) |
+ FIELD_PREP(RISCV_IOMMU_DC_IOHGATP_PPN, pt_info.ppn);
+ } else {
+ if (!riscv_iommu_fsc_supported(iommu, pt_info.fsc_iosatp_mode))
+ return -ENODEV;
- dc.fsc = FIELD_PREP(RISCV_IOMMU_PC_FSC_MODE, pt_info.fsc_iosatp_mode) |
- FIELD_PREP(RISCV_IOMMU_PC_FSC_PPN, pt_info.ppn);
+ dc.fsc = FIELD_PREP(RISCV_IOMMU_PC_FSC_MODE, pt_info.fsc_iosatp_mode) |
+ FIELD_PREP(RISCV_IOMMU_PC_FSC_PPN, pt_info.ppn);
+ }
dc.ta = FIELD_PREP(RISCV_IOMMU_PC_TA_PSCID, domain->pscid) |
RISCV_IOMMU_PC_TA_V;
--
2.50.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
WARNING: multiple messages have this Message-ID (diff)
From: fangyu.yu@linux.alibaba.com
To: tomasz.jeznach@linux.dev, joro@8bytes.org, will@kernel.org,
robin.murphy@arm.com, pjw@kernel.org, palmer@dabbelt.com,
aou@eecs.berkeley.edu, alex@ghiti.fr, baolu.lu@linux.intel.com,
jroedel@suse.de, zong.li@sifive.com,
andrew.jones@oss.qualcomm.com, anup@brainfault.org,
jgg@nvidia.com, jgg@ziepe.ca, kevin.tian@intel.com,
atish.patra@linux.dev, skhawaja@google.com, vasant.hegde@amd.com
Cc: fangyu.yu@linux.alibaba.com, guoren@kernel.org,
iommu@lists.linux.dev, linux-kernel@vger.kernel.org,
linux-riscv@lists.infradead.org
Subject: [RFC PATCH v3 05/10] iommu/riscv: support GSCID and GVMA invalidation command
Date: Fri, 21 Aug 2026 21:27:45 +0800 [thread overview]
Message-ID: <20260821132749.82070-6-fangyu.yu@linux.alibaba.com> (raw)
In-Reply-To: <20260821132749.82070-1-fangyu.yu@linux.alibaba.com>
From: Zong Li <zong.li@sifive.com>
This patch adds a ID Allocator for GSCID and a wrap for setting up
GSCID in IOTLB invalidation command.
Set up iohgatp to enable second stage table and flush stage-2 table if
the GSCID is set.
The GSCID of domain should be freed when release domain. GSCID will be
allocated for parent domain in nested IOMMU process.
Signed-off-by: Zong Li <zong.li@sifive.com>
Signed-off-by: Fangyu Yu <fangyu.yu@linux.alibaba.com>
---
drivers/iommu/riscv/iommu-bits.h | 7 ++++
drivers/iommu/riscv/iommu.c | 62 ++++++++++++++++++++++++++------
2 files changed, 58 insertions(+), 11 deletions(-)
diff --git a/drivers/iommu/riscv/iommu-bits.h b/drivers/iommu/riscv/iommu-bits.h
index f2ef9bd3cde9..65d1f2250011 100644
--- a/drivers/iommu/riscv/iommu-bits.h
+++ b/drivers/iommu/riscv/iommu-bits.h
@@ -720,6 +720,13 @@ static inline void riscv_iommu_cmd_inval_vma(struct riscv_iommu_command *cmd)
cmd->dword1 = 0;
}
+static inline void riscv_iommu_cmd_inval_gvma(struct riscv_iommu_command *cmd)
+{
+ cmd->dword0 = FIELD_PREP(RISCV_IOMMU_CMD0_OPCODE, RISCV_IOMMU_CMD_IOTINVAL_OPCODE) |
+ FIELD_PREP(RISCV_IOMMU_CMD0_FUNC, RISCV_IOMMU_CMD_IOTINVAL_FUNC_GVMA);
+ cmd->dword1 = 0;
+}
+
static inline void riscv_iommu_cmd_inval_set_addr(struct riscv_iommu_command *cmd,
u64 addr)
{
diff --git a/drivers/iommu/riscv/iommu.c b/drivers/iommu/riscv/iommu.c
index c5b6214ee672..99f05f1db35b 100644
--- a/drivers/iommu/riscv/iommu.c
+++ b/drivers/iommu/riscv/iommu.c
@@ -48,6 +48,10 @@
static DEFINE_IDA(riscv_iommu_pscids);
#define RISCV_IOMMU_MAX_PSCID (BIT(20) - 1)
+/* IOMMU GSCID allocation namespace. */
+static DEFINE_IDA(riscv_iommu_gscids);
+#define RISCV_IOMMU_MAX_GSCID (BIT(16) - 1)
+
/* Device resource-managed allocations */
struct riscv_iommu_devres {
void *addr;
@@ -819,6 +823,7 @@ struct riscv_iommu_domain {
struct list_head bonds;
spinlock_t lock; /* protect bonds list updates. */
int pscid;
+ int gscid;
};
PT_IOMMU_CHECK_DOMAIN(struct riscv_iommu_domain, riscvpt.iommu, domain);
@@ -981,7 +986,7 @@ static void riscv_iommu_tlbi_calc(struct riscv_iommu_tlbi *tlbi,
}
static void riscv_iommu_iotlb_inval_iommu(struct riscv_iommu_device *iommu,
- int pscid,
+ int pscid, int gscid,
struct riscv_iommu_tlbi *tlbi)
{
bool use_nl = tlbi->non_leaf &&
@@ -989,8 +994,13 @@ static void riscv_iommu_iotlb_inval_iommu(struct riscv_iommu_device *iommu,
struct riscv_iommu_command cmd;
unsigned int i;
- riscv_iommu_cmd_inval_vma(&cmd);
- riscv_iommu_cmd_inval_set_pscid(&cmd, pscid);
+ if (gscid) {
+ riscv_iommu_cmd_inval_gvma(&cmd);
+ riscv_iommu_cmd_inval_set_gscid(&cmd, gscid);
+ } else {
+ riscv_iommu_cmd_inval_vma(&cmd);
+ riscv_iommu_cmd_inval_set_pscid(&cmd, pscid);
+ }
/*
* If non-leaf entries were changed and the IOMMU doesn't
@@ -1074,7 +1084,7 @@ static void riscv_iommu_iotlb_inval(struct riscv_iommu_domain *domain,
if (iommu == prev)
continue;
- riscv_iommu_iotlb_inval_iommu(iommu, domain->pscid, &tlbi);
+ riscv_iommu_iotlb_inval_iommu(iommu, domain->pscid, domain->gscid, &tlbi);
prev = iommu;
}
@@ -1208,6 +1218,7 @@ static void riscv_iommu_iodir_update(struct riscv_iommu_device *iommu,
WRITE_ONCE(dc->fsc, new_dc->fsc);
WRITE_ONCE(dc->ta, new_dc->ta & RISCV_IOMMU_PC_TA_PSCID);
+ WRITE_ONCE(dc->iohgatp, new_dc->iohgatp);
/* Update device context, write TC.V as the last step. */
dma_wmb();
WRITE_ONCE(dc->tc, tc);
@@ -1258,16 +1269,19 @@ static void riscv_iommu_free_paging_domain(struct iommu_domain *iommu_domain)
WARN_ON(!list_empty(&domain->bonds));
- if ((int)domain->pscid > 0)
+ if (domain->pscid > 0)
ida_free(&riscv_iommu_pscids, domain->pscid);
+ if (domain->gscid > 0)
+ ida_free(&riscv_iommu_gscids, domain->gscid);
pt_iommu_deinit(&domain->riscvpt.iommu);
kfree(domain);
}
-static bool riscv_iommu_pt_supported(struct riscv_iommu_device *iommu, int pgd_mode)
+static bool riscv_iommu_fsc_supported(struct riscv_iommu_device *iommu,
+ int mode)
{
- switch (pgd_mode) {
+ switch (mode) {
case RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV39:
return iommu->caps & RISCV_IOMMU_CAPABILITIES_SV39;
@@ -1280,6 +1294,22 @@ static bool riscv_iommu_pt_supported(struct riscv_iommu_device *iommu, int pgd_m
return false;
}
+static bool riscv_iommu_iohgatp_supported(struct riscv_iommu_device *iommu,
+ int mode)
+{
+ switch (mode) {
+ case RISCV_IOMMU_DC_IOHGATP_MODE_SV39X4:
+ return iommu->caps & RISCV_IOMMU_CAPABILITIES_SV39X4;
+
+ case RISCV_IOMMU_DC_IOHGATP_MODE_SV48X4:
+ return iommu->caps & RISCV_IOMMU_CAPABILITIES_SV48X4;
+
+ case RISCV_IOMMU_DC_IOHGATP_MODE_SV57X4:
+ return iommu->caps & RISCV_IOMMU_CAPABILITIES_SV57X4;
+ }
+ return false;
+}
+
static int riscv_iommu_attach_paging_domain(struct iommu_domain *iommu_domain,
struct device *dev,
struct iommu_domain *old)
@@ -1292,11 +1322,21 @@ static int riscv_iommu_attach_paging_domain(struct iommu_domain *iommu_domain,
pt_iommu_riscv_64_hw_info(&domain->riscvpt, &pt_info);
- if (!riscv_iommu_pt_supported(iommu, pt_info.fsc_iosatp_mode))
- return -ENODEV;
+ if (domain->gscid) {
+ if (!riscv_iommu_iohgatp_supported(iommu, pt_info.iohgatp_mode))
+ return -ENODEV;
+
+ dc.iohgatp =
+ FIELD_PREP(RISCV_IOMMU_DC_IOHGATP_MODE, pt_info.iohgatp_mode) |
+ FIELD_PREP(RISCV_IOMMU_DC_IOHGATP_GSCID, domain->gscid) |
+ FIELD_PREP(RISCV_IOMMU_DC_IOHGATP_PPN, pt_info.ppn);
+ } else {
+ if (!riscv_iommu_fsc_supported(iommu, pt_info.fsc_iosatp_mode))
+ return -ENODEV;
- dc.fsc = FIELD_PREP(RISCV_IOMMU_PC_FSC_MODE, pt_info.fsc_iosatp_mode) |
- FIELD_PREP(RISCV_IOMMU_PC_FSC_PPN, pt_info.ppn);
+ dc.fsc = FIELD_PREP(RISCV_IOMMU_PC_FSC_MODE, pt_info.fsc_iosatp_mode) |
+ FIELD_PREP(RISCV_IOMMU_PC_FSC_PPN, pt_info.ppn);
+ }
dc.ta = FIELD_PREP(RISCV_IOMMU_PC_TA_PSCID, domain->pscid) |
RISCV_IOMMU_PC_TA_V;
--
2.50.1
next prev parent reply other threads:[~2026-08-21 13:28 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-21 13:27 [RFC PATCH v3 00/10] iommu/riscv: Add hardware dirty tracking for second-stage domains fangyu.yu
2026-08-21 13:27 ` fangyu.yu
2026-08-21 13:27 ` [RFC PATCH v3 01/10] iommupt: Add RISC-V Second-stage (iohgatp) page table support fangyu.yu
2026-08-21 13:27 ` fangyu.yu
2026-08-21 13:55 ` Jason Gunthorpe
2026-08-21 13:55 ` Jason Gunthorpe
2026-08-22 14:55 ` fangyu.yu
2026-08-22 14:55 ` fangyu.yu
2026-08-21 13:27 ` [RFC PATCH v3 02/10] iommupt: Add RISC-V dirty tracking PTE ops fangyu.yu
2026-08-21 13:27 ` fangyu.yu
2026-08-21 14:03 ` Jason Gunthorpe
2026-08-21 14:03 ` Jason Gunthorpe
2026-08-22 15:01 ` fangyu.yu
2026-08-22 15:01 ` fangyu.yu
2026-08-21 13:27 ` [RFC PATCH v3 03/10] iommu/riscv: report iommu capabilities fangyu.yu
2026-08-21 13:27 ` fangyu.yu
2026-08-21 13:27 ` [RFC PATCH v3 04/10] iommu/riscv: use data structure instead of individual values fangyu.yu
2026-08-21 13:27 ` fangyu.yu
2026-08-21 13:27 ` fangyu.yu [this message]
2026-08-21 13:27 ` [RFC PATCH v3 05/10] iommu/riscv: support GSCID and GVMA invalidation command fangyu.yu
2026-08-21 13:27 ` [RFC PATCH v3 06/10] RISC-V: KVM: Enable KVM_VFIO interfaces on RISC-V arch fangyu.yu
2026-08-21 13:27 ` fangyu.yu
2026-08-21 13:27 ` [RFC PATCH v3 07/10] iommu/riscv: Add domain_alloc_paging_flags for second-stage domain fangyu.yu
2026-08-21 13:27 ` fangyu.yu
2026-08-21 13:27 ` [RFC PATCH v3 08/10] iommu/riscv: Pre-enable GADE for second-stage domains fangyu.yu
2026-08-21 13:27 ` fangyu.yu
2026-08-21 13:27 ` [RFC PATCH v3 09/10] iommu/riscv: Add dirty tracking support " fangyu.yu
2026-08-21 13:27 ` 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=20260821132749.82070-6-fangyu.yu@linux.alibaba.com \
--to=fangyu.yu@linux.alibaba.com \
--cc=alex@ghiti.fr \
--cc=andrew.jones@oss.qualcomm.com \
--cc=anup@brainfault.org \
--cc=aou@eecs.berkeley.edu \
--cc=atish.patra@linux.dev \
--cc=baolu.lu@linux.intel.com \
--cc=guoren@kernel.org \
--cc=iommu@lists.linux.dev \
--cc=jgg@nvidia.com \
--cc=jgg@ziepe.ca \
--cc=joro@8bytes.org \
--cc=jroedel@suse.de \
--cc=kevin.tian@intel.com \
--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=skhawaja@google.com \
--cc=tomasz.jeznach@linux.dev \
--cc=vasant.hegde@amd.com \
--cc=will@kernel.org \
--cc=zong.li@sifive.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.