1/*
2 * Copyright (c) 2016-2018, 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	/* Enable the data cache. */
122	ldcopr	r9, SCTLR
123	orr	r9, r9, #SCTLR_C_BIT
124	stcopr	r9, SCTLR
125	isb
126
127skip_mmu_on:
128	/* Prepare arguments for BL1 SMC wrapper. */
129	ldr	r0, [r6, #SMC_CTX_GPREG_R0]	/* smc_fid */
130	mov	r1, #0				/* cookie */
131	mov	r2, r6				/* handle */
132	mov	r3, r7				/* flags */
133	bl	bl1_smc_wrapper
134
135	/* Get the smc_context for next BL image */
136	bl	smc_get_next_ctx
137	mov	r4, r0
138
139	/* Only turn-off MMU if going to secure world */
140	ldr	r5, [r4, #SMC_CTX_SCR]
141	tst	r5, #SCR_NS_BIT
142	bne	skip_mmu_off
143
144	/* Disable the MMU */
145	bl	disable_mmu_icache_secure
146	stcopr	r0, TLBIALL
147	dsb	sy
148	isb
149
150skip_mmu_off:
151	/* -----------------------------------------------------
152	 * Do the transition to next BL image.
153	 * -----------------------------------------------------
154	 */
155	mov	r0, r4
156	monitor_exit
157endfunc smc_handler
158