aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2016-01-14 16:46:24 +0000
committerPeter Maydell <peter.maydell@linaro.org>2016-01-14 16:46:24 +0000
commit1936149658127ee60870c0c494f430ca549a174c (patch)
tree17f529c24ecfe0876ee6e1e41b37e04430f04b55
parenta1c0d275d0075201fb6d2d07f117c4e38c3b4842 (diff)
AArch64 EL3: don't assume SCR_EL3's only nonzero bit is NS
Make sure we initialize SCR_EL3 on startup and preserve bits in it across world switches. This is important for AArch64 because SCR_EL3 contains the register-width bit for EL1, and if the implementation is correctly honouring that bit then attempting to do an exception-return with it incorrectly set will result in an illegal exception return. Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--el3/aarch64/el3_monitor_asm.S4
-rw-r--r--el3/el3.c12
2 files changed, 14 insertions, 2 deletions
diff --git a/el3/aarch64/el3_monitor_asm.S b/el3/aarch64/el3_monitor_asm.S
index 2eac3b3..ea69b6d 100644
--- a/el3/aarch64/el3_monitor_asm.S
+++ b/el3/aarch64/el3_monitor_asm.S
@@ -94,8 +94,8 @@ monitor_switch:
stp x0, x1, [sp, #-16]! /* Save the input regs x0:x3 */
stp x2, x3, [sp, #-16]! /* Save the input regs x0:x3 */
mrs x3, scr_el3
- and x3, x3, #0x1
- cbz x3, switch_to_nsec
+ and x2, x3, #0x1
+ cbz x2, switch_to_nsec
switch_to_sec:
adr x0, nsec_state
MONITOR_SAVE_STATE
diff --git a/el3/el3.c b/el3/el3.c
index 78e69d1..f8c9107 100644
--- a/el3/el3.c
+++ b/el3/el3.c
@@ -328,6 +328,18 @@ void el3_start(uintptr_t base, uintptr_t size)
el3_monitor_init();
+ /* Initialize SCR. In particular, we must ensure that SCR_EL3.RW is 1
+ * so that we define EL1 as AArch64; otherwise the exception return
+ * will fail; we also want SCR_EL3.NS to be 0.
+ * Setting SCR_ST and SCR_HCE isn't necessary but this configuration
+ * is essentially "turn off all the trap-to-EL3 possibilities".
+ */
+#ifdef AARCH64
+ WRITE_SCR(SCR_ST | SCR_RW | SCR_HCE);
+#else
+ WRITE_SCR(SCR_HCE);
+#endif
+
/* Set-up our state to return to secure EL1 to start its init on exception
* return.
*/