From 948487311bfd8d68cc707d64a397c8cad8dc25e5 Mon Sep 17 00:00:00 2001 From: Marcelo Povoa Date: Fri, 14 Feb 2014 15:15:31 -0800 Subject: [PATCH] aarch64: Change default exception level to EL2 Since booting Linux requires that we are running at EL1 or EL2, transition already from EL3 to EL2. It is assumed for now that the system implements all exception levels, which is not a requirement. BUG=None BRANCH=none TEST=Boot to ramstage worked as before and used current_el() to verify that we are indeed at EL2 Change-Id: I29d8fc830367158cba53703d1dc2f0ad398b9d49 Signed-off-by: Marcelo Povoa Reviewed-on: https://chromium-review.googlesource.com/186741 Reviewed-by: David Hendricks --- src/arch/aarch64/bootblock.inc | 5 +++++ src/arch/aarch64/cpu.S | 20 ++++++++++++++++++++ src/arch/aarch64/exception_asm.S | 8 ++++---- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/arch/aarch64/bootblock.inc b/src/arch/aarch64/bootblock.inc index fcaf5af502..e65515f20b 100644 --- a/src/arch/aarch64/bootblock.inc +++ b/src/arch/aarch64/bootblock.inc @@ -68,6 +68,11 @@ call_bootblock: sub sp, sp, #16 + /* + * Switch to EL2 already because Linux requires to be + * in EL1 or EL2, see its "Booting AArch64 Linux" doc + */ + bl switch_el3_to_el2 bl main .align 3 diff --git a/src/arch/aarch64/cpu.S b/src/arch/aarch64/cpu.S index c4bdd3ee6d..54f5e59395 100644 --- a/src/arch/aarch64/cpu.S +++ b/src/arch/aarch64/cpu.S @@ -26,6 +26,7 @@ * Flush the whole D-cache. * * Corrupted registers: x0-x7, x9-x11 + * From: Linux arch/arm64/mm/cache.S */ ENTRY(flush_dcache_all) dsb sy // ensure ordering with previous memory accesses @@ -106,3 +107,22 @@ ENTRY(arm_init_caches) ret x8 ENDPROC(arm_init_caches) + +/* From u-boot transition.S */ +ENTRY(switch_el3_to_el2) + mov x0, #0x5b1 /* Non-secure EL0/EL1 | HVC | 64bit EL2 */ + msr scr_el3, x0 + msr cptr_el3, xzr /* Disable coprocessor traps to EL3 */ + mov x0, #0x33ff + msr cptr_el2, x0 /* Disable coprocessor traps to EL2 */ + + /* Return to the EL2_SP2 mode from EL3 */ + mov x0, sp + msr sp_el2, x0 /* Migrate SP */ + mrs x0, vbar_el3 + msr vbar_el2, x0 /* Migrate VBAR */ + mov x0, #0x3c9 + msr spsr_el3, x0 /* EL2_SP2 | D | A | I | F */ + msr elr_el3, x30 + eret +ENDPROC(switch_el3_to_el2) diff --git a/src/arch/aarch64/exception_asm.S b/src/arch/aarch64/exception_asm.S index f375d4cba8..b1f1a94174 100644 --- a/src/arch/aarch64/exception_asm.S +++ b/src/arch/aarch64/exception_asm.S @@ -80,11 +80,11 @@ ENTRY(exception_prologue) stp x3, x4, [sp, #-16]! stp x1, x2, [sp, #-16]! - /* FIXME: Don't assume always running in EL3 */ - mrs x1, elr_el3 + /* FIXME: Don't assume always running in EL2 */ + mrs x1, elr_el2 stp x1, x0, [sp, #-16]! - mrs x1, esr_el3 + mrs x1, esr_el2 mov x0, sp ret @@ -99,5 +99,5 @@ exception_handler: .global set_vbar set_vbar: - msr vbar_el3, x0 + msr vbar_el2, x0 ret