xref: /optee_os/core/arch/arm/plat-vexpress/main.c (revision 9a9d08a192f65c983c8d35d557a695a9e0046cde)
1 /*
2  * Copyright (c) 2014, STMicroelectronics International N.V.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <platform_config.h>
29 #include <pm_debug.h>
30 
31 #include <stdint.h>
32 #include <string.h>
33 
34 #include <drivers/gic.h>
35 #include <drivers/pl011.h>
36 #include <sm/sm.h>
37 #include <sm/tee_mon.h>
38 
39 #include <util.h>
40 
41 #include <arm.h>
42 #include <kernel/thread.h>
43 #include <kernel/panic.h>
44 #include <trace.h>
45 #include <kernel/misc.h>
46 #include <kernel/tee_time.h>
47 #include <mm/tee_pager.h>
48 #include <mm/core_mmu.h>
49 #include <mm/tee_mmu.h>
50 #include <mm/tee_mm.h>
51 #include <utee_defines.h>
52 #include <tee/tee_cryp_provider.h>
53 #include <tee/entry.h>
54 #include <tee/arch_svc.h>
55 #include <console.h>
56 #include <malloc.h>
57 #include "plat_tee_func.h"
58 
59 #include <assert.h>
60 
61 #define PADDR_INVALID		0xffffffff
62 
63 extern uint8_t __text_init_start[];
64 extern uint8_t __data_start[];
65 extern uint8_t __data_end[];
66 extern uint8_t __bss_start[];
67 extern uint8_t __bss_end[];
68 extern uint8_t __init_start[];
69 extern uint8_t __init_size[];
70 extern uint8_t __heap1_start[];
71 extern uint8_t __heap1_end[];
72 extern uint8_t __heap2_start[];
73 extern uint8_t __heap2_end[];
74 extern uint8_t __pageable_part_start[];
75 extern uint8_t __pageable_part_end[];
76 extern uint8_t __pageable_start[];
77 extern uint8_t __pageable_end[];
78 
79 static void main_fiq(void);
80 #if defined(CFG_WITH_ARM_TRUSTED_FW)
81 /* Implemented in assembly, referenced in this file only */
82 uint32_t cpu_on_handler(uint32_t a0, uint32_t a1);
83 
84 static uint32_t main_cpu_off_handler(uint32_t a0, uint32_t a1);
85 static uint32_t main_cpu_suspend_handler(uint32_t a0, uint32_t a1);
86 static uint32_t main_cpu_resume_handler(uint32_t a0, uint32_t a1);
87 static uint32_t main_system_off_handler(uint32_t a0, uint32_t a1);
88 static uint32_t main_system_reset_handler(uint32_t a0, uint32_t a1);
89 #else
90 static uint32_t main_default_pm_handler(uint32_t a0, uint32_t a1);
91 #endif
92 
93 static const struct thread_handlers handlers = {
94 	.std_smc = plat_tee_entry,
95 	.fast_smc = plat_tee_entry,
96 	.fiq = main_fiq,
97 	.svc = tee_svc_handler,
98 	.abort = tee_pager_abort_handler,
99 #if defined(CFG_WITH_ARM_TRUSTED_FW)
100 	.cpu_on = cpu_on_handler,
101 	.cpu_off = main_cpu_off_handler,
102 	.cpu_suspend = main_cpu_suspend_handler,
103 	.cpu_resume = main_cpu_resume_handler,
104 	.system_off = main_system_off_handler,
105 	.system_reset = main_system_reset_handler,
106 #else
107 	.cpu_on = main_default_pm_handler,
108 	.cpu_off = main_default_pm_handler,
109 	.cpu_suspend = main_default_pm_handler,
110 	.cpu_resume = main_default_pm_handler,
111 	.system_off = main_default_pm_handler,
112 	.system_reset = main_default_pm_handler,
113 #endif
114 };
115 
116 #if defined(CFG_WITH_ARM_TRUSTED_FW)
117 static void main_init_sec_mon(uint32_t nsec_entry __unused)
118 {
119 	assert(nsec_entry == PADDR_INVALID);
120 	/* Do nothing as we don't have a secure monitor */
121 }
122 #else
123 static void main_init_sec_mon(uint32_t nsec_entry)
124 {
125 	struct sm_nsec_ctx *nsec_ctx;
126 
127 	assert(nsec_entry != PADDR_INVALID);
128 
129 	/* Initialize secure monitor */
130 	nsec_ctx = sm_get_nsec_ctx();
131 	nsec_ctx->mon_lr = nsec_entry;
132 	nsec_ctx->mon_spsr = CPSR_MODE_SVC | CPSR_I;
133 
134 }
135 #endif
136 
137 #if defined(CFG_WITH_ARM_TRUSTED_FW)
138 static void main_init_nsacr(void)
139 {
140 }
141 #else
142 static void main_init_nsacr(void)
143 {
144 	/* Normal world can use CP10 and CP11 (SIMD/VFP) */
145 	write_nsacr(read_nsacr() | NSACR_CP10 | NSACR_CP11);
146 }
147 #endif
148 
149 #ifdef CFG_WITH_VFP
150 static void main_init_cpacr(void)
151 {
152 	uint32_t cpacr = read_cpacr();
153 
154 	/* Enabled usage of CP10 and CP11 (SIMD/VFP) */
155 	cpacr &= ~CPACR_CP(10, CPACR_CP_ACCESS_FULL);
156 	cpacr |= CPACR_CP(10, CPACR_CP_ACCESS_PL1_ONLY);
157 	cpacr &= ~CPACR_CP(11, CPACR_CP_ACCESS_FULL);
158 	cpacr |= CPACR_CP(11, CPACR_CP_ACCESS_PL1_ONLY);
159 	write_cpacr(cpacr);
160 }
161 #else
162 static void main_init_cpacr(void)
163 {
164 	/* We're not using VFP/SIMD instructions, leave it disabled */
165 }
166 #endif
167 
168 #if PLATFORM_FLAVOR_IS(fvp) || PLATFORM_FLAVOR_IS(juno)
169 static void main_init_gic(void)
170 {
171 	/*
172 	 * On ARMv8, GIC configuration is initialized in ARM-TF,
173 	 */
174 	gic_init_base_addr(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET);
175 	gic_it_add(IT_CONSOLE_UART);
176 	/* Route FIQ to primary CPU */
177 	gic_it_set_cpu_mask(IT_CONSOLE_UART, gic_it_get_target(0));
178 	gic_it_set_prio(IT_CONSOLE_UART, 0x1);
179 	gic_it_enable(IT_CONSOLE_UART);
180 
181 }
182 #elif PLATFORM_FLAVOR_IS(qemu)
183 static void main_init_gic(void)
184 {
185 	/* Initialize GIC */
186 	gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET);
187 	gic_it_add(IT_CONSOLE_UART);
188 	gic_it_set_cpu_mask(IT_CONSOLE_UART, 0x1);
189 	gic_it_set_prio(IT_CONSOLE_UART, 0xff);
190 	gic_it_enable(IT_CONSOLE_UART);
191 }
192 #elif PLATFORM_FLAVOR_IS(qemu_virt)
193 static void main_init_gic(void)
194 {
195 	/* Initialize GIC */
196 	gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET);
197 }
198 #endif
199 
200 #ifdef CFG_WITH_PAGER
201 
202 static size_t get_block_size(void)
203 {
204 	struct core_mmu_table_info tbl_info;
205 	unsigned l;
206 
207 	if (!core_mmu_find_table(CFG_TEE_RAM_START, UINT_MAX, &tbl_info))
208 		panic();
209 	l = tbl_info.level - 1;
210 	if (!core_mmu_find_table(CFG_TEE_RAM_START, l, &tbl_info))
211 		panic();
212 	return 1 << tbl_info.shift;
213 }
214 
215 static void main_init_runtime(uint32_t pageable_part)
216 {
217 	size_t n;
218 	size_t init_size = (size_t)__init_size;
219 	size_t pageable_size = __pageable_end - __pageable_start;
220 	size_t hash_size = (pageable_size / SMALL_PAGE_SIZE) *
221 			   TEE_SHA256_HASH_SIZE;
222 	tee_mm_entry_t *mm;
223 	uint8_t *paged_store;
224 	uint8_t *hashes;
225 	uint8_t *tmp_hashes = __init_start + init_size;
226 	size_t block_size;
227 
228 
229 	TEE_ASSERT(pageable_size % SMALL_PAGE_SIZE == 0);
230 
231 
232 	/* Copy it right after the init area. */
233 	memcpy(tmp_hashes, __data_end + init_size, hash_size);
234 
235 	/*
236 	 * Zero BSS area. Note that globals that would normally would go
237 	 * into BSS which are used before this has to be put into .nozi.*
238 	 * to avoid getting overwritten.
239 	 */
240 	memset(__bss_start, 0, __bss_end - __bss_start);
241 
242 	malloc_init(__heap1_start, __heap1_end - __heap1_start);
243 	malloc_add_pool(__heap2_start, __heap2_end - __heap2_start);
244 
245 	hashes = malloc(hash_size);
246 	EMSG("hash_size %zu", hash_size);
247 	TEE_ASSERT(hashes);
248 	memcpy(hashes, tmp_hashes, hash_size);
249 
250 	/*
251 	 * Need tee_mm_sec_ddr initialized to be able to allocate secure
252 	 * DDR below.
253 	 */
254 	teecore_init_ta_ram();
255 
256 	mm = tee_mm_alloc(&tee_mm_sec_ddr, pageable_size);
257 	TEE_ASSERT(mm);
258 	paged_store = (uint8_t *)tee_mm_get_smem(mm);
259 	/* Copy init part into pageable area */
260 	memcpy(paged_store, __init_start, init_size);
261 	/* Copy pageable part after init part into pageable area */
262 	memcpy(paged_store + init_size, (void *)pageable_part,
263 		__pageable_part_end - __pageable_part_start);
264 
265 	/* Check that hashes of what's in pageable area is OK */
266 	DMSG("Checking hashes of pageable area");
267 	for (n = 0; (n * SMALL_PAGE_SIZE) < pageable_size; n++) {
268 		const uint8_t *hash = hashes + n * TEE_SHA256_HASH_SIZE;
269 		const uint8_t *page = paged_store + n * SMALL_PAGE_SIZE;
270 		TEE_Result res;
271 
272 		DMSG("hash pg_idx %zu hash %p page %p", n, hash, page);
273 		res = hash_sha256_check(hash, page, SMALL_PAGE_SIZE);
274 		if (res != TEE_SUCCESS) {
275 			EMSG("Hash failed for page %zu at %p: res 0x%x",
276 				n, page, res);
277 			panic();
278 		}
279 	}
280 
281 	/*
282 	 * Copy what's not initialized in the last init page. Needed
283 	 * because we're not going fault in the init pages again. We can't
284 	 * fault in pages until we've switched to the new vector by calling
285 	 * thread_init_handlers() below.
286 	 */
287 	if (init_size % SMALL_PAGE_SIZE) {
288 		uint8_t *p;
289 
290 		memcpy(__init_start + init_size, paged_store + init_size,
291 			SMALL_PAGE_SIZE - (init_size % SMALL_PAGE_SIZE));
292 
293 		p = (uint8_t *)(((vaddr_t)__init_start + init_size) &
294 				~SMALL_PAGE_MASK);
295 
296 		cache_maintenance_l1(DCACHE_AREA_CLEAN, p, SMALL_PAGE_SIZE);
297 		cache_maintenance_l1(ICACHE_AREA_INVALIDATE, p,
298 				     SMALL_PAGE_SIZE);
299 	}
300 
301 	/*
302 	 * Inialize the virtual memory pool used for main_mmu_l2_ttb which
303 	 * is supplied to tee_pager_init() below.
304 	 */
305 	block_size = get_block_size();
306 	if (!tee_mm_init(&tee_mm_vcore,
307 			ROUNDDOWN(CFG_TEE_RAM_START, block_size),
308 			ROUNDUP(CFG_TEE_RAM_START + CFG_TEE_RAM_VA_SIZE,
309 				block_size),
310 			SMALL_PAGE_SHIFT, 0))
311 		panic();
312 
313 	/*
314 	 * Claim virtual memory which isn't paged, note that there migth be
315 	 * a gap between tee_mm_vcore.lo and TEE_RAM_START which is also
316 	 * claimed to avoid later allocations to get that memory.
317 	 */
318 	mm = tee_mm_alloc2(&tee_mm_vcore, tee_mm_vcore.lo,
319 			(vaddr_t)(__text_init_start - tee_mm_vcore.lo));
320 	TEE_ASSERT(mm);
321 
322 	/*
323 	 * Allocate virtual memory for the pageable area and let the pager
324 	 * take charge of all the pages already assigned to that memory.
325 	 */
326 	mm = tee_mm_alloc2(&tee_mm_vcore, (vaddr_t)__pageable_start,
327 			   pageable_size);
328 	TEE_ASSERT(mm);
329 	tee_pager_add_area(mm, TEE_PAGER_AREA_RO | TEE_PAGER_AREA_X,
330 			   paged_store, hashes);
331 	tee_pager_add_pages((vaddr_t)__pageable_start,
332 		ROUNDUP(init_size, SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE, false);
333 	tee_pager_add_pages((vaddr_t)__pageable_start +
334 				ROUNDUP(init_size, SMALL_PAGE_SIZE),
335 			(pageable_size - ROUNDUP(init_size, SMALL_PAGE_SIZE)) /
336 				SMALL_PAGE_SIZE, true);
337 
338 }
339 #else
340 static void main_init_runtime(uint32_t pageable_part __unused)
341 {
342 	/*
343 	 * Zero BSS area. Note that globals that would normally would go
344 	 * into BSS which are used before this has to be put into .nozi.*
345 	 * to avoid getting overwritten.
346 	 */
347 	memset(__bss_start, 0, __bss_end - __bss_start);
348 
349 	malloc_init(__heap1_start, __heap1_end - __heap1_start);
350 
351 	/*
352 	 * Initialized at this stage in the pager version of this function
353 	 * above
354 	 */
355 	teecore_init_ta_ram();
356 }
357 #endif
358 
359 static void main_init_primary_helper(uint32_t pageable_part,
360 				     uint32_t nsec_entry)
361 {
362 	/*
363 	 * Mask asynchronous exceptions before switch to the thread vector
364 	 * as the thread handler requires those to be masked while
365 	 * executing with the temporary stack. The thread subsystem also
366 	 * asserts that IRQ is blocked when using most if its functions.
367 	 */
368 	thread_set_exceptions(THREAD_EXCP_ALL);
369 	main_init_cpacr();
370 
371 	main_init_runtime(pageable_part);
372 
373 	DMSG("TEE initializing\n");
374 
375 	thread_init_primary(&handlers);
376 	thread_init_per_cpu();
377 	main_init_sec_mon(nsec_entry);
378 
379 
380 	main_init_gic();
381 	main_init_nsacr();
382 
383 	if (init_teecore() != TEE_SUCCESS)
384 		panic();
385 	DMSG("Primary CPU switching to normal world boot\n");
386 }
387 
388 static void main_init_secondary_helper(uint32_t nsec_entry)
389 {
390 	/*
391 	 * Mask asynchronous exceptions before switch to the thread vector
392 	 * as the thread handler requires those to be masked while
393 	 * executing with the temporary stack. The thread subsystem also
394 	 * asserts that IRQ is blocked when using most if its functions.
395 	 */
396 	thread_set_exceptions(THREAD_EXCP_ALL);
397 
398 	thread_init_per_cpu();
399 	main_init_sec_mon(nsec_entry);
400 	main_init_cpacr();
401 	main_init_nsacr();
402 
403 	DMSG("Secondary CPU Switching to normal world boot\n");
404 }
405 
406 #if defined(CFG_WITH_ARM_TRUSTED_FW)
407 /* called from assembly only */
408 uint32_t *main_init_primary(uint32_t pageable_part);
409 uint32_t *main_init_primary(uint32_t pageable_part)
410 {
411 	main_init_primary_helper(pageable_part, PADDR_INVALID);
412 	return thread_vector_table;
413 }
414 #else
415 /* called from assembly only */
416 void main_init_primary(uint32_t pageable_part, uint32_t nsec_entry);
417 void main_init_primary(uint32_t pageable_part, uint32_t nsec_entry)
418 {
419 	main_init_primary_helper(pageable_part, nsec_entry);
420 }
421 
422 /* called from assembly only */
423 void main_init_secondary(uint32_t nsec_entry);
424 void main_init_secondary(uint32_t nsec_entry)
425 {
426 	main_init_secondary_helper(nsec_entry);
427 }
428 #endif
429 
430 static void main_fiq(void)
431 {
432 	uint32_t iar;
433 
434 	DMSG("enter");
435 
436 	iar = gic_read_iar();
437 
438 	while (pl011_have_rx_data(CONSOLE_UART_BASE)) {
439 		DMSG("cpu %zu: got 0x%x",
440 		     get_core_pos(), pl011_getchar(CONSOLE_UART_BASE));
441 	}
442 
443 	gic_write_eoir(iar);
444 
445 	DMSG("return");
446 }
447 
448 #if defined(CFG_WITH_ARM_TRUSTED_FW)
449 static uint32_t main_cpu_off_handler(uint32_t a0, uint32_t a1)
450 {
451 	(void)&a0;
452 	(void)&a1;
453 	/* Could stop generic timer here */
454 	PM_DEBUG("cpu %zu: a0 0%x", get_core_pos(), a0);
455 	return 0;
456 }
457 
458 static uint32_t main_cpu_suspend_handler(uint32_t a0, uint32_t a1)
459 {
460 	(void)&a0;
461 	(void)&a1;
462 	/* Could save generic timer here */
463 	PM_DEBUG("cpu %zu: a0 0%x", get_core_pos(), a0);
464 	return 0;
465 }
466 
467 static uint32_t main_cpu_resume_handler(uint32_t a0, uint32_t a1)
468 {
469 	(void)&a0;
470 	(void)&a1;
471 	/* Could restore generic timer here */
472 	PM_DEBUG("cpu %zu: a0 0%x", get_core_pos(), a0);
473 	return 0;
474 }
475 
476 /* called from assembly only */
477 uint32_t main_cpu_on_handler(uint32_t a0, uint32_t a1);
478 uint32_t main_cpu_on_handler(uint32_t a0, uint32_t a1)
479 {
480 	(void)&a0;
481 	(void)&a1;
482 	PM_DEBUG("cpu %zu: a0 0%x", get_core_pos(), a0);
483 	main_init_secondary_helper(PADDR_INVALID);
484 	return 0;
485 }
486 
487 static uint32_t main_system_off_handler(uint32_t a0, uint32_t a1)
488 {
489 	(void)&a0;
490 	(void)&a1;
491 	PM_DEBUG("cpu %zu: a0 0%x", get_core_pos(), a0);
492 	return 0;
493 }
494 
495 static uint32_t main_system_reset_handler(uint32_t a0, uint32_t a1)
496 {
497 	(void)&a0;
498 	(void)&a1;
499 	PM_DEBUG("cpu %zu: a0 0%x", get_core_pos(), a0);
500 	return 0;
501 }
502 
503 #else /* !CFG_WITH_ARM_TRUSTED_FW */
504 static uint32_t main_default_pm_handler(uint32_t a0, uint32_t a1)
505 {
506 	/*
507 	 * This function is not supported in this configuration, and
508 	 * should never be called. Panic to catch unintended calls.
509 	 */
510 	(void)&a0;
511 	(void)&a1;
512 	panic();
513 	return 1;
514 }
515 #endif
516 
517 void console_putc(int ch)
518 {
519 	pl011_putc(ch, CONSOLE_UART_BASE);
520 	if (ch == '\n')
521 		pl011_putc('\r', CONSOLE_UART_BASE);
522 }
523 
524 void console_flush(void)
525 {
526 	pl011_flush(CONSOLE_UART_BASE);
527 }
528