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;
 }