1/*
2 * Copyright (c) 2016-2022, 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/bl1.h>
10#include <common/bl_common.h>
11#include <context.h>
12#include <lib/xlat_tables/xlat_tables.h>
13#include <smccc_helpers.h>
14#include <smccc_macros.S>
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_xc, r1
75
76	/* Some BL32 stages expect lr_svc to provide the BL33 entry address */
77	cps	#MODE32_svc
78	ldr	lr, [r8, #ENTRY_POINT_INFO_LR_SVC_OFFSET]
79	cps	#MODE32_mon
80
81	add	r8, r8, #ENTRY_POINT_INFO_ARGS_OFFSET
82	ldm	r8, {r0, r1, r2, r3}
83	exception_return
84endfunc bl1_aarch32_smc_handler
85
86	/* -----------------------------------------------------
87	 * Save Secure/Normal world context and jump to
88	 * BL1 SMC handler.
89	 * -----------------------------------------------------
90	 */
91func smc_handler
92	/* -----------------------------------------------------
93	 * Save the GP registers.
94	 * -----------------------------------------------------
95	 */
96	smccc_save_gp_mode_regs
97
98	/*
99	 * `sp` still points to `smc_ctx_t`. Save it to a register
100	 * and restore the C runtime stack pointer to `sp`.
101	 */
102	mov	r6, sp
103	ldr	sp, [r6, #SMC_CTX_SP_MON]
104
105	ldr	r0, [r6, #SMC_CTX_SCR]
106	and	r7, r0, #SCR_NS_BIT		/* flags */
107
108	/* Switch to Secure Mode */
109	bic	r0, #SCR_NS_BIT
110	stcopr	r0, SCR
111	isb
112
113	/* If caller is from Secure world then turn on the MMU */
114	tst	r7, #SCR_NS_BIT
115	bne	skip_mmu_on
116
117	/* Turn on the MMU */
118	mov	r0, #DISABLE_DCACHE
119	bl	enable_mmu_svc_mon
120
121	/*
122	 * Invalidate `smc_ctx_t` in data cache to prevent dirty data being
123	 * used.
124	 */
125	mov	r0, r6
126	mov	r1, #SMC_CTX_SIZE
127	bl	inv_dcache_range
128
129	/* Enable the data cache. */
130	ldcopr	r9, SCTLR
131	orr	r9, r9, #SCTLR_C_BIT
132	stcopr	r9, SCTLR
133	isb
134
135skip_mmu_on:
136	/* Prepare arguments for BL1 SMC wrapper. */
137	ldr	r0, [r6, #SMC_CTX_GPREG_R0]	/* smc_fid */
138	mov	r1, #0				/* cookie */
139	mov	r2, r6				/* handle */
140	mov	r3, r7				/* flags */
141	bl	bl1_smc_wrapper
142
143	/* Get the smc_context for next BL image */
144	bl	smc_get_next_ctx
145	mov	r4, r0
146
147	/* Only turn-off MMU if going to secure world */
148	ldr	r5, [r4, #SMC_CTX_SCR]
149	tst	r5, #SCR_NS_BIT
150	bne	skip_mmu_off
151
152	/* Disable the MMU */
153	bl	disable_mmu_icache_secure
154	stcopr	r0, TLBIALL
155	dsb	sy
156	isb
157
158skip_mmu_off:
159	/* -----------------------------------------------------
160	 * Do the transition to next BL image.
161	 * -----------------------------------------------------
162	 */
163	mov	r0, r4
164	monitor_exit
165endfunc smc_handler
166