[PATCH v4 0/2] iommu/iommufd: Expose PCI host bridge MMIO windows for opt-in IOVA avoidance

From: Guanghui Feng

Date: Sun Oct 25 2026 - 09:31:45 EST


When a device sits behind a PCIe switch and ACS Upstream Forwarding is
not fully enabled, DMA TLPs whose IOVA happens to fall within a host
bridge MMIO window may be routed peer-to-peer to another downstream
device instead of upstream to the root complex for IOMMU translation.
This can lead to faults, data corruption, or silent misrouting.

The DMA IOVA layer already avoids this via iova_reserve_pci_windows().
However, passthrough paths that let userspace pick IOVAs (VFIO type1,
iommufd) had no mechanism to learn about these ranges. Commit
cd2c9fcf5c66 ("iommu/dma: Move PCI window region reservation back into
dma specific path.") intentionally keeps this information out of the
IOMMU reserved-region API to avoid pessimistically restricting
userspace.

Following Jason Gunthorpe's suggestion [1], this series takes an opt-in
approach: the kernel reports the information, userspace decides whether
to avoid it.

Patch 1 adds iommu_for_each_pci_mmio_window(), a callback-based
iterator in the IOMMU core that enumerates host bridge MMIO windows
with zero intermediate allocation. dma-iommu.c is refactored to use
it, sharing the same algorithm.

Patch 2 adds the IOMMU_GET_PCI_MMIO_WINDOWS ioctl to iommufd, a
per-device query that returns these windows to userspace without
reserving or enforcing them.

[1] https://lore.kernel.org/all/20260921115513.GK11599@xxxxxxxx/

v3: https://lore.kernel.org/all/20261004162213.3787623-1-guanghuifeng@xxxxxxxxxxxxxxxxx/
v2: https://lore.kernel.org/all/20260921103922.1113752-1-guanghuifeng@xxxxxxxxxxxxxxxxx/
v1: https://lore.kernel.org/all/20260921070234.897736-1-guanghuifeng@xxxxxxxxxxxxxxxxx/

Changes since v3:
- Patch 1: redesign helper as a callback-based iterator
(iommu_for_each_pci_mmio_window) per Jason's review [2]. This
eliminates intermediate iommu_resv_region allocations, avoids size_t
truncation on 32-bit PAE (callback receives phys_addr_t directly),
and allows dma-iommu.c to share the same algorithm with zero overhead.
- Patch 1: dma-iommu.c now uses the shared iterator as Jason requested
("if you are going to add a function to the iommu core then
dma-iommu.c should also use it").
- Patch 2: rename 'windows' field to 'out_windows' per iommufd
convention.
- Patch 2: remove irrelevant 1:1 IOVA discussion from kdoc (iommufd
only supports identity-mapped devices).
- Patch 2: explicitly state that windows are reported in host bridge
resource list order, typically non-overlapping but no sorting
guarantee.
- Patch 2: handler simplified to use callback directly (no linked list
allocation/cleanup needed).

[2] https://lore.kernel.org/all/20261022193527.GG3381610@xxxxxxxx/

Changes since v2:
- Complete redesign from forced reservation to opt-in query (per Robin
Murphy's and Jason Gunthorpe's v2 review).

Changes since v1:
- (Superseded by later changes.)

Guanghui Feng (2):
iommu: Add iommu_for_each_pci_mmio_window() iterator
iommufd: Add IOMMU_GET_PCI_MMIO_WINDOWS ioctl

drivers/iommu/dma-iommu.c | 29 +++++++----
drivers/iommu/iommu-priv.h | 25 ++++++++++
drivers/iommu/iommu.c | 51 ++++++++++++++++++++
drivers/iommu/iommufd/device.c | 64 +++++++++++++++++++++++++
drivers/iommu/iommufd/iommufd_private.h | 1 +
drivers/iommu/iommufd/main.c | 3 ++
include/uapi/linux/iommufd.h | 59 +++++++++++++++++++++++
7 files changed, 224 insertions(+), 8 deletions(-)

--
2.43.7