mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Andrew Jones <andrew.jones@oss.qualcomm.com>
To: linux-riscv@lists.infradead.org, iommu@lists.linux.dev
Cc: linux-kernel@vger.kernel.org, tomasz.jeznach@linux.dev,
	tjeznach@rivosinc.com, jgg@ziepe.ca, jgg@nvidia.com,
	joro@8bytes.org, will@kernel.org, robin.murphy@arm.com,
	pjw@kernel.org, palmer@dabbelt.com, anup@brainfault.org,
	tglx@kernel.org, kevin.tian@intel.com,
	fangyu.yu@linux.alibaba.com
Subject: [PATCH v6 09/16] iommu/riscv: Reserve an MSI IOVA window for iommufd
Date: Fri, 25 Sep 2026 17:16:52 +0200	[thread overview]
Message-ID: <20260925151659.419512-10-andrew.jones@oss.qualcomm.com> (raw)
In-Reply-To: <20260925151659.419512-1-andrew.jones@oss.qualcomm.com>

iommufd requires an IOMMU_RESV_SW_MSI region to allocate stable IOVAs
for MSI targets. Advertise such a region when the device uses an IMSIC
MSI hierarchy so interrupt remapping can map IMSIC pages instead of
falling back to physical addresses.

Reserve one page per possible CPU, sufficient for each supervisor IMSIC
page. Use a 16 MiB base instead of the 128 MiB convention used by ARM
SMMU. kvmtool places its guest IMSIC at 128 MiB, so with IRQ bypass the
domain-wide guest MSI address match can also capture host-delivered
MSI writes to the SW MSI window and misdeliver them to the guest.

16 MiB falls in a hole in the current kvmtool and QEMU virt memory maps,
away from their guest IMSIC windows and RAM. Keep the window below
4 GiB so devices with 32-bit MSI address registers can use it.

This only avoids known conflicts. A VMM can place a guest's IMSIC at
any valid address, including the chosen SW MSI range. As long as a
fixed SW MSI window is required, changing its base cannot solve this
in general or guarantee disjoint host and guest MSI address spaces.

Signed-off-by: Andrew Jones <andrew.jones@oss.qualcomm.com>
Tested-by: Fangyu Yu <fangyu.yu@linux.alibaba.com>
---
 drivers/iommu/riscv/iommu.c             | 20 ++++++++++++++++++++
 drivers/iommu/riscv/iommu.h             |  4 ++++
 drivers/irqchip/irq-riscv-imsic-state.c | 22 ++++++++++++++++++++++
 include/linux/irqchip/riscv-imsic.h     |  6 ++++++
 4 files changed, 52 insertions(+)

diff --git a/drivers/iommu/riscv/iommu.c b/drivers/iommu/riscv/iommu.c
index fbdca69c436e..dcad99131670 100644
--- a/drivers/iommu/riscv/iommu.c
+++ b/drivers/iommu/riscv/iommu.c
@@ -20,10 +20,12 @@
 #include <linux/init.h>
 #include <linux/iommu.h>
 #include <linux/iopoll.h>
+#include <linux/irqchip/riscv-imsic.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/generic_pt/iommu.h>
 
+#include "../dma-iommu.h"
 #include "../iommu-pages.h"
 #include "iommu-bits.h"
 #include "iommu.h"
@@ -1514,6 +1516,23 @@ 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_dev_has_imsic_msi_parent(dev)) {
+		/* Each hart has one S-mode IMSIC page, a.k.a MSI target page */
+		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(&region->list, head);
+	}
+
+	iommu_dma_get_resv_regions(dev, head);
+}
+
 static const struct iommu_ops riscv_iommu_ops = {
 	.of_xlate = riscv_iommu_of_xlate,
 	.capable = riscv_iommu_capable,
@@ -1524,6 +1543,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 5676001548cc..6d5c70e9ac6d 100644
--- a/drivers/iommu/riscv/iommu.h
+++ b/drivers/iommu/riscv/iommu.h
@@ -15,9 +15,13 @@
 #include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/iopoll.h>
+#include <linux/sizes.h>
 
 #include "iommu-bits.h"
 
+/* IOVA base for the SW MSI reservation */
+#define RISCV_IOMMU_MSI_IOVA_BASE	SZ_16M
+
 struct riscv_iommu_device;
 
 struct riscv_iommu_queue {
diff --git a/drivers/irqchip/irq-riscv-imsic-state.c b/drivers/irqchip/irq-riscv-imsic-state.c
index b8d1bbbf42f7..df38a7670a89 100644
--- a/drivers/irqchip/irq-riscv-imsic-state.c
+++ b/drivers/irqchip/irq-riscv-imsic-state.c
@@ -64,6 +64,28 @@ const struct imsic_global_config *imsic_get_global_config(void)
 }
 EXPORT_SYMBOL_GPL(imsic_get_global_config);
 
+/**
+ * imsic_dev_has_imsic_msi_parent - Check for an IMSIC MSI parent
+ * @dev: Device to check
+ *
+ * Return: true if @dev's MSI domain or any parent domain is the IMSIC base
+ * domain.
+ */
+bool imsic_dev_has_imsic_msi_parent(struct device *dev)
+{
+	struct irq_domain *domain;
+
+	if (!imsic || !imsic->base_domain)
+		return false;
+
+	for (domain = dev_get_msi_domain(dev); domain; domain = domain->parent)
+		if (domain == imsic->base_domain)
+			return true;
+
+	return false;
+}
+EXPORT_SYMBOL_GPL(imsic_dev_has_imsic_msi_parent);
+
 static bool __imsic_eix_read_clear(unsigned long id, bool pend)
 {
 	unsigned long isel, imask;
diff --git a/include/linux/irqchip/riscv-imsic.h b/include/linux/irqchip/riscv-imsic.h
index 61af3a5bea09..662cb0442424 100644
--- a/include/linux/irqchip/riscv-imsic.h
+++ b/include/linux/irqchip/riscv-imsic.h
@@ -81,6 +81,7 @@ struct imsic_global_config {
 #ifdef CONFIG_RISCV_IMSIC
 
 const struct imsic_global_config *imsic_get_global_config(void);
+bool imsic_dev_has_imsic_msi_parent(struct device *dev);
 
 #else
 
@@ -89,6 +90,11 @@ static inline const struct imsic_global_config *imsic_get_global_config(void)
 	return NULL;
 }
 
+static inline bool imsic_dev_has_imsic_msi_parent(struct device *dev)
+{
+	return false;
+}
+
 #endif
 
 #if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_RISCV_IMSIC)
-- 
2.43.0


  parent reply	other threads:[~2026-09-25 15:17 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-25 15:16 [PATCH v6 00/16] iommu/riscv: Enable MSI remapping, IOMMU_DMA and VFIO Andrew Jones
2026-09-25 15:16 ` [PATCH v6 01/16] iommu/dma: Prepare MSI physical address lists Andrew Jones
2026-10-02 16:21   ` Robin Murphy
2026-10-03 12:03     ` Andrew Jones
2026-10-03 12:10       ` Jason Gunthorpe
2026-09-25 15:16 ` [PATCH v6 02/16] iommufd: Convert struct iommufd_sw_msi_maps to a growable bitmap Andrew Jones
2026-10-15 19:35   ` Jason Gunthorpe
2026-09-25 15:16 ` [PATCH v6 03/16] iommufd: Split software MSI map lookup and allocation Andrew Jones
2026-09-25 15:16 ` [PATCH v6 04/16] iommufd: Bound software MSI mappings to the reserved range Andrew Jones
2026-09-25 15:16 ` [PATCH v6 05/16] iommufd: Prepare software MSI maps for address lists Andrew Jones
2026-09-25 15:16 ` [PATCH v6 06/16] iommufd: Install software MSI map ranges atomically Andrew Jones
2026-09-25 15:16 ` [PATCH v6 07/16] iommufd: Prepare software MSI installation for address lists Andrew Jones
2026-09-28 10:23   ` Andrew Jones
2026-09-25 15:16 ` [PATCH v6 08/16] iommu/dma: Introduce iommu_dma_prepare_msi_list() Andrew Jones
2026-09-25 15:16 ` Andrew Jones [this message]
2026-10-15 19:35   ` [PATCH v6 09/16] iommu/riscv: Reserve an MSI IOVA window for iommufd Jason Gunthorpe
2026-10-15 19:51     ` Nicolin Chen
2026-10-22 14:40       ` Andrew Jones
2026-09-25 15:16 ` [PATCH v6 10/16] irqchip/riscv-imsic: Add MSI address list Andrew Jones
2026-09-25 15:51   ` Anup Patel
2026-10-15 21:33     ` Thomas Gleixner
2026-09-28  3:27   ` Nutty.Liu
2026-09-28 10:20   ` Andrew Jones
2026-10-15 21:32   ` Thomas Gleixner
2026-09-25 15:16 ` [PATCH v6 11/16] irqchip/riscv-imsic: Support IOMMU MSI address lists Andrew Jones
2026-09-25 15:52   ` Anup Patel
2026-09-28  3:18   ` Nutty.Liu
2026-10-15 21:32   ` Thomas Gleixner
2026-09-25 15:16 ` [PATCH v6 12/16] iommu/dma: Enable IOMMU_DMA for 64-bit RISC-V Andrew Jones
2026-09-28  3:17   ` Nutty.Liu
2026-09-25 15:16 ` [PATCH v6 13/16] vfio: enable IOMMU_TYPE1 for RISC-V Andrew Jones
2026-09-25 15:16 ` [PATCH v6 14/16] RISC-V: KVM: Enable KVM_VFIO interfaces on RISC-V arch Andrew Jones
2026-09-25 15:51   ` Anup Patel
2026-09-25 15:16 ` [PATCH v6 15/16] riscv: defconfig: Enable IOMMUFD and VFIO Andrew Jones
2026-09-28  3:17   ` Nutty.Liu
2026-09-25 15:16 ` [PATCH v6 16/16] selftests/vfio: Allow building on RISC-V Andrew Jones
2026-09-28  3:16   ` Nutty.Liu
2026-09-28 10:24 ` [PATCH v6 00/16] iommu/riscv: Enable MSI remapping, IOMMU_DMA and VFIO Andrew Jones
2026-10-15 19:35 ` Jason Gunthorpe

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=20260925151659.419512-10-andrew.jones@oss.qualcomm.com \
    --to=andrew.jones@oss.qualcomm.com \
    --cc=anup@brainfault.org \
    --cc=fangyu.yu@linux.alibaba.com \
    --cc=iommu@lists.linux.dev \
    --cc=jgg@nvidia.com \
    --cc=jgg@ziepe.ca \
    --cc=joro@8bytes.org \
    --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=tglx@kernel.org \
    --cc=tjeznach@rivosinc.com \
    --cc=tomasz.jeznach@linux.dev \
    --cc=will@kernel.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®