ARM SMMU versions 1 and 2
The ARM SMMU specification outlines an IOMMU architecture for ARM processors, similar to Intel's VT-d. The SMMU mediates accesses to RAM by devices, and can translate addresses generated by DMA engines so as to correct them as the OS requires.
This page is current with versions 1 and 2 of the SMMU specification. This page does not serve as an exhaustive description of the SMMU. It is meant to serve as a refresher to jog the memory of people who have already read the SMMU specification.
A common 's' in a register name, as in SMMU_sCR0 implies that versions of this register exist for both secure and non-secure mode and that both versions are being talked about in that instance.
The SMMU supports processing transactions from multiple streams at once, and translation of multiple contexts at once.
- Just in general, the SMMU spec refers to DMA engines and MCUs on the chipset as being "upstream" from the SMMU and it refers to RAM as being "downstream" from the SMMU.
- The "Stream mapping table" is a term used to refer to the combined working of the SMMU_SMRn + SMMU_S2CRn registers. Do not confuse the SMMU_SMRn ("Stream matching registers") with the umbrella term "Stream mapping registers". ARM defines Stream mapping as (Section 2.3.2) "the process of mapping a StreamID to the associated Stream-to-Context register, SMMU_S2CRn".
- "Contexts" are synonymous with Intel's "domain" terminology used in the VT-d specification; they refer to a set of IO-page tables for translating IO-Addresses into output addresses on the bus/memory controller.
- Transactions: Any write to or read from the SMMU by any agent is an SMMU transaction.
- Client transactions: Client transactions are requests sent through the SMMU which can be potentially translated. These are generally bus messages.
- Configuration transactions: Configuration transactions are accesses to the SMMU register interface to program the SMMU's behaviour (using the SMMU_* registers).
- StreamIDs: These are used to identify the source of a transaction. They identify a device uniquely, or otherwise a set of devices working together deliberately to appear to be the same device.
- A single device may also pretend to be multiple devices by using multiple StreamIDs.
- An example of a StreamID might be a PCI Bus+Slot+Function combination.
Contrast against Intel VT-d
Both SMMU and VT-d support 1st-stage translation. 1st-stage translation can be used:
- To isolate devices and ensure that they don't access memory beyond what they are expected to (i.e, beyond the scatter gather list that has currently been programmed into the device).
VT-d 1st-stage translation can be used:
- To isolate guest VMs and ensure that they don't touch memory outside of what they have been allocated as their guest physical address space (IPA addrspace).
Only SMMU supports 2nd-stage translation. 2nd stage translation can be used:
- When passing a device through to a guest VM, to translate the IPA addresses that the guest will program into the device, into their correct PAs.
Only VT-d supports PASID 2nd-stage translation. PASID translation can be used:
- To enable a device to directly walk the page tables of userspace processes, and translate virtual addresses into physical addresses.
- For example, the virtual address of a graphics texture buffer can be sent to the GFX card directly, and the VT-d DHRU will be able to walk the page tables of the sending process and translate the virtual address on its own.
- PASID translation is then chained into the standard translation flow to isolate the device's address accesses in the standard way that an IOMMU is normally used.
VT-d only supports PCI devices in its current form (at the time of writing) while SMMU supports multiple buses but leaves it up to the OEM implementation to determine how to map a bus technology's device IDs onto the identifier nomenclature ("StreamIDs") employed by the SMMU specification. For example, for the SMMU, an OEM is likely to map the 16-bit PCI Bus+Slot+Function onto the 15/16-bit StreamID space provided by the SMMU.
Secure/Non-secure mode split and SSD
The SMMU splits its registers for use between secure and non-secure mode; both modes can use the SMMU at the same time and there is register banking for some of the registers to facilitate this. Because both modes can use the SMMU at the same time, the SMMU also needs to know which devices have been partitioned into secure-mode devices and which are left for non-secure mode. In particular, secure mode devices can generate client transactions which access both secure memory and non-secure memory whereas non-secure mode devices can only access non-secure memory.
There is a distinction to be kept in mind about the difference between the SMMU's SSD feature (Security-State Determination) and the marking of a transaction by an upstream bus technology/device as either secure or non-secure. A non-secure device may maliciously mark its transactions as being secure, so the SSD feature which sits within the SMMU is meant to thwart that. When an upstream device is determined to be SSD-non-secure, the SMMU will never generate a downstream transaction which is marked secure. When an upstream device is determined to be SSD-secure, the SMMU may generate a downstream transaction which is either secure or non-secure.
- The SMMU may not have a programmable SSD register space, in which case the SSD determination is done via some [implementation defined] mechanism attached to the SMMU.
- The SMMU SSD register space is present if SMMU_IDR1.SSDTP == 0b01 or 0b11.
- When this field has either of those values, the SSD space is present in the SMMU.
- When the SSD space is present in the SMMU, the SMMU_SSDRn registers are present.
- These SMMU_SSDRn registers are bitfields, 32 bits each. If bit<N> is 1 then device<N> is non-secure, else it is secure.
Splitting the Stream Mapping table between secure and non-secure mode
The Stream Mapping table is global and shared between Secure and non-secure mode. Secure mode must decide how many Stream Mapping register groups it will expose for non-secure mode's use. ARM recommends that secure mode software leaves at least one Stream mapping register group for use by non-secure software.
Having an SMMU_S2CR which has been allocated to secure be configured to mode point to a context bank which is non-secure is UNPREDICTABLE. Having an SMMU_S2CR which has been allocated to non-secure mode be configured to point to a context bank which is secure will trigger an Unimplemented Context Bank SMMU Fault.
Splitting the Context banks between secure and non-secure mode
Some number of context banks can be reserved for use by secure mode using SMMU_SCR1.NSNUMCBO. The allocation begins from the top of the available context bank space. The SMMU will intelligently present the correct number of context banks to non-secure mode through non-secure accesses to SMMU_IDR1.NUMCB. SMMU_SCR1.NSNUMCBO actually reserves a number of context banks for non-secure mode. The leftover context banks that come after those reserved by SMMU_SCR1.NSNUMCBO are what are actually reserved for secure mode. .
Translation, bypass and faulting
The SMMU will do one of 3 things with any client transaction that is sent to it:
- Translate the transaction using translation tables.
- Allow the transaction to bypass translation, and just modify the attributes of the transaction (read/write, shareability, caching, etc).
- Generate an SMMU fault.
The SSD register space, if available, tells the OS which devices are secure vs non-secure. For a secure-mode OS, it allows the OS to set which StreamIDs are secure/non-secure. A Secure-mode OS should set these registers up. A non-secure mode OS may choose to read these registers to determine which devices are under its purvue.
Also, secure mode software may need to prevent access by non-secure software to the global register file of the SMMU. This can be done by setting SMMU_SCR1.GASRAE==1 (Section 2.10.1).
The number of supported streamID bits is determined by reading SMMU_IDR0.NUMSIDB[3:0].
- Ranges from 0-15.
- Can be 0 in the case of an SMMU which is dedicated to handling transactions from a single upstream StreamID.
- Support for 16-bit streamIDs exists if SMMU_IDR0.EXIDS==1 AND SMMU_IDR0.NUMSIDB==15.
- 16-bit Stream IDs are enabled by setting SMMU_sCR0.EXIDENABLE==1.
Furthermore, if the OS intends to use Stream Indexing instead of Stream Matching, then the number of StreamIDs is further constrained by the number of SMMU_S2CRn registers available. The number of SMMU_S2CRn registers is directly determined by the number of SMMU_SMRn registers (Section 2.3.2, "Stream indexing": This means the maximum StreamID is determined by the number of implemented SMMU_S2CRns). See #Stream Matching Registers for how to determine the number of SMMU_S2CRn registers by inferring it from the number of SMMU_SMRn regs.
The OS should determine the max number of StreamIDs based on the Stream Mapping technique it intends to use, and set up metadata accordingly.
Stream Matching Registers
SMMUv1 supports up to 128 SMMU_SMRs. SMMUv2 may optionally support the Extended Stream Matching Extension which provides up to 1024 SMMU_SMRs.
The number of SMMU_SMRn regs determines the number of SMMU_S2CRn regs (Section 2.3.2, "Stream matching": the optional Extended Stream Matching Extension, that provides up to 1024 Stream Match Registers and associated Stream-to-Context registers).
- Support for Stream Matching is indicated via SMMU_IDR0.SMS == 1.
- Support for Extended Stream Matching is indicated via SMMU_IDR0.EXSMRGS == 1.
- Enable Extended Stream Matching using SMMU_sCR2.EXSMRGENABLE==1.
- Setting SMMU_SCR2.EXNSSMRGDISABLE==1 with a secure write to SMMU_SCR2 disables the use of Extended Stream Matching by non-secure mode.
- Support for compressed Indexing (which is a subfeature under Stream Matching) is indicated via a secure read of SMMU_IDR2.COMPINDEXS == 1. A non-secure read of this bit only states whether or not compressed indexing is available for use by non-secure software.
- The number of Stream Mapping Register Groups is determined by reading SMMU_IDR0.NUMSMRG.
- It is possible for an implementation not to support Stream Matching, but still allow software to reference the Stream Mapping Table (which is the combination of the SMMU_SMRn and SMMU_S2CRn register sets).
- In such a case, the SMMU_SMRn register group will be RES0.
ARM found it important to mention that if the SMMU support Extended Stream Matching and the extension is not enabled, the (up to) 128 SMMU_SMRs that are exposed, map onto the final 128 SMMU_SMRs provided by the extension. Since it's apparently important, I'll mention it too.
Context Banks and number of supported Contexts
The max number of supported contexts is implied by the max number of SMMU_CBARn registers (Section 2.3.4: "The number of SMMU_CBARn regs matches the number of entries in the translation context bank table, and is IMPLEMENTATION DEFINED. SMMU_IDR1.NUMCB specifies the number of implemented SMMU_CBARn regs."). That said, NUMCB is an 8-bit field, and section 2.6.1 says: "The SMMU architecture provides space for up to 128 translation context banks".
- Multiple SMMU_SMRn regs may cause multiple StreamIDs to map to the same Context when Stream Matching is used.
- Each incoming StreamID maps directly to a specific Context when Stream Indexing is used.
Section 2.6.1: On reset no translation context bank table entry initializatoin is required. Typically, the SMMU implementation [sic] initializes the required values before use.
Support for stage1 and stage2
- Support for stage1 translation is indicated via SMMU_IDR0.S1TS.
- Support for stage2 translation is indicated via SMMU_IDR0.S2TS.
- Support for stage1 followed by stage2 translation is indicated via SMMU_IDR0.NTS.
- If SMMU_IDR0.NTS is set, then both SMMU_IDR0.S1TS and SMMU_IDR0.S2TS must be set.
If both stage1 and stage2 are supported, then all contexts except the first X can support either stage1 or stage2 translation. The first X context banks may be restricted such that they only support stage2. To detect the number X which can only be used for stage2 translation, see SMMU_IDR1.NUMS2CB. The SMMU_CBARn.TYPE field governs the stage of translation for a context bank which supports both stages.
Stream Mapping Table
Section 2.3.10: "On reset, no initialization is performed on the Stream mapping table entries.". Ergo the OS must explicitly initialize all the stream mapping reg groups "before the SMMU is enabled" [sic].
Section 2.5.2: "In SMMUv2, All TLBs are disabled from reset. All MMUs are disabled from reset and the contexnts of the TLBs have no effect on address translation."
However, an implementation may require an IMPLEMENTATION DEFINED TLB invalidation routine to be called before enabling TLBs/MMU after #RESET. Such a routine must be doucmented clearly by the device. If TLBs which have not been invalidated since #RESET are used their behaviour is UNPREDICTABLE.
Client transaction flowchart
Do not allow a single StreamID to map to multiple contexts. Multiple stream IDs can however, map to a single context.
- Client transactions are enabled with the "Client Port Disable" bit: SMMU_sCR0.CLIENTPD==0.
- If SMMU_sCR0.CLIENTPD==1, then bypass is assumed for all incoming transactions.
- Bypass attribute transformation is done based on the values in SMMU_sCR0.
- If SMMU_sCR0.CLIENTPD==0, client transaction processing is enabled, and:
- Stream Mapping table is searched.
- Stream Mapping table search is done using either Stream Matching, Compressed Stream Indexing or Stream Indexing.
- If Stream Mapping search yields no results then either:
- [if SMMU_sCR0.USFCFG==1 -- USFCFG means "Unidentified Stream Fault Config"] An Unidentified Stream SMMU fault is generated.
- [if SMMU_sCR0.USFCFG==0] The unidentifiable stream ID is handled by bypassing it and applying the attribute transformation specified in SMMU_sCR0.
- If Stream mapping table search yields multiple results:
- [if SMMU_sCR0.SMCFCFG==1 -- SMCFCFG means "Stream Match Conflict Fault Config"] A Stream Match Conflict SMMU Fault is generated.
- [if SMMU_sCR0.SMCFCFG==0 ] The conflict is handled via bypass and applying the attribute transformation specified in SMMU_sCR0 (just like the Unidentified Stream case).
- If Stream Mapping table search yields a single result ('This is the desired normal case').
- The Stream Mapping table lookup will identify one of the 128 SMMU_S2CRn Stream to Context Registers.
- The S2C register will determine which of the 3 handling mechanisms will be used to deal with the incoming client transaction (translation, bypass or fault).
- [if SMMU_S2CRn.Type == Fault] An Invalid Context SMMU fault is generated.
- [if SMMU_S2CRn.Type == bypass] The client transaction is handled via bypass and the attributes specified in SMMU_S2CRn are applied to the transaction.
- [if SMMU_S2CRn.Type == Translation] The client transaction is handled by translation and:
- The attributes in SMMU_CBARn (stage 1 Context Bank Attribute Reg) and SMMU_SBA2Rn (stage 2 Context Bank Attribute Reg) are 'optionally' applied to the output transaction which is generated downstream.
- [if SMMU_CBn_SCTLR.M==1 for the particular stage in question] then translation is done for that stage using the configuration in SMMU_CBARn.
- Stream Mapping table is searched.
Flow for Translation-type scenarios
As stated before on this page, Stream Mapping is defined by ARM as "'the process of mapping a StreamID to the associated Stream-to-Context register'".
When a client transaction comes in from upstream, if client transaction processing is enabled (SMMU_sCR0.CLIENTPD==0), the SMMU must decide what SMMU context to use to translate the transaction into the output transaction which will eventually be emitted downstream by the SMMU. The process of determining which Context bank should be used to handle client transactions sent by a particular upstream StreamID is an "associative search" [sic] which uses one of 3 methods: Stream Matching, Compressed Stream Indexing or Stream Indexing.
The Stream Mapping table is global and shared between Secure and non-secure mode. Secure mode must decide how many Stream Mapping register groups it will expose for non-secure mode's use. ARM recommends that secure mode software leaves at least one Stream mapping register group for use by non-secure software. To set the number of Stream mapping regs exposed to non-secure mode, use SMMU_SCR1.NSNUMSMRGO. The SMMU will intelligently deduce the number of SMR regs to tell non-secure mode about, and will report the appropriate number to a non-secure reader through SMMU_IDR0.NUMSMRG.
Transaction attribute combinations
See tables 2-2 and 2-3 for information on how cacheability, shareability, INSTCFG (instruction fetch), etc combine to form the final output attributes of the client transaction.
The SMMU maintains its own TLB of translations to speed up client transactions. The topology of the TLBs is IMPLEMENTATION DEFINED. TLB implementations may cache entries for any level or stage (or combination thereof) of translation. TLB maintenance can be done via either: (1) Broadcast TLB operations or (2) TLB maintenance register accesses.
Section 2.5: "Software must treat all TLB entries as being tagged with the input address. For other attributes [sic] TLB enteries are categorized so that the tagging applied to an entry depends on the translation regime. For a particular translation regime, a TLB entry must specify 'appropriate information' [sic], and certain conditions [sic] must be satisfied. For example, a non-secure stage 1 TLB entry must specify an ASID."
TLB Prefetching behaviour
The SMMU is allowed to prefetch the translation tables pointed to by a context bank if that context bank is pointed to by an entry in the Stream Mapping table. This is permitted even if there is no client transaction which is using/ has used that translation (section 2.5.1).
Section 2.8.2: TLB entries that are allocated as a result of HYPC accesses are Hyp tagged. All HYP tagged TLB entries are considered to belong to the same software entity and have no associated ASID or VMID.
Ergo the SMMU assumes that there is only one piece of software that is acting as a hypervisor.
MONC contexts (Section 2.9.2)
SMMUv2 provides the following TLB maintenance operations for maintaining MONC TLB tagged entries:
- SMMU_TLBIALLM: Invalidate all EL3 Monitor entries.
- SMMU_TLBIVAM: Invalidates all EL3 Monitor entries which are associated with a 64-bit VA.
- SMMU_TLBIVALM: Same as TLBIVAM, but invalidates only the last level table entries.
ARM found it necessary to warn that: These operations are not required to invalidate non-MONC Secure TLB entries.
E2HC contexts (Section 2.10)
E2HC context TLB entries are tagged by the TLB as E2H, but have no security state tagging. They are coupled with an ASID if they are non-global.
TLB entries for E2HC contexts matching combinations of (E2H identification) or (E2H identification+ASID tagging) are required to be invalidated by:
E2H identified TLB entries are not required to be invalidated by:
- Secure TLBI operations.
Additionally, the standard SMMU_CBn_TLBI* operations work on E2HC context TLB entries, except that instead of matching based on VMID, they match based on (E2H identification) or (E2H identification + ASID tagging).
In particular other than the specific TLB invalidate operations bulleted above, E2HC contexts are not considered to be hypervisor contexts by the SMMU.
Operation of the TLB is UNPREDICTABLE if there exist TLB entries allocated in the cache identified as HYPC and E2HC concurrently. Software must invalidate the HYPC/E2HC TLBs when switching between operating the SMMU with E2HC vs HYPC support enabled. Please see Section 2.10, example 2-1 for a full listing of the procedure for enabling E2HC operation.
Each context bank is one page large, where "one page" is defined as PAGESIZE which may be either 4KiB or 64KiB. The intention is that a hypervisor can Accessing an unimplemented context bank's register space will either result in an IMPLEMENTATION DEFINED result of either RAZ/WI or a Configuration Access SMMU Fault.
The SMMU_CBA2Rn.MONC, SMMU_CBARn.HYPC and SMMU_CBA2Rn.VA64 bits work together to define the security context and page table format (long vs short) for translation of a particular context bank.
Hypervisor Contexts (HYPC) (section 2.8)
Hypervisor mode contexts (HYPC) are the page tables of an OS running in HYP mode and not the 2nd stage page tables for a guest IPA. The SMMU is able to walk HYPC page tables. For that reason a HYPC bank cannot be a stage1 followed by stage2 context. I couldn't think of a good reason for a normal hypervisor to prefer to use HYPC tables when it can just use normal IO page tables. I could also be misinterpreting the purpose of this feature, as it appears to be linked to VHE extensions, and it may pertain to a special page table format used by VHE guests.
Support for HYPC is mututally exclusive with support for E2HC. HYPC is supported:
- For both SMMUv1 and SMMUv2, if VHE is not supported, then HYPC is supported.
- In an SMMUv2 implementation that has VHE, if SMMU_CR0.HYPMODE==0, HYPC is available, else E2HC is available.
VHE is supported by the SMMU if:
To set a context bank to be a HYPC bank, set SMMU_CBARn.HYPC==1.
- Do not set the HYPC bit on secure context banks -- that's illogical. See section 2.8.3 for details.
- The SMMU_CBn_TCR2.SEP field is ignored for HYPC contexts.
Monitor Contexts (MONC) (Section 2.9)
I couldn't determine whether MONC contexts are meant for use by devices claimed specifically by Monitor Mode (EL3) or whether this bit is meant to be set by all secure mode software. The specific wording of the manual is: Section 2.9: In SMMUv2, for a secure bank, when the value of the corresponding SMMU_CBA2Rn.MONC bit is 1, the bank is a MONC (Secure Monitor) context bank. MONC Translation context banks are intended to be used by the Secure EL3 translation regime.
The phrasing seems to support the latter of the two interpretations.
- Do not set both HYPC and MONC on any bank because that is UNPREDICTABLE.
- MONC only pertains to contexts reserved for secure mode use. Non-secure contexts ignore and treat the MONC bit as 0. Set it to 0.
- Sign extension via SMMU_CBn_TCR2.SEP is ignored for MONC banks.
VHE EL2 Contexts (E2HC) (Section 2.10)
E2HC contexts are meant to be used by hypervisor guests running in pseudo-EL2 (ARM's VHE feature) on top of another hypervisor which is running in real-EL2. The SMMU can only be programmed to use either E2HC or HYPC, but not both at the same time. This is a decision which must be made globally and it affects all software using the SMMU whether secure or nonsecure, whether EL3, EL2 or EL1. In fact, the HYPC and E2HC bits are polymorphically at the same position in the register.
E2HC contexts must be programmed to be of SMMU_CBARn.TYPE of 0b01 (stage1 followed by stage2 bypass). Unlike HYPC however, the E2HC translation regime is split between two TTBR registers. See the TLB management section to understand how the TLB entries for E2HC are handled by the TLB.
IRQs / SMMU Faults
Context bank faults
The SMMU may raise faults for a context bank when processing a stage of translation for a particular context bank.
- For SMMUv1, the SMMU_CBAR register states which interrupt is raised to signal faults while processing that context.
- For SMMUv2, each context bank has its own IRQ pin.