I'm trying to understand the start-of-day code for Xen on Arm64. In the function create_page_tables in boot.S, there's a portion where we try to map Xen text and data into the level 3 table then check if we need an 1:1 mapping.
/* Map Xen */
adr_l x4, boot_third
lsr x2, x19, #THIRD_SHIFT /* Base address for 4K mapping */
lsl x2, x2, #THIRD_SHIFT
mov x3, #PT_MEM_L3 /* x2 := Section map */
orr x2, x2, x3
/* ... map of vaddr(start) in boot_third */
mov x1, xzr
1: str x2, [x4, x1] /* Map vaddr(start) */
add x2, x2, #PAGE_SIZE /* Next page */
add x1, x1, #8 /* Next slot */
cmp x1, #(XEN_PT_LPAE_ENTRIES<<3) /* 512 entries per page*/
/*
* If Xen is loaded at exactly XEN_VIRT_START then we don't
* need an additional 1:1 mapping, the virtual mapping will
* suffice.
*/
ldr x0, =XEN_VIRT_START
cmp x19, x0
bne 1f
ret
b.lt 1b
x19 stores the physical address of the start entry point, which is the start of Xen text.
What I'm confused here is we're mapping Xen page by page into the first index of the L3 table, without taking into account the L3 table index.
For example if both x19 and XEN_VIRT_START is 0x00100000, don't we have to start mapping at index 0x10 since the L3 index is bits [20:12], assuming a 4KB granule size, to have the virtual mapping suffice the 1:1 condition? With this mapping, a VA such as 0x0010FC4 will be looked up in the 0x10-th slot in the L3 table, which will not map to the 1:1 PA 0x0010FC4. But since x19 and XEN_VIRT_START are equal, the code is gonna map an additional 1:1 page, which means we're screwed right?
Another point I don't understand is the comment says we're "section map", is that equivalent to "block mapping"? And isn't that not possible at L3 table since L3 entry has to be a page entry?
What I am missing here? Thanks in advance!
Your question is based on wrong assumptions.
First off, Xen is NOT adding the 1:1 mapping in the passage you've shown. It is adding the regular VA mapping, the 1:1 mapping comes below and only consists of a single page, if required at all.
Then, if XEN_VIRT_START were
0x00100000, we'd have to take L3 index0x100, not0x10. Now, there seems to be a requirement that XEN_VIRT_START is a multiple of0x00200000(that is to say, it is aligned to the granule of L3 tables), otherwise this code breaks. I have no idea whether this is documented anywhere, I'm not familiar with Xen. But the L0-L2 tables do take the virtual address into account:And lastly, "section map" seems to be their word for the opposite of a block mapping, i.e. just a single page: