/* * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include #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. * ------------------------------------------------ */ /* ---------------------------------------------- * 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