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