| .. SPDX-License-Identifier: GPL-2.0-or-later | |
| iommu-testdev — IOMMU test device for bare-metal testing | |
| ======================================================== | |
| Overview | |
| -------- | |
| ``iommu-testdev`` is a minimal, test-only PCI device designed to exercise | |
| IOMMU translation (such as ARM SMMUv3) without requiring firmware or a guest | |
| OS. Tests can populate IOMMU translation tables with known values and trigger | |
| DMA operations that flow through the IOMMU translation path. It is **not** a | |
| faithful PCIe endpoint and must be considered a QEMU-internal test vehicle. | |
| Key Features | |
| ------------ | |
| * **Bare-metal IOMMU testing**: No guest kernel or firmware required | |
| * **Configurable DMA attributes**: Supports address space configuration via | |
| MMIO registers | |
| * **Deterministic verification**: Write-then-read DMA pattern with automatic | |
| result checking | |
| Status | |
| ------ | |
| * Location: ``hw/misc/iommu-testdev.c`` | |
| * Header: ``include/hw/misc/iommu-testdev.h`` | |
| * Build guard: ``CONFIG_IOMMU_TESTDEV`` | |
| Device Interface | |
| ---------------- | |
| The device exposes a single PCI BAR0 with 32-bit MMIO registers: | |
| * ``ITD_REG_DMA_TRIGGERING`` (0x00): Read triggers DMA and consumes | |
| the armed request | |
| * ``ITD_REG_DMA_GVA_LO`` (0x04): DMA IOVA bits [31:0] | |
| * ``ITD_REG_DMA_GVA_HI`` (0x08): DMA IOVA bits [63:32] | |
| * ``ITD_REG_DMA_GPA_LO`` (0x1C): DMA GPA bits [31:0] for readback validation | |
| * ``ITD_REG_DMA_GPA_HI`` (0x20): DMA GPA bits [63:32] for readback validation | |
| * ``ITD_REG_DMA_LEN`` (0x0C): DMA transfer length | |
| * ``ITD_REG_DMA_RESULT`` (0x10): DMA result | |
| (0=success, 0xffffffff=idle, 0xfffffffe=armed) | |
| * ``ITD_REG_DMA_DBELL`` (0x14): Write 1 to arm DMA, write 0 to disarm. | |
| Arming only marks the request and sets BUSY (no latch/check), but it | |
| provides an explicit gate for qtests and leaves room for async/latching. | |
| * ``ITD_REG_DMA_ATTRS`` (0x18): DMA attributes which shadow some fields in | |
| MemTxAttrs: | |
| - bit[0]: secure (1=Secure, 0=Non-Secure) | |
| - bits[2:1]: ArmSecuritySpace (0=Secure, 1=Non-Secure) | |
| - bit[3]: space_valid (1=space is valid, 0=ignore space and default to Non-Secure) | |
| ``space`` field in MemTxAttrs is consumed only when ``space_valid`` is set. | |
| For Secure/Non-Secure, ``secure`` and ``space`` must match; mismatches | |
| return ``ITD_DMA_ERR_BAD_ATTRS``. Other bits are reserved but can be wired | |
| up easily if future tests need to pass extra attributes. | |
| Translation Setup Workflow | |
| -------------------------- | |
| ``iommu-testdev`` never builds SMMU/AMD-Vi/RISC-V IOMMU structures on its own. | |
| Architecture-specific construction lives entirely in qtest/libqos helpers. | |
| Those helpers populate guest memory with page tables/architecture-specific | |
| structures and program the emulated IOMMU registers directly. See the | |
| ``qsmmu_setup_and_enable_translation()`` function in | |
| ``tests/qtest/libqos/qos-smmuv3.c`` for an example of how SMMUv3 translation | |
| is set up for this device. | |
| DMA Operation Flow | |
| ------------------ | |
| Arming semantics: | |
| * Writing ``DMA_DBELL`` with bit0=1 marks the request armed and sets | |
| ``DMA_RESULT`` to BUSY. It does not latch GVA/LEN/ATTRS; values are sampled | |
| when ``DMA_TRIGGERING`` is read. | |
| * Writing ``DMA_DBELL`` with bit0=0 disarms the request and sets | |
| ``DMA_RESULT`` to IDLE. | |
| * Reading ``DMA_TRIGGERING`` consumes the armed request and clears the armed | |
| state, even on error. | |
| The flow would be split into these steps, mainly for timing control and | |
| debuggability: qtests can easily exercise and assert distinct paths | |
| (NOT_ARMED, BAD_LEN, TX/RD failures, mismatch) instead of having all side | |
| effects hidden behind a single step: | |
| 1. Test programs IOMMU translation tables | |
| 2. Test configures DMA IOVA (GVA_LO/HI), GPA for readback, length, and attributes | |
| 3. Test writes 1 to DMA_DBELL to arm the operation | |
| 4. Test reads DMA_TRIGGERING to execute DMA | |
| 5. Test polls DMA_RESULT: | |
| - 0x00000000: Success | |
| - 0xFFFFFFFE: Armed (waiting for trigger). DMA runs synchronously, so | |
| BUSY is not observed once the trigger read completes. | |
| - 0xDEAD0006: Bad attrs (secure/space mismatch for S/NS) | |
| - 0xDEAD000X: Various error codes | |
| The device performs a write-then-read sequence using a known pattern | |
| (0x12345678) and verifies data integrity automatically. | |
| Running the qtest | |
| ----------------- | |
| The SMMUv3 test suite uses this device and covers multiple translation modes:: | |
| cd build | |
| QTEST_QEMU_BINARY=./qemu-system-aarch64 \\ | |
| ./tests/qtest/iommu-smmuv3-test --tap -k | |
| This test suite exercises: | |
| * Stage 1 only translation | |
| * Stage 2 only translation | |
| * Nested (Stage 1 + Stage 2) translation | |
| Instantiation | |
| ------------- | |
| The device is not wired into any board by default. Tests instantiate it | |
| via QEMU command line:: | |
| -device iommu-testdev | |
| For ARM platforms with SMMUv3:: | |
| -M virt,iommu=smmuv3 -device iommu-testdev | |
| When the IOMMU sits on the same PCI root complex (``pci.0``), the device is | |
| placed behind it automatically. For other PCI topologies, specify the bus | |
| explicitly. | |
| Limitations | |
| ----------- | |
| * No realistic PCIe enumeration, MSI/MSI-X, or interrupt handling | |
| * No ATS/PRI support | |
| * No actual device functionality beyond DMA test pattern | |
| * Test-only; not suitable for production or machine realism | |
| * Address space support (Secure/Root/Realm) is architecture-dependent and | |
| gated by ``space_valid`` | |
| * Readback uses the programmed GPA and reads via system memory, avoiding a | |
| second IOMMU access for the readback step | |
| See also | |
| -------- | |
| * ``tests/qtest/iommu-smmuv3-test.c`` — SMMUv3 test suite | |
| * ``tests/qtest/libqos/qos-smmuv3.{c,h}`` — SMMUv3 test library | |
| * SMMUv3 emulation: ``hw/arm/smmu*`` |