diff options
Diffstat (limited to 'bl1/aarch32/bl1_exceptions.S')
-rw-r--r-- | bl1/aarch32/bl1_exceptions.S | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/bl1/aarch32/bl1_exceptions.S b/bl1/aarch32/bl1_exceptions.S new file mode 100644 index 0000000..4a6815f --- /dev/null +++ b/bl1/aarch32/bl1_exceptions.S @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <bl1/bl1.h> +#include <common/bl_common.h> +#include <context.h> +#include <lib/xlat_tables/xlat_tables.h> +#include <smccc_helpers.h> +#include <smccc_macros.S> + + .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. + * ------------------------------------------------ + */ + + /* ---------------------------------------------- + * Detect if this is a RUN_IMAGE or other SMC. + * ---------------------------------------------- + */ + mov lr, #BL1_SMC_RUN_IMAGE + cmp lr, r0 + bne smc_handler + + /* ------------------------------------------------ + * Make sure only Secure world reaches here. + * ------------------------------------------------ + */ + ldcopr r8, SCR + tst r8, #SCR_NS_BIT + blne report_exception + + /* --------------------------------------------------------------------- + * Pass control to next secure image. + * Here it expects r1 to contain the address of a entry_point_info_t + * structure describing the BL entrypoint. + * --------------------------------------------------------------------- + */ + mov r8, r1 + mov r0, r1 + bl bl1_print_next_bl_ep_info + +#if SPIN_ON_BL1_EXIT + bl print_debug_loop_message +debug_loop: + b debug_loop +#endif + + mov r0, r8 + bl bl1_plat_prepare_exit + + stcopr r0, TLBIALL + dsb sy + isb + + /* + * Extract PC and SPSR based on struct `entry_point_info_t` + * and load it in LR and SPSR registers respectively. + */ + ldr lr, [r8, #ENTRY_POINT_INFO_PC_OFFSET] + ldr r1, [r8, #(ENTRY_POINT_INFO_PC_OFFSET + 4)] + msr spsr_xc, r1 + + /* Some BL32 stages expect lr_svc to provide the BL33 entry address */ + cps #MODE32_svc + ldr lr, [r8, #ENTRY_POINT_INFO_LR_SVC_OFFSET] + cps #MODE32_mon + + add r8, r8, #ENTRY_POINT_INFO_ARGS_OFFSET + ldm r8, {r0, r1, r2, r3} + exception_return +endfunc bl1_aarch32_smc_handler + + /* ----------------------------------------------------- + * Save Secure/Normal world context and jump to + * BL1 SMC handler. + * ----------------------------------------------------- + */ +func smc_handler + /* ----------------------------------------------------- + * Save the GP registers. + * ----------------------------------------------------- + */ + smccc_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_svc_mon + + /* + * Invalidate `smc_ctx_t` in data cache to prevent dirty data being + * used. + */ + mov r0, r6 + mov r1, #SMC_CTX_SIZE + bl inv_dcache_range + + /* 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 |