Dear all,
I'm using zynq7010 for an embedded design (two cortex A9 cores)
Actually, the "translation_table.s" file witch fill the MMU translation table with defaut values, use a granularity of 1MB of memory.
The SDK subroutine void Xil_SetTlbAttributes(INTPTR Addr, u32 attrib) witch i use to modify attributes for portion of memory, use an hardcoded granularity of 1MB to point to the good entry in the table and set the value:
section = Addr / 0x100000U; ptr = &MMUTable; ptr += section; if(ptr != NULL) { *ptr = (Addr & 0xFFF00000U) | attrib; }
I have read (UG585) that the MMU is able to support more fine grained sections (chapter 3.2.5 The MMU is compatible with the Virtual Memory System Architecture version 7 (VMSAv7)
requirements supporting 4 KB, 64 KB, 1 MB, and 16 MB page table entries)
As far as i know, linux kernel use 4K tables entries to manage the memory of the system.
I searched, within a lot of documents (UG585, ARM processor documents ...) i am not able to find configurations registers of the MMU to be able to use 4K granularity for my translation table.
My background experience is on small MCU, and i do not understand how big CPU like cortex A9 is configured (how registers are organized and so on... I have the feeling that there is a lot of configurable blocks close to the core itselt and each block has a configuration and a set of registers, and there are machine op code to write those registers instead of addresses ...)
I also had a look in the boot.s file within the SDK and between lines 260-271
#ifdef SHAREABLE_DDR /* Mark the entire DDR memory as shareable */ ldr r3, =0x3ff /* 1024 entries to cover 1G DDR */ ldr r0, =TblBase /* MMU Table address in memory */ ldr r2, =0x15de6 /* S=b1 TEX=b101 AP=b11, Domain=b1111, C=b0, B=b1 */ shareable_loop: str r2, [r0] /* write the entry to MMU table */ add r0, r0, #0x4 /* next entry in the table */ add r2, r2, #0x100000 /* next section */ subs r3, r3, #1 bge shareable_loop /* loop till 1G is covered */ #endif
we can see that the MMU translation table is written to change DDR parameter if needed. It is also assumed here 1MB granularity. So i searched within the code executed before if a see anywhere if a register is written to tell the MMU "Hey ! you have to assume that the table granularity i gave you is 1MB !! " or "hey, the translation table is located at this address in memory".
I was unable to find none of them ... so the is a huge probability that i missunderstood something ... or i am completely blind and the answer is in front of my eyes.
does anybody can help me to understand well how this system works ?
Thank's in advance for help !
best regards !
nico
As this is Cortex-A9, that means you have Armv7-A with the short-descriptor format.It's not a register field that sets the size of translation, rather than the level of the table. The translation table base registers (TTBRs) always point to a "level 1" table, which describes memory at a 1MB granularity. Each entry in the table can say fault, translate or point to a level 2 table. The level 2 table sub-divides the 1MB address region covered by the L1 table entry into 4K pages. Again, with one entry in the L2 table per 4K page.
I'm not familiar with the code you are using, so can't specifically on what you'd need to do with that code. But from a CPU point of view, you'll need to create some number of level 2 tables and point the level 1 table entries at them. That'll let you map at 4K page level.
For a more detailed explanation, see the Armv7-A Cortex-A Programmer's Guide, starting at this section: https://developer.arm.com/documentation/den0013/d/The-Memory-Management-Unit/First-level-address-translation?lang=en
Dear Martin,
Thank's a lot for your time! i appreciate really !
Your explanation is very clear, i do understand better how it works now.
I will read the document you attached and then, try to understand how Linux manages the table with the two levels to reach 4k granularity.
I will post here if i have others questions or misunderstanding.
Have a nice day.