---
title: 'Arm SMMUv2: Architecture and Performance'
url: https://www.emergentmind.com/topics/arm-smmuv2
type: topic
---

# Arm SMMUv2: Architecture and Performance

Arm SMMUv2 is Arm’s System Memory Management Unit architecture version 2, an IOMMU architecture used to translate device-visible addresses issued by DMA-capable bus masters into physical addresses while enforcing isolation and access control. In the cited ARMv8/Linux case studies, it appears concretely as the CoreLink MMU-500 in Xilinx Zynq UltraScale+ MPSoCs, positioned between Processing System or Programmable Logic masters and DRAM, and programmed through Linux’s `arm-smmu.c` driver and IOMMU API [2511.19258]. Experimental work on the same MMU-500 class further shows that SMMUv2 is not only a protection mechanism but also a timing-relevant shared resource whose translation structures can measurably perturb DMA latency under contention [2508.19670].

## 1. Architectural role in the memory system

Arm SMMUv2 is presented in the cited work as the non-CPU analogue of the CPU MMU. The conceptual distinction is straightforward: a CPU-side access follows a virtual-address translation path, whereas a device-side access follows an I/O-address translation path mediated by the IOMMU. In the experimental Arm platforms discussed here, the SMMU sits directly on the DMA path: upstream are client devices or AXI masters; downstream are the memory system and DRAM. The 2025 interference study states that Arm SMMUv2 is “the standard IOMMU implementation for arm64 systems,” that it uses a stream-based model with StreamIDs and optional SubstreamIDs, supports both stage-1 and stage-2 translations, uses IOTLBs to cache translations, and defines three circular buffer queues “for translation updates, fault handling, and page requests” [2508.19670].

The implementation papers make that placement concrete. On Zynq UltraScale+, DMA requests from Processing System DMA engines or custom Programmable Logic IP blocks traverse the SMMU before reaching memory. In the ExaNeSt RDMA prototype, the SMMU is explicitly described as translating an incoming AXI address and AXI ID, mapped to a context, into an outgoing physical address according to translation tables and memory attributes. The same work describes the SMMU as cooperating conceptually with the coherence interconnect, underscoring that translation and coherence are coupled in practice [2511.21018].

A broader systems perspective comes from the formal paper on memory accesses and interrupts, which does not name SMMUv2 explicitly but models IOMMU-like components as translation nodes embedded in larger graphs of address spaces. It emphasizes that a single access by a core or DMA engine can traverse multiple translation and caching steps, and that a destination resource may appear at different physical addresses for different agents. This suggests that SMMUv2 is best understood not as an isolated block, but as one element in a heterogeneous translation fabric whose correctness depends on runtime configuration as much as on static topology [1703.06571].

## 2. Programming model: streams, contexts, and translation state

The architectural programming model exposed in the case studies is centered on stream matching and context-bank selection. The Linux bring-up thesis describes the key SMMUv2 register families used in practice: `SMMU_SMRn` for Stream Match Registers, `SMMU_S2CRn` for Stream-to-Context Registers, `SMMU_CBARn` for Context Bank Attribute Registers, and per-context-bank state such as `SMMU_CBn_TTBR0`, `TTBR1`, `TCR`, `TCR2`, and `SCTLR` [2511.19258].

`SMRn` entries perform stream matching. `SMRn.VALID = 1` enables an entry, `SMRn.ID` holds the stream identifier to match, and `SMRn.MASK[i] == 1` means the corresponding ID bit is ignored. Multiple matching `SMRn` entries are cautioned to have unpredictable behavior. `S2CRn.Type[17:16]` is used to select Translation Context (`00`), Bypass (`01`), Fault (`10`), or Reserved/treated-as-fault (`11`). When `Type = 00`, `CBNDX` selects the context bank. `CBARn.Type[17:16]` is summarized in the thesis as distinguishing stage-2 context, stage-1 with stage-2 bypass, stage-1 with stage-2 fault, and stage-1 followed by stage-2 translation [2511.19258].

The ExaNeSt RDMA thesis maps these abstractions to the MMU-500 terminology used on Zynq UltraScale+. It calls a translation context a “context bank,” notes that the architecture theoretically supports up to 128 context banks, and states that the evaluated Zynq platform exposes only 16. A context bank is described as including translation configuration state, fault-status capture, and TLB-maintenance support. In that implementation, each context bank, effectively each page table, is associated with one protection domain, giving 16 protection domains tied to the 16 available context banks. With 64 virtualized PLDMA channels per protection domain, the design reaches

$$
64 \times 16 = 1024
$$

outstanding transfers [2511.21018].

Per-context translation control follows the standard SMMUv2 style. `TTBR0` and `TTBR1` are translation-table base registers; `TCR` determines translation properties and which TTBR is used; `TCR2` extends control for granule size and intermediate physical address size. In the cited Linux environment, the driver effectively uses `TTBR0` for everything. The ExaNeSt thesis simplifies the model by treating each context bank as one page table, more precisely as a context containing a field that points to a unique page table for that context [2511.21018].

Stream identification on Zynq is unusually explicit in the appendix of the ExaNeSt work. The StreamID is given as a 15-bit quantity:

$$
\text{StreamID} = \{\text{TBU Number}[14:10], \text{Master ID}[9:6], \text{AXI ID}[5:0]\}.
$$

The same thesis lists TBU associations for several PS ports, while the Linux bring-up thesis reports an implementation-specific inference on Zynq that the lower 6 bits correspond to AXI ID and the next 4 bits to master device or port, with upper bits zero in the reported tests. The latter is explicitly an experimental inference rather than an architectural guarantee [2511.19258].

## 3. MMU-500 deployments on Zynq UltraScale+ and Linux

The two 2025 theses are practical MMU-500/SMMUv2 bring-up studies on ARMv8-A Cortex-A53 systems running Linux 4.4.0 or Linux 4.9.0. One uses a Trenz TE0808 module with XCZU9EG-FFVC900-1; the other uses the ExaNeSt Quad-FPGA Daughter Board. Both identify the SMMU hardware as `arm,mmu-500` or explicitly as MMU-500, and both use Arm’s `arm-smmu.c` driver as the software integration point [2511.19258].

Initial experiments use the Linux IOMMU infrastructure in a conventional way. The bring-up thesis allocates an IOMMU domain with `iommu_domain_alloc()`, obtains the device’s group with `iommu_group_get()`, attaches the group with `iommu_attach_group()`, and inserts mappings with `iommu_map()`. This is how the SMMU context bank and its page tables are established for the chosen domain. Single-page experiments then install explicit mappings such as `0x70000000 -> 0x60000000` and `0x70002000 -> 0x60002000`, issue DMA to the virtual addresses, and verify that memory changes at the mapped physical destinations, thereby demonstrating translation for both PS-originated DMA and PL-originated AXI traffic [2511.19258].

A more distinctive technique reuses a user process’s own page tables. The thesis adds a `ttbr` field to `struct iommu_domain`, initializes it to zero, and patches `arm-smmu.c` so that if `domain.ttbr != 0`, the context bank’s `TTBR0` is taken from that supplied value rather than from the IOMMU page-table allocator. During `DMA_OPEN_IOCTL`, the kernel module obtains the current process’s `mm_struct->pgd`, walks the four-level AArch64 page tables to find the physical address of the PGD page, and stores that value in the IOMMU domain’s `ttbr` field. The result is a domain whose SMMU page-table root is the user process’s page-table root [2511.19258].

That reuse is not a drop-in operation. The thesis reports that the SMMU context-bank defaults did not match the CPU MMU’s address-size regime. The input address-space size is described by

$$
2^{(64 - T0SZ)}.
$$

The default SMMU `CBn_TCR.T0SZ` value of 16 implied 48 input VA bits, whereas the CPU MMU used 25, implying 40 VA bits. Similarly, `CBn_TCR2.PASize` initially implied 48-bit physical addresses, while the CPU MMU used 40-bit physical addresses. The driver was therefore patched to force 40-bit input VA size and 40-bit output physical address size when using the externally supplied TTBR. The same debugging effort also corrected `S2CRn.INSTCFG` so that the relevant stream was treated as data rather than instruction fetch [2511.19258].

These experiments establish several practical points. First, SMMUv2 can translate traffic from both built-in DMA engines and custom PL masters. Second, Linux’s generic IOMMU API is sufficient for basic context establishment and single-page mappings. Third, sharing CPU page tables with the SMMU is possible in this environment, but only after aligning `TTBR`, `TCR`, `TCR2`, and stream configuration. The same thesis also notes an important caveat: successful DMA alone does not prove that translation actually occurred, because the authors observed cases where unmapped addresses still completed “with no translation at all,” as if the addresses were physical. That observation directly challenges a common misconception in SMMU bring-up.

## 4. Fault reporting, recovery, and virtual-address RDMA

The most detailed SMMUv2 fault case study is the thesis on virtual-address RDMA page faults, which explicitly modifies the mainline Linux driver of the “ARM SMMU (version 2)” and identifies the underlying hardware as MMU-500 [2511.21018]. The system uses user-level zero-copy RDMA over pageable virtual memory rather than requiring all DMA buffers to be pinned. A user process on the Cortex-A53 side initiates RDMA, an R5 scheduler segments and schedules transfers, and a custom PLDMA engine in programmable logic issues AXI accesses using virtual addresses. The SMMU then performs the VA-to-PA translation for those DMA requests.

Fault reporting is organized around context-bank fault registers. The cited thesis names `SMMU_CBn_FSR` as the Fault Status Register, `SMMU_CBn_FAR` and `FAR_HIGH` as the fault-address capture registers, `SMMU_CBn_FSYNRm` as the Fault Syndrome Register, `SMMU_CBn_RESUME` for stall-mode resumption, and `SMMU_CBn_SCTLR` plus `SMMU_SCR0.STALLD` as control state. Translation fault is indicated by `FSR.TF`, described as the second bit, `FAR` contains input-address bits `[31:0]`, `FAR_HIGH` provides the upper bits `[63:32]`, and only 16 upper bits are meaningful on that system, so up to 40 bits of address information are reconstructed. `FSYNR.WNR` distinguishes write from read, and if a new fault arrives while `FSR` is already non-zero, `FSR.MULTI` is set and “no details of the fault are recorded” [2511.21018].

The thesis gives an unusually concrete treatment of `HUPCF`, the hit-under-previous-fault control. In terminate mode with `HUPCF = 0`, if a fault is active for a context, each subsequent transaction for that context terminates and `FSR` records only the original active fault. With `HUPCF = 1`, later faults terminate independently and `FSR.MULTI` records multiplicity. In stall mode with `HUPCF = 0`, subsequent transactions stall until the fault is resolved; with `HUPCF = 1`, more transactions may proceed. The authors report that enabling `HUPCF` prevented apparently unrelated destination-side failures caused by an earlier source-side fault in the same context [2511.21018].

Although the thesis discusses both terminate and stall models, the evaluated mechanism uses terminate mode rather than SMMU-native stall/retry. In other words, replay is not done by writing `RESUME` to restart the same stalled SMMU transaction. Instead, the driver’s context-fault handler reads fault registers, classifies the event, associates it with the relevant protection domain and process, and schedules deferred work. Two tasklets are introduced: `pf_send_handler` for source-address faults and `pf_rcv_tasklet` for destination-address faults. Fault resolution itself uses either a Netlink-based “Touch-A-Page” path, where userspace touches the faulting page and lets the CPU MMU handle the page fault, or a kernel `get_user_pages()`-based “Touch-Ahead” path, which pages in the faulting page and up to three following pages [2511.21018].

The destination-side replay path additionally requires protocol metadata not present in SMMU fault registers. For that purpose, the PLDMA receiver path was extended with a 512-entry, 128-bit FIFO logging source node ID, transaction ID, sequence number, PDID, and encoded faulty IOVA information for packets that saw an AXI slave error or NACK. After the page becomes resident, software sends a RAPF (“Retransmit After Page Fault handled”) message to the R5 firmware, which validates the sequence number and retransmits the corresponding transaction. Source-side faults remain weaker: recovery resolves the page, but retransmission is timeout-driven rather than immediate [2511.21018].

This implementation establishes two limits of SMMUv2 fault handling as deployed here. First, the work is centered on translation faults; permission faults are mentioned but not fully developed. Second, SMMU fault metadata alone is insufficient for full RDMA replay semantics; external protocol state is needed.

## 5. Formal semantics, update discipline, and verification relevance

The cited formal literature addresses Arm SMMUv2 mostly by implication rather than direct specification, but the implications are substantial. The paper on memory accesses and interrupts models systems as decoding nets in which addresses are interpreted relative to nodes, and each node may accept addresses locally or translate them onward. It defines names as `(nodeid, addr)`, gives translation nodes an `accept` set and a `translate` function, and defines resolution as the set of accepted names reachable by recursive decode steps. Although the paper does not mention SMMUv2-specific structures such as context banks or stream tables, its framework naturally accommodates an IOMMU-like translation node on a DMA path and supports reasoning about reachability, isolation, and configuration invariants [1703.06571].

For SMMUv2, that model suggests a useful abstraction: device-visible addresses, interconnect addresses, and final memory resources should not be conflated into a single globally meaningful “physical address.” The same formal work stresses that the destination memory cell or register may appear at different physical addresses for different agents. That observation aligns closely with the Zynq case studies, where device-visible virtual addresses, CPU physical addresses, and SMMU-translated addresses coexist. A plausible implication is that correctness arguments for SMMUv2 must be phrased as path-sensitive reachability properties rather than as simple equality of address values.

The Armv8-A relaxed virtual-memory paper offers a second, more concurrency-oriented perspective. It is not a model of SMMUv2, and it explicitly does not cover stream tables, context banks, command queues, or non-CPU agents. It does, however, formalize translation walks as explicit read events, distinguishes stage-1 and stage-2 translation, and shows that successful or permission-faulting translations may be cached whereas translation faults are architecturally forbidden from being cached. It also states that valid-to-invalid and valid-to-different-valid updates require TLB invalidation and, in the relevant classes of mapping changes, break-before-make discipline, while stable injective page tables collapse the translated model back to the ordinary Arm memory model [2203.00642].

By analogy rather than direct architectural claim, this points to several likely SMMUv2-relevant disciplines. Invalid-to-valid updates should be simpler than remap or unmap operations, because stale valid translations are the hard case. Translation caches should not be assumed coherent with page-table memory absent explicit invalidation. Reuse of address-space identifiers or contexts should be treated as a global synchronization problem. And when mappings are static during the behavior of interest, a verifier may be able to reason largely at the level of final physical accesses. These are inferences, not stated SMMUv2 theorems, but they are consistent with the implementation-centric difficulties seen in the MMU-500 bring-up and page-fault studies.

## 6. Performance, interference, and operational trade-offs

Empirical work on Arm CoreLink MMU-500 shows that Arm SMMUv2 can be a measurable source of DMA interference. On a Xilinx UltraScale+ ZCU104 platform, the cited study reverse-engineers a 64-entry micro-TLB depth for the evaluated implementation and identifies two primary contention sources: the distributed Translation Buffer Units, treated as micro-TLBs, and the Translation Control Unit cache hierarchy, including macro-TLB, page-table-walk cache, and prefetch structures. Under the strongest tested TCU-stressing interference condition at 300 MHz, with SMMU enabled and 16-byte DMA transfers, the maximum latency slowdown reaches \(1.79\times\). The same study reports that the SMMU adds almost no cost in solo mode when translations are cached, but under contention average latency rises by roughly \(1.47\times\) to \(1.51\times\), and even minimum latency increases. Throughput degradation is largest for small payloads: at 16 bytes, solo throughput is about 84.6 KB/s and falls to 57.4 KB/s or 56.7 KB/s under the two interference scenarios, whereas at 4 KB all configurations nearly converge [2508.19670].

The interpretation offered is that SMMU-induced overhead is approximately constant per transaction, about 100 ns in the authors’ reading, so small transfers are disproportionately affected because translation latency is a large fraction of total DMA time. This result is operationally important because it shifts SMMUv2 from being viewed only as a protection primitive to also being treated as a timing-relevant shared resource. In mixed-criticality settings, the paper argues that VM or device isolation alone is insufficient if the devices still share SMMU translation structures [2508.19670].

The ExaNeSt page-fault thesis illuminates a different performance trade-off. It reports an “ideal” round-trip latency of about 4 µs for a one-FPGA remote DMA write of 16 bytes when setup and unmapping costs are excluded. It then measures per-buffer overheads for pinning, unpinning, and touching memory pages: for 4 KB buffers, 6 µs, 2 µs, and 3 µs respectively; for 64 KB, 49 µs, 14 µs, and 40 µs. Against that baseline, on-demand SMMU fault handling does not beat pre-touched or pinned transfers when those setup costs are excluded, but it can avoid continually paying registration costs and the memory-utilization disadvantages of pinning. For destination faults, the `get_user_pages()`-based “Touch-Ahead” path improves end-to-end latency over Netlink “Touch-A-Page” by \(1.7\times\) at 16 KB and \(1.2\times\) at 32 KB and 64 KB. For source faults, with 1 ms timeout-driven replay, the same mechanism improves latency by \(3.9\times\) at 16 KB and 32 KB and by \(4.7\times\) at 64 KB [2511.21018].

Several operational conclusions follow directly from these studies. Successful translation on SMMUv2 is not equivalent to end-to-end correctness, because coherence problems can remain after address translation is working, as the user-page-table experiment reports. SMMU fault registers are precise enough for address diagnosis but insufficient for application-level replay protocols. Translation overhead can be nearly invisible in uncontended steady state yet dominate latency for small transfers under contention. And page-fault-tolerant virtual-address DMA on SMMUv2 is feasible, but in the cited implementation it relies on software-managed recovery above the SMMU rather than on native in-hardware replay.

Source: https://www.emergentmind.com/topics/arm-smmuv2