From 07570d592ea5b8a0ea22f23d2d502782b9d6c1c5 Mon Sep 17 00:00:00 2001 From: Yatharth Kochar Date: Mon, 14 Nov 2016 12:01:04 +0000 Subject: [PATCH] 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 Signed-off-by: dp-arm --- include/lib/aarch64/arch.h | 10 +++ include/plat/arm/common/plat_arm.h | 1 + include/plat/arm/soc/common/soc_css_def.h | 11 ++- plat/arm/board/juno/aarch64/juno_helpers.S | 94 ++++++++++++++++++++++ plat/arm/board/juno/juno_bl1_setup.c | 18 ++++- plat/arm/board/juno/juno_bl2_setup.c | 56 +++++++++++++ plat/arm/board/juno/platform.mk | 10 ++- plat/arm/common/arm_bl1_setup.c | 1 + plat/arm/common/arm_bl2_setup.c | 15 ++-- plat/arm/common/arm_common.mk | 10 ++- 10 files changed, 215 insertions(+), 11 deletions(-) create mode 100644 plat/arm/board/juno/juno_bl2_setup.c diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h index d766490d1..4b323d335 100644 --- a/include/lib/aarch64/arch.h +++ b/include/lib/aarch64/arch.h @@ -261,6 +261,16 @@ #define DISABLE_ALL_EXCEPTIONS \ (DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT | DAIF_DBG_BIT) +/* + * RMR_EL3 definitions + */ +#define RMR_EL3_RR_BIT (1 << 1) +#define RMR_EL3_AA64_BIT (1 << 0) + +/* + * HI-VECTOR address for AArch32 state + */ +#define HI_VECTOR_BASE (0xFFFF0000) /* * TCR defintions diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h index b24af78d9..d68a3e3bd 100644 --- a/include/plat/arm/common/plat_arm.h +++ b/include/plat/arm/common/plat_arm.h @@ -157,6 +157,7 @@ void arm_bl2_platform_setup(void); void arm_bl2_plat_arch_setup(void); uint32_t arm_get_spsr_for_bl32_entry(void); uint32_t arm_get_spsr_for_bl33_entry(void); +int arm_bl2_handle_post_image_load(unsigned int image_id); /* BL2U utility functions */ void arm_bl2u_early_platform_setup(struct meminfo *mem_layout, diff --git a/include/plat/arm/soc/common/soc_css_def.h b/include/plat/arm/soc/common/soc_css_def.h index 3b4cc79f8..efd78f044 100644 --- a/include/plat/arm/soc/common/soc_css_def.h +++ b/include/plat/arm/soc/common/soc_css_def.h @@ -96,9 +96,16 @@ /* * Required platform porting definitions common to all ARM CSS SoCs */ - +#if JUNO_AARCH32_EL3_RUNTIME +/* + * Following change is required to initialize TZC + * for enabling access to the HI_VECTOR (0xFFFF0000) + * location needed for JUNO AARCH32 support. + */ +#define PLAT_ARM_SCP_TZC_DRAM1_SIZE ULL(0x8000) +#else /* 2MB used for SCP DDR retraining */ #define PLAT_ARM_SCP_TZC_DRAM1_SIZE ULL(0x00200000) - +#endif #endif /* __SOC_CSS_DEF_H__ */ diff --git a/plat/arm/board/juno/aarch64/juno_helpers.S b/plat/arm/board/juno/aarch64/juno_helpers.S index ac54ac9b3..49fef16ff 100644 --- a/plat/arm/board/juno/aarch64/juno_helpers.S +++ b/plat/arm/board/juno/aarch64/juno_helpers.S @@ -34,12 +34,18 @@ #include #include #include +#include +#include #include #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 @@ -205,6 +211,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 e805c9a38..93ca1c319 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 #include #include +#include #include #include #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 000000000..ffb6387e0 --- /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 +#include +#include +#include + +#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 39977240b..085543813 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 8c1fde43f..ffbf113b1 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 007108d12..66e350aad 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 891e2fbd4..f7ec57ef7 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