Secure and Non-Secure MPU Overlap and Address Range Validation
In ARM Cortex-M systems with TrustZone enabled, the Memory Protection Unit (MPU) is a critical component for enforcing memory access rules between secure and non-secure worlds. The cmse_check_address_range
function is used to validate whether a memory range provided by the non-secure world is accessible under specific conditions, such as non-secure, unprivileged, and read-write permissions. However, when both Secure MPU (MPU_S) and Non-Secure MPU (MPU_NS) are active, issues can arise if the memory regions are not properly configured.
The core issue occurs when a buffer allocated in the non-secure world (e.g., at address 0x20000000
) is accessed from the secure world using cmse_check_address_range
. The Secure MPU is configured to cover the same physical memory but using a secure alias address (e.g., 0x30000000
). Despite the physical memory being the same, the cmse_check_address_range
function triggers a secure fault because the secure MPU does not recognize the non-secure address range as valid. This indicates that the Secure MPU must explicitly define regions for both the non-secure and secure aliases of the same physical memory.
This behavior is expected due to the way ARM TrustZone and the MPU handle address translation and access permissions. The Secure MPU must be configured to recognize both the non-secure and secure address ranges for the same physical memory to avoid faults during cross-world data transfers. This requirement is often overlooked, leading to runtime faults and system instability.
Memory Region Configuration and Address Translation Mismatch
The root cause of the issue lies in the mismatch between memory region configurations in the Secure and Non-Secure MPUs and the address translation mechanisms used by TrustZone. When TrustZone is enabled, the same physical memory can be accessed using both secure and non-secure addresses. For example, a memory region located at 0x20000000
in the non-secure world might have a secure alias at 0x30000000
. However, the MPU does not automatically translate between these addresses. Instead, it treats them as entirely separate regions.
The cmse_check_address_range
function performs its validation based on the address provided and the permissions specified. If the Secure MPU is only configured to recognize the secure alias address (0x30000000
), it will not validate the non-secure address (0x20000000
) as accessible, even though they point to the same physical memory. This results in a secure fault when the function attempts to check the non-secure address range.
Additionally, the issue is exacerbated by the fact that the Secure MPU and Non-Secure MPU operate independently. The Non-Secure MPU might be correctly configured to allow access to the non-secure address range, but the Secure MPU must also be explicitly configured to recognize the same range for cross-world access. This dual configuration requirement is often missed during system setup, leading to runtime faults.
Configuring Dual MPU Regions and Validating Cross-World Access
To resolve this issue, the Secure MPU must be configured to recognize both the non-secure and secure address ranges for the same physical memory. This involves defining two separate MPU regions: one for the non-secure address range (e.g., 0x20000000
) and one for the secure alias address range (e.g., 0x30000000
). Both regions must have the same access permissions and attributes to ensure consistent behavior.
The following steps outline the process for configuring the MPU and validating cross-world access:
-
Define Non-Secure MPU Region: Ensure the Non-Secure MPU is configured to allow access to the non-secure address range (
0x20000000
). This region should have the appropriate permissions (e.g., read-write) for the non-secure world. -
Define Secure MPU Region for Non-Secure Address: In the Secure MPU, define a region that covers the non-secure address range (
0x20000000
). This region must have the same permissions as the corresponding Non-Secure MPU region to allow cross-world access. -
Define Secure MPU Region for Secure Alias: In the Secure MPU, define a second region that covers the secure alias address range (
0x30000000
). This region should also have the same permissions as the non-secure region to ensure consistency. -
Use
cmse_check_address_range
with Correct Permissions: When callingcmse_check_address_range
, ensure the permissions (e.g.,CMSE_NONSECURE | CMSE_MPU_UNPRIV | CMSE_MPU_READWRITE
) match the MPU configurations. This ensures the function validates the address range correctly. -
Test Cross-World Data Transfers: After configuring the MPU regions, test cross-world data transfers to verify that the secure fault no longer occurs. Use debug tools to monitor MPU behavior and ensure both regions are being recognized correctly.
By following these steps, the system can avoid secure faults caused by mismatched MPU configurations and ensure reliable cross-world data transfers. Proper MPU configuration is critical for systems using ARM TrustZone, as it directly impacts the security and stability of the system.
Example MPU Configuration Table
The following table provides an example of how the Secure and Non-Secure MPU regions should be configured for a memory region located at 0x20000000
in the non-secure world and 0x30000000
in the secure world:
MPU | Address Range | Permissions | Attributes |
---|---|---|---|
MPU_NS | 0x20000000-0x2000FFFF | Read-Write, Unprivileged | Non-Secure, Cacheable |
MPU_S | 0x20000000-0x2000FFFF | Read-Write, Unprivileged | Non-Secure, Cacheable |
MPU_S | 0x30000000-0x3000FFFF | Read-Write, Unprivileged | Secure, Cacheable |
This table illustrates the dual MPU region configuration required to avoid secure faults during cross-world access. Both the non-secure and secure address ranges must be explicitly defined in the Secure MPU to ensure proper validation by cmse_check_address_range
.
Debugging Tips
- Monitor MPU Faults: Use a debugger to monitor MPU faults and identify which region is causing the issue. This can help pinpoint misconfigurations.
- Verify Address Translation: Ensure the address translation between non-secure and secure worlds is correctly implemented in the hardware.
- Check MPU Region Overlaps: Ensure there are no overlaps or conflicts between MPU regions that could cause unexpected behavior.
By addressing these configuration and validation steps, developers can ensure robust and secure operation of ARM Cortex-M systems with TrustZone enabled.