-
Notifications
You must be signed in to change notification settings - Fork 22
RFC: FEAT_MEC Design in RMM
Memory Encryption Contexts (MEC) is an extension to the RME. FEAT_MEC introduces multiple memory encryption contexts to the Realm physical address space for assignment to Realm virtual machines, controlled by Realm EL2. This feature allows the association of specific encryption contexts to a Realm, facilitating secure isolation between Realm Virtual Machines.
The memory protected by a Realm’s MEC includes all memory which can be accessed by the Realm, and the RTTs which are owned by the Realm. Other Granules owned by the Realm, such as REC and RD, are protected with the RMM’s MEC.
For more details , refer these specifications and flows :
Realm Management Monitor specification
Arm Architecture Reference Manual for A-profile architecture
Memory Encryption Contexts (MEC) example software flows
RMM v1.0 without FEAT_MEC support, zeroes a granule when it transitions to DELEGATED state. The zeroing operation on a granule combines two distinct requirements:
(a) Sanitization – This process prepares the granule for use in a new Memory Encryption context, which may involve clearing any residual sensitive data of previous user from memory and Cache flush to Point of Encryption. Once completed, the granule can be safely used in the new context, ensuring the architectural guarantees of confidentiality for the new user and also for the previous user.
(b) Initialization – This sets up the memory for use either in a new Realm or internally within the RMM. This is typically done by zeroing the contents of the memory. Note that when a granule is initialized (zero-filled) with the encryption context of its next owner—referred to as the Memory-Encryption Context ID (MECID)—sanitization is automatically satisfied.
The RMM must ensure that memory accesses using mismatched MECIDs do not occur, as they can corrupt memory within the Realm PA space. Once the sanitization is completed, then the granule can be associated with a new MECID. MMU descriptor changes and MECID register programming must follow the guidelines mentioned in MEC example flow diagram.
When FEAT_MEC is present, these 2 requirements need to be handled distinctly. As per the MEC example flow diagram, the operation needed for sanitize has these cases:
-
Initial Use by Realm: If a Non-Secure (NS) granule is delegated to Realm PAS and used for a Realm for the first time, a DCCI PoPA as part of delegation is sufficient for
sanitize. -
Reassignment Between Realms: If a granule has already been used by Realm x and is then reassigned to Realm y (via the delegate state), the RMM must perform both DC ZVA and DCCI PoE for
sanitize. Note that if Realm x data is flushed with DCCI PoE and DC ZVA is done using the Realm y MECID, it initializes the granule for Realm y use. -
Returning granule to NS PAS while Realm is live If a granule used by Realm x is returned to NS PAS while Realm x still exists, then DC ZVA alone is sufficient for
sanitize. DCCI PoPA as part of undelegate will take care of cache flush. -
Reassignment to new Realm, after previous Realm is Dead/destroyed: If the granule is reassigned to Realm y after Realm x is dead (ie. Realm x has issued a FIRME_MEC_REFRESH SMC call), then DCCI PoE is sufficient for
sanitize. -
Return to NS PAS After Realm is Dead/destroyed: If the granule is returned to NS PAS after the Realm is dead, the DCCI PoPA is sufficient for
sanitize.
4 and 5 are optimizations of 2 and 3 respectively. The current RMM ABI does not allow easy implementation of these optimizations as RMI_REALM_DESTROY is the final call in the sequence for a Realm teardown and hence when a granule is returned to DELEGATE, the Realm is still not destroyed. And at the point where Realm is returned in NS PAS or re-assigned to a new Realm, RMM does not have the information to associate a granule to the previous Realm. And hence the design does not cater for this optimization.
Although the MEC example flow diagram doesn’t strictly require it, a granule that moves NS PAS → DELEGATED → DATA_UNKNOWN may still expose garbled residues of its former contents to the Realm. Zero-initializing the granule before Realm use eliminates that uncertainty, giving the Realm a clean, predictable data pattern instead of bytes influenced by the previous NS context. (Granules provisioned through RMI_DATA_CREATE() are unaffected, because their contents are immediately overwritten with data supplied by the NS Host.)
Further analysis showed that zero-initializing a granule with the MECID of its next owner automatically satisfies sanitization. Therefore, shifting the zero-fill step to the moment the granule leaves the DELEGATED state—rather than when it enters—lets RMM use a single flow that works with or without FEAT_MEC.
Before performing this initialization, RMM must flush any cache lines that still hold data encrypted with the previous MECID. When a granule is handed back to the non-secure host (NS PAS), RMM likewise must zero it, fulfilling the sanitization requirement.
This change:
- Preserves the original security guarantee: Realm data is not visible to the non‑secure host (NS Host) and to any other Realm
- Eliminates the duplication of maintaining separate code paths for systems with and without FEAT_MEC
- Eliminates redundant sanitization and initialization in several code paths. When FEAT_MEC is disabled, the extra zero‑ing previously performed for granules initialized by RMI_RTT_CREATE and RMI_DATA_CREATE have been removed. When FEAT_MEC is enabled, the change also removes duplicate sanitization of granules initialized by all RMI_*_CREATE APIs.
- Facilitates easier implementation of additional hardening (described later in this document) before returning a granule to NS Host, because hardening sanitization now occurs during the DELEGATE → UNDELEGATE transition. This allows the Realm MECID to be changed safely, unlike the previous model where sanitization happened while other granules could still be mapped and using the existing Realm MECID.
For a granule destined for Realm/RMM use, sanitization is now delivered by zero-initializing the granule with the next-owner’s MECID and this zeroing occurs only when the granule leaves the DELEGATED state. Consequently, RMM must perform this initialization (e.g., DC ZVA) before the granule’s first use. This requirement was already implicit with FEAT_MEC, because previous sanitization could have been performed with either the RMM MECID or the Realm MECID, leaving it uncertain whether the granule is zeroed in the new encryption context.
| Step | Transition | RMM Action (FEAT_MEC absent/present) | Comments |
|---|---|---|---|
| 1 | NS PAS → Delegated | No action / No Action | DCCI PoPA in EL3 will take care of data flush |
| 2 | Realm data (eg: DATA) and Realm RTTs → Delegated | No Action / DCCI PoE | Flushes data of the previous encryption context |
| 3 | RMM internal (eg: RD, REC) → Delegated | No Action / DCCI PoE | Flushes data of the previous encryption context |
| 4 | Delegated → Realm data (eg: DATA)/RTT | DC ZVA / DC ZVA (Realm MECID) | Initialize granule before use. There is an optimization that RTT create do not rely on the granule being zero. The RTT can be directly created. |
| 5 | Delegated → RMM internal (eg: RD, REC) | DC ZVA / DC ZVA (RMM MECID) | Initialize granule before use. |
| 6 | Delegated → NS PAS | DC ZVA / DC ZVA (RMM MECID) | Sanitize granule. DCCI PoPA in EL3 will take care of data flush |
Threat model: We are defending against an attacker who can observe ciphertext of pages after sanitization and wants to infer the RMM key used.
Hardening 1: Use random data instead of zeroes to sanitize a granule before returning to the NS Host
Zeros are predictable, so an attacker who sees the ciphertext can infer that the plaintext was all 0s. Overwriting with unpredictable bytes (drawn from RDNR or another entropy source) hides that pattern and protects RMM/Realm keys derived from the data.
For this sanitize method, we write a sequence of incrementing numbers to the target granule, starting from a randomly chosen global seed. This prevents the NS Host from seeing a page zeroed out using the RMM MEC Key. This method can be selected in setting the RMM_MEM_SCRUB_METHOD=1 option.
Continue writing zeros—not random bytes—using DC ZVA. The scrub key is not sensitive; leaking its pattern is harmless because it is never used for real data. This approach preserves the single-instruction speed advantage of DC ZVA while avoiding any semantic leakage of the RMM key.
This method can be enabled by setting the option RMM_MEM_SCRUB_METHOD=2. Enabling this option dedicates one MECID exclusively for sanitization, removing it from use by Realms.
Keeping these as a configurable option allows platforms to evaluate performance cost and make a decision regarding this.
These were the original flows prior to the Unified Sanitization Model design change.
Sanitize when FEAT_MEC is Present
| Step | Transition | RMM Action | Comments |
|---|---|---|---|
| 1 | NS PAS → Delegated | No action needed | DCCI PoPA will take care of cache |
| 2 a | Realm data (eg: DATA) and Realm RTTs → Delegated | Perform DCZVA + DCCI PoE using Realm MECID | |
| 2 b | Realm granule managed by RMM (eg: RD, REC) → Delegated | Perform DCZVA + DCCI PoE using RMM MECID | |
| 3 | Delegated → Assign to another Realm | No action needed | |
| 4 | Delegated → NS PAS | No action needed | DCCI PoPA will take care of cache |
Initialize when FEAT_MEC is Present
-
For RMM internal use (e.g., RD, REC): Perform DCZVA using the RMM MECID
-
For Realm RTT tables: DCZVA using the Realm MECID
-
For Realm memory mapped via RMI_DATA_CREATE_UNKNOWN: DCZVA using the Realm MECID
-
No action needed for initialize for other granule types.
Sanitize When FEAT_MEC is Absent
| Step | Transition | RMM Action | Comments |
|---|---|---|---|
| 1 | NS PAS → Delegated | DCZVA | |
| 2 | Realm granule → Delegated | DCZVA | |
| 3 | Delegated → Assigned to another Realm | No action needed | |
| 4 | Delegated → NS PAS | No action needed |
Initialize when FEAT_MEC is Absent
- No action needed for initialize for any granule.