IOMMU / MODEL VALIDATION
What the translation lab’s model can demonstrate
A small executable model, with explicit boundaries.
The translation lab’s C++ model: what it implements and where it stops. dmakit, the emulated AMD IOMMU used from the Linux DMA chapter on, is a separate and larger model; its README lists its coverage and limits.
What claims does this page make? 3 points
- Spec rule: Host Mode 1 to 6 as valid translation depths and the EPHSup requirement for PRI follow AMD IOMMU Specification 48882 rev 3.11.
- Platform assumption: real MPS, MRRS, PRI support and Compiler Explorer or compiler behaviour depend on the device, platform and toolchain, not on this page.
- Teaching model: the four-level guest walk, 256-byte mock requests, one fictional NIC and the passing repository checks show regression only, not conformance.
Behaviour and boundaries
| Area | Implemented | Boundary |
|---|---|---|
| Translation | Guest Only, Host Only and nested guest + host; PASID/GCR3 selection; Host Mode 1–6 and skipped-bit checks. | Four-level guest; AMD-specific names. PASIDs are software-limited to avoid GLX aliases; oversized table indices are not emulated as hardware faults. Guest Only uses Host Mode 0. Nested Mode 1 is limited by this example’s table allocation. |
| Pages & permissions | 4 KiB, 2 MiB and 1 GiB data leaves; mixed sizes; presence and cumulative write checks. | Host pages are read-enabled. Guest U/S and A/D are preset. Privileged/execute requests and arbitrary page sizes are not modelled. |
| DMA | RX writes, TX reads, 256-byte mock requests split at 4 KiB and translation boundaries; no copy for a rejected segment. | One fictional NIC descriptor; MPS/MRRS assumed 256 bytes. This is not a vendor NIC register model. A later fault does not roll back already successful segments; no real NIC packet timing. |
| ATS & PRI | 4 KiB ATC entries, permission query, one pending PRI group, mock page-in, invalidation and retry. | Page-in restores only the injected missing leaf and preserves all other mappings and permissions. The PRI recipe sets PCIe PRI Enable and DTE.PPR, assuming global PPREn/PPRLogEn and EPHSup. Semantic requests/responses; no complete PCIe TLP encoding, timeout model, concurrency or real OS page migration. |
| Commands & logs | Bounded rings, producer/consumer ownership, fetch versus completion, selected IO_PAGE_FAULT encoding. | Serialized commands and compact teaching rings. Browser buffer lessons cover more event/command descriptions than the C++ executor implements. |
| Interrupts | Selected legacy IRTE fields and a mock APIC pending-vector/acknowledgement sequence. | No actual MSI, APIC register model or AVIC implementation. Full interrupt fault reporting is outside this C++ example. |
| Memory representation | Sparse maps keyed by synthetic SPA; separate guest pointers and optional CPU linear metadata. | Decoded teaching fields alongside packed words. Selected consistency checks reject contradictory edits; this is not a general raw-memory parser. |
Reuse the C++ files
Open the tabbed project. Download the project to keep its files separate, or download the combined .cpp to use one file; the lab opens with the default configuration, so no setup is needed. Run submits the entire current program to Compiler Explorer, including edits in other tabs.
| File | Responsibility |
|---|---|
| main.cpp | Runs one example and handles model errors. |
| scenario.hpp | All scenario inputs: mappings, PCIe/PRI controls, descriptor bytes, interrupt settings and the permitted page-in edit. |
| page_tables.hpp | Entry fetch and GCR3/guest/host walks. |
| log_buffers.hpp | Ring<T> and the selected ordinary DMA fault record. |
| ats_commands.hpp | Translation caches, serialized command processor and mock PRI response. |
| dma_engine.hpp | Descriptor checks, copy boundaries and synthetic packet/RAM data. |
| interrupts.hpp | IRTE lookup and completion notification. |
| types.hpp | Common address and record types. |
The components share the iommu_demo namespace and one
generated scenario. Their include dependencies are explicit; header
definitions are inline so they can be included by more than one
translation unit. Only scenario.hpp changes between
generated configurations; the other seven files are reusable
unchanged. The site’s tests check that the generator keeps that
property; the downloaded project has no tests of its own. This is a
teaching project, not a general driver library. To use two scenarios
simultaneously, give each instance its own state before extending
the API.
Compile main.cpp using
g++ -std=c++23 -O2 -Wall -Wextra main.cpp -o iommu-demo,
then run ./iommu-demo. Clang can be substituted. C++26
support depends on the compiler. The normal example uses
C++17-compatible language features while defaulting to C++23.
Editing a file pauses playground synchronization. Switching tabs preserves edits. Regenerate replaces all files from the applied configuration; Reset all files restores the last generated project. Packed and decoded fields must agree when manually editing entries.
What the checks establish
Repository checks compile generated examples with GCC using
-Wall -Wextra -Werror, compare their outcomes with the
browser model, and check selected encodings against independently
written expected values. Scenarios include all three translation
paths, PASID limits, mixed leaf sizes, permission/presence faults,
address zero and the highest canonical page, Host Mode changes,
skipped bits and ATS/PRI retry. Checks compare copied packet/RAM bytes
and complete fault records, as well as transfer outcomes.
Source status. AMD and Arm claims are checked against the published specifications (AMD 48882 3.11, Arm IHI 0070 H.a). PCIe claims cite section names only: the PCIe specification is members-only, so its text was not checked here. Intel and Linux kernel claims rest on the Intel manuals and the kernel source they cite, and have no AMD or Arm specification text to check against. Treat them as read from those sources, not as verified against hardware.
The modular build is also compiled with a second translation unit to catch header linkage problems, and its output is compared with the combined-source build. Archive checks ensure the downloaded files survive extraction unchanged. A negative C++ check deliberately introduces contradictory packed and decoded fields and verifies a controlled stop.
This is regression evidence, not proof of architectural correctness. The browser and C++ implementations can share a mistaken assumption. Further assurance would need independent architectural test vectors, wider reserved-bit/error coverage, concurrent cache-invalidation cases and comparison with a trusted emulator or authorized hardware. No silicon testing or external conformance suite was run for this example.
Browser interaction checks cover file selection, edit preservation, whole-project submission and the visual map. Rendered checks cover all IOMMU pages at 320, 390, 768 and 1440 pixels, palette contrast, 200% text, keyboard file selection and reduced motion. They do not cover every browser or device. No confidential data should be entered into an external compiler.
Public references
- AMD IOMMU 48882 revision 3.11: device entries, translation, commands, event/PPR logs and interrupt remapping. Publisher PDF.
- Linux DMA mapping guide: distinct CPU, physical and DMA address spaces.
- Linux AMD IOMMU implementation: a public implementation reference, not code copied into this mock.
- Linux PCIe capability fields: PASID, ATS and PRI controls.
- AMD QDMA guide (PG302): one DMA IP's MPS and 4 KiB splitting.