[RFC PATCH 04/12] iommu/riscv: Add vIOMMU object support
Gong Shuai
gong.shuai at sanechips.com.cn
Wed Oct 14 23:52:24 PDT 2026
From: Wu Fei <wu.fei9 at sanechips.com.cn>
Implement the vIOMMU ops so user space can allocate a RISC-V IOMMU
vIOMMU on a stage-2 parent domain and query the size to allocate for
it. The object keeps the parent domain and the GSCID the parent was
allocated, which the nested domain and cache invalidation support added
on top of it will need.
Signed-off-by: Wu Fei <wu.fei9 at sanechips.com.cn>
Signed-off-by: Gong Shuai <gong.shuai at sanechips.com.cn>
---
drivers/iommu/riscv/iommu.c | 60 +++++++++++++++++++++++++++++++++++++
1 file changed, 60 insertions(+)
diff --git a/drivers/iommu/riscv/iommu.c b/drivers/iommu/riscv/iommu.c
index dd97c2731d95..bf02cd984d86 100644
--- a/drivers/iommu/riscv/iommu.c
+++ b/drivers/iommu/riscv/iommu.c
@@ -19,6 +19,7 @@
#include <linux/dma-map-ops.h>
#include <linux/init.h>
#include <linux/iommu.h>
+#include <linux/iommufd.h>
#include <linux/iopoll.h>
#include <linux/irqchip/riscv-imsic.h>
#include <linux/kernel.h>
@@ -862,6 +863,7 @@ struct riscv_iommu_domain {
struct mutex mutex; /* serialize domain state updates */
int pscid;
int gscid;
+ bool nest_parent;
struct riscv_iommu_msi_table msi_table;
};
PT_IOMMU_CHECK_DOMAIN(struct riscv_iommu_domain, riscvpt.iommu, domain);
@@ -1497,6 +1499,20 @@ static bool riscv_iommu_iohgatp_supported(struct riscv_iommu_device *iommu,
return false;
}
+static bool riscv_iommu_supports_s1(struct riscv_iommu_device *iommu)
+{
+ return (iommu->caps & RISCV_IOMMU_CAPABILITIES_SV57) ||
+ (iommu->caps & RISCV_IOMMU_CAPABILITIES_SV48) ||
+ (iommu->caps & RISCV_IOMMU_CAPABILITIES_SV39);
+}
+
+static bool riscv_iommu_supports_s2(struct riscv_iommu_device *iommu)
+{
+ return (iommu->caps & RISCV_IOMMU_CAPABILITIES_SV57X4) ||
+ (iommu->caps & RISCV_IOMMU_CAPABILITIES_SV48X4) ||
+ (iommu->caps & RISCV_IOMMU_CAPABILITIES_SV39X4);
+}
+
static int riscv_iommu_msi_table_alloc(struct riscv_iommu_domain *domain,
struct riscv_iommu_device *iommu,
struct riscv_iommu_info *info)
@@ -1734,6 +1750,7 @@ riscv_iommu_domain_alloc_paging_flags(struct device *dev, u32 flags,
ret = -ENOMEM;
goto err_free;
}
+ domain->nest_parent = !!(flags & IOMMU_HWPT_ALLOC_NEST_PARENT);
/*
* Capture the current number of MSI PTEs now since it must remain
@@ -1906,6 +1923,47 @@ static void riscv_iommu_release_device(struct device *dev)
kfree_rcu_mightsleep(info);
}
+struct riscv_viommu {
+ struct iommufd_viommu core;
+ struct riscv_iommu_device *iommu;
+ struct riscv_iommu_domain *s2_parent;
+ int gscid;
+};
+
+static const struct iommufd_viommu_ops riscv_viommu_ops = {
+};
+
+static size_t riscv_iommu_get_viommu_size(struct device *dev,
+ enum iommu_viommu_type viommu_type)
+{
+ struct riscv_iommu_device *iommu = dev_to_iommu(dev);
+
+ if (viommu_type != IOMMU_VIOMMU_TYPE_RISCV)
+ return 0;
+
+ if (!riscv_iommu_supports_s1(iommu) || !riscv_iommu_supports_s2(iommu))
+ return 0;
+
+ return VIOMMU_STRUCT_SIZE(struct riscv_viommu, core);
+}
+
+static int riscv_viommu_init(struct iommufd_viommu *viommu,
+ struct iommu_domain *parent_domain,
+ const struct iommu_user_data *user_data)
+{
+ struct riscv_viommu *rv_viommu = container_of(viommu, struct riscv_viommu, core);
+ struct riscv_iommu_device *iommu =
+ container_of(viommu->iommu_dev, struct riscv_iommu_device, iommu);
+ struct riscv_iommu_domain *s2_parent = iommu_domain_to_riscv(parent_domain);
+
+ rv_viommu->iommu = iommu;
+ rv_viommu->s2_parent = s2_parent;
+ rv_viommu->gscid = s2_parent->gscid;
+ viommu->ops = &riscv_viommu_ops;
+
+ return 0;
+}
+
static void riscv_iommu_get_resv_regions(struct device *dev, struct list_head *head)
{
struct iommu_resv_region *region;
@@ -1930,6 +1988,8 @@ static const struct iommu_ops riscv_iommu_ops = {
.blocked_domain = &riscv_iommu_blocking_domain,
.release_domain = &riscv_iommu_blocking_domain,
.domain_alloc_paging_flags = riscv_iommu_domain_alloc_paging_flags,
+ .get_viommu_size = riscv_iommu_get_viommu_size,
+ .viommu_init = riscv_viommu_init,
.device_group = riscv_iommu_device_group,
.probe_device = riscv_iommu_probe_device,
.release_device = riscv_iommu_release_device,
--
2.53.0
More information about the kvm-riscv
mailing list