diff --git a/Makefile b/Makefile index a263c4eb3..78860b374 100644 --- a/Makefile +++ b/Makefile @@ -261,6 +261,25 @@ endif # This can be overridden by the platform. include lib/cpus/cpu-ops.mk +ifeq (${ARCH},aarch32) +NEED_BL32 := yes + +################################################################################ +# Build `AARCH32_SP` as BL32 image for AArch32 +################################################################################ +ifneq (${AARCH32_SP},none) +# We expect to locate an sp.mk under the specified AARCH32_SP directory +AARCH32_SP_MAKE := $(wildcard bl32/${AARCH32_SP}/${AARCH32_SP}.mk) + +ifeq (${AARCH32_SP_MAKE},) + $(error Error: No bl32/${AARCH32_SP}/${AARCH32_SP}.mk located) +endif + +$(info Including ${AARCH32_SP_MAKE}) +include ${AARCH32_SP_MAKE} +endif + +endif ################################################################################ # Check incompatible options @@ -285,15 +304,11 @@ ifeq (${NEED_BL33},yes) endif endif +# For AArch32, LOAD_IMAGE_V2 must be enabled. ifeq (${ARCH},aarch32) - # For AArch32, LOAD_IMAGE_V2 must be enabled. ifeq (${LOAD_IMAGE_V2}, 0) $(error "For AArch32, LOAD_IMAGE_V2 must be enabled.") endif - # TRUSTED_BOARD_BOOT is currently not supported for AArch32. - ifeq (${TRUSTED_BOARD_BOOT},1) - $(error "TRUSTED_BOARD_BOOT is currently not supported for AArch32") - endif endif # When building for systems with hardware-assisted coherency, there's no need to @@ -398,26 +413,6 @@ endif endif endif -ifeq (${ARCH},aarch32) -NEED_BL32 := yes - -################################################################################ -# Build `AARCH32_SP` as BL32 image for AArch32 -################################################################################ -ifneq (${AARCH32_SP},none) -# We expect to locate an sp.mk under the specified AARCH32_SP directory -AARCH32_SP_MAKE := $(wildcard bl32/${AARCH32_SP}/${AARCH32_SP}.mk) - -ifeq (${AARCH32_SP_MAKE},) - $(error Error: No bl32/${AARCH32_SP}/${AARCH32_SP}.mk located) -endif - -$(info Including ${AARCH32_SP_MAKE}) -include ${AARCH32_SP_MAKE} -endif - -endif - ################################################################################ # Build options checks ################################################################################ diff --git a/bl1/aarch32/bl1_entrypoint.S b/bl1/aarch32/bl1_entrypoint.S index e3d915fb4..39ebcf73d 100644 --- a/bl1/aarch32/bl1_entrypoint.S +++ b/bl1/aarch32/bl1_entrypoint.S @@ -71,9 +71,21 @@ func bl1_entrypoint */ /* - * MMU needs to be disabled because both BL1 and BL2 execute + * Get the smc_context for next BL image, + * program the gp/system registers and save it in `r4`. + */ + bl smc_get_next_ctx + mov r4, r0 + + /* Only turn-off MMU if going to secure world */ + ldr r5, [r4, #SMC_CTX_SCR] + tst r5, #SCR_NS_BIT + bne skip_mmu_off + + /* + * MMU needs to be disabled because both BL1 and BL2/BL2U execute * in PL1, and therefore share the same address space. - * BL2 will initialize the address space according to its + * BL2/BL2U will initialize the address space according to its * own requirement. */ bl disable_mmu_icache_secure @@ -81,11 +93,8 @@ func bl1_entrypoint dsb sy isb - /* - * Get the smc_context for next BL image, - * program the gp/system registers and exit - * secure monitor mode - */ - bl smc_get_next_ctx +skip_mmu_off: + /* Restore smc_context from `r4` and exit secure monitor mode. */ + mov r0, r4 monitor_exit endfunc bl1_entrypoint diff --git a/bl1/aarch32/bl1_exceptions.S b/bl1/aarch32/bl1_exceptions.S index de7ddc557..f73db4022 100644 --- a/bl1/aarch32/bl1_exceptions.S +++ b/bl1/aarch32/bl1_exceptions.S @@ -8,11 +8,18 @@ #include #include #include +#include +#include +#include +#include .globl bl1_aarch32_smc_handler func bl1_aarch32_smc_handler + /* On SMC entry, `sp` points to `smc_ctx_t`. Save `lr`. */ + str lr, [sp, #SMC_CTX_LR_MON] + /* ------------------------------------------------ * SMC in BL1 is handled assuming that the MMU is * turned off by BL2. @@ -20,12 +27,12 @@ func bl1_aarch32_smc_handler */ /* ---------------------------------------------- - * Only RUN_IMAGE SMC is supported. + * Detect if this is a RUN_IMAGE or other SMC. * ---------------------------------------------- */ - mov r8, #BL1_SMC_RUN_IMAGE - cmp r8, r0 - blne report_exception + mov lr, #BL1_SMC_RUN_IMAGE + cmp lr, r0 + bne smc_handler /* ------------------------------------------------ * Make sure only Secure world reaches here. @@ -70,3 +77,76 @@ debug_loop: ldm r8, {r0, r1, r2, r3} eret endfunc bl1_aarch32_smc_handler + + /* ----------------------------------------------------- + * Save Secure/Normal world context and jump to + * BL1 SMC handler. + * ----------------------------------------------------- + */ +func smc_handler + /* ----------------------------------------------------- + * Save the GP registers. + * ----------------------------------------------------- + */ + smcc_save_gp_mode_regs + + /* + * `sp` still points to `smc_ctx_t`. Save it to a register + * and restore the C runtime stack pointer to `sp`. + */ + mov r6, sp + ldr sp, [r6, #SMC_CTX_SP_MON] + + ldr r0, [r6, #SMC_CTX_SCR] + and r7, r0, #SCR_NS_BIT /* flags */ + + /* Switch to Secure Mode */ + bic r0, #SCR_NS_BIT + stcopr r0, SCR + isb + + /* If caller is from Secure world then turn on the MMU */ + tst r7, #SCR_NS_BIT + bne skip_mmu_on + + /* Turn on the MMU */ + mov r0, #DISABLE_DCACHE + bl enable_mmu_secure + + /* Enable the data cache. */ + ldcopr r9, SCTLR + orr r9, r9, #SCTLR_C_BIT + stcopr r9, SCTLR + isb + +skip_mmu_on: + /* Prepare arguments for BL1 SMC wrapper. */ + ldr r0, [r6, #SMC_CTX_GPREG_R0] /* smc_fid */ + mov r1, #0 /* cookie */ + mov r2, r6 /* handle */ + mov r3, r7 /* flags */ + bl bl1_smc_wrapper + + /* Get the smc_context for next BL image */ + bl smc_get_next_ctx + mov r4, r0 + + /* Only turn-off MMU if going to secure world */ + ldr r5, [r4, #SMC_CTX_SCR] + tst r5, #SCR_NS_BIT + bne skip_mmu_off + + /* Disable the MMU */ + bl disable_mmu_icache_secure + stcopr r0, TLBIALL + dsb sy + isb + +skip_mmu_off: + /* ----------------------------------------------------- + * Do the transition to next BL image. + * ----------------------------------------------------- + */ + mov r0, r4 + monitor_exit +endfunc smc_handler diff --git a/bl1/bl1_fwu.c b/bl1/bl1_fwu.c index b0985320e..ace364d42 100644 --- a/bl1/bl1_fwu.c +++ b/bl1/bl1_fwu.c @@ -47,6 +47,8 @@ __dead2 static void bl1_fwu_done(void *client_cookie, void *reserved); */ static unsigned int sec_exec_image_id = INVALID_IMAGE_ID; +void cm_set_next_context(void *cpu_context); + /******************************************************************************* * Top level handler for servicing FWU SMCs. ******************************************************************************/ @@ -364,8 +366,10 @@ static int bl1_fwu_image_execute(unsigned int image_id, INFO("BL1-FWU: Executing Secure image\n"); +#ifdef AARCH64 /* Save NS-EL1 system registers. */ cm_el1_sysregs_context_save(NON_SECURE); +#endif /* Prepare the image for execution. */ bl1_prepare_next_image(image_id); @@ -373,7 +377,11 @@ static int bl1_fwu_image_execute(unsigned int image_id, /* Update the secure image id. */ sec_exec_image_id = image_id; +#ifdef AARCH64 *handle = cm_get_context(SECURE); +#else + *handle = smc_get_ctx(SECURE); +#endif return 0; } @@ -419,6 +427,10 @@ static register_t bl1_fwu_image_resume(register_t image_param, resume_sec_state = SECURE; } + INFO("BL1-FWU: Resuming %s world context\n", + (resume_sec_state == SECURE) ? "secure" : "normal"); + +#ifdef AARCH64 /* Save the EL1 system registers of calling world. */ cm_el1_sysregs_context_save(caller_sec_state); @@ -428,10 +440,16 @@ static register_t bl1_fwu_image_resume(register_t image_param, /* Update the next context. */ cm_set_next_eret_context(resume_sec_state); - INFO("BL1-FWU: Resuming %s world context\n", - (resume_sec_state == SECURE) ? "secure" : "normal"); - *handle = cm_get_context(resume_sec_state); +#else + /* Update the next context. */ + cm_set_next_context(cm_get_context(resume_sec_state)); + + /* Prepare the smc context for the next BL image. */ + smc_set_next_ctx(resume_sec_state); + + *handle = smc_get_ctx(resume_sec_state); +#endif return image_param; } @@ -461,6 +479,8 @@ static int bl1_fwu_sec_image_done(void **handle, unsigned int flags) image_desc->state = IMAGE_STATE_RESET; sec_exec_image_id = INVALID_IMAGE_ID; + INFO("BL1-FWU: Resuming Normal world context\n"); +#ifdef AARCH64 /* * Secure world is done so no need to save the context. * Just restore the Non-Secure context. @@ -470,9 +490,16 @@ static int bl1_fwu_sec_image_done(void **handle, unsigned int flags) /* Update the next context. */ cm_set_next_eret_context(NON_SECURE); - INFO("BL1-FWU: Resuming Normal world context\n"); - *handle = cm_get_context(NON_SECURE); +#else + /* Update the next context. */ + cm_set_next_context(cm_get_context(NON_SECURE)); + + /* Prepare the smc context for the next BL image. */ + smc_set_next_ctx(NON_SECURE); + + *handle = smc_get_ctx(NON_SECURE); +#endif return 0; } diff --git a/bl1/bl1_main.c b/bl1/bl1_main.c index 71ece00dd..fa4f3a4c0 100644 --- a/bl1/bl1_main.c +++ b/bl1/bl1_main.c @@ -279,3 +279,20 @@ register_t bl1_smc_handler(unsigned int smc_fid, WARN("Unimplemented BL1 SMC Call: 0x%x \n", smc_fid); SMC_RET1(handle, SMC_UNK); } + +/******************************************************************************* + * BL1 SMC wrapper. This function is only used in AArch32 mode to ensure ABI + * compliance when invoking bl1_smc_handler. + ******************************************************************************/ +register_t bl1_smc_wrapper(uint32_t smc_fid, + void *cookie, + void *handle, + unsigned int flags) +{ + register_t x1, x2, x3, x4; + + assert(handle); + + get_smc_params_from_ctx(handle, x1, x2, x3, x4); + return bl1_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags); +} diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h index 7a42c98a1..23e78678e 100644 --- a/include/plat/arm/common/arm_def.h +++ b/include/plat/arm/common/arm_def.h @@ -224,9 +224,10 @@ /******************************************************************************* * BL2 specific defines. ******************************************************************************/ -#if ARM_BL31_IN_DRAM +#if ARM_BL31_IN_DRAM || defined(AARCH32) /* - * BL31 is loaded in the DRAM. + * For AArch32 BL31 is not applicable. + * For AArch64 BL31 is loaded in the DRAM. * Put BL2 just below BL1. */ #define BL2_BASE (BL1_RW_BASE - PLAT_ARM_MAX_BL2_SIZE) diff --git a/make_helpers/tbbr/tbbr_tools.mk b/make_helpers/tbbr/tbbr_tools.mk index 4912c90dd..610ccb883 100644 --- a/make_helpers/tbbr/tbbr_tools.mk +++ b/make_helpers/tbbr/tbbr_tools.mk @@ -75,6 +75,7 @@ ifneq (${SCP_BL2},) $(eval $(call FIP_ADD_PAYLOAD,${BUILD_PLAT}/scp_fw_key.crt,--scp-fw-key-cert)) endif +ifeq (${ARCH},aarch64) # Add the BL31 CoT (key cert + img cert + image) $(if ${BL31},$(eval $(call CERT_ADD_CMD_OPT,${BL31},--soc-fw,true)),\ $(eval $(call CERT_ADD_CMD_OPT,$(call IMG_BIN,31),--soc-fw,true))) @@ -83,6 +84,7 @@ $(eval $(call CERT_ADD_CMD_OPT,${BUILD_PLAT}/soc_fw_content.crt,--soc-fw-cert)) $(eval $(call CERT_ADD_CMD_OPT,${BUILD_PLAT}/soc_fw_key.crt,--soc-fw-key-cert)) $(eval $(call FIP_ADD_PAYLOAD,${BUILD_PLAT}/soc_fw_content.crt,--soc-fw-cert)) $(eval $(call FIP_ADD_PAYLOAD,${BUILD_PLAT}/soc_fw_key.crt,--soc-fw-key-cert)) +endif # Add the BL32 CoT (key cert + img cert + image) ifeq (${NEED_BL32},yes) diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index afcb4b53d..6a759c5a7 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -137,5 +137,9 @@ ifneq (${ENABLE_STACK_PROTECTOR},0) PLAT_BL_COMMON_SOURCES += plat/arm/board/fvp/fvp_stack_protector.c endif +ifeq (${ARCH},aarch32) + NEED_BL32 := yes +endif + include plat/arm/board/common/board_common.mk include plat/arm/common/arm_common.mk