[PATCH v3 09/19] iommu/riscv: Publish IOMMU_RESV_SW_MSI region for iommufd MSI remapping
Andrew Jones <[email protected]>
| Newsgroups | org.infradead.lists.linux-riscv,dev.linux.lists.iommu,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
iommufd's SW MSI path (iommufd_sw_map_msi) requires an IOMMU_RESV_SW_MSI reservation region to know the IOVA base (sw_msi_start) for MSI page mappings. Without it, sw_msi_start stays at PHYS_ADDR_MAX and iommufd_sw_map_msi silently returns passthrough. Add a get_resv_regions callback that, when IMSIC-based MSI is in use, reserves an IOVA range of num_possible_cpus() pages starting at RISCV_IOMMU_MSI_IOVA_BASE. This is large enough to hold one 4 KiB IMSIC supervisor page per hart. RISCV_IOMMU_MSI_IOVA_BASE is set to 128 MiB, matching the ARM SMMU convention. That value is arbitrary for ARM too; its introducing commit (f3ebee80b313) calls it an "arbitrary MSI IOVA window", so there is nothing riscv-specific lost by reusing it here. Signed-off-by: Andrew Jones <[email protected]> --- drivers/iommu/riscv/iommu-ir.c | 16 ++++++++++++++++ drivers/iommu/riscv/iommu.c | 8 ++++++++ drivers/iommu/riscv/iommu.h | 5 +++++ 3 files changed, 29 insertions(+) diff --git a/drivers/iommu/riscv/iommu-ir.c b/drivers/iommu/riscv/iommu-ir.c index 5873addf2a1b..1e157faf7bbe 100644 --- a/drivers/iommu/riscv/iommu-ir.c +++ b/drivers/iommu/riscv/iommu-ir.c @@ -117,3 +117,19 @@ int riscv_iommu_ir_attach_paging_domain(struct iommu_domain *iommu_domain, struc void riscv_iommu_ir_free_paging_domain(struct iommu_domain *iommu_domain) { } + +void riscv_iommu_ir_get_resv_regions(struct device *dev, struct list_head *head) +{ + struct riscv_iommu_info *info = dev_iommu_priv_get(dev); + struct iommu_resv_region *region; + + if (!info || !info->irqdomain) + return; + + region = iommu_alloc_resv_region(RISCV_IOMMU_MSI_IOVA_BASE, + (size_t)num_possible_cpus() * PAGE_SIZE, + IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO, + IOMMU_RESV_SW_MSI, GFP_KERNEL); + if (region) + list_add_tail(®ion->list, head); +} diff --git a/drivers/iommu/riscv/iommu.c b/drivers/iommu/riscv/iommu.c index 27dfd60834ac..106cc8216942 100644 --- a/drivers/iommu/riscv/iommu.c +++ b/drivers/iommu/riscv/iommu.c @@ -23,6 +23,7 @@ #include <linux/kernel.h> #include <linux/pci.h> +#include "../dma-iommu.h" #include "../iommu-pages.h" #include "iommu-bits.h" #include "iommu.h" @@ -1493,6 +1494,12 @@ static void riscv_iommu_release_device(struct device *dev) kfree_rcu_mightsleep(info); } +static void riscv_iommu_get_resv_regions(struct device *dev, struct list_head *head) +{ + riscv_iommu_ir_get_resv_regions(dev, head); + iommu_dma_get_resv_regions(dev, head); +} + static const struct iommu_ops riscv_iommu_ops = { .of_xlate = riscv_iommu_of_xlate, .identity_domain = &riscv_iommu_identity_domain, @@ -1502,6 +1509,7 @@ static const struct iommu_ops riscv_iommu_ops = { .device_group = riscv_iommu_device_group, .probe_device = riscv_iommu_probe_device, .release_device = riscv_iommu_release_device, + .get_resv_regions = riscv_iommu_get_resv_regions, }; static int riscv_iommu_init_check(struct riscv_iommu_device *iommu) diff --git a/drivers/iommu/riscv/iommu.h b/drivers/iommu/riscv/iommu.h index ded18aec8010..16b3c9c4cf8c 100644 --- a/drivers/iommu/riscv/iommu.h +++ b/drivers/iommu/riscv/iommu.h @@ -16,10 +16,14 @@ #include <linux/iopoll.h> #include <linux/irqdomain.h> #include <linux/rcupdate.h> +#include <linux/sizes.h> #include <linux/generic_pt/iommu.h> #include "iommu-bits.h" +/* IOVA base for the SW MSI reservation; same convention as ARM SMMU. */ +#define RISCV_IOMMU_MSI_IOVA_BASE SZ_128M + /* This struct contains protection domain specific IOMMU driver data. */ struct riscv_iommu_domain { union { @@ -93,6 +97,7 @@ void riscv_iommu_ir_irq_domain_remove(struct device *dev, struct riscv_iommu_inf int riscv_iommu_ir_attach_paging_domain(struct iommu_domain *iommu_domain, struct device *dev, struct iommu_domain *old); void riscv_iommu_ir_free_paging_domain(struct iommu_domain *iommu_domain); +void riscv_iommu_ir_get_resv_regions(struct device *dev, struct list_head *head); #define riscv_iommu_readl(iommu, addr) \ readl_relaxed((iommu)->reg + (addr)) -- 2.43.0 _______________________________________________ linux-riscv mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-riscv