summaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/arm64/armv8/mmu.c26
-rw-r--r--src/arch/arm64/include/armv8/arch/mmu.h1
2 files changed, 27 insertions, 0 deletions
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 */