/usr/local/DS-5_v5.27.1/bin/FVP_MPS2_AEMv8M \--parameter fvp_mps2.platform_type=2 \--parameter cpu0.baseline=0 \--parameter cpu0.INITVTOR_S=0x10000000 \--parameter cpu0.semihosting-enable=0 \--parameter fvp_mps2.DISABLE_GATING=0 \--parameter fvp_mps2.telnetterminal0.start_telnet=1 \--parameter fvp_mps2.telnetterminal1.start_telnet=0 \--parameter fvp_mps2.telnetterminal2.start_telnet=0 \--parameter fvp_mps2.telnetterminal0.quiet=0 \--parameter fvp_mps2.telnetterminal1.quiet=1 \--parameter fvp_mps2.telnetterminal2.quiet=1 \--application cpu0=~/TF-M/trusted-firmware-m/cmake_build/bl2/ext/mcuboot/mcuboot.axf \--data cpu0=~/TF-M/trusted-firmware-m/cmake_build/tfm_sign.bin@0x10080000
This will load tfm_sign.bin to 0x10080000.
The 1MB tfm_sign.bin has such a layout:
<1024B header><512K tfm_s.bin + pad><511K tfm_ns.bin + TLV + pad>
Therefore, we know tfm_s.bin is loaded to 0x10080400, and tfm_ns.bin is loaded to 0x10100400.
From trusted-firmware-m/platform/ext/target/mps2/an521/partition/region_defs.h, we know
NS_CODE_START = 0x100400,
and comparing the memory starts from 0x10100400 and the memory starts from 0x100400, we know these two ranges have the same content. In other word, after start the FVP_MPS2_AEMv8M, tfm_ns.bin, which should locate at 0x10100400, is loaded/mapped to address 0x100400. My question is how is this implemented.
Another observation is the memory content of 0x100400 and 0x10100400 are always the same. If I change the data stored at 0x100400, the data at 0x10100400 also changes, and vice versa. How to explain this? Thanks.
Hi there,
In the Armv8-M FVP, we use a memory alias scheme for memory partitioning between Secure address and Non-secure address spaces. The concept is introduced in this document:
https://developer.arm.com/products/architecture/m-profile/docs/100767/latest/system-design-for-armv8m
In most low cost devices, instead of having two separated sets of flash and sram, it is desirable to have just a single flash and a single sram, and used a memory protection controllers (MPC) to partition them into secure and non-secure spaces. An easy solution is to have those memory macros to be alias into two spaces, using one of the bit in the address line to determine the security domain, and use MPC units to configure memory pages inside to be visible in either secure alias or non-secure alias.
In the system design for the FVP, we use bit 28 of the address line to define address partitioning in the IDAU. As a result, 0x10100000 (Secure) and 0x00100000 (Non-secure) has the same contents. Please note Secure software need to config SAU in system initialization to allow 0x00100000 to be Non-secure. At reset, when SAU is disabled all memory spaces should be secure (apart from exempted regions used by debug components).
regards,
Joseph
Hi, Joseph,
Thank you very much for your quick response. The answer is very informative and useful. Also great are your books and whitepapers such as "ARMv8-M Architecture Technical Overview".
I have a couple follow up questions.
1. IDAU defines a fixed memory map, SAU optionally overrides the security attributes for some parts of the memory. May I say IDAU is usually configured to achieve basic security configurations, and users can employ SAU to further customize security configurations if the basic IDAU configs are not fit enough for an application?
2. If address partitioning in the IDAU configs 0x00000000 - 0x0FFFFFFF (Non-secure); 0x10000000 - 0x1FFFFFFF (Non-secure), does it always mean addr (0x00000000 + A) and (0x10000000 + A) have the same contents?
Or in other word, as you mentioned, "As a result, 0x10100000 (Secure) and 0x00100000 (Non-secure) has the same contents", how is this achieved?
Is it possible that using bit 28 of the address line to define address partitioning in the IDAU, but 0x10100000 (Secure) and 0x00100000 (Non-secure) have different contents?
Here you mentioned "Please note Secure software need to config SAU in system initialization to allow 0x00100000 to be Non-secure."
"config SAU in system initialization", do you mean enabling SAU by setting the bit[0] of SAU_CTRL to 1?
Thanks.
1. It depends on the type of systems you are using.
For simple SoC design, the IDAU might provide all necessary information, and SAU only need to set ALLNS bit and enable bit in SAU_CTRL register to enable the Non-secure memory map.
For microcontrollers, the designs need to be much more flexible and potentially IDAU define large portions of memory as Non-secure, and Secure software override that to decide how much Secure memory space it needed. In that case programming of SAU region registers are needed.
2. There might be a typo in your question. Do you mean 0x10000000-0x1FFFFFFF is Secure?
Assumed that is the case, it also depends on the memory partitioning hardware design. The memory protection controller we used in our example system is outside of the processor and is a part of the CoreLink SDK-200. With this design, we use the memory alias approach so address 0x00100000 and 0x10100000 are mapped to the same address location in a memory block (could be flash, SRAM, etc. This is device specific). Many microcontroller designs follow the same approach, but this is not a strict requirement for using Armv8-M processors.
The memory protection controller (MPC) design can potentially mask out the Non-secure data from Secure alias. So if a Non-secure data is in 0x00100000 (Non-secure alias range), Secure software can only read the data via Non-secure alias, but not from the Secure alias (0x10100000). This is the recommended approach for Normal memory as this reduce the risk of code injection attacks.
It is entirely possible to use bit 28 of the address line to define security domain in the IDAU, and have different contents in the two space. The alias approach used by MPC allow us to dynamically remap memory pages between security domains. But if dynamic memory page configuration is not required, you can have entirely different memory devices allocated in these address spaces.
Setting SAU_CTRL bit 0 to 1 is the minimal requirement. If IDAU is used to define the memory space partitioning, then you also set the ALLNS bit of this register to 1.
If needed, you can program SAU region registers to override IDAU setting. In that case ALLNS bit should not be set to 1.