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@linux.dev,
anup@brainfault.org, jgg@nvidia.com, jgg@ziepe.ca,
kevin.tian@intel.com, atish.patra@linux.dev, skhawaja@google.com,
vasant.hegde@amd.com, joerg.roedel@amd.com,
tanchi25@mails.ucas.ac.cn, gong.shuai@sanechips.com.cn
Cc: fangyu.yu@linux.alibaba.com, guoren@kernel.org,
iommu@lists.linux.dev, linux-kernel@vger.kernel.org,
linux-riscv@lists.infradead.org, kvm-riscv@lists.infradead.org,
Nutty Liu <nutty.liu@hotmail.com>
Subject: [PATCH v6 05/10] iommu/riscv: support GSCID and GVMA invalidation command
Date: Sat, 31 Oct 2026 16:30:09 +0800 [thread overview]
Message-ID: <20261031083014.15040-6-fangyu.yu@linux.alibaba.com> (raw)
In-Reply-To: <20261031083014.15040-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>
Reviewed-by: Nutty Liu <nutty.liu@hotmail.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 918fce4aa8c4..162752bb698e 100644
--- a/drivers/iommu/riscv/iommu.c
+++ b/drivers/iommu/riscv/iommu.c
@@ -49,6 +49,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;
@@ -842,6 +846,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);
@@ -1004,7 +1009,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 &&
@@ -1012,8 +1017,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
@@ -1097,7 +1107,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;
}
@@ -1231,6 +1241,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);
@@ -1281,16 +1292,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;
@@ -1303,6 +1317,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)
@@ -1315,11 +1345,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
--
kvm-riscv mailing list
kvm-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kvm-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@linux.dev,
anup@brainfault.org, jgg@nvidia.com, jgg@ziepe.ca,
kevin.tian@intel.com, atish.patra@linux.dev, skhawaja@google.com,
vasant.hegde@amd.com, joerg.roedel@amd.com,
tanchi25@mails.ucas.ac.cn, gong.shuai@sanechips.com.cn
Cc: fangyu.yu@linux.alibaba.com, guoren@kernel.org,
iommu@lists.linux.dev, linux-kernel@vger.kernel.org,
linux-riscv@lists.infradead.org, kvm-riscv@lists.infradead.org,
Nutty Liu <nutty.liu@hotmail.com>
Subject: [PATCH v6 05/10] iommu/riscv: support GSCID and GVMA invalidation command
Date: Sat, 31 Oct 2026 16:30:09 +0800 [thread overview]
Message-ID: <20261031083014.15040-6-fangyu.yu@linux.alibaba.com> (raw)
In-Reply-To: <20261031083014.15040-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>
Reviewed-by: Nutty Liu <nutty.liu@hotmail.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 918fce4aa8c4..162752bb698e 100644
--- a/drivers/iommu/riscv/iommu.c
+++ b/drivers/iommu/riscv/iommu.c
@@ -49,6 +49,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;
@@ -842,6 +846,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);
@@ -1004,7 +1009,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 &&
@@ -1012,8 +1017,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
@@ -1097,7 +1107,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;
}
@@ -1231,6 +1241,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);
@@ -1281,16 +1292,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;
@@ -1303,6 +1317,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)
@@ -1315,11 +1345,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@linux.dev,
anup@brainfault.org, jgg@nvidia.com, jgg@ziepe.ca,
kevin.tian@intel.com, atish.patra@linux.dev, skhawaja@google.com,
vasant.hegde@amd.com, joerg.roedel@amd.com,
tanchi25@mails.ucas.ac.cn, gong.shuai@sanechips.com.cn
Cc: fangyu.yu@linux.alibaba.com, guoren@kernel.org,
iommu@lists.linux.dev, linux-kernel@vger.kernel.org,
linux-riscv@lists.infradead.org, kvm-riscv@lists.infradead.org,
Nutty Liu <nutty.liu@hotmail.com>
Subject: [PATCH v6 05/10] iommu/riscv: support GSCID and GVMA invalidation command
Date: Sat, 31 Oct 2026 16:30:09 +0800 [thread overview]
Message-ID: <20261031083014.15040-6-fangyu.yu@linux.alibaba.com> (raw)
In-Reply-To: <20261031083014.15040-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>
Reviewed-by: Nutty Liu <nutty.liu@hotmail.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 918fce4aa8c4..162752bb698e 100644
--- a/drivers/iommu/riscv/iommu.c
+++ b/drivers/iommu/riscv/iommu.c
@@ -49,6 +49,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;
@@ -842,6 +846,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);
@@ -1004,7 +1009,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 &&
@@ -1012,8 +1017,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
@@ -1097,7 +1107,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;
}
@@ -1231,6 +1241,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);
@@ -1281,16 +1292,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;
@@ -1303,6 +1317,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)
@@ -1315,11 +1345,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-10-31 8:30 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-31 8:30 [PATCH v6 00/10] iommu/riscv: Add hardware dirty tracking for second-stage domains fangyu.yu
2026-10-31 8:30 ` fangyu.yu
2026-10-31 8:30 ` fangyu.yu
2026-10-31 8:30 ` [PATCH v6 01/10] iommu/generic_pt: Fix the RISC-V supported feature mask fangyu.yu
2026-10-31 8:30 ` fangyu.yu
2026-10-31 8:30 ` fangyu.yu
2026-10-31 8:30 ` [PATCH v6 02/10] iommupt: Add RISC-V Second-stage (iohgatp) page table support fangyu.yu
2026-10-31 8:30 ` fangyu.yu
2026-10-31 8:30 ` fangyu.yu
2026-10-31 8:30 ` [PATCH v6 03/10] iommupt: Add RISC-V dirty tracking PTE ops fangyu.yu
2026-10-31 8:30 ` fangyu.yu
2026-10-31 8:30 ` fangyu.yu
2026-10-31 8:30 ` [PATCH v6 04/10] iommu/riscv: use data structure instead of individual values fangyu.yu
2026-10-31 8:30 ` fangyu.yu
2026-10-31 8:30 ` fangyu.yu
2026-10-31 8:30 ` fangyu.yu [this message]
2026-10-31 8:30 ` [PATCH v6 05/10] iommu/riscv: support GSCID and GVMA invalidation command fangyu.yu
2026-10-31 8:30 ` fangyu.yu
2026-10-31 8:30 ` [PATCH v6 06/10] RISC-V: KVM: Enable KVM_VFIO interfaces on RISC-V arch fangyu.yu
2026-10-31 8:30 ` fangyu.yu
2026-10-31 8:30 ` fangyu.yu
2026-10-31 8:30 ` [PATCH v6 07/10] iommu/riscv: Add domain_alloc_paging_flags for second-stage domain fangyu.yu
2026-10-31 8:30 ` fangyu.yu
2026-10-31 8:30 ` fangyu.yu
2026-10-31 8:30 ` [PATCH v6 08/10] iommu/riscv: Pre-enable GADE for second-stage domains fangyu.yu
2026-10-31 8:30 ` fangyu.yu
2026-10-31 8:30 ` fangyu.yu
2026-10-31 8:30 ` [PATCH v6 09/10] iommu/riscv: Add dirty tracking support " fangyu.yu
2026-10-31 8:30 ` fangyu.yu
2026-10-31 8:30 ` fangyu.yu
2026-11-02 9:18 ` Gong Shuai
2026-11-02 9:18 ` Gong Shuai
2026-11-02 9:18 ` Gong Shuai
2026-11-02 13:13 ` Jason Gunthorpe
2026-11-02 13:13 ` Jason Gunthorpe
2026-11-02 13:13 ` Jason Gunthorpe
2026-11-02 13:21 ` fangyu.yu
2026-11-02 13:21 ` fangyu.yu
2026-11-02 13:21 ` fangyu.yu
2026-10-31 8:30 ` [PATCH v6 10/10] iommu/riscv: Add IOTINVAL.GVMA invalidations fangyu.yu
2026-10-31 8:30 ` fangyu.yu
2026-10-31 8:30 ` 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=20261031083014.15040-6-fangyu.yu@linux.alibaba.com \
--to=fangyu.yu@linux.alibaba.com \
--cc=alex@ghiti.fr \
--cc=andrew.jones@linux.dev \
--cc=anup@brainfault.org \
--cc=aou@eecs.berkeley.edu \
--cc=atish.patra@linux.dev \
--cc=baolu.lu@linux.intel.com \
--cc=gong.shuai@sanechips.com.cn \
--cc=guoren@kernel.org \
--cc=iommu@lists.linux.dev \
--cc=jgg@nvidia.com \
--cc=jgg@ziepe.ca \
--cc=joerg.roedel@amd.com \
--cc=joro@8bytes.org \
--cc=jroedel@suse.de \
--cc=kevin.tian@intel.com \
--cc=kvm-riscv@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-riscv@lists.infradead.org \
--cc=nutty.liu@hotmail.com \
--cc=palmer@dabbelt.com \
--cc=pjw@kernel.org \
--cc=robin.murphy@arm.com \
--cc=skhawaja@google.com \
--cc=tanchi25@mails.ucas.ac.cn \
--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.