1/* 2 * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7#include <arch.h> 8#include <asm_macros.S> 9#include <bl1.h> 10#include <bl_common.h> 11#include <context.h> 12#include <smcc_helpers.h> 13#include <smcc_macros.S> 14#include <xlat_tables.h> 15 16 .globl bl1_aarch32_smc_handler 17 18 19func bl1_aarch32_smc_handler 20 /* On SMC entry, `sp` points to `smc_ctx_t`. Save `lr`. */ 21 str lr, [sp, #SMC_CTX_LR_MON] 22 23 /* ------------------------------------------------ 24 * SMC in BL1 is handled assuming that the MMU is 25 * turned off by BL2. 26 * ------------------------------------------------ 27 */ 28 29 /* ---------------------------------------------- 30 * Detect if this is a RUN_IMAGE or other SMC. 31 * ---------------------------------------------- 32 */ 33 mov lr, #BL1_SMC_RUN_IMAGE 34 cmp lr, r0 35 bne smc_handler 36 37 /* ------------------------------------------------ 38 * Make sure only Secure world reaches here. 39 * ------------------------------------------------ 40 */ 41 ldcopr r8, SCR 42 tst r8, #SCR_NS_BIT 43 blne report_exception 44 45 /* --------------------------------------------------------------------- 46 * Pass control to next secure image. 47 * Here it expects r1 to contain the address of a entry_point_info_t 48 * structure describing the BL entrypoint. 49 * --------------------------------------------------------------------- 50 */ 51 mov r8, r1 52 mov r0, r1 53 bl bl1_print_next_bl_ep_info 54 55#if SPIN_ON_BL1_EXIT 56 bl print_debug_loop_message 57debug_loop: 58 b debug_loop 59#endif 60 61 mov r0, r8 62 bl bl1_plat_prepare_exit 63 64 stcopr r0, TLBIALL 65 dsb sy 66 isb 67 68 /* 69 * Extract PC and SPSR based on struct `entry_point_info_t` 70 * and load it in LR and SPSR registers respectively. 71 */ 72 ldr lr, [r8, #ENTRY_POINT_INFO_PC_OFFSET] 73 ldr r1, [r8, #(ENTRY_POINT_INFO_PC_OFFSET + 4)] 74 msr spsr, r1 75 76 add r8, r8, #ENTRY_POINT_INFO_ARGS_OFFSET 77 ldm r8, {r0, r1, r2, r3} 78 eret 79endfunc bl1_aarch32_smc_handler 80 81 /* ----------------------------------------------------- 82 * Save Secure/Normal world context and jump to 83 * BL1 SMC handler. 84 * ----------------------------------------------------- 85 */ 86func smc_handler 87 /* ----------------------------------------------------- 88 * Save the GP registers. 89 * ----------------------------------------------------- 90 */ 91 smcc_save_gp_mode_regs 92 93 /* 94 * `sp` still points to `smc_ctx_t`. Save it to a register 95 * and restore the C runtime stack pointer to `sp`. 96 */ 97 mov r6, sp 98 ldr sp, [r6, #SMC_CTX_SP_MON] 99 100 ldr r0, [r6, #SMC_CTX_SCR] 101 and r7, r0, #SCR_NS_BIT /* flags */ 102 103 /* Switch to Secure Mode */ 104 bic r0, #SCR_NS_BIT 105 stcopr r0, SCR 106 isb 107 108 /* If caller is from Secure world then turn on the MMU */ 109 tst r7, #SCR_NS_BIT 110 bne skip_mmu_on 111 112 /* Turn on the MMU */ 113 mov r0, #DISABLE_DCACHE 114 bl enable_mmu_secure 115 116 /* Enable the data cache. */ 117 ldcopr r9, SCTLR 118 orr r9, r9, #SCTLR_C_BIT 119 stcopr r9, SCTLR 120 isb 121 122skip_mmu_on: 123 /* Prepare arguments for BL1 SMC wrapper. */ 124 ldr r0, [r6, #SMC_CTX_GPREG_R0] /* smc_fid */ 125 mov r1, #0 /* cookie */ 126 mov r2, r6 /* handle */ 127 mov r3, r7 /* flags */ 128 bl bl1_smc_wrapper 129 130 /* Get the smc_context for next BL image */ 131 bl smc_get_next_ctx 132 mov r4, r0 133 134 /* Only turn-off MMU if going to secure world */ 135 ldr r5, [r4, #SMC_CTX_SCR] 136 tst r5, #SCR_NS_BIT 137 bne skip_mmu_off 138 139 /* Disable the MMU */ 140 bl disable_mmu_icache_secure 141 stcopr r0, TLBIALL 142 dsb sy 143 isb 144 145skip_mmu_off: 146 /* ----------------------------------------------------- 147 * Do the transition to next BL image. 148 * ----------------------------------------------------- 149 */ 150 mov r0, r4 151 monitor_exit 152endfunc smc_handler 153