123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- /*
- * 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
|