Changes to support execution in AArch32 state for JUNO
Following steps are required to boot JUNO in AArch32 state:
1> BL1, in AArch64 state, loads BL2.
2> BL2, in AArch64 state, initializes DDR.
Loads SP_MIN & BL33 (AArch32 executable)images.
Calls RUN_IMAGE SMC to go back to BL1.
3> BL1 writes AArch32 executable opcodes, to load and branch
at the entrypoint address of SP_MIN, at HI-VECTOR address and
then request for warm reset in AArch32 state using RMR_EL3.
This patch makes following changes to facilitate above steps:
* Added assembly function to carry out step 3 above.
* Added region in TZC that enables Secure access to the
HI-VECTOR(0xFFFF0000) address space.
* AArch32 image descriptor is used, in BL2, to load
SP_MIN and BL33 AArch32 executable images.
A new flag `JUNO_AARCH32_EL3_RUNTIME` is introduced that
controls above changes. By default this flag is disabled.
NOTE: BL1 and BL2 are not supported in AArch32 state for JUNO.
Change-Id: I091d56a0e6d36663e6d9d2bb53c92c672195d1ec
Signed-off-by: Yatharth Kochar <yatharth.kochar@arm.com>
Signed-off-by: dp-arm <dimitris.papastamos@arm.com>
diff --git a/plat/arm/board/juno/aarch64/juno_helpers.S b/plat/arm/board/juno/aarch64/juno_helpers.S
index ac54ac9..49fef16 100644
--- a/plat/arm/board/juno/aarch64/juno_helpers.S
+++ b/plat/arm/board/juno/aarch64/juno_helpers.S
@@ -34,12 +34,18 @@
#include <cortex_a53.h>
#include <cortex_a57.h>
#include <cortex_a72.h>
+#include <cpu_macros.S>
+#include <css_def.h>
#include <v2m_def.h>
#include "../juno_def.h"
.globl plat_reset_handler
.globl plat_arm_calc_core_pos
+#if JUNO_AARCH32_EL3_RUNTIME
+ .globl plat_get_my_entrypoint
+ .globl juno_reset_to_aarch32_state
+#endif
#define JUNO_REVISION(rev) REV_JUNO_R##rev
#define JUNO_HANDLER(rev) plat_reset_handler_juno_r##rev
@@ -206,6 +212,20 @@
endfunc plat_reset_handler
/* -----------------------------------------------------
+ * void juno_do_reset_to_aarch32_state(void);
+ *
+ * Request warm reset to AArch32 mode.
+ * -----------------------------------------------------
+ */
+func juno_do_reset_to_aarch32_state
+ mov x0, #RMR_EL3_RR_BIT
+ dsb sy
+ msr rmr_el3, x0
+ isb
+ wfi
+endfunc juno_do_reset_to_aarch32_state
+
+ /* -----------------------------------------------------
* unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
* Helper function to calculate the core position.
* -----------------------------------------------------
@@ -213,3 +233,77 @@
func plat_arm_calc_core_pos
b css_calc_core_pos_swap_cluster
endfunc plat_arm_calc_core_pos
+
+#if JUNO_AARCH32_EL3_RUNTIME
+ /* ---------------------------------------------------------------------
+ * uintptr_t plat_get_my_entrypoint (void);
+ *
+ * Main job of this routine is to distinguish between a cold and a warm
+ * boot. On JUNO platform, this distinction is based on the contents of
+ * the Trusted Mailbox. It is initialised to zero by the SCP before the
+ * AP cores are released from reset. Therefore, a zero mailbox means
+ * it's a cold reset. If it is a warm boot then a request to reset to
+ * AArch32 state is issued. This is the only way to reset to AArch32
+ * in EL3 on Juno. A trampoline located at the high vector address
+ * has already been prepared by BL1.
+ *
+ * This functions returns the contents of the mailbox, i.e.:
+ * - 0 for a cold boot;
+ * - request warm reset in AArch32 state for warm boot case;
+ * ---------------------------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE
+ ldr x0, [x0]
+ cbz x0, return
+ b juno_do_reset_to_aarch32_state
+1:
+ b 1b
+return:
+ ret
+endfunc plat_get_my_entrypoint
+
+/*
+ * Emit a "movw r0, #imm16" which moves the lower
+ * 16 bits of `_val` into r0.
+ */
+.macro emit_movw _reg_d, _val
+ mov_imm \_reg_d, (0xe3000000 | \
+ ((\_val & 0xfff) | \
+ ((\_val & 0xf000) << 4)))
+.endm
+
+/*
+ * Emit a "movt r0, #imm16" which moves the upper
+ * 16 bits of `_val` into r0.
+ */
+.macro emit_movt _reg_d, _val
+ mov_imm \_reg_d, (0xe3400000 | \
+ (((\_val & 0x0fff0000) >> 16) | \
+ ((\_val & 0xf0000000) >> 12)))
+.endm
+
+/*
+ * This function writes the trampoline code at HI-VEC (0xFFFF0000)
+ * address which loads r0 with the entrypoint address for
+ * BL32 (a.k.a SP_MIN) when EL3 is in AArch32 mode. A warm reset
+ * to AArch32 mode is then requested by writing into RMR_EL3.
+ */
+func juno_reset_to_aarch32_state
+ emit_movw w0, BL32_BASE
+ emit_movt w1, BL32_BASE
+ /* opcode "bx r0" to branch using r0 in AArch32 mode */
+ mov_imm w2, 0xe12fff10
+
+ /* Write the above opcodes at HI-VECTOR location */
+ mov_imm x3, HI_VECTOR_BASE
+ str w0, [x3], #4
+ str w1, [x3], #4
+ str w2, [x3]
+
+ bl juno_do_reset_to_aarch32_state
+1:
+ b 1b
+endfunc juno_reset_to_aarch32_state
+
+#endif /* JUNO_AARCH32_EL3_RUNTIME */
diff --git a/plat/arm/board/juno/juno_bl1_setup.c b/plat/arm/board/juno/juno_bl1_setup.c
index e805c9a..93ca1c3 100644
--- a/plat/arm/board/juno/juno_bl1_setup.c
+++ b/plat/arm/board/juno/juno_bl1_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -32,11 +32,15 @@
#include <errno.h>
#include <platform.h>
#include <plat_arm.h>
+#include <sp805.h>
#include <tbbr_img_def.h>
#include <v2m_def.h>
#define RESET_REASON_WDOG_RESET (0x2)
+void juno_reset_to_aarch32_state(void);
+
+
/*******************************************************************************
* The following function checks if Firmware update is needed,
* by checking if TOC in FIP image is valid or watchdog reset happened.
@@ -85,3 +89,15 @@
while (1)
wfi();
}
+
+#if JUNO_AARCH32_EL3_RUNTIME
+void bl1_plat_prepare_exit(entry_point_info_t *ep_info)
+{
+#if !ARM_DISABLE_TRUSTED_WDOG
+ /* Disable watchdog before leaving BL1 */
+ sp805_stop(ARM_SP805_TWDG_BASE);
+#endif
+
+ juno_reset_to_aarch32_state();
+}
+#endif /* JUNO_AARCH32_EL3_RUNTIME */
diff --git a/plat/arm/board/juno/juno_bl2_setup.c b/plat/arm/board/juno/juno_bl2_setup.c
new file mode 100644
index 0000000..ffb6387
--- /dev/null
+++ b/plat/arm/board/juno/juno_bl2_setup.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <bl_common.h>
+#include <desc_image_load.h>
+#include <plat_arm.h>
+
+#if JUNO_AARCH32_EL3_RUNTIME
+/*******************************************************************************
+ * This function changes the spsr for BL32 image to bypass
+ * the check in BL1 AArch64 exception handler. This is needed in the aarch32
+ * boot flow as the core comes up in aarch64 and to enter the BL32 image a warm
+ * reset in aarch32 state is required.
+ ******************************************************************************/
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ int err = arm_bl2_handle_post_image_load(image_id);
+
+ if (!err && (image_id == BL32_IMAGE_ID)) {
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+ assert(bl_mem_params);
+ bl_mem_params->ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS);
+ }
+
+ return err;
+}
+#endif /* JUNO_AARCH32_EL3_RUNTIME */
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index 3997724..0855438 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -48,8 +48,14 @@
PLAT_INCLUDES := -Iplat/arm/board/juno/include
-PLAT_BL_COMMON_SOURCES := plat/arm/board/juno/aarch64/juno_helpers.S
+PLAT_BL_COMMON_SOURCES := plat/arm/board/juno/${ARCH}/juno_helpers.S
+# Flag to enable support for AArch32 state on JUNO
+JUNO_AARCH32_EL3_RUNTIME := 0
+$(eval $(call assert_boolean,JUNO_AARCH32_EL3_RUNTIME))
+$(eval $(call add_define,JUNO_AARCH32_EL3_RUNTIME))
+
+ifeq (${ARCH},aarch64)
BL1_SOURCES += lib/cpus/aarch64/cortex_a53.S \
lib/cpus/aarch64/cortex_a57.S \
lib/cpus/aarch64/cortex_a72.S \
@@ -59,6 +65,7 @@
${JUNO_SECURITY_SOURCES}
BL2_SOURCES += plat/arm/board/juno/juno_err.c \
+ plat/arm/board/juno/juno_bl2_setup.c \
${JUNO_SECURITY_SOURCES}
BL2U_SOURCES += ${JUNO_SECURITY_SOURCES}
@@ -71,6 +78,7 @@
${JUNO_GIC_SOURCES} \
${JUNO_INTERCONNECT_SOURCES} \
${JUNO_SECURITY_SOURCES}
+endif
# Enable workarounds for selected Cortex-A53 and A57 errata.
ERRATA_A53_855873 := 1