According to the ARM manual:
In the case of a 4kB granule, the hardware can use a 4-level look up process. The 48-bit address has nine address bits for each level translated (that is, 512 entries each), with the final 12 bits selecting a byte within the 4kB coming directly from the original address.
Bits [47:39] of the virtual address index into the 512 entry L0 table. Each of these table entries spans a 512GB range and points to an L1 table. Within that 512 entry L1 table, bits [38:30] are used as index to select an entry and each entry points to either a 1GB block or an L2 table.
Bits [29:21] index into a 512 entry L2 table and each entry points to a 2MB block or next table level. At the last level, bits [20:12] index into a 512 entry L2 table and each entry points to a 4kB block
This makes 100% sense for me. L0, L1, L2 tables and the final offset to arrive at a physical address.
However, look at this code: https://github.com/bztsrc/raspi3-tutorial/blob/abaf5a5b2bc1a9fdfe5a9d8191c061671555da3d/10_virtualmemory/mmu.c#L66, explained here:
Because we choose 4k as page size, and one translation entry is 8 bytes, that means we have 512 entries on each page. Therefore indeces 0..511 belong to the first page, 512..1023 to the second and so forth. With other words, the address of paging[0] equals to _end (first page), and paging[512] equals to _end + PAGESIZE (second page).
It looks like it's setting the L0, L1 and L2 as mentioned in the manual. So the first 512 entries would be the entries of the L0 table, the 513-1024 entries would be the L1 and 1025-1536 entries would be the L2 table.
However in the code it starts doing this like this:
paging[4*512+511]=(unsigned long)((unsigned char*)&_end+5*PAGESIZE) | // physical address
PT_PAGE | // we have area in it mapped by pages
PT_AF | // accessed flag
PT_KERNEL | // privileged
PT_ISH | // inner shareable
PT_MEM; // normal memory
The index 4*512+511 = 2559
is way past the L2 table I imagined. I think I misunderstood something very wrong!
Should paging[0]
and paging[511]
span the first table (L0), then paging[512]
and paging[2013]
span the second table (L1) and paging[1024]
and paging[2559]
span the last table (L2)?
What about r<<21
and r*PAGESIZE
, what do these mean?