Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
status: open
kind: defect
opened: 2026-10-04
---

# A unit passes DMA untranslated outside its protected memory regions while it is handed over

`vtd::init` (`kernel/src/arch/x86_64/vtd/mod.rs`) hands every unit over with
translation off. That covers a unit firmware left translating, whatever its
table mode. VT-d Rev. 4.1 gives no condition under which system software may
switch firmware's tables for its own under translation. §6.6 requires
identical remapping results, and nothing documented lets this kernel know
firmware's mappings. `DMA_CTRL_PLATFORM_OPT_IN` (§8.1) says only where
platform DMA goes.

The hand-over is guarded where every described unit is programmed, has both
protected memory regions (`CAP.PLMR`, `CAP.PHMR`) and takes register-based
invalidation. On such units the regions block DMA to what they cover whether
or not the unit translates (§11.4.8.1). They are programmed on every unit
after any firmware left on is switched off, and released once the last unit
translates (`vtd/pmr.rs`). The low region and the high region are each the
largest stretch of the OS's RAM (usable or ACPI-reclaimable, never NVS) that
avoids every RMRR and holds every 2 MiB page the hand-over's tables were
carved from, and this kernel's image. The boot logs the regions, what they
cover and the functions mastering the bus as they go on. The T14's four units
are guarded. The queue and interrupt remapping are programmed after the
release.

What passes untranslated during the hand-over:

- **A machine whose hand-over is unguarded:** all of memory. Its log says why:
- a unit without both regions (QEMU's);
- a unit that refuses register-based invalidation (major version 6 or later,
§11.4.6.1), or whose IOTLB registers lie outside the window this kernel
maps;
- fewer units programmed than described;
- tables or kernel outside every region.

Such a machine invalidates through the queue, enabled before translation
comes on.
- **A guarded machine:**
- RAM outside the two chosen stretches;
- every RMRR;
- peer MMIO.
- **Before the hand-over, on any machine:**
- Where firmware leaves translation off, as the T14's does, every function
reaches all of memory from ExitBootServices until the regions go on.
- Where firmware leaves it on, `mm::init` has already taken
`EfiBootServicesData` as free (`lib/bootmap/src/lib.rs`,
`is_usable_type`). A unit may walk firmware's tables in memory the pmm has
handed out.

Evidence:
- No machine here is handed a unit translating.
- `iommu-firmware-left` stages one:
- QEMU 11.1.1 runs the unguarded hand-over (`vtd_firmware_left`);
- the T14 runs the guarded one (`iommu_firmware_left`'s row, which reads
the regions go on before translation first goes off and come off before
the first unit is programmed).

Owner: the IOMMU track (`issues/the-iommu-refuses-nothing-yet.md`).

**Exit**: during the hand-over no function reaches memory outside its RMRRs.
Each of these cases is closed by a documented mechanism and read on a
machine or a host test:

1. a unit without protected memory regions. §11.4.8.1 marks the regions
"planned for deprecation", so new units will be this case. Abort-DMA mode
(§3.4.4) is one mechanism; it needs `ECAP.ADMS` and is ruled out while a
device an RMRR names masters the bus;
2. a unit that refuses register-based invalidation;
3. RAM a guarded hand-over leaves outside its regions;
4. peer MMIO.
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ opened: 2026-10-04
# A unit this kernel does not program keeps what firmware left on

`vtd::init` (`kernel/src/arch/x86_64/vtd/mod.rs`) switches off what firmware
left on (`Unit::hand_over`) only inside `enable`, which a unit reaches only if
`plan` accepts it and it is among the first `MAX_UNITS` described. A unit
left on (`Unit::hand_over`) only in a unit's hand-over (`translate`), which a
unit reaches only if `plan` accepts it and it is among the first `MAX_UNITS` described. A unit
`plan` refuses, and every unit past `MAX_UNITS`, keeps whatever firmware left
on while the kernel treats it as absent: translation through firmware's tables,
and interrupt remapping, which blocks every compatibility-format message this
protected memory regions (`vtd/pmr.rs` switches them off on programmed units
only), and interrupt remapping, which blocks every compatibility-format message this
kernel then sends through the unit unless firmware also left `CFI` on with
`EIME` off (VT-d Rev. 4.1 §5.1.4). The module header's "leaves the unit
switched off" is false of such a unit.
Expand Down
20 changes: 18 additions & 2 deletions issues/the-iommu-refuses-nothing-yet.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ a unit firmware left translating:
scalable or abort-DMA mode, with `CAP.ESRTPS` clear, may not have its root
table switched under translation (VT-d Rev. 4.1 §6.6), so translation goes
off for that one switch. The older protection registers are `PMEN`'s
protected memory regions (§11.4.8.1). The weakness is
`issues/a-unit-in-scalable-or-abort-mode-loses-translation-for-its-root-table-switch.md`.
protected memory regions (§11.4.8.1). Every hand-over now takes
translation off inside them where every unit has them; what remains is
`issues/a-unit-passes-dma-untranslated-outside-its-protected-memory-regions-while-it-is-handed-over.md`.
- **"Apply it at hand-over"**, on reserved memory: "From the hand-over on,
only display and USB controllers keep access to their reserved region; any
other device's access is refused. A device that firmware was still using
Expand All @@ -67,6 +68,21 @@ a unit firmware left translating:
boot, he answered: "You can do with the t14 what you want." The grant goes
beyond the question asked.

**Proposed, for the owner** (pull request #1086's review): a fault from an
enumerated function that no driver runs halts the machine only when the
address is one its domain maps. A mapped address means the unit contradicted
tables this kernel wrote, which the shared identity domain does not confine
to one unit. An unmapped address is firmware's DMA straying outside its
grant: the function is stopped, the fault logged, and the machine goes on, as
"Apply it at hand-over" already rules for reserved regions. An unclaimed
function sits in the identity domain, which maps all of `[0, top)` with
nothing carved out, so "unmapped" is `address >= top` and the handler stays
bounded and lock-free. The change is to the representation: `Owner::Kernel`
today merges functions this kernel drives with functions nobody drives, and
the split gives the second its own arm. One caveat: the iGPU is not wholly
undriven. Its scanout reads the firmware framebuffer the kernel's panic
console draws into, so stopping it blanks that console.

Owner: the orchestrator.

**Exit**: a test or a T14 row reads each ruled refusal, each with its
Expand Down
Loading