Use 4 levels of page tables when enabling the MMU. This will allow us to

boot on an SoC that places physical memory at an address past where three
levels of page tables can access in an identity mapping.

Submitted by:   Wojciech Macek <wma@semihalf.com>,
                Patrick Wildt <patrick@bitrig.org>
Differential Revision:	https://reviews.freebsd.org/D3885 (partial)
Differential Revision:	https://reviews.freebsd.org/D3744
This commit is contained in:
Andrew Turner 2015-10-19 13:20:23 +00:00
parent 2ca3cc5132
commit 80c4b9e575
2 changed files with 76 additions and 6 deletions

View File

@ -100,6 +100,16 @@ _start:
br x15
virtdone:
/*
* Now that we are in virtual address space,
* we don't need the identity mapping in TTBR0 and
* can set the TCR to a more useful value.
*/
ldr x2, tcr
mrs x3, id_aa64mmfr0_el1
bfi x2, x3, #32, #3
msr tcr_el1, x2
/* Set up the stack */
adr x25, initstack_end
mov sp, x25
@ -167,7 +177,7 @@ ENTRY(mpentry)
/* Load the kernel page table */
adr x26, pagetable_l1_ttbr1
/* Load the identity page table */
adr x27, pagetable_l1_ttbr0
adr x27, pagetable_l0_ttbr0
/* Enable the mmu */
bl start_mmu
@ -177,6 +187,16 @@ ENTRY(mpentry)
br x15
mp_virtdone:
/*
* Now that we are in virtual address space,
* we don't need the identity mapping in TTBR0 and
* can set the TCR to a more useful value.
*/
ldr x2, tcr
mrs x3, id_aa64mmfr0_el1
bfi x2, x3, #32, #3
msr tcr_el1, x2
ldr x4, =secondary_stacks
mov x5, #(PAGE_SIZE * KSTACK_PAGES)
mul x5, x0, x5
@ -373,9 +393,9 @@ create_pagetables:
*/
add x27, x26, #PAGE_SIZE
mov x6, x27 /* The initial page table */
#if defined(SOCDEV_PA) && defined(SOCDEV_VA)
/* Create a table for the UART */
mov x6, x27 /* The initial page table */
mov x7, #DEVICE_MEM
mov x8, #(SOCDEV_VA) /* VA start */
mov x9, #(SOCDEV_PA) /* PA start */
@ -384,17 +404,55 @@ create_pagetables:
#endif
/* Create the VA = PA map */
mov x6, x27 /* The initial page table */
mov x7, #NORMAL_UNCACHED /* Uncached as it's only needed early on */
mov x9, x27
mov x8, x9 /* VA start (== PA start) */
mov x10, #1
bl build_l1_block_pagetable
/* Move to the l0 table */
add x27, x27, #PAGE_SIZE
/* Link the l0 -> l1 table */
mov x9, x6
mov x6, x27
bl link_l0_pagetable
/* Restore the Link register */
mov x30, x5
ret
/*
* Builds an L0 -> L1 table descriptor
*
* This is a link for a 512GiB block of memory with up to 1GiB regions mapped
* within it by build_l1_block_pagetable.
*
* x6 = L0 table
* x8 = Virtual Address
* x9 = L1 PA (trashed)
* x11, x12 and x13 are trashed
*/
link_l0_pagetable:
/*
* Link an L0 -> L1 table entry.
*/
/* Find the table index */
lsr x11, x8, #L0_SHIFT
and x11, x11, #Ln_ADDR_MASK
/* Build the L0 block entry */
mov x12, #L0_TABLE
/* Only use the output address bits */
lsr x9, x9, #12
orr x12, x12, x9, lsl #12
/* Store the entry */
str x12, [x6, x11, lsl #3]
ret
/*
* Builds an L1 -> L2 table descriptor
*
@ -535,8 +593,13 @@ start_mmu:
ldr x2, mair
msr mair_el1, x2
/* Setup TCR according to PARange bits from ID_AA64MMFR0_EL1 */
ldr x2, tcr
/*
* Setup TCR according to PARange bits from ID_AA64MMFR0_EL1.
* Some machines have physical memory mapped >512GiB, which can not
* be identity-mapped using the default 39 VA bits. Thus, use
* 48 VA bits for now and switch back to 39 after the VA jump.
*/
ldr x2, tcr_early
mrs x3, id_aa64mmfr0_el1
bfi x2, x3, #32, #3
msr tcr_el1, x2
@ -559,6 +622,9 @@ mair:
tcr:
.quad (TCR_TxSZ(64 - VIRT_BITS) | TCR_ASID_16 | TCR_TG1_4K | \
TCR_CACHE_ATTRS | TCR_SMP_ATTRS)
tcr_early:
.quad (TCR_T1SZ(64 - VIRT_BITS) | TCR_T0SZ(64 - 48) | \
TCR_ASID_16 | TCR_TG1_4K | TCR_CACHE_ATTRS | TCR_SMP_ATTRS)
sctlr_set:
/* Bits to set */
.quad (SCTLR_UCI | SCTLR_nTWE | SCTLR_nTWI | SCTLR_UCT | SCTLR_DZE | \
@ -586,6 +652,8 @@ pagetable_l1_ttbr1:
.space PAGE_SIZE
pagetable_l1_ttbr0:
.space PAGE_SIZE
pagetable_l0_ttbr0:
.space PAGE_SIZE
pagetable_end:
el2_pagetable:

View File

@ -231,7 +231,9 @@
#define TCR_T1SZ_SHIFT 16
#define TCR_T0SZ_SHIFT 0
#define TCR_TxSZ(x) (((x) << TCR_T1SZ_SHIFT) | ((x) << TCR_T0SZ_SHIFT))
#define TCR_T1SZ(x) ((x) << TCR_T1SZ_SHIFT)
#define TCR_T0SZ(x) ((x) << TCR_T0SZ_SHIFT)
#define TCR_TxSZ(x) (TCR_T1SZ(x) | TCR_T0SZ(x))
/* Saved Program Status Register */
#define DBG_SPSR_SS (0x1 << 21)