summaryrefslogtreecommitdiff
path: root/plat/arm
diff options
context:
space:
mode:
authorYatharth Kochar <yatharth.kochar@arm.com>2016-11-14 12:01:04 +0000
committerdp-arm <dimitris.papastamos@arm.com>2017-04-20 15:05:21 +0100
commit07570d592ea5b8a0ea22f23d2d502782b9d6c1c5 (patch)
tree7744838900739daf5cb61d5623c298abd7c403b3 /plat/arm
parentdc787588a557d09fbf46c8562d7060cd39e275d9 (diff)
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>
Diffstat (limited to 'plat/arm')
-rw-r--r--plat/arm/board/juno/aarch64/juno_helpers.S94
-rw-r--r--plat/arm/board/juno/juno_bl1_setup.c18
-rw-r--r--plat/arm/board/juno/juno_bl2_setup.c56
-rw-r--r--plat/arm/board/juno/platform.mk10
-rw-r--r--plat/arm/common/arm_bl1_setup.c1
-rw-r--r--plat/arm/common/arm_bl2_setup.c15
-rw-r--r--plat/arm/common/arm_common.mk10
7 files changed, 195 insertions, 9 deletions
diff --git a/plat/arm/board/juno/aarch64/juno_helpers.S b/plat/arm/board/juno/aarch64/juno_helpers.S
index ac54ac9b..49fef16f 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 @@ func plat_reset_handler
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 @@ endfunc plat_reset_handler
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 e805c9a3..93ca1c31 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 @@ __dead2 void bl1_plat_fwu_done(void *client_cookie, void *reserved)
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 00000000..ffb6387e
--- /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 39977240..08554381 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -48,8 +48,14 @@ endif
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 @@ BL1_SOURCES += lib/cpus/aarch64/cortex_a53.S \
${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 @@ BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
${JUNO_GIC_SOURCES} \
${JUNO_INTERCONNECT_SOURCES} \
${JUNO_SECURITY_SOURCES}
+endif
# Enable workarounds for selected Cortex-A53 and A57 errata.
ERRATA_A53_855873 := 1
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
index 8c1fde43..ffbf113b 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -44,6 +44,7 @@
#pragma weak bl1_plat_arch_setup
#pragma weak bl1_platform_setup
#pragma weak bl1_plat_sec_mem_layout
+#pragma weak bl1_plat_prepare_exit
/* Data structure which holds the extents of the trusted SRAM for BL1*/
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index 007108d1..66e350aa 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -249,11 +249,7 @@ void bl2_plat_arch_setup(void)
}
#if LOAD_IMAGE_V2
-/*******************************************************************************
- * This function can be used by the platforms to update/use image
- * information for given `image_id`.
- ******************************************************************************/
-int bl2_plat_handle_post_image_load(unsigned int image_id)
+int arm_bl2_handle_post_image_load(unsigned int image_id)
{
int err = 0;
bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
@@ -286,6 +282,15 @@ int bl2_plat_handle_post_image_load(unsigned int image_id)
return err;
}
+/*******************************************************************************
+ * This function can be used by the platforms to update/use image
+ * information for given `image_id`.
+ ******************************************************************************/
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ return arm_bl2_handle_post_image_load(image_id);
+}
+
#else /* LOAD_IMAGE_V2 */
/*******************************************************************************
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 891e2fbd..f7ec57ef 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -137,8 +137,14 @@ BL2_SOURCES += drivers/io/io_fip.c \
plat/arm/common/arm_bl2_setup.c \
plat/arm/common/arm_io_storage.c
ifeq (${LOAD_IMAGE_V2},1)
-BL2_SOURCES += plat/arm/common/${ARCH}/arm_bl2_mem_params_desc.c\
- plat/arm/common/arm_image_load.c \
+# Because BL1/BL2 execute in AArch64 mode but BL32 in AArch32 we need to use
+# the AArch32 descriptors.
+ifeq (${JUNO_AARCH32_EL3_RUNTIME},1)
+BL2_SOURCES += plat/arm/common/aarch32/arm_bl2_mem_params_desc.c
+else
+BL2_SOURCES += plat/arm/common/${ARCH}/arm_bl2_mem_params_desc.c
+endif
+BL2_SOURCES += plat/arm/common/arm_image_load.c \
common/desc_image_load.c
endif