Xen on ARM: boot page tables setup

62 Views Asked by At

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!

1

There are 1 best solutions below

3
Siguza On

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 index 0x100, not 0x10. Now, there seems to be a requirement that XEN_VIRT_START is a multiple of 0x00200000 (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:

create_page_tables:
        /* Prepare the page-tables for mapping Xen */
        ldr   x0, =XEN_VIRT_START
        create_table_entry boot_pgtable, boot_first, x0, 0, x1, x2, x3
        create_table_entry boot_first, boot_second, x0, 1, x1, x2, x3
        create_table_entry boot_second, boot_third, x0, 2, x1, x2, x3

And lastly, "section map" seems to be their word for the opposite of a block mapping, i.e. just a single page:

#define PT_MEM_L3 0xf7f /* nG=1 AF=1 SH=11 AP=01 NS=1 ATTR=111 T=1 P=1 */