xlat v2: Split MMU setup and enable
At present, the function provided by the translation library to enable
MMU constructs appropriate values for translation library, and programs
them to the right registers. The construction of initial values,
however, is only required once as both the primary and secondaries
program the same values.
Additionally, the MMU-enabling function is written in C, which means
there's an active stack at the time of enabling MMU. On some systems,
like Arm DynamIQ, having active stack while enabling MMU during warm
boot might lead to coherency problems.
This patch addresses both the above problems by:
- Splitting the MMU-enabling function into two: one that sets up
values to be programmed into the registers, and another one that
takes the pre-computed values and writes to the appropriate
registers. With this, the primary effectively calls both functions
to have the MMU enabled, but secondaries only need to call the
latter.
- Rewriting the function that enables MMU in assembly so that it
doesn't use stack.
This patch fixes a bunch of MISRA issues on the way.
Change-Id: I0faca97263a970ffe765f0e731a1417e43fbfc45
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
diff --git a/lib/xlat_tables_v2/aarch32/enable_mmu.S b/lib/xlat_tables_v2/aarch32/enable_mmu.S
new file mode 100644
index 0000000..97cdde7
--- /dev/null
+++ b/lib/xlat_tables_v2/aarch32/enable_mmu.S
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <assert_macros.S>
+#include <xlat_tables_v2.h>
+
+ .global enable_mmu_direct
+
+func enable_mmu_direct
+ /* Assert that MMU is turned off */
+#if ENABLE_ASSERTIONS
+ ldcopr r1, SCTLR
+ tst r1, #SCTLR_M_BIT
+ ASM_ASSERT(eq)
+#endif
+
+ /* Invalidate TLB entries */
+ TLB_INVALIDATE(r0, TLBIALL)
+
+ mov r3, r0
+ ldr r0, =mmu_cfg_params
+
+ /* MAIR0 */
+ ldr r1, [r0, #(MMU_CFG_MAIR0 << 2)]
+ stcopr r1, MAIR0
+
+ /* TTBCR */
+ ldr r2, [r0, #(MMU_CFG_TCR << 2)]
+ stcopr r2, TTBCR
+
+ /* TTBR0 */
+ ldr r1, [r0, #(MMU_CFG_TTBR0_LO << 2)]
+ ldr r2, [r0, #(MMU_CFG_TTBR0_HI << 2)]
+ stcopr16 r1, r2, TTBR0_64
+
+ /* TTBR1 is unused right now; set it to 0. */
+ mov r1, #0
+ mov r2, #0
+ stcopr16 r1, r2, TTBR1_64
+
+ /*
+ * Ensure all translation table writes have drained into memory, the TLB
+ * invalidation is complete, and translation register writes are
+ * committed before enabling the MMU
+ */
+ dsb ish
+ isb
+
+ /* Enable enable MMU by honoring flags */
+ ldcopr r1, SCTLR
+ ldr r2, =(SCTLR_WXN_BIT | SCTLR_C_BIT | SCTLR_M_BIT)
+ orr r1, r1, r2
+
+ /* Clear C bit if requested */
+ tst r3, #DISABLE_DCACHE
+ bicne r1, r1, #SCTLR_C_BIT
+
+ stcopr r1, SCTLR
+ isb
+
+ bx lr
+endfunc enable_mmu_direct
diff --git a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
index f66f802..94dcf57 100644
--- a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
+++ b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -18,6 +18,8 @@
#error ARMv7 target does not support LPAE MMU descriptors
#endif
+uint32_t mmu_cfg_params[MMU_CFG_PARAM_MAX];
+
/*
* Returns 1 if the provided granule size is supported, 0 otherwise.
*/
@@ -109,22 +111,16 @@
* Function for enabling the MMU in Secure PL1, assuming that the page tables
* have already been created.
******************************************************************************/
-void enable_mmu_arch(unsigned int flags,
- uint64_t *base_table,
+void setup_mmu_cfg(unsigned int flags,
+ const uint64_t *base_table,
unsigned long long max_pa,
uintptr_t max_va)
{
- u_register_t mair0, ttbcr, sctlr;
+ u_register_t mair0, ttbcr;
uint64_t ttbr0;
assert(IS_IN_SECURE());
- sctlr = read_sctlr();
- assert((sctlr & SCTLR_M_BIT) == 0);
-
- /* Invalidate TLBs at the current exception level */
- tlbiall();
-
/* Set attributes in the right indices of the MAIR */
mair0 = MAIR0_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX);
mair0 |= MAIR0_ATTR_SET(ATTR_IWBWA_OWBWA_NTR,
@@ -185,30 +181,9 @@
ttbr0 |= TTBR_CNP_BIT;
#endif
- /* Now program the relevant system registers */
- write_mair0(mair0);
- write_ttbcr(ttbcr);
- write64_ttbr0(ttbr0);
- write64_ttbr1(0);
-
- /*
- * Ensure all translation table writes have drained
- * into memory, the TLB invalidation is complete,
- * and translation register writes are committed
- * before enabling the MMU
- */
- dsbish();
- isb();
-
- sctlr |= SCTLR_WXN_BIT | SCTLR_M_BIT;
-
- if (flags & DISABLE_DCACHE)
- sctlr &= ~SCTLR_C_BIT;
- else
- sctlr |= SCTLR_C_BIT;
-
- write_sctlr(sctlr);
-
- /* Ensure the MMU enable takes effect immediately */
- isb();
+ /* Now populate MMU configuration */
+ mmu_cfg_params[MMU_CFG_MAIR0] = mair0;
+ mmu_cfg_params[MMU_CFG_TCR] = ttbcr;
+ mmu_cfg_params[MMU_CFG_TTBR0_LO] = (uint32_t) ttbr0;
+ mmu_cfg_params[MMU_CFG_TTBR0_HI] = ttbr0 >> 32;
}