diff --git a/xen/arch/arm/arm64/head.S b/xen/arch/arm/arm64/head.S index ba24b05fa2..4c9a69be63 100644 --- a/xen/arch/arm/arm64/head.S +++ b/xen/arch/arm/arm64/head.S @@ -33,6 +33,11 @@ #define PT_DEV 0xe71 /* nG=1 AF=1 SH=10 AP=01 NS=1 ATTR=100 T=0 P=1 */ #define PT_DEV_L3 0xe73 /* nG=1 AF=1 SH=10 AP=01 NS=1 ATTR=100 T=1 P=1 */ +/* Convenience defines to get slot used by Xen mapping. */ +#define XEN_ZEROETH_SLOT zeroeth_table_offset(XEN_VIRT_START) +#define XEN_FIRST_SLOT first_table_offset(XEN_VIRT_START) +#define XEN_SECOND_SLOT second_table_offset(XEN_VIRT_START) + #define __HEAD_FLAG_PAGE_SIZE ((PAGE_SHIFT - 10) / 2) #define __HEAD_FLAG_PHYS_BASE 1 @@ -312,6 +317,13 @@ real_start_efi: ldr x0, =primary_switched br x0 primary_switched: + /* + * The 1:1 map may clash with other parts of the Xen virtual memory + * layout. As it is not used anymore, remove it completely to + * avoid having to worry about replacing existing mapping + * afterwards. + */ + bl remove_identity_mapping bl setup_fixmap #ifdef CONFIG_EARLY_PRINTK /* Use a virtual address to access the UART. */ @@ -648,10 +660,67 @@ enable_mmu: ret ENDPROC(enable_mmu) +/* + * Remove the 1:1 map from the page-tables. It is not easy to keep track + * where the 1:1 map was mapped, so we will look for the top-level entry + * exclusive to the 1:1 map and remove it. + * + * Inputs: + * x19: paddr(start) + * + * Clobbers x0 - x1 + */ +remove_identity_mapping: + /* + * Find the zeroeth slot used. Remove the entry from zeroeth + * table if the slot is not XEN_ZEROETH_SLOT. + */ + lsr x1, x19, #ZEROETH_SHIFT /* x1 := zeroeth slot */ + cmp x1, #XEN_ZEROETH_SLOT + beq 1f + /* It is not in slot XEN_ZEROETH_SLOT, remove the entry. */ + ldr x0, =boot_pgtable /* x0 := root table */ + str xzr, [x0, x1, lsl #3] + b identity_mapping_removed + +1: + /* + * Find the first slot used. Remove the entry for the first + * table if the slot is not XEN_FIRST_SLOT. + */ + lsr x1, x19, #FIRST_SHIFT + and x1, x1, #LPAE_ENTRY_MASK /* x1 := first slot */ + cmp x1, #XEN_FIRST_SLOT + beq 1f + /* It is not in slot XEN_FIRST_SLOT, remove the entry. */ + ldr x0, =boot_first /* x0 := first table */ + str xzr, [x0, x1, lsl #3] + b identity_mapping_removed + +1: + /* + * Find the second slot used. Remove the entry for the first + * table if the slot is not XEN_SECOND_SLOT. + */ + lsr x1, x19, #SECOND_SHIFT + and x1, x1, #LPAE_ENTRY_MASK /* x1 := first slot */ + cmp x1, #XEN_SECOND_SLOT + beq identity_mapping_removed + /* It is not in slot 1, remove the entry */ + ldr x0, =boot_second /* x0 := second table */ + str xzr, [x0, x1, lsl #3] + +identity_mapping_removed: + /* See asm-arm/arm64/flushtlb.h for the explanation of the sequence. */ + dsb nshst + tlbi alle2 + dsb nsh + isb + + ret +ENDPROC(remove_identity_mapping) + setup_fixmap: - /* Now we can install the fixmap and dtb mappings, since we - * don't need the 1:1 map any more */ - dsb sy #if defined(CONFIG_EARLY_PRINTK) /* Fixmap is only used by early printk */ /* Add UART to the fixmap table */ ldr x1, =xen_fixmap /* x1 := vaddr (xen_fixmap) */ @@ -669,19 +738,10 @@ setup_fixmap: ldr x1, =FIXMAP_ADDR(0) lsr x1, x1, #(SECOND_SHIFT - 3) /* x1 := Slot for FIXMAP(0) */ str x2, [x4, x1] /* Map it in the fixmap's slot */ + + /* Ensure any page table updates made above have occurred. */ + dsb nshst #endif - - /* - * Flush the TLB in case the 1:1 mapping happens to clash with - * the virtual addresses used by the fixmap or DTB. - */ - dsb sy /* Ensure any page table updates made above - * have occurred. */ - - isb - tlbi alle2 - dsb sy /* Ensure completion of TLB flush */ - isb ret ENDPROC(setup_fixmap)