diff --git a/src/arch/arm64/armv8/mmu.c b/src/arch/arm64/armv8/mmu.c index 5d957d454f..9280fc2d7c 100644 --- a/src/arch/arm64/armv8/mmu.c +++ b/src/arch/arm64/armv8/mmu.c @@ -199,6 +199,26 @@ static void sanity_check(uint64_t addr, uint64_t size) size >= GRANULE_SIZE); } +/* Func : get_pte + * Desc : Returns the page table entry governing a specific address. */ +static uint64_t get_pte(void *addr) +{ + int shift = BITS_PER_VA > L1_ADDR_SHIFT ? L1_ADDR_SHIFT : L2_ADDR_SHIFT; + uint64_t *pte = (uint64_t *)_ttb; + + while (1) { + int index = ((uintptr_t)addr >> shift) & + ((1UL << BITS_RESOLVED_PER_LVL) - 1); + + if ((pte[index] & DESC_MASK) != TABLE_DESC || + shift <= GRANULE_SIZE_SHIFT) + return pte[index]; + + pte = (uint64_t *)(pte[index] & XLAT_ADDR_MASK); + shift -= BITS_RESOLVED_PER_LVL; + } +} + /* Func : mmu_config_range * Desc : This function repeatedly calls init_xlat_table with the base * address. Based on size returned from init_xlat_table, base_addr is updated @@ -256,6 +276,12 @@ void mmu_init(void) void mmu_enable(void) { + if (((get_pte(_ttb) >> BLOCK_INDEX_SHIFT) & BLOCK_INDEX_MASK) + != BLOCK_INDEX_MEM_NORMAL || + ((get_pte(_ettb - 1) >> BLOCK_INDEX_SHIFT) & BLOCK_INDEX_MASK) + != BLOCK_INDEX_MEM_NORMAL) + die("TTB memory type must match TCR (normal, cacheable)!"); + uint32_t sctlr = raw_read_sctlr_el3(); sctlr |= SCTLR_C | SCTLR_M | SCTLR_I; raw_write_sctlr_el3(sctlr); diff --git a/src/arch/arm64/include/armv8/arch/mmu.h b/src/arch/arm64/include/armv8/arch/mmu.h index 7c3b6a74d6..a8120736fa 100644 --- a/src/arch/arm64/include/armv8/arch/mmu.h +++ b/src/arch/arm64/include/armv8/arch/mmu.h @@ -102,6 +102,7 @@ #define BLOCK_INDEX_MEM_NORMAL_NC 3 #define BLOCK_INDEX_MEM_NORMAL 4 +#define BLOCK_INDEX_MASK 0x7 #define BLOCK_INDEX_SHIFT 2 /* MAIR attributes */