[arch][arm64] determine the correct TCR_EL1.IPS at runtime

Change the early startup code to set TCR_EL1.IPS to
ID_AA64MMFR0_EL1.PARange if it has a defined value (the currently
defined values have the same meanings), but use 48-bit PAs if 52-bit
PAs are supported because 52-bit PAs have a different translation
table format that we don't support. Stash the computed TCR_EL1 in a
variable and use it in the context switch code.
This commit is contained in:
Peter Collingbourne
2022-05-12 15:37:03 -07:00
committed by Travis Geiselbrecht
parent cd96c43006
commit 576a7a7c82
3 changed files with 31 additions and 8 deletions

View File

@@ -197,8 +197,6 @@
MMU_MAIR_ATTR4 | MMU_MAIR_ATTR5 | \
MMU_MAIR_ATTR6 | MMU_MAIR_ATTR7 )
#define MMU_TCR_IPS_DEFAULT MMU_TCR_IPS(2) /* TODO: read at runtime, or configure per platform */
/* Enable cached page table walks:
* inner/outer (IRGN/ORGN): write-back + write-allocate
*/
@@ -212,8 +210,9 @@
MMU_TCR_ORGN0(MMU_RGN_WRITE_BACK_ALLOCATE) | \
MMU_TCR_IRGN0(MMU_RGN_WRITE_BACK_ALLOCATE) | \
MMU_TCR_T0SZ(64 - MMU_USER_SIZE_SHIFT))
#define MMU_TCR_FLAGS_KERNEL (MMU_TCR_IPS_DEFAULT | MMU_TCR_FLAGS1 | MMU_TCR_FLAGS0 | MMU_TCR_EPD0)
#define MMU_TCR_FLAGS_USER (MMU_TCR_IPS_DEFAULT | MMU_TCR_FLAGS1 | MMU_TCR_FLAGS0)
#define MMU_TCR_FLAGS_BASE (MMU_TCR_FLAGS1 | MMU_TCR_FLAGS0)
#define MMU_TCR_FLAGS_KERNEL (MMU_TCR_EPD0)
#define MMU_TCR_FLAGS_USER (0)
#define MMU_PTE_KERNEL_RO_FLAGS \
(MMU_PTE_ATTR_UXN | \

View File

@@ -30,6 +30,9 @@ pte_t arm64_kernel_translation_table[MMU_KERNEL_PAGE_TABLE_ENTRIES_TOP]
__ALIGNED(MMU_KERNEL_PAGE_TABLE_ENTRIES_TOP * 8)
__SECTION(".bss.prebss.translation_table");
/* the base TCR flags, computed from early init code in start.S */
uint64_t arm64_mmu_tcr_flags __SECTION(".bss.prebss.tcr_flags");
static inline bool is_valid_vaddr(arch_aspace_t *aspace, vaddr_t vaddr) {
return (vaddr >= aspace->base && vaddr <= aspace->base + aspace->size - 1);
}
@@ -630,12 +633,12 @@ void arch_mmu_context_switch(arch_aspace_t *aspace) {
if (TRACE_CONTEXT_SWITCH)
TRACEF("aspace %p\n", aspace);
uint64_t tcr;
uint64_t tcr = arm64_mmu_tcr_flags;
uint64_t ttbr;
if (aspace) {
DEBUG_ASSERT((aspace->flags & ARCH_ASPACE_FLAG_KERNEL) == 0);
tcr = MMU_TCR_FLAGS_USER;
tcr |= MMU_TCR_FLAGS_USER;
ttbr = ((uint64_t)MMU_ARM64_USER_ASID << 48) | aspace->tt_phys;
ARM64_WRITE_SYSREG(ttbr0_el1, ttbr);
@@ -643,7 +646,7 @@ void arch_mmu_context_switch(arch_aspace_t *aspace) {
TRACEF("ttbr 0x%llx, tcr 0x%llx\n", ttbr, tcr);
ARM64_TLBI(aside1, (uint64_t)MMU_ARM64_USER_ASID << 48);
} else {
tcr = MMU_TCR_FLAGS_KERNEL;
tcr |= MMU_TCR_FLAGS_KERNEL;
if (TRACE_CONTEXT_SWITCH)
TRACEF("tcr 0x%llx\n", tcr);

View File

@@ -266,6 +266,25 @@ arm_reset:
b .Lmap_range_one_table_loop
.Linitial_mapping_done:
/* compute the base TCR configuration and save away in a global for future use */
ldr tmp, =MMU_TCR_FLAGS_BASE
/* Set TCR_EL1.IPS to ID_AA64MMFR0_EL1.PARange */
mrs tmp2, id_aa64mmfr0_el1
and tmp2, tmp2, #0xf
/*
* Give up if we see a reserved value. 52-bit PAs have a different translation
* table format that we don't support, so use 48-bit PAs in that case.
*/
cmp tmp2, #6
b.hi .
b.lo 1f
mov tmp2, #5
1:
orr tmp, tmp, tmp2, lsl #32
adrp tmp2, arm64_mmu_tcr_flags
str tmp, [tmp2, #:lo12:arm64_mmu_tcr_flags]
#if WITH_SMP
adrp tmp, page_tables_not_ready
add tmp, tmp, #:lo12:page_tables_not_ready
@@ -295,7 +314,9 @@ arm_reset:
/* Initialize TCR_EL1 */
/* set cacheable attributes on translation walk */
/* (SMP extensions) non-shareable, inner write-back write-allocate */
ldr tmp, =MMU_TCR_FLAGS_KERNEL
adrp tmp, arm64_mmu_tcr_flags
ldr tmp, [tmp, #:lo12:arm64_mmu_tcr_flags]
orr tmp, tmp, #MMU_TCR_FLAGS_KERNEL
msr tcr_el1, tmp
isb