This is v7 of the IOMMU test framework. Compared to v6, v7 splits the
smmuv3-common.h work into smaller patches, adds MAINTAINERS entries for
iommu-testdev and the qos-smmuv3 helpers, updates the DMA test pattern to
0x12345678, and switches the qtest PCI enumeration to qpci_device_foreach().
I plan to invest long-term in maintaining iommu-testdev and qos-smmuv3, so
I added two entries in MAINTAINERS. This is my first time touching the
MAINTAINERS file; I read docs/devel/maintainers.rst and made changes
accordingly, but I am still unsure if this follows the expected rules.
Feedback is welcome: should we add additional maintainer(s) for these
entries?
Also, qos-smmuv3 currently contains a large amount of page-table building
code. If there is a better splitting strategy, I am happy to rework it.
Motivation
----------
Currently, thoroughly testing IOMMU emulation (e.g., ARM SMMUv3) requires
a significant software stack. We need to boot a full guest operating
system (like Linux) with the appropriate drivers (e.g., IOMMUFD) and rely
on firmware (e.g., ACPI with IORT tables or Hafnium) to correctly
configure the IOMMU and orchestrate DMA from a peripheral device.
This dependency on a complex software stack presents several challenges:
* High Barrier to Entry: Writing targeted tests for specific IOMMU
features (like fault handling, specific translation regimes, etc.)
becomes cumbersome.
* Difficult to Debug: It's hard to distinguish whether a bug originates
from the IOMMU emulation itself, the guest driver, the firmware
tables, or the guest kernel's configuration.
* Slow Iteration: The need to boot a full guest OS slows down the
development and testing cycle.
The primary goal of this work is to create a lightweight, self-contained
testing environment that allows us to exercise the IOMMU's core logic
directly at the qtest level, removing the need for any guest-side software.
Our Approach: A Dedicated Test Framework
-----------------------------------------
To achieve this, we introduce three main components:
* A minimal hardware device: iommu-testdev
* A reusable IOMMU helper library: libqos/qos-smmuv3
* A comprehensive qtest suite: iommu-smmuv3-test
The iommu-testdev is intentionally not a conformant, general-purpose PCIe
or platform device. It is a purpose-built, highly simplified "DMA engine"
designed to be analogous to a minimal PCIe Root Complex that bypasses the
full, realistic topology (Host Bridges, Switches, Endpoints) to provide a
direct, programmable path for a DMA request to reach the IOMMU. Its sole
purpose is to trigger a DMA transaction when its registers are written to,
making it perfectly suited for direct control from a test environment like
qtest.
The Qtest Framework
-------------------
The new qtest (iommu-smmuv3-test.c) serves as the "bare-metal driver"
for both the IOMMU and the iommu-testdev. It leverages the libqos helper
library to manually perform all the setup that would typically be handled
by the guest kernel and firmware, but in a completely controlled and
predictable manner:
1. IOMMU Configuration: It directly initializes the SMMU's registers to a
known state using helper functions from qos-smmuv3.
2. Translation Structure Setup: It uses the libqos library to construct
the necessary translation structures in memory, including Stream Table
Entries (STEs), Context Descriptors (CDs), and Page Tables (PTEs).
3. DMA Trigger: It programs the iommu-testdev to initiate a DMA operation
targeting a specific IOVA with configurable attributes.
4. Verification: It waits for the transaction to complete and verifies
that the memory was accessed correctly after address translation by
the IOMMU.
This framework provides a solid and extensible foundation for validating
the IOMMU's core translation paths. The current test suite covers:
- Stage 1 only translation (VA -> PA via CD page tables)
- Stage 2 only translation (IPA -> PA via STE S2 tables)
- Nested translation (VA -> IPA -> PA, Stage 1 + Stage 2)
The infrastructure is designed to be extended to support additional
security spaces and IOMMU features.
Testing:
--------
QTEST_QEMU_BINARY=./build/qemu-system-aarch64 \
./build/tests/qtest/iommu-smmuv3-test --tap -k
If you want to check coverage report, please follow instructions below
which are shared by Pierrick in previous review [1]
# install gcovr if not already installed, `sudo apt install gcovr`
# on ubuntu for example
$ export CFLAGS="--coverage"
$ ./configure --target-list=aarch64-softmmu
$ ninja -C build
$ QTEST_QEMU_BINARY=./build/qemu-system-aarch64 \
./build/tests/qtest/iommu-smmuv3-test
$ rm -rf build/coverage_html
$ mkdir build/coverage_html
$ gcovr \
--gcov-ignore-parse-errors suspicious_hits.warn \
--gcov-ignore-parse-errors negative_hits.warn \
--merge-mode-functions=separate \
--html-details build/coverage_html/index.html \
--filter 'hw/arm/smmu*'
# check the version of gcovr if meeting some unsupported options error.
# Upgrading to 8.4 version may resolve the error.
$ gcovr --version
$ pip install --user --upgrade gcovr
$ echo file://$(pwd)/build/coverage_html/index.html
# open this in browser by clicking on your terminal
[1]
https://lore.kernel.org/qemu-devel/[email protected]/
Major Changes from v6 to v7:
-----------------------------
- Split the smmuv3-common.h work into smaller patches
(registerfields conversion, NSCFG bits, helper setters)
- Add MAINTAINERS entries for iommu-testdev and qos-smmuv3 helpers
- Tighten documentation wording and update the DMA test pattern value
- Simplify qtest PCI device discovery and rename QSMMU_IOVA constant
- This series is also saved in github repo [4]
[4] https://github.com/hnusdr/qemu/tree/iommu-testdev-v7-community
Major Changes from v5 to v6:
-----------------------------
- Split batch testing into individual test cases per translation mode
- Removed cleanup functions and related codes or comments
- Improved error handling with explicit assertions
- Add coverage build and test instructions shared by Pierrick
- Keep Reviewed-by and Tested-by from Pierrick's review
- This series is also saved in github repo [2]
[2] https://github.com/hnusdr/qemu/tree/iommu-testdev-v6-community
Major Changes from v4 to v5:
-----------------------------
- Remove a duplicated patch that was accidentally included in v4.
Major Changes from v3 to v4:
-----------------------------
1. Added shared smmuv3-common.h so both the device and libqos consume the same
STE/CD/register definitions as Alex suggested [3]
2. Slimmed iommu-testdev down to a pure DMA trigger with a tighter MMIO
contract (new doorbell helper, simplified attributes/errors).
3. Updated `qos-smmuv3` and the qtest so they include the common header,
honor per-test expected results, and rely solely on the streamlined device
interface.
4. Compacted changes of v2 to v3.
[3] https://lore.kernel.org/qemu-devel/[email protected]/
Major Changes from v2 to v3:
-----------------------------
1. Generalization/Renaming: rebranded `smmu-testdev` → `iommu-testdev` (code,
headers, docs) to reflect the broadened scope.
2. Separation of concerns: iommu-testdev is now a pure DMA trigger; all
SMMUv3-specific setup (STE/CD/page tables, multi-mode support, space offsets)
lives in `qos-smmuv3.{c,h}` and is consumed by the new qtest.
3. Improved modularity & coverage: the stacked design (device + helper + qtest)
made it straightforward to add S1/S2/Nested tests, a cleaner config system,
and clearer validation logic.
4. Code/documentation quality: added tracepoints, better error handling/naming,
and refreshed `docs/specs/iommu-testdev.rst` with the new layout.
Future Work
-----------
The current implementation focuses on basic translation path validation
in the Non-Secure address space. Future extensions could include:
* Multi-space testing (Secure, Root, Realm) for SMMUv3
* Support for other IOMMU types (Intel VT-d, AMD-Vi, RISC-V IOMMU)
Tao Tang (7):
hw/arm/smmuv3: Extract common definitions to smmuv3-common.h
hw/arm/smmuv3-common: Define STE/CD fields via registerfields
hw/misc: Introduce iommu-testdev for bare-metal IOMMU testing
hw/arm/smmuv3-common: Add NSCFG bit definition for CD
hw/arm/smmuv3-common: Add STE/CD set helpers for repeated field setup
tests/qtest/libqos: Add SMMUv3 helper library
tests/qtest: Add SMMUv3 bare-metal test using iommu-testdev
MAINTAINERS | 13 +
docs/specs/index.rst | 1 +
docs/specs/iommu-testdev.rst | 112 ++++++
hw/arm/smmuv3-internal.h | 255 +------------
hw/misc/Kconfig | 5 +
hw/misc/iommu-testdev.c | 271 ++++++++++++++
hw/misc/meson.build | 1 +
hw/misc/trace-events | 10 +
include/hw/arm/smmuv3-common.h | 423 +++++++++++++++++++++
include/hw/misc/iommu-testdev.h | 68 ++++
tests/qtest/iommu-smmuv3-test.c | 121 ++++++
tests/qtest/libqos/meson.build | 3 +
tests/qtest/libqos/qos-smmuv3.c | 632 ++++++++++++++++++++++++++++++++
tests/qtest/libqos/qos-smmuv3.h | 256 +++++++++++++
tests/qtest/meson.build | 1 +
15 files changed, 1918 insertions(+), 254 deletions(-)
create mode 100644 docs/specs/iommu-testdev.rst
create mode 100644 hw/misc/iommu-testdev.c
create mode 100644 include/hw/arm/smmuv3-common.h
create mode 100644 include/hw/misc/iommu-testdev.h
create mode 100644 tests/qtest/iommu-smmuv3-test.c
create mode 100644 tests/qtest/libqos/qos-smmuv3.c
create mode 100644 tests/qtest/libqos/qos-smmuv3.h
--
2.34.1