Skip to content

iommu/xen: reserve dom0's PCI windows, and fix the modular pcifront link - #105

Open
kaniini wants to merge 2 commits into
edera/mainlinefrom
ariadne/eng-221-xen-iommu-pci-windows
Open

kaniini wants to merge 2 commits into
edera/mainlinefrom
ariadne/eng-221-xen-iommu-pci-windows

Conversation

@kaniini

@kaniini kaniini commented Nov 13, 2026

Copy link
Copy Markdown

Two fixes to the Xen PV-IOMMU driver from the Mythos audit.

PCI host-bridge windows not reserved in dom0 (ENG-221). iova_reserve_pci_windows() is skipped for every device the driver owns, on the grounds that a Xen guest's windows are invented (pcifront hands out iomem_resource, a PVH guest without a host-bridge _CRS gets the catch-all default). Dom0 sees the real host bridges, and the driver reserves only the MSI range, so once dma-iommu has used the IOVA space above it, IOVAs land inside the host-bridge window on sibling devices' BARs. On a fabric without ACS the DMA is decoded as peer-to-peer and delivered to the sibling instead of the IOMMU. xen_iommu_manages_iova() now answers false in the initial domain, so dom0 keeps the reservation as on bare metal; guests are unchanged.

pcifront_machine_sbdf() undefined with XEN_PCIDEV_FRONTEND=m (ENG-224). include/xen/pci.h declared the function for =m as well as =y, and the built-in IOMMU driver calls it, so that combination failed to link. The header now declares it only when pcifront is built in and gives built-in callers the -ENODEV stub otherwise. Since the IOMMU driver with that stub would silently use a pcifront device's guest BDF, which means nothing to Xen, XEN_IOMMU also gains depends on XEN_PCIDEV_FRONTEND != m. Checked with olddefconfig: pcifront modular drops XEN_IOMMU, pcifront built in keeps it.

Built with the latest linux-kernel-oci x86_64 host.config (XEN_IOMMU=y, XEN_PCIDEV_FRONTEND=y, XEN_DOM0=y): full vmlinux, no warnings. Not runtime-tested; the window reservation shows up as reserved entries for the host-bridge ranges in a PVH dom0's IOVA domain, and would need a non-ACS fabric to demonstrate the collision.

The latent superpage items in the ENG-221 notes (shadow page table updated regardless of hypercall result, per-4K stepping, the cumulative map.mapped contract, identity release_domain) are not part of this change; none is reachable while Xen advertises only 4K pages.

ENG-221
ENG-224

Commit 1b82771 ("iommu/dma: Don't reserve PCI windows under a
paravirtual IOMMU") skips iova_reserve_pci_windows() for every device
the Xen IOMMU driver owns, because the windows a guest sees are
invented: pcifront hands out iomem_resource itself and a PVH guest with
no host-bridge _CRS gets Linux's catch-all default.  That holds for a
guest.  Dom0 sees the real host bridges, and their windows route to the
real BARs of the devices behind them.

A PVH dom0 device gets a translated DMA domain, and dma-iommu hands out
IOVAs top-down below 4 GiB.  The driver reserves only the MSI range, so
once the space above it is used, IOVAs land inside the host-bridge
window where sibling devices' BARs live.  On a root port or switch
without ACS a DMA to such an address is decoded as peer-to-peer and
delivered to the sibling's BAR: it never reaches the IOMMU, so the
transfer is lost and the sibling's registers are written.  Xen enables
ACS where it can, which redirects such requests upstream, but that is
defence in depth, not a reason to skip the reservation.

Have xen_iommu_manages_iova() answer false in the initial domain, so
dom0 reserves its windows as on bare metal.

Signed-off-by: Ariadne Conill <ariadne@ariadne.space>
… when modular

include/xen/pci.h declares pcifront_machine_sbdf() as a real function
whenever CONFIG_XEN_PCIDEV_FRONTEND is defined, which it is for =m as
well as =y.  XEN_IOMMU is a bool and calls it from built-in code, so
XEN_IOMMU=y with XEN_PCIDEV_FRONTEND=m fails to link vmlinux.

Declare the function only when pcifront is built in and give built-in
callers the -ENODEV stub otherwise.  The IOMMU driver with that stub
would silently use a pcifront device's guest BDF, which means nothing to
Xen, so also keep XEN_IOMMU from being configured with a modular
pcifront rather than let it build into a driver that cannot name the
devices it manages.

Signed-off-by: Ariadne Conill <ariadne@ariadne.space>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants