* x19: paddr(start)
* x20: phys offset
*
- * Clobbers x0 - x4, x25
- *
- * Register usage within this function:
- * x25: Identity map in place
+ * Clobbers x0 - x4
*/
create_page_tables:
- /*
- * If Xen is loaded at exactly XEN_VIRT_START then we don't
- * need an additional 1:1 mapping, the virtual mapping will
- * suffice.
- */
- cmp x19, #XEN_VIRT_START
- cset x25, eq /* x25 := identity map in place, or not */
-
- load_paddr x4, boot_pgtable
-
- /* Setup boot_pgtable: */
- load_paddr x1, boot_first
-
- /* ... map boot_first in boot_pgtable[0] */
- mov x3, #PT_PT /* x2 := table map of boot_first */
- orr x2, x1, x3 /* + rights for linear PT */
- str x2, [x4, #0] /* Map it in slot 0 */
-
- /* ... map of paddr(start) in boot_pgtable+boot_first_id */
- lsr x1, x19, #ZEROETH_SHIFT/* Offset of base paddr in boot_pgtable */
- cbz x1, 1f /* It's in slot 0, map in boot_first
- * or boot_second later on */
+ /* Prepare the page-tables for mapping Xen */
+ ldr x0, =XEN_VIRT_START
+ create_table_entry boot_pgtable, boot_first, x0, ZEROETH_SHIFT, x1, x2, x3
+ create_table_entry boot_first, boot_second, x0, FIRST_SHIFT, x1, x2, x3
+ create_table_entry boot_second, boot_third, x0, SECOND_SHIFT, x1, x2, x3
- /*
- * Level zero does not support superpage mappings, so we have
- * to use an extra first level page in which we create a 1GB mapping.
- */
- load_paddr x2, boot_first_id
-
- mov x3, #PT_PT /* x2 := table map of boot_first_id */
- orr x2, x2, x3 /* + rights for linear PT */
- str x2, [x4, x1, lsl #3]
-
- load_paddr x4, boot_first_id
-
- lsr x1, x19, #FIRST_SHIFT /* x1 := Offset of base paddr in boot_first_id */
- lsl x2, x1, #FIRST_SHIFT /* x2 := Base address for 1GB mapping */
- mov x3, #PT_MEM /* x2 := Section map */
- orr x2, x2, x3
- and x1, x1, #LPAE_ENTRY_MASK /* x1 := Slot offset */
- str x2, [x4, x1, lsl #3] /* Mapping of paddr(start) */
- mov x25, #1 /* x25 := identity map now in place */
-
-1: /* Setup boot_first: */
- load_paddr x4, boot_first /* Next level into boot_first */
-
- /* ... map boot_second in boot_first[0] */
- load_paddr x1, boot_second
- mov x3, #PT_PT /* x2 := table map of boot_second */
- orr x2, x1, x3 /* + rights for linear PT */
- str x2, [x4, #0] /* Map it in slot 0 */
-
- /* ... map of paddr(start) in boot_first */
- cbnz x25, 1f /* x25 is set if already created */
- lsr x2, x19, #FIRST_SHIFT /* x2 := Offset of base paddr in boot_first */
- and x1, x2, #LPAE_ENTRY_MASK /* x1 := Slot to use */
- cbz x1, 1f /* It's in slot 0, map in boot_second */
-
- lsl x2, x2, #FIRST_SHIFT /* Base address for 1GB mapping */
- mov x3, #PT_MEM /* x2 := Section map */
- orr x2, x2, x3
- str x2, [x4, x1, lsl #3] /* Create mapping of paddr(start)*/
- mov x25, #1 /* x25 := identity map now in place */
-
-1: /* Setup boot_second: */
- load_paddr x4, boot_second
-
- /* ... map boot_third in boot_second[1] */
- load_paddr x1, boot_third
- mov x3, #PT_PT /* x2 := table map of boot_third */
- orr x2, x1, x3 /* + rights for linear PT */
- str x2, [x4, #8] /* Map it in slot 1 */
-
- /* ... map of paddr(start) in boot_second */
- cbnz x25, 1f /* x25 is set if already created */
- lsr x2, x19, #SECOND_SHIFT /* x2 := Offset of base paddr in boot_second */
- and x1, x2, #LPAE_ENTRY_MASK /* x1 := Slot to use */
- cmp x1, #1
- b.eq virtphys_clash /* It's in slot 1, which we cannot handle */
-
- lsl x2, x2, #SECOND_SHIFT /* Base address for 2MB mapping */
- mov x3, #PT_MEM /* x2 := Section map */
- orr x2, x2, x3
- str x2, [x4, x1, lsl #3] /* Create mapping of paddr(start)*/
- mov x25, #1 /* x25 := identity map now in place */
-
-1: /* Setup boot_third: */
- load_paddr x4, boot_third
+ /* Map Xen */
+ adr_l x4, boot_third
lsr x2, x19, #THIRD_SHIFT /* Base address for 4K mapping */
lsl x2, x2, #THIRD_SHIFT
cmp x1, #(LPAE_ENTRIES<<3) /* 512 entries per page */
b.lt 1b
- /* Defer fixmap and dtb mapping until after paging enabled, to
- * avoid them clashing with the 1:1 mapping. */
+ /*
+ * If Xen is loaded at exactly XEN_VIRT_START then we don't
+ * need an additional 1:1 mapping, the virtual mapping will
+ * suffice.
+ */
+ cmp x19, #XEN_VIRT_START
+ bne 1f
+ ret
+1:
+ /*
+ * Setup the 1:1 mapping so we can turn the MMU on. Note that
+ * only the first page of Xen will be part of the 1:1 mapping.
+ */
+
+ /*
+ * Find the zeroeth slot used. If the slot is not
+ * XEN_ZEROETH_SLOT, then the 1:1 mapping will use its own set of
+ * page-tables from the first level.
+ */
+ lsr x0, x19, #ZEROETH_SHIFT /* x0 := zeroeth slot */
+ cmp x0, #XEN_ZEROETH_SLOT
+ beq 1f
+ create_table_entry boot_pgtable, boot_first_id, x19, ZEROETH_SHIFT, x0, x1, x2
+ b link_from_first_id
+
+1:
+ /*
+ * Find the first slot used. If the slot is not XEN_FIRST_SLOT,
+ * then the 1:1 mapping will use its own set of page-tables from
+ * the second level.
+ */
+ lsr x0, x19, #FIRST_SHIFT
+ and x0, x0, #LPAE_ENTRY_MASK /* x0 := first slot */
+ cmp x0, #XEN_FIRST_SLOT
+ beq 1f
+ create_table_entry boot_first, boot_second_id, x19, FIRST_SHIFT, x0, x1, x2
+ b link_from_second_id
- /* boot pagetable setup complete */
+1:
+ /*
+ * Find the second slot used. If the slot is XEN_SECOND_SLOT, then the
+ * 1:1 mapping will use its own set of page-tables from the
+ * third level. For slot XEN_SECOND_SLOT, Xen is not yet able to handle
+ * it.
+ */
+ lsr x0, x19, #SECOND_SHIFT
+ and x0, x0, #LPAE_ENTRY_MASK /* x0 := first slot */
+ cmp x0, #XEN_SECOND_SLOT
+ beq virtphys_clash
+ create_table_entry boot_second, boot_third_id, x19, SECOND_SHIFT, x0, x1, x2
+ b link_from_third_id
+
+link_from_first_id:
+ create_table_entry boot_first_id, boot_second_id, x19, FIRST_SHIFT, x0, x1, x2
+link_from_second_id:
+ create_table_entry boot_second_id, boot_third_id, x19, SECOND_SHIFT, x0, x1, x2
+link_from_third_id:
+ create_mapping_entry boot_third_id, x19, x19, x0, x1, x2
+ ret
- cbnz x25, 1f /* Did we manage to create an identity mapping ? */
- PRINT("Unable to build boot page tables - Failed to identity map Xen.\r\n")
- b fail
virtphys_clash:
/* Identity map clashes with boot_third, which we cannot handle yet */
PRINT("- Unable to build boot page tables - virt and phys addresses clash. -\r\n")
b fail
-
-1:
- ret
ENDPROC(create_page_tables)
/*