xref: /optee_os/core/arch/arm/kernel/entry_a64.S (revision 997ff82731597ddcf8d6ad0fb3301adca8c0c6a8)
1/* SPDX-License-Identifier: BSD-2-Clause */
2/*
3 * Copyright (c) 2015, Linaro Limited
4 * Copyright (c) 2021, Arm Limited
5 */
6
7#include <platform_config.h>
8
9#include <arm64_macros.S>
10#include <arm.h>
11#include <asm.S>
12#include <generated/asm-defines.h>
13#include <keep.h>
14#include <kernel/thread_private.h>
15#include <sm/optee_smc.h>
16#include <sm/teesmc_opteed.h>
17#include <sm/teesmc_opteed_macros.h>
18
19	/*
20	 * Setup SP_EL0 and SPEL1, SP will be set to SP_EL0.
21	 * SP_EL0 is assigned stack_tmp_export + cpu_id * stack_tmp_stride
22	 * SP_EL1 is assigned thread_core_local[cpu_id]
23	 */
24	.macro set_sp
25		bl	__get_core_pos
26		cmp	x0, #CFG_TEE_CORE_NB_CORE
27		/* Unsupported CPU, park it before it breaks something */
28		bge	unhandled_cpu
29		adr_l	x1, stack_tmp_stride
30		ldr	w1, [x1]
31		mul	x1, x0, x1
32		adr_l	x0, stack_tmp_export
33		ldr	x0, [x0]
34		msr	spsel, #0
35		add	sp, x1, x0
36		bl	thread_get_core_local
37		msr	spsel, #1
38		mov	sp, x0
39		msr	spsel, #0
40	.endm
41
42	.macro set_sctlr_el1
43		mrs	x0, sctlr_el1
44		orr	x0, x0, #SCTLR_I
45		orr	x0, x0, #SCTLR_SA
46		orr	x0, x0, #SCTLR_SPAN
47#if defined(CFG_CORE_RWDATA_NOEXEC)
48		orr	x0, x0, #SCTLR_WXN
49#endif
50#if defined(CFG_SCTLR_ALIGNMENT_CHECK)
51		orr	x0, x0, #SCTLR_A
52#else
53		bic	x0, x0, #SCTLR_A
54#endif
55		msr	sctlr_el1, x0
56	.endm
57
58FUNC _start , :
59#if defined(CFG_CORE_SEL1_SPMC)
60	/*
61	 * With OP-TEE as SPMC at S-EL1 the SPMD (SPD_spmd) in TF-A passes
62	 * the DTB in x0, pagaeble part in x1 and the rest of the registers
63	 * are unused
64	 */
65	mov	x19, x1		/* Save pagable part */
66	mov	x20, x0		/* Save DT address */
67#else
68	mov	x19, x0		/* Save pagable part address */
69#if defined(CFG_DT_ADDR)
70	ldr     x20, =CFG_DT_ADDR
71#else
72	mov	x20, x2		/* Save DT address */
73#endif
74#endif
75
76	adr	x0, reset_vect_table
77	msr	vbar_el1, x0
78	isb
79
80	set_sctlr_el1
81	isb
82
83#ifdef CFG_WITH_PAGER
84	/*
85	 * Move init code into correct location and move hashes to a
86	 * temporary safe location until the heap is initialized.
87	 *
88	 * The binary is built as:
89	 * [Pager code, rodata and data] : In correct location
90	 * [Init code and rodata] : Should be copied to __init_start
91	 * [struct boot_embdata + data] : Should be saved before
92	 * initializing pager, first uint32_t tells the length of the data
93	 */
94	adr	x0, __init_start	/* dst */
95	adr	x1, __data_end		/* src */
96	adr	x2, __init_end
97	sub	x2, x2, x0		/* init len */
98	ldr	w4, [x1, x2]		/* length of hashes etc */
99	add	x2, x2, x4		/* length of init and hashes etc */
100	/* Copy backwards (as memmove) in case we're overlapping */
101	add	x0, x0, x2		/* __init_start + len */
102	add	x1, x1, x2		/* __data_end + len */
103	adr	x3, cached_mem_end
104	str	x0, [x3]
105	adr	x2, __init_start
106copy_init:
107	ldp	x3, x4, [x1, #-16]!
108	stp	x3, x4, [x0, #-16]!
109	cmp	x0, x2
110	b.gt	copy_init
111#else
112	/*
113	 * The binary is built as:
114	 * [Core, rodata and data] : In correct location
115	 * [struct boot_embdata + data] : Should be moved to __end, first
116	 * uint32_t tells the length of the struct + data
117	 */
118	adr_l	x0, __end		/* dst */
119	adr_l	x1, __data_end		/* src */
120	ldr	w2, [x1]		/* struct boot_embdata::total_len */
121	/* Copy backwards (as memmove) in case we're overlapping */
122	add	x0, x0, x2
123	add	x1, x1, x2
124	adr	x3, cached_mem_end
125	str	x0, [x3]
126	adr_l	x2, __end
127
128copy_init:
129	ldp	x3, x4, [x1, #-16]!
130	stp	x3, x4, [x0, #-16]!
131	cmp	x0, x2
132	b.gt	copy_init
133#endif
134
135	/*
136	 * Clear .bss, this code obviously depends on the linker keeping
137	 * start/end of .bss at least 8 byte aligned.
138	 */
139	adr_l	x0, __bss_start
140	adr_l	x1, __bss_end
141clear_bss:
142	str	xzr, [x0], #8
143	cmp	x0, x1
144	b.lt	clear_bss
145
146#ifdef CFG_VIRTUALIZATION
147	/*
148	 * Clear .nex_bss, this code obviously depends on the linker keeping
149	 * start/end of .bss at least 8 byte aligned.
150	 */
151	adr	x0, __nex_bss_start
152	adr	x1, __nex_bss_end
153clear_nex_bss:
154	str	xzr, [x0], #8
155	cmp	x0, x1
156	b.lt	clear_nex_bss
157#endif
158
159	/* Setup SP_EL0 and SP_EL1, SP will be set to SP_EL0 */
160	set_sp
161
162	bl	thread_init_thread_core_local
163
164	/* Enable aborts now that we can receive exceptions */
165	msr	daifclr, #DAIFBIT_ABT
166
167	/*
168	 * Invalidate dcache for all memory used during initialization to
169	 * avoid nasty surprices when the cache is turned on. We must not
170	 * invalidate memory not used by OP-TEE since we may invalidate
171	 * entries used by for instance ARM Trusted Firmware.
172	 */
173	adr_l	x0, __text_start
174	ldr	x1, cached_mem_end
175	sub	x1, x1, x0
176	bl	dcache_cleaninv_range
177
178	/* Enable Console */
179	bl	console_init
180
181#ifdef CFG_CORE_ASLR
182	mov	x0, x20
183	bl	get_aslr_seed
184#else
185	mov	x0, #0
186#endif
187
188	adr	x1, boot_mmu_config
189	bl	core_init_mmu_map
190
191#ifdef CFG_CORE_ASLR
192	/*
193	 * Process relocation information again updating for the new
194	 * offset. We're doing this now before MMU is enabled as some of
195	 * the memory will become write protected.
196	 */
197	ldr	x0, boot_mmu_config + CORE_MMU_CONFIG_LOAD_OFFSET
198	/*
199	 * Update cached_mem_end address with load offset since it was
200	 * calculated before relocation.
201	 */
202	adr	x5, cached_mem_end
203	ldr	x6, [x5]
204	add	x6, x6, x0
205	str	x6, [x5]
206	bl	relocate
207#endif
208
209	bl	__get_core_pos
210	bl	enable_mmu
211#ifdef CFG_CORE_ASLR
212	/*
213	 * Reinitialize console, since register_serial_console() has
214	 * previously registered a PA and with ASLR the VA is different
215	 * from the PA.
216	 */
217	bl	console_init
218#endif
219
220#ifdef CFG_VIRTUALIZATION
221	/*
222	 * Initialize partition tables for each partition to
223	 * default_partition which has been relocated now to a different VA
224	 */
225	bl	core_mmu_set_default_prtn_tbl
226#endif
227
228	mov	x0, x19		/* pagable part address */
229	mov	x1, #-1
230	bl	boot_init_primary_early
231#ifndef CFG_VIRTUALIZATION
232	mov	x21, sp
233	adr_l	x0, threads
234	ldr	x0, [x0, #THREAD_CTX_STACK_VA_END]
235	mov	sp, x0
236	bl	thread_get_core_local
237	mov	x22, x0
238	str	wzr, [x22, #THREAD_CORE_LOCAL_FLAGS]
239#endif
240	mov	x0, x20		/* DT address */
241	bl	boot_init_primary_late
242#ifndef CFG_VIRTUALIZATION
243	mov	x0, #THREAD_CLF_TMP
244	str     w0, [x22, #THREAD_CORE_LOCAL_FLAGS]
245	mov	sp, x21
246#endif
247
248	/*
249	 * In case we've touched memory that secondary CPUs will use before
250	 * they have turned on their D-cache, clean and invalidate the
251	 * D-cache before exiting to normal world.
252	 */
253	adr_l	x0, __text_start
254	ldr	x1, cached_mem_end
255	sub	x1, x1, x0
256	bl	dcache_cleaninv_range
257
258
259	/*
260	 * Clear current thread id now to allow the thread to be reused on
261	 * next entry. Matches the thread_init_boot_thread in
262	 * boot.c.
263	 */
264#ifndef CFG_VIRTUALIZATION
265	bl 	thread_clr_boot_thread
266#endif
267
268#ifdef CFG_CORE_FFA
269	adr	x0, cpu_on_handler
270	/*
271	 * Compensate for the load offset since cpu_on_handler() is
272	 * called with MMU off.
273	 */
274	ldr	x1, boot_mmu_config + CORE_MMU_CONFIG_LOAD_OFFSET
275	sub	x0, x0, x1
276	bl	thread_spmc_register_secondary_ep
277	b	thread_ffa_msg_wait
278#else
279	/*
280	 * Pass the vector address returned from main_init
281	 * Compensate for the load offset since cpu_on_handler() is
282	 * called with MMU off.
283	 */
284	ldr	x0, boot_mmu_config + CORE_MMU_CONFIG_LOAD_OFFSET
285	adr	x1, thread_vector_table
286	sub	x1, x1, x0
287	mov	x0, #TEESMC_OPTEED_RETURN_ENTRY_DONE
288	smc	#0
289	/* SMC should not return */
290	panic_at_smc_return
291#endif
292END_FUNC _start
293DECLARE_KEEP_INIT _start
294
295	.balign	8
296LOCAL_DATA cached_mem_end , :
297	.skip	8
298END_DATA cached_mem_end
299
300#ifdef CFG_CORE_ASLR
301LOCAL_FUNC relocate , :
302	/* x0 holds load offset */
303#ifdef CFG_WITH_PAGER
304	adr_l	x6, __init_end
305#else
306	adr_l	x6, __end
307#endif
308	ldp	w2, w3, [x6, #BOOT_EMBDATA_RELOC_OFFSET]
309
310	mov_imm	x1, TEE_RAM_START
311	add	x2, x2, x6	/* start of relocations */
312	add	x3, x3, x2	/* end of relocations */
313
314	/*
315	 * Relocations are not formatted as Rela64, instead they are in a
316	 * compressed format created by get_reloc_bin() in
317	 * scripts/gen_tee_bin.py
318	 *
319	 * All the R_AARCH64_RELATIVE relocations are translated into a
320	 * list list of 32-bit offsets from TEE_RAM_START. At each address
321	 * a 64-bit value pointed out which increased with the load offset.
322	 */
323
324#ifdef CFG_WITH_PAGER
325	/*
326	 * With pager enabled we can only relocate the pager and init
327	 * parts, the rest has to be done when a page is populated.
328	 */
329	sub	x6, x6, x1
330#endif
331
332	b	2f
333	/* Loop over the relocation addresses and process all entries */
3341:	ldr	w4, [x2], #4
335#ifdef CFG_WITH_PAGER
336	/* Skip too large addresses */
337	cmp	x4, x6
338	b.ge	2f
339#endif
340	add	x4, x4, x1
341	ldr	x5, [x4]
342	add	x5, x5, x0
343	str	x5, [x4]
344
3452:	cmp	x2, x3
346	b.ne	1b
347
348	ret
349END_FUNC relocate
350#endif
351
352/*
353 * void enable_mmu(unsigned long core_pos);
354 *
355 * This function depends on being mapped with in the identity map where
356 * physical address and virtual address is the same. After MMU has been
357 * enabled the instruction pointer will be updated to execute as the new
358 * offset instead. Stack pointers and the return address are updated.
359 */
360LOCAL_FUNC enable_mmu , : , .identity_map
361	adr	x1, boot_mmu_config
362	load_xregs x1, 0, 2, 6
363	/*
364	 * x0 = core_pos
365	 * x2 = tcr_el1
366	 * x3 = mair_el1
367	 * x4 = ttbr0_el1_base
368	 * x5 = ttbr0_core_offset
369	 * x6 = load_offset
370	 */
371	msr	tcr_el1, x2
372	msr	mair_el1, x3
373
374	/*
375	 * ttbr0_el1 = ttbr0_el1_base + ttbr0_core_offset * core_pos
376	 */
377	madd	x1, x5, x0, x4
378	msr	ttbr0_el1, x1
379	msr	ttbr1_el1, xzr
380	isb
381
382	/* Invalidate TLB */
383	tlbi	vmalle1
384
385	/*
386	 * Make sure translation table writes have drained into memory and
387	 * the TLB invalidation is complete.
388	 */
389	dsb	sy
390	isb
391
392	/* Enable the MMU */
393	mrs	x1, sctlr_el1
394	orr	x1, x1, #SCTLR_M
395	msr	sctlr_el1, x1
396	isb
397
398	/* Update vbar */
399	mrs	x1, vbar_el1
400	add	x1, x1, x6
401	msr	vbar_el1, x1
402	isb
403
404	/* Invalidate instruction cache and branch predictor */
405	ic	iallu
406	isb
407
408	/* Enable I and D cache */
409	mrs	x1, sctlr_el1
410	orr	x1, x1, #SCTLR_I
411	orr	x1, x1, #SCTLR_C
412	msr	sctlr_el1, x1
413	isb
414
415	/* Adjust stack pointers and return address */
416	msr	spsel, #1
417	add	sp, sp, x6
418	msr	spsel, #0
419	add	sp, sp, x6
420	add	x30, x30, x6
421
422	ret
423END_FUNC enable_mmu
424
425	.balign	8
426DATA boot_mmu_config , : /* struct core_mmu_config */
427	.skip	CORE_MMU_CONFIG_SIZE
428END_DATA boot_mmu_config
429
430FUNC cpu_on_handler , :
431	mov	x19, x0
432	mov	x20, x1
433	mov	x21, x30
434
435	adr	x0, reset_vect_table
436	msr	vbar_el1, x0
437	isb
438
439	set_sctlr_el1
440	isb
441
442	/* Enable aborts now that we can receive exceptions */
443	msr	daifclr, #DAIFBIT_ABT
444
445	bl	__get_core_pos
446	bl	enable_mmu
447
448	/* Setup SP_EL0 and SP_EL1, SP will be set to SP_EL0 */
449	set_sp
450
451	mov	x0, x19
452	mov	x1, x20
453#ifdef CFG_CORE_FFA
454	bl	boot_cpu_on_handler
455	b	thread_ffa_msg_wait
456#else
457	mov	x30, x21
458	b	boot_cpu_on_handler
459#endif
460END_FUNC cpu_on_handler
461DECLARE_KEEP_PAGER cpu_on_handler
462
463LOCAL_FUNC unhandled_cpu , :
464	wfi
465	b	unhandled_cpu
466END_FUNC unhandled_cpu
467
468	/*
469	 * This macro verifies that the a given vector doesn't exceed the
470	 * architectural limit of 32 instructions. This is meant to be placed
471	 * immedately after the last instruction in the vector. It takes the
472	 * vector entry as the parameter
473	 */
474	.macro check_vector_size since
475	  .if (. - \since) > (32 * 4)
476	    .error "Vector exceeds 32 instructions"
477	  .endif
478	.endm
479
480	.section .identity_map, "ax", %progbits
481	.align	11
482LOCAL_FUNC reset_vect_table , :, .identity_map, , nobti
483	/* -----------------------------------------------------
484	 * Current EL with SP0 : 0x0 - 0x180
485	 * -----------------------------------------------------
486	 */
487SynchronousExceptionSP0:
488	b	SynchronousExceptionSP0
489	check_vector_size SynchronousExceptionSP0
490
491	.align	7
492IrqSP0:
493	b	IrqSP0
494	check_vector_size IrqSP0
495
496	.align	7
497FiqSP0:
498	b	FiqSP0
499	check_vector_size FiqSP0
500
501	.align	7
502SErrorSP0:
503	b	SErrorSP0
504	check_vector_size SErrorSP0
505
506	/* -----------------------------------------------------
507	 * Current EL with SPx: 0x200 - 0x380
508	 * -----------------------------------------------------
509	 */
510	.align	7
511SynchronousExceptionSPx:
512	b	SynchronousExceptionSPx
513	check_vector_size SynchronousExceptionSPx
514
515	.align	7
516IrqSPx:
517	b	IrqSPx
518	check_vector_size IrqSPx
519
520	.align	7
521FiqSPx:
522	b	FiqSPx
523	check_vector_size FiqSPx
524
525	.align	7
526SErrorSPx:
527	b	SErrorSPx
528	check_vector_size SErrorSPx
529
530	/* -----------------------------------------------------
531	 * Lower EL using AArch64 : 0x400 - 0x580
532	 * -----------------------------------------------------
533	 */
534	.align	7
535SynchronousExceptionA64:
536	b	SynchronousExceptionA64
537	check_vector_size SynchronousExceptionA64
538
539	.align	7
540IrqA64:
541	b	IrqA64
542	check_vector_size IrqA64
543
544	.align	7
545FiqA64:
546	b	FiqA64
547	check_vector_size FiqA64
548
549	.align	7
550SErrorA64:
551	b   	SErrorA64
552	check_vector_size SErrorA64
553
554	/* -----------------------------------------------------
555	 * Lower EL using AArch32 : 0x0 - 0x180
556	 * -----------------------------------------------------
557	 */
558	.align	7
559SynchronousExceptionA32:
560	b	SynchronousExceptionA32
561	check_vector_size SynchronousExceptionA32
562
563	.align	7
564IrqA32:
565	b	IrqA32
566	check_vector_size IrqA32
567
568	.align	7
569FiqA32:
570	b	FiqA32
571	check_vector_size FiqA32
572
573	.align	7
574SErrorA32:
575	b	SErrorA32
576	check_vector_size SErrorA32
577
578END_FUNC reset_vect_table
579
580BTI(emit_aarch64_feature_1_and     GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
581