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 v3 13/19] iommu/riscv: Implement irq_compose_msi_msg for IMSIC remapping
Date: Fri, 7 Aug 2026 20:17:07 +0200 [thread overview]
Message-ID: <20260807181713.228535-14-andrew.jones@oss.qualcomm.com> (raw)
In-Reply-To: <20260807181713.228535-1-andrew.jones@oss.qualcomm.com>
Wire up irq_compose_msi_msg() on the IOMMU-IR irq chip to look up the
pre-mapped IOVA for the target IMSIC page and rewrite the composed
message to use it, redirecting MSI writes through the IOMMU instead
of landing at the raw IMSIC physical address.
The lookup is O(1), since the "extract" function used to build the
table's index is also used here, which is necessary since the number
of IMSICs may eventually be in the hundreds and irq_compose_msi_msg()
may run in atomic context.
domain->msi_iova is read here without domain->mutex, since compose can
run in atomic context, and RCU only protects info->domain itself. Pair
smp_store_release()/smp_load_acquire() on domain->msi_iova to ensure
it's observably filled before publishing its pointer. That guarantees
a non-NULL domain->msi_iova observed here is safe to use.
A NULL domain->msi_iova falls back to the raw IMSIC physical address,
same as when info->domain itself is NULL, since a live paging domain
should not normally reach compose without a populated table.
Signed-off-by: Andrew Jones <andrew.jones@oss.qualcomm.com>
---
drivers/iommu/riscv/iommu-ir.c | 49 +++++++++++++++++++++++++++++++---
1 file changed, 45 insertions(+), 4 deletions(-)
diff --git a/drivers/iommu/riscv/iommu-ir.c b/drivers/iommu/riscv/iommu-ir.c
index 7d9a1eaca92e..98be3e3fddad 100644
--- a/drivers/iommu/riscv/iommu-ir.c
+++ b/drivers/iommu/riscv/iommu-ir.c
@@ -91,17 +91,56 @@ static int riscv_iommu_ir_build_msi_iova(struct riscv_iommu_domain *domain, stru
return ret;
}
- domain->msi_iova = no_free_ptr(msi_iova);
+ /* Pair with smp_load_acquire() in riscv_iommu_ir_compose_msi_msg() */
+ smp_store_release(&domain->msi_iova, no_free_ptr(msi_iova));
return 0;
}
+static void riscv_iommu_ir_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
+{
+ struct riscv_iommu_info *info = data->domain->host_data;
+ struct riscv_iommu_domain *domain;
+ dma_addr_t *msi_iova;
+ struct msi_desc *desc;
+ phys_addr_t pa;
+ size_t idx;
+
+ BUG_ON(irq_chip_compose_msi_msg(data->parent_data, msg));
+
+ desc = irq_data_get_msi_desc(data);
+ if (WARN_ON_ONCE(!desc))
+ return;
+
+ guard(rcu)();
+
+ domain = rcu_dereference(info->domain);
+ if (!domain) {
+ msi_desc_set_iommu_msi_iova(desc, 0, 0);
+ return;
+ }
+
+ /* Pair with smp_store_release() in riscv_iommu_ir_build_msi_iova() */
+ msi_iova = smp_load_acquire(&domain->msi_iova);
+ if (!msi_iova) {
+ msi_desc_set_iommu_msi_iova(desc, 0, 0);
+ return;
+ }
+
+ pa = ((u64)msg->address_hi << 32) | msg->address_lo;
+ idx = riscv_iommu_ir_msi_iova_idx(pa);
+
+ msi_desc_set_iommu_msi_iova(desc, msi_iova[idx], IMSIC_MMIO_PAGE_SHIFT);
+ msi_msg_set_addr(desc, msg, pa);
+}
+
static struct irq_chip riscv_iommu_ir_irq_chip = {
.name = "IOMMU-IR",
.irq_ack = irq_chip_ack_parent,
.irq_mask = irq_chip_mask_parent,
.irq_unmask = irq_chip_unmask_parent,
.irq_set_affinity = irq_chip_set_affinity_parent,
+ .irq_compose_msi_msg = riscv_iommu_ir_compose_msi_msg,
};
static int riscv_iommu_ir_irq_domain_alloc_irqs(struct irq_domain *irqdomain,
@@ -267,10 +306,12 @@ int riscv_iommu_ir_attach_paging_domain(struct iommu_domain *iommu_domain, struc
if (msi_iova) {
guard(mutex)(&domain->mutex);
- if (domain->msi_iova)
+ if (domain->msi_iova) {
kfree(msi_iova);
- else
- domain->msi_iova = msi_iova;
+ } else {
+ /* Pair with smp_load_acquire() in riscv_iommu_ir_compose_msi_msg() */
+ smp_store_release(&domain->msi_iova, msi_iova);
+ }
return 0;
}
--
2.43.0
next prev parent reply other threads:[~2026-08-07 18:17 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-07 18:16 [PATCH v3 00/19] iommu/riscv: Enable MSI remapping, IOMMU_DMA and VFIO Andrew Jones
2026-08-07 18:16 ` [PATCH v3 01/19] iommufd: Convert struct iommufd_sw_msi_maps to a growable bitmap Andrew Jones
2026-08-07 18:16 ` [PATCH v3 02/19] iommufd: Add iommufd_sw_map_msi() Andrew Jones
2026-08-07 18:16 ` [PATCH v3 03/19] iommu/dma: Add iommu_dma_sw_map_msi() Andrew Jones
2026-08-07 18:16 ` [PATCH v3 04/19] iommu/dma: Add iommu_dma_map_msi() Andrew Jones
2026-08-07 18:16 ` [PATCH v3 05/19] genirq/msi: Provide DOMAIN_BUS_MSI_REMAP Andrew Jones
2026-08-07 18:17 ` [PATCH v3 06/19] irqchip/riscv-imsic: Compose MSI updates through the hierarchy Andrew Jones
2026-08-07 20:25 ` Thomas Gleixner
2026-08-10 8:01 ` Andrew Jones
2026-08-07 18:17 ` [PATCH v3 07/19] iommu/riscv: Add IRQ domain for interrupt remapping Andrew Jones
2026-08-07 20:32 ` Thomas Gleixner
2026-08-07 20:36 ` Thomas Gleixner
2026-08-10 8:11 ` Andrew Jones
2026-08-07 18:17 ` [PATCH v3 08/19] iommu/riscv: Prepare info->domain for concurrent RCU read access Andrew Jones
2026-08-07 18:17 ` [PATCH v3 09/19] iommu/riscv: Publish IOMMU_RESV_SW_MSI region for iommufd MSI remapping Andrew Jones
2026-08-07 18:17 ` [PATCH v3 10/19] iommu/riscv: Pre-map IMSIC MSI targets Andrew Jones
2026-08-07 18:17 ` [PATCH v3 11/19] iommu/riscv: Copy MSI IOVA table when replacing an iommufd domain Andrew Jones
2026-08-07 18:17 ` [PATCH v3 12/19] iommu/riscv: Gate identity boundary switches with live MSIs Andrew Jones
2026-08-07 18:17 ` Andrew Jones [this message]
2026-08-07 18:17 ` [PATCH v3 14/19] iommu/dma: Enable IOMMU_DMA for 64-bit RISC-V Andrew Jones
2026-08-07 18:17 ` [PATCH v3 15/19] iommu/riscv: report iommu capabilities Andrew Jones
2026-08-07 18:17 ` [PATCH v3 16/19] vfio: enable IOMMU_TYPE1 for RISC-V Andrew Jones
2026-08-07 18:17 ` [PATCH v3 17/19] RISC-V: KVM: Enable KVM_VFIO interfaces on RISC-V arch Andrew Jones
2026-08-07 18:17 ` [PATCH v3 18/19] riscv: defconfig: Enable IOMMUFD and VFIO Andrew Jones
2026-08-07 18:17 ` [PATCH v3 19/19] selftests/vfio: Allow building on RISC-V Andrew Jones
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=20260807181713.228535-14-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®