[RFC PATCH v3 00/14] iommu/riscv: Add irqbypass support
Andrew Jones
andrew.jones at oss.qualcomm.com
Mon Sep 28 07:30:59 PDT 2026
This series adds the RISC-V IOMMU side of IRQ bypass, allowing MSIs from
assigned devices to be delivered directly to guest IMSIC interrupt files.
It uses the IOMMU's flat MSI page table to translate guest IMSIC addresses
to their host backing, with support for both hardware guest interrupt
files (VS-files) and memory-resident interrupt files (MRIFs).
It has been a year since v2[1], and much of the design and implementation
has changed. Host MSI remapping, IOMMU_DMA, and VFIO enablement have been
split into a prerequisite series[3]. This posting contains only the
IOMMU/IRQ-side support. The KVM patches will be posted separately: they
are currently a minimal client for testing this interface, with further
work needed for general device assignment.
The design evolved while considering two-stage guests in the discussions
with Jason on v4 of the host MSI-remapping series[2]. With a guest vIOMMU,
the address in the device's MSI message may be any guest IOVA which the
guest's first-stage page tables map to a guest IMSIC GPA. The hypervisor
cannot determine the target vCPU simply by decoding that IOVA. Instead,
the intended hardware path is:
Guest MSI IOVA -> S1 -> guest IMSIC GPA -> MSI table -> VS-file or MRIF
An MSI-table match completes the translation; addresses outside the MSI
pattern use the ordinary second-stage page tables. With S1 Bare, the
device uses the guest IMSIC GPA directly. Populating the MSI table with
all guest IMSIC targets allows guest changes to S1 mappings or interrupt
affinity without corresponding MSI-table updates. When a vCPU's host
backing changes, the hypervisor updates the entry for that guest IMSIC
GPA, leaving the device message and guest S1 mapping unchanged.
The MSI table belongs to the second-stage IOMMU domain and is shared by
all devices attached to it. RISC-V requires second-stage translation to
be enabled when using the MSI table. This is separate from host MSI
remapping, which uses ordinary page-table mappings prepared by the common
DMA-IOMMU/iommufd code and composed by the IMSIC driver.
A per-IOMMU interrupt-remapping irqdomain, installed as the MSI parent of
eligible devices at probe time, provides the irq_set_vcpu_affinity()
entry point. The IRQ hierarchy remains stable across IOMMU domain changes.
The callback obtains the device from the MSI descriptor and operates on
its currently attached second-stage domain. The irqdomain has no private
per-IRQ mapping state or MSI table of its own.
The affinity protocol supplies an owner, the guest IMSIC address pattern
and mask, and the complete set of guest targets. The first forwarded IRQ
populates the table and installs its configuration in every attached
device context. Further IRQs share that table after checking the owner
and address layout. A separate target-update command changes a guest
IMSIC's backing without changing per-IRQ forwarding state. The last IRQ
to stop forwarding removes the table configuration from the devices.
The main changes since v2 are therefore:
- Separate host MSI remapping from guest IRQ bypass, and use second-stage
domains for the guest MSI tables
- Replace per-IRQ MSI-entry mapping and reference counting with complete
guest-topology setup, domain-wide table lifetime, and individual target
updates. This is intended to accommodate guest-controlled S1 mappings.
- Add IOMMU-side MRIF support alongside hardware guest interrupt files.
- Move the KVM client out of this series
This remains an RFC, particularly for the relationship between the IRQ
hierarchy and the domain-owned MSI table. Jason raised the alternative of
a per-VM irqdomain owning the table[2]; the arrangement proposed here
keeps the IRQ hierarchy stable and ties the mappings to the S2 domain
shared by the devices.
The dependency stack is based on linux-iommu/next at 634706fe6e36, with:
- "iommu/riscv: Enable MSI remapping, IOMMU_DMA and VFIO" v6[3].
- Fangyu's "iommu/riscv: Add hardware dirty tracking for second-stage
domains" RFC v4[4], which also supplies second-stage domain allocation
and page-table support.
The branch below contains all of the above, this series, and the minimal
KVM IRQ-bypass client:
https://github.com/jones-drew/linux/commits/riscv/iommu-irqbypass-rfc-v3-kvm/
Testing requires userspace to select a second-stage domain, for example
by allocating an iommufd HWPT with IOMMU_HWPT_ALLOC_NEST_PARENT. The
corresponding kvmtool branch is available here:
https://github.com/jones-drew/kvmtool/commits/iommufd-nested-rfc-v1/
LLM-based coding assistants were used during development for code
exploration, patch review, test execution, and drafting and editing
commit messages and this cover letter. I reviewed and finalized all
resulting code and text. Per-patch Assisted-by tags are omitted in
light of the ongoing discussion about simplifying coding-assistant
attribution.
Thanks,
drew
[1] https://lore.kernel.org/all/20250920203851.2205115-20-ajones@ventanamicro.com/
[2] https://lore.kernel.org/all/20260820214150.545737-3-andrew.jones@oss.qualcomm.com/
[3] https://lore.kernel.org/all/20260925151659.419512-1-andrew.jones@oss.qualcomm.com/
[4] https://lore.kernel.org/all/20260915032828.11250-1-fangyu.yu@linux.alibaba.com/
Andrew Jones (14):
iommu/riscv: Allocate MSI tables for second-stage domains
iommu/riscv: Prepare domain bonds for outer locking
iommu/riscv: Serialize MSI table publication with domain attachment
iommu/riscv: Reject live S2 replacement with forwarded IRQs
iommu/riscv: Derive the IOMMU from the device in IODIR updates
iommu/riscv: Cache the programmed device context
iommu/riscv: Prepare MSI table updates for interrupt remapping
irqchip/riscv-imsic: Define IOMMU IRQ bypass protocol
genirq/msi: Provide DOMAIN_BUS_MSI_REMAP
iommu/riscv: Add IRQ domain for interrupt remapping
iommu/riscv: Prepare info->domain for concurrent RCU access
iommu/riscv: Prepare interrupt remapping for IRQ bypass
iommu/riscv: Validate IRQ forwarding requests
iommu/riscv: Implement IRQ forwarding
drivers/iommu/riscv/Makefile | 1 +
drivers/iommu/riscv/iommu-bits.h | 27 ++
drivers/iommu/riscv/iommu-ir.c | 505 ++++++++++++++++++++++++
drivers/iommu/riscv/iommu.c | 352 +++++++++++++++--
drivers/iommu/riscv/iommu.h | 56 +++
drivers/irqchip/irq-msi-lib.c | 8 +-
drivers/irqchip/irq-riscv-imsic-state.c | 6 +
include/linux/irqchip/riscv-imsic.h | 60 +++
include/linux/irqdomain_defs.h | 1 +
9 files changed, 974 insertions(+), 42 deletions(-)
create mode 100644 drivers/iommu/riscv/iommu-ir.c
--
2.43.0
More information about the linux-riscv
mailing list