xref: /rk3399_ARM-atf/bl32/tsp/aarch64/tsp_entrypoint.S (revision 61f72a34250d063da67f4fc2b0eb8c3fda3376be)
1/*
2 * Copyright (c) 2013-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 <tsp.h>
10#include <xlat_tables_defs.h>
11#include "../tsp_private.h"
12
13
14	.globl	tsp_entrypoint
15	.globl  tsp_vector_table
16
17
18
19	/* ---------------------------------------------
20	 * Populate the params in x0-x7 from the pointer
21	 * to the smc args structure in x0.
22	 * ---------------------------------------------
23	 */
24	.macro restore_args_call_smc
25	ldp	x6, x7, [x0, #TSP_ARG6]
26	ldp	x4, x5, [x0, #TSP_ARG4]
27	ldp	x2, x3, [x0, #TSP_ARG2]
28	ldp	x0, x1, [x0, #TSP_ARG0]
29	smc	#0
30	.endm
31
32	.macro	save_eret_context reg1 reg2
33	mrs	\reg1, elr_el1
34	mrs	\reg2, spsr_el1
35	stp	\reg1, \reg2, [sp, #-0x10]!
36	stp	x30, x18, [sp, #-0x10]!
37	.endm
38
39	.macro restore_eret_context reg1 reg2
40	ldp	x30, x18, [sp], #0x10
41	ldp	\reg1, \reg2, [sp], #0x10
42	msr	elr_el1, \reg1
43	msr	spsr_el1, \reg2
44	.endm
45
46func tsp_entrypoint _align=3
47
48	/* ---------------------------------------------
49	 * Set the exception vector to something sane.
50	 * ---------------------------------------------
51	 */
52	adr	x0, tsp_exceptions
53	msr	vbar_el1, x0
54	isb
55
56	/* ---------------------------------------------
57	 * Enable the SError interrupt now that the
58	 * exception vectors have been setup.
59	 * ---------------------------------------------
60	 */
61	msr	daifclr, #DAIF_ABT_BIT
62
63	/* ---------------------------------------------
64	 * Enable the instruction cache, stack pointer
65	 * and data access alignment checks
66	 * ---------------------------------------------
67	 */
68	mov	x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT)
69	mrs	x0, sctlr_el1
70	orr	x0, x0, x1
71	msr	sctlr_el1, x0
72	isb
73
74	/* ---------------------------------------------
75	 * Invalidate the RW memory used by the BL32
76	 * image. This includes the data and NOBITS
77	 * sections. This is done to safeguard against
78	 * possible corruption of this memory by dirty
79	 * cache lines in a system cache as a result of
80	 * use by an earlier boot loader stage.
81	 * ---------------------------------------------
82	 */
83	adr	x0, __RW_START__
84	adr	x1, __RW_END__
85	sub	x1, x1, x0
86	bl	inv_dcache_range
87
88	/* ---------------------------------------------
89	 * Zero out NOBITS sections. There are 2 of them:
90	 *   - the .bss section;
91	 *   - the coherent memory section.
92	 * ---------------------------------------------
93	 */
94	ldr	x0, =__BSS_START__
95	ldr	x1, =__BSS_SIZE__
96	bl	zeromem
97
98#if USE_COHERENT_MEM
99	ldr	x0, =__COHERENT_RAM_START__
100	ldr	x1, =__COHERENT_RAM_UNALIGNED_SIZE__
101	bl	zeromem
102#endif
103
104	/* --------------------------------------------
105	 * Allocate a stack whose memory will be marked
106	 * as Normal-IS-WBWA when the MMU is enabled.
107	 * There is no risk of reading stale stack
108	 * memory after enabling the MMU as only the
109	 * primary cpu is running at the moment.
110	 * --------------------------------------------
111	 */
112	bl	plat_set_my_stack
113
114	/* ---------------------------------------------
115	 * Initialize the stack protector canary before
116	 * any C code is called.
117	 * ---------------------------------------------
118	 */
119#if STACK_PROTECTOR_ENABLED
120	bl	update_stack_protector_canary
121#endif
122
123	/* ---------------------------------------------
124	 * Perform early platform setup & platform
125	 * specific early arch. setup e.g. mmu setup
126	 * ---------------------------------------------
127	 */
128	bl	tsp_early_platform_setup
129	bl	tsp_plat_arch_setup
130
131	/* ---------------------------------------------
132	 * Jump to main function.
133	 * ---------------------------------------------
134	 */
135	bl	tsp_main
136
137	/* ---------------------------------------------
138	 * Tell TSPD that we are done initialising
139	 * ---------------------------------------------
140	 */
141	mov	x1, x0
142	mov	x0, #TSP_ENTRY_DONE
143	smc	#0
144
145tsp_entrypoint_panic:
146	b	tsp_entrypoint_panic
147endfunc tsp_entrypoint
148
149
150	/* -------------------------------------------
151	 * Table of entrypoint vectors provided to the
152	 * TSPD for the various entrypoints
153	 * -------------------------------------------
154	 */
155func tsp_vector_table
156	b	tsp_yield_smc_entry
157	b	tsp_fast_smc_entry
158	b	tsp_cpu_on_entry
159	b	tsp_cpu_off_entry
160	b	tsp_cpu_resume_entry
161	b	tsp_cpu_suspend_entry
162	b	tsp_sel1_intr_entry
163	b	tsp_system_off_entry
164	b	tsp_system_reset_entry
165	b	tsp_abort_yield_smc_entry
166endfunc tsp_vector_table
167
168	/*---------------------------------------------
169	 * This entrypoint is used by the TSPD when this
170	 * cpu is to be turned off through a CPU_OFF
171	 * psci call to ask the TSP to perform any
172	 * bookeeping necessary. In the current
173	 * implementation, the TSPD expects the TSP to
174	 * re-initialise its state so nothing is done
175	 * here except for acknowledging the request.
176	 * ---------------------------------------------
177	 */
178func tsp_cpu_off_entry
179	bl	tsp_cpu_off_main
180	restore_args_call_smc
181endfunc tsp_cpu_off_entry
182
183	/*---------------------------------------------
184	 * This entrypoint is used by the TSPD when the
185	 * system is about to be switched off (through
186	 * a SYSTEM_OFF psci call) to ask the TSP to
187	 * perform any necessary bookkeeping.
188	 * ---------------------------------------------
189	 */
190func tsp_system_off_entry
191	bl	tsp_system_off_main
192	restore_args_call_smc
193endfunc tsp_system_off_entry
194
195	/*---------------------------------------------
196	 * This entrypoint is used by the TSPD when the
197	 * system is about to be reset (through a
198	 * SYSTEM_RESET psci call) to ask the TSP to
199	 * perform any necessary bookkeeping.
200	 * ---------------------------------------------
201	 */
202func tsp_system_reset_entry
203	bl	tsp_system_reset_main
204	restore_args_call_smc
205endfunc tsp_system_reset_entry
206
207	/*---------------------------------------------
208	 * This entrypoint is used by the TSPD when this
209	 * cpu is turned on using a CPU_ON psci call to
210	 * ask the TSP to initialise itself i.e. setup
211	 * the mmu, stacks etc. Minimal architectural
212	 * state will be initialised by the TSPD when
213	 * this function is entered i.e. Caches and MMU
214	 * will be turned off, the execution state
215	 * will be aarch64 and exceptions masked.
216	 * ---------------------------------------------
217	 */
218func tsp_cpu_on_entry
219	/* ---------------------------------------------
220	 * Set the exception vector to something sane.
221	 * ---------------------------------------------
222	 */
223	adr	x0, tsp_exceptions
224	msr	vbar_el1, x0
225	isb
226
227	/* Enable the SError interrupt */
228	msr	daifclr, #DAIF_ABT_BIT
229
230	/* ---------------------------------------------
231	 * Enable the instruction cache, stack pointer
232	 * and data access alignment checks
233	 * ---------------------------------------------
234	 */
235	mov	x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT)
236	mrs	x0, sctlr_el1
237	orr	x0, x0, x1
238	msr	sctlr_el1, x0
239	isb
240
241	/* --------------------------------------------
242	 * Give ourselves a stack whose memory will be
243	 * marked as Normal-IS-WBWA when the MMU is
244	 * enabled.
245	 * --------------------------------------------
246	 */
247	bl	plat_set_my_stack
248
249	/* --------------------------------------------
250	 * Enable MMU and D-caches together.
251	 * --------------------------------------------
252	 */
253	mov	x0, #0
254	bl	bl32_plat_enable_mmu
255
256	/* ---------------------------------------------
257	 * Enter C runtime to perform any remaining
258	 * book keeping
259	 * ---------------------------------------------
260	 */
261	bl	tsp_cpu_on_main
262	restore_args_call_smc
263
264	/* Should never reach here */
265tsp_cpu_on_entry_panic:
266	b	tsp_cpu_on_entry_panic
267endfunc tsp_cpu_on_entry
268
269	/*---------------------------------------------
270	 * This entrypoint is used by the TSPD when this
271	 * cpu is to be suspended through a CPU_SUSPEND
272	 * psci call to ask the TSP to perform any
273	 * bookeeping necessary. In the current
274	 * implementation, the TSPD saves and restores
275	 * the EL1 state.
276	 * ---------------------------------------------
277	 */
278func tsp_cpu_suspend_entry
279	bl	tsp_cpu_suspend_main
280	restore_args_call_smc
281endfunc tsp_cpu_suspend_entry
282
283	/*-------------------------------------------------
284	 * This entrypoint is used by the TSPD to pass
285	 * control for `synchronously` handling a S-EL1
286	 * Interrupt which was triggered while executing
287	 * in normal world. 'x0' contains a magic number
288	 * which indicates this. TSPD expects control to
289	 * be handed back at the end of interrupt
290	 * processing. This is done through an SMC.
291	 * The handover agreement is:
292	 *
293	 * 1. PSTATE.DAIF are set upon entry. 'x1' has
294	 *    the ELR_EL3 from the non-secure state.
295	 * 2. TSP has to preserve the callee saved
296	 *    general purpose registers, SP_EL1/EL0 and
297	 *    LR.
298	 * 3. TSP has to preserve the system and vfp
299	 *    registers (if applicable).
300	 * 4. TSP can use 'x0-x18' to enable its C
301	 *    runtime.
302	 * 5. TSP returns to TSPD using an SMC with
303	 *    'x0' = TSP_HANDLED_S_EL1_INTR
304	 * ------------------------------------------------
305	 */
306func	tsp_sel1_intr_entry
307#if DEBUG
308	mov_imm	x2, TSP_HANDLE_SEL1_INTR_AND_RETURN
309	cmp	x0, x2
310	b.ne	tsp_sel1_int_entry_panic
311#endif
312	/*-------------------------------------------------
313	 * Save any previous context needed to perform
314	 * an exception return from S-EL1 e.g. context
315	 * from a previous Non secure Interrupt.
316	 * Update statistics and handle the S-EL1
317	 * interrupt before returning to the TSPD.
318	 * IRQ/FIQs are not enabled since that will
319	 * complicate the implementation. Execution
320	 * will be transferred back to the normal world
321	 * in any case. The handler can return 0
322	 * if the interrupt was handled or TSP_PREEMPTED
323	 * if the expected interrupt was preempted
324	 * by an interrupt that should be handled in EL3
325	 * e.g. Group 0 interrupt in GICv3. In both
326	 * the cases switch to EL3 using SMC with id
327	 * TSP_HANDLED_S_EL1_INTR. Any other return value
328	 * from the handler will result in panic.
329	 * ------------------------------------------------
330	 */
331	save_eret_context x2 x3
332	bl	tsp_update_sync_sel1_intr_stats
333	bl	tsp_common_int_handler
334	/* Check if the S-EL1 interrupt has been handled */
335	cbnz	x0, tsp_sel1_intr_check_preemption
336	b	tsp_sel1_intr_return
337tsp_sel1_intr_check_preemption:
338	/* Check if the S-EL1 interrupt has been preempted */
339	mov_imm	x1, TSP_PREEMPTED
340	cmp	x0, x1
341	b.ne	tsp_sel1_int_entry_panic
342tsp_sel1_intr_return:
343	mov_imm	x0, TSP_HANDLED_S_EL1_INTR
344	restore_eret_context x2 x3
345	smc	#0
346
347	/* Should never reach here */
348tsp_sel1_int_entry_panic:
349	no_ret	plat_panic_handler
350endfunc tsp_sel1_intr_entry
351
352	/*---------------------------------------------
353	 * This entrypoint is used by the TSPD when this
354	 * cpu resumes execution after an earlier
355	 * CPU_SUSPEND psci call to ask the TSP to
356	 * restore its saved context. In the current
357	 * implementation, the TSPD saves and restores
358	 * EL1 state so nothing is done here apart from
359	 * acknowledging the request.
360	 * ---------------------------------------------
361	 */
362func tsp_cpu_resume_entry
363	bl	tsp_cpu_resume_main
364	restore_args_call_smc
365
366	/* Should never reach here */
367	no_ret	plat_panic_handler
368endfunc tsp_cpu_resume_entry
369
370	/*---------------------------------------------
371	 * This entrypoint is used by the TSPD to ask
372	 * the TSP to service a fast smc request.
373	 * ---------------------------------------------
374	 */
375func tsp_fast_smc_entry
376	bl	tsp_smc_handler
377	restore_args_call_smc
378
379	/* Should never reach here */
380	no_ret	plat_panic_handler
381endfunc tsp_fast_smc_entry
382
383	/*---------------------------------------------
384	 * This entrypoint is used by the TSPD to ask
385	 * the TSP to service a Yielding SMC request.
386	 * We will enable preemption during execution
387	 * of tsp_smc_handler.
388	 * ---------------------------------------------
389	 */
390func tsp_yield_smc_entry
391	msr	daifclr, #DAIF_FIQ_BIT | DAIF_IRQ_BIT
392	bl	tsp_smc_handler
393	msr	daifset, #DAIF_FIQ_BIT | DAIF_IRQ_BIT
394	restore_args_call_smc
395
396	/* Should never reach here */
397	no_ret	plat_panic_handler
398endfunc tsp_yield_smc_entry
399
400	/*---------------------------------------------------------------------
401	 * This entrypoint is used by the TSPD to abort a pre-empted Yielding
402	 * SMC. It could be on behalf of non-secure world or because a CPU
403	 * suspend/CPU off request needs to abort the preempted SMC.
404	 * --------------------------------------------------------------------
405	 */
406func tsp_abort_yield_smc_entry
407
408	/*
409	 * Exceptions masking is already done by the TSPD when entering this
410	 * hook so there is no need to do it here.
411	 */
412
413	/* Reset the stack used by the pre-empted SMC */
414	bl	plat_set_my_stack
415
416	/*
417	 * Allow some cleanup such as releasing locks.
418	 */
419	bl	tsp_abort_smc_handler
420
421	restore_args_call_smc
422
423	/* Should never reach here */
424	bl	plat_panic_handler
425endfunc tsp_abort_yield_smc_entry
426