Add arch_vm_mm_reset()
When running tests on Android dev boards, it is necessary to be able
to break out of the reboot-test loop, boot into the Android Bootloader,
and flash a new system image. The bootloader expects the MMU to be
disabled, so record the initial values of the corresponding system
registers and provide a function to reset them before branching to the
bootloader.
Change-Id: Ic191223e4dc849118e24f2cd7e2ecc113f05b310
diff --git a/src/arch/aarch64/hftest/mm.c b/src/arch/aarch64/hftest/mm.c
index 86f27d8..60ca2f0 100644
--- a/src/arch/aarch64/hftest/mm.c
+++ b/src/arch/aarch64/hftest/mm.c
@@ -30,6 +30,11 @@
static uintreg_t mm_tcr_el1;
static uintreg_t mm_sctlr_el1;
+static uintreg_t mm_reset_ttbr0_el1;
+static uintreg_t mm_reset_mair_el1;
+static uintreg_t mm_reset_tcr_el1;
+static uintreg_t mm_reset_sctlr_el1;
+
/**
* Initialize MMU for a test running in EL1.
*/
@@ -53,6 +58,15 @@
}
/*
+ * Preserve initial values of the system registers in case we want to
+ * reset them.
+ */
+ mm_reset_ttbr0_el1 = read_msr(ttbr0_el1);
+ mm_reset_mair_el1 = read_msr(mair_el1);
+ mm_reset_tcr_el1 = read_msr(tcr_el1);
+ mm_reset_sctlr_el1 = read_msr(sctlr_el1);
+
+ /*
* 0 -> Device-nGnRnE memory
* 0xff -> Normal memory, Inner/Outer Write-Back Non-transient,
* Write-Alloc, Read-Alloc.
@@ -99,3 +113,16 @@
write_msr(sctlr_el1, mm_sctlr_el1);
isb();
}
+
+void arch_vm_mm_reset(void)
+{
+ /* Set system registers to their reset values. */
+ write_msr(ttbr0_el1, mm_reset_ttbr0_el1);
+ write_msr(mair_el1, mm_reset_mair_el1);
+ write_msr(tcr_el1, mm_reset_tcr_el1);
+
+ dsb(sy);
+ isb();
+ write_msr(sctlr_el1, mm_reset_sctlr_el1);
+ isb();
+}
diff --git a/src/arch/aarch64/inc/hf/arch/vm/mm.h b/src/arch/aarch64/inc/hf/arch/vm/mm.h
index d212fa5..993f801 100644
--- a/src/arch/aarch64/inc/hf/arch/vm/mm.h
+++ b/src/arch/aarch64/inc/hf/arch/vm/mm.h
@@ -20,3 +20,8 @@
bool arch_vm_mm_init(void);
void arch_vm_mm_enable(paddr_t table);
+
+/**
+ * Reset MMU-related system registers. Must be called after arch_vm_mm_init().
+ */
+void arch_vm_mm_reset(void);