I am using Trusted Firmware Image(LSK and Android filesystem) provided by Linaro on Juno board r1. In my case, I just want to some trivial test in EL3, e.g., reading specific memory.
To make things easier, I didn't do anything until the system is completely booted. Then I load a kernel module which sends a SMC instruction and the SMC exception will be handled in BL3-1 by a custom handler. In the handler, I disabled MMU for EL3 and attempted to access a physical address directly. But I found that if the physical address is larger than 0xffffffff(4G), the content I got will be all 0. The physical address lower than 0xffffffff works perfectly. And If I mapped that physical address into a virtual address smaller than 0xffffffff(Linaro's EL3 only support virtual address lower than 0xffffffff), it also works.
So, why I can not get the correct content of a physical address larger than 0xffffffff after I disabled MMU in EL3?
Is there anyone know the details?
Thanks a lot for helping me!
Hello,
First of all keep in mind that address 0x100000000 is reserved - The second region of DRAM actually starts at 0x880000000.
This issue is because of how the TrustZone Address Space Controller (TZC-400) has been programmed in order to prevent Secure accesses to certain regions of Non-secure memory, as mentioned in this tutorial here. The ARM Trusted Firmware uses a 32-bit VA space and 32-bit PA space, so it programs the TZC-400 to prevent Secure accesses to the upper region of DRAM.
You can see the various regions programmed by the TZC-400 in this Trusted Firmware source file.
You'll notice that regions 2 and 3 (3 being the one you're interested in) are both programmed with security attributes TZC_REGION_S_NONE.
So you need to reprogram the security attributes to be TZC_REGION_S_RDWR.
Digging through the sources, this macro collapses to 0x3, and is shifted left by 30 and bitwise OR'd with PLAT_ARM_TZC_FILTERS, which collapses to 0x1. So we need to reprogram the attribute registers with value 0xC0000001.
From the TZC-400 TRM, we see that the attribute registers for regions 2 and 3 are at offsets 0x150 and 0x170 respectively, so we can enter these commands in the DS-5 debugger command window to reprogram them:
memory set_typed AXI<PROT=1>:0x000000002A4A0150 (unsigned int) 0xC0000001memory set_typed AXI<PROT=1>:0x000000002A4A0170 (unsigned int) 0xC0000001
memory set_typed AXI<PROT=1>:0x000000002A4A0150 (unsigned int) 0xC0000001
memory set_typed AXI<PROT=1>:0x000000002A4A0170 (unsigned int) 0xC0000001
I tested this and it works - Before entering the commands I am unable to see the second region of DRAM (starting at 0x880000000), and then I can see it after entering the commands.
I hope that helps,
Ash.
Just adding some additional info to my post:
LDR X0, =0xC0000001LDR X2, =0x2A4A0150 //; Region 2 attrsLDR X3, =0x2A4A0170 //; Region 3 attrsSTR X0, [X2]STR X0, [X3]DSB SY
LDR X0, =0xC0000001
LDR X2, =0x2A4A0150 //; Region 2 attrs
LDR X3, =0x2A4A0170 //; Region 3 attrs
STR X0, [X2]STR X0, [X3]
DSB SY
You'll only really need the DSB if you're planning to enable the MMU so that you can map some areas of DRAM as Normal-type, to ensure that those accesses are made after the TZC-400 has been reprogrammed.
View all questions in Arm Development Platforms forum