[PATCH v2 09/14] iommu/riscv: Publish IOMMU_RESV_SW_MSI region for iommufd MSI remapping
Andrew Jones <[email protected]> Fri, 24 Jul 2026 17:12:13 +0200
| Newsgroups | dev.linux.lists.iommu,org.infradead.lists.linux-riscv,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.c | 16 ++++++++++++++++ drivers/iommu/riscv/iommu.h | 3 +++ 2 files changed, 19 insertions(+) diff --git a/drivers/iommu/riscv/iommu.c b/drivers/iommu/riscv/iommu.c index 27dfd60834ac..98ce9ec50e65 100644 --- a/drivers/iommu/riscv/iommu.c +++ b/drivers/iommu/riscv/iommu.c @@ -1493,6 +1493,21 @@ 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) +{ + struct iommu_resv_region *region; + + if (!imsic_enabled()) + 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); +} + static const struct iommu_ops riscv_iommu_ops = { .of_xlate = riscv_iommu_of_xlate, .identity_domain = &riscv_iommu_identity_domain, @@ -1502,6 +1517,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..9a8fd5300675 100644 --- a/drivers/iommu/riscv/iommu.h +++ b/drivers/iommu/riscv/iommu.h @@ -20,6 +20,9 @@ #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 { -- 2.43.0