iommu: AMD-Vi backend behind the vendor-neutral core

The second hardware backend. The IOMMU core, DMA-region capabilities, and
per-device enforcement are unchanged; this adds AMD-Vi (IVRS) as an
alternative to Intel VT-d (DMAR) under the same Backend vtable.

- parseIvrs records the IOMMU control-register base from the first IVHD;
  the platform layer gains iommu_is_amd, and the core picks the backend by
  vendor at init. VT-d and AMD-Vi are mutually exclusive on real hardware.
- iommu-amd.zig: a 2 MiB device table (every DTE zeroed = deny-all until a
  device is claimed), AMD native-format page tables (4 KiB leaves), a
  command buffer (INVALIDATE_DEVTAB_ENTRY / INVALIDATE_IOMMU_PAGES /
  COMPLETION_WAIT) and an event log for faults. The DTE forwards
  interrupts unmapped, so MSI passthrough works exactly as on VT-d.
- The boot log and the iommu self-test are now vendor-aware.

**UNTESTED on real AMD hardware** — danos is developed on Intel, so this
is validated only against QEMU's amd-iommu, and every log line and doc
says so. QEMU quirk handled: its amd-iommu does not observe the
COMPLETION_WAIT store form, but consumes the command ring synchronously on
the tail-register write, so invalidations are already applied by the time
we poll — the backend warns once and proceeds.

Cases: amd-iommu (detection + scratch-domain walker) and
amd-iommu-usb-storage (full storage stack through AMD device-table
translation with per-grant capabilities), both green. 106/106.

This completes the IOVA/IOMMU-enforcement track: per-device DMA domains on
both vendors, with buffers reachable only through delegated capabilities.
This commit is contained in:
Daniel Samson
2026-07-26 18:31:27 +01:00
parent 4e7cbc9792
commit 6a687fbc2b
5 changed files with 355 additions and 19 deletions
+17
View File
@@ -193,6 +193,23 @@ CASES = [
"qemu_extra": ["-device", "intel-iommu,intremap=off", "-device", "e1000e"],
"expect": r"(?s)(?=.*DANOS-IOMMU-FAULT: bdf=)(?=.*iommu-fault-test: system alive)(?=.*DANOS-TEST-RESULT: PASS)",
"fail": r"iommu-fault-test: FAIL|DANOS-TEST-RESULT: FAIL|CPU EXCEPTION|KERNEL PANIC"},
# AMD-Vi: the same detection + scratch-domain walker proof as the `iommu` case, but on
# the AMD backend (IVRS parse, device table, command buffer). QEMU's amd-iommu needs
# dma-remap=on (default off = translation silently ignored). UNTESTED on real AMD.
{"name": "amd-iommu",
"build_case": "iommu",
"qemu_extra": ["-device", "amd-iommu,dma-remap=on,intremap=off"],
"expect": r"(?s)(?=.*iommu online \(AMD-Vi\))(?=.*DANOS-IOMMU: enabled base=0x[0-9a-f]+ domains active)(?=.*DANOS-TEST-RESULT: PASS)",
"fail": r"DANOS-TEST-RESULT: FAIL|DANOS-IOMMU-FAULT"},
# DMA under AMD-Vi translation: the full USB storage stack through AMD device-table
# translation. Tentative — land depends on QEMU amd-iommu behaving. UNTESTED on real AMD.
{"name": "amd-iommu-usb-storage",
"build_case": "fat-mount",
"smp": 4,
"timeout": 150,
"qemu_extra": ["-device", "amd-iommu,dma-remap=on,intremap=off"],
"expect": r"(?s)(?=.*iommu online \(AMD-Vi\))(?=.*fat: mounted /mnt/usb)(?=.*fat-test: ok)",
"fail": r"DANOS-TEST-RESULT: FAIL|DANOS-IOMMU-FAULT"},
# Port I/O grants: a claimed device's io_port resource lets a driver read/write its
# ports (PS/2 status 0x64), gated by the claim; out-of-range/unclaimed is refused.
{"name": "ioport",