How to access a physical address which is larger than 4G in Trusted firmware provided by Linaro

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!

Parents
  • 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) 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.

Reply
  • 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) 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.

Children
More questions in this forum