xref: /optee_os/core/arch/arm/plat-vexpress/main.c (revision 57903c16c7dafb08abc57680de73ef4a7c43cb4a)
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 
30 #include <stdint.h>
31 #include <string.h>
32 
33 #include <drivers/gic.h>
34 #include <drivers/pl011.h>
35 #include <sm/sm.h>
36 #include <sm/tee_mon.h>
37 
38 #include <util.h>
39 
40 #include <arm.h>
41 #include <kernel/thread.h>
42 #include <kernel/panic.h>
43 #include <kernel/pm_stubs.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 #endif
84 
85 static const struct thread_handlers handlers = {
86 	.std_smc = plat_tee_entry,
87 	.fast_smc = plat_tee_entry,
88 	.fiq = main_fiq,
89 	.svc = tee_svc_handler,
90 	.abort = tee_pager_abort_handler,
91 #if defined(CFG_WITH_ARM_TRUSTED_FW)
92 	.cpu_on = cpu_on_handler,
93 	.cpu_off = pm_do_nothing,
94 	.cpu_suspend = pm_do_nothing,
95 	.cpu_resume = pm_do_nothing,
96 	.system_off = pm_do_nothing,
97 	.system_reset = pm_do_nothing,
98 #else
99 	.cpu_on = pm_panic,
100 	.cpu_off = pm_panic,
101 	.cpu_suspend = pm_panic,
102 	.cpu_resume = pm_panic,
103 	.system_off = pm_panic,
104 	.system_reset = pm_panic,
105 #endif
106 };
107 
108 #if defined(CFG_WITH_ARM_TRUSTED_FW)
109 static void main_init_sec_mon(uint32_t nsec_entry __unused)
110 {
111 	assert(nsec_entry == PADDR_INVALID);
112 	/* Do nothing as we don't have a secure monitor */
113 }
114 #else
115 static void main_init_sec_mon(uint32_t nsec_entry)
116 {
117 	struct sm_nsec_ctx *nsec_ctx;
118 
119 	assert(nsec_entry != PADDR_INVALID);
120 
121 	/* Initialize secure monitor */
122 	nsec_ctx = sm_get_nsec_ctx();
123 	nsec_ctx->mon_lr = nsec_entry;
124 	nsec_ctx->mon_spsr = CPSR_MODE_SVC | CPSR_I;
125 
126 }
127 #endif
128 
129 #if defined(CFG_WITH_ARM_TRUSTED_FW)
130 static void main_init_nsacr(void)
131 {
132 }
133 #else
134 static void main_init_nsacr(void)
135 {
136 	/* Normal world can use CP10 and CP11 (SIMD/VFP) */
137 	write_nsacr(read_nsacr() | NSACR_CP10 | NSACR_CP11);
138 }
139 #endif
140 
141 #ifdef CFG_WITH_VFP
142 static void main_init_cpacr(void)
143 {
144 	uint32_t cpacr = read_cpacr();
145 
146 	/* Enabled usage of CP10 and CP11 (SIMD/VFP) */
147 	cpacr &= ~CPACR_CP(10, CPACR_CP_ACCESS_FULL);
148 	cpacr |= CPACR_CP(10, CPACR_CP_ACCESS_PL1_ONLY);
149 	cpacr &= ~CPACR_CP(11, CPACR_CP_ACCESS_FULL);
150 	cpacr |= CPACR_CP(11, CPACR_CP_ACCESS_PL1_ONLY);
151 	write_cpacr(cpacr);
152 }
153 #else
154 static void main_init_cpacr(void)
155 {
156 	/* We're not using VFP/SIMD instructions, leave it disabled */
157 }
158 #endif
159 
160 #if PLATFORM_FLAVOR_IS(fvp) || PLATFORM_FLAVOR_IS(juno)
161 static void main_init_gic(void)
162 {
163 	/*
164 	 * On ARMv8, GIC configuration is initialized in ARM-TF,
165 	 */
166 	gic_init_base_addr(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET);
167 	gic_it_add(IT_CONSOLE_UART);
168 	/* Route FIQ to primary CPU */
169 	gic_it_set_cpu_mask(IT_CONSOLE_UART, gic_it_get_target(0));
170 	gic_it_set_prio(IT_CONSOLE_UART, 0x1);
171 	gic_it_enable(IT_CONSOLE_UART);
172 
173 }
174 #elif PLATFORM_FLAVOR_IS(qemu)
175 static void main_init_gic(void)
176 {
177 	/* Initialize GIC */
178 	gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET);
179 	gic_it_add(IT_CONSOLE_UART);
180 	gic_it_set_cpu_mask(IT_CONSOLE_UART, 0x1);
181 	gic_it_set_prio(IT_CONSOLE_UART, 0xff);
182 	gic_it_enable(IT_CONSOLE_UART);
183 }
184 #elif PLATFORM_FLAVOR_IS(qemu_virt)
185 static void main_init_gic(void)
186 {
187 	/* Initialize GIC */
188 	gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET);
189 }
190 #endif
191 
192 #ifdef CFG_WITH_PAGER
193 
194 static size_t get_block_size(void)
195 {
196 	struct core_mmu_table_info tbl_info;
197 	unsigned l;
198 
199 	if (!core_mmu_find_table(CFG_TEE_RAM_START, UINT_MAX, &tbl_info))
200 		panic();
201 	l = tbl_info.level - 1;
202 	if (!core_mmu_find_table(CFG_TEE_RAM_START, l, &tbl_info))
203 		panic();
204 	return 1 << tbl_info.shift;
205 }
206 
207 static void main_init_runtime(uint32_t pageable_part)
208 {
209 	size_t n;
210 	size_t init_size = (size_t)__init_size;
211 	size_t pageable_size = __pageable_end - __pageable_start;
212 	size_t hash_size = (pageable_size / SMALL_PAGE_SIZE) *
213 			   TEE_SHA256_HASH_SIZE;
214 	tee_mm_entry_t *mm;
215 	uint8_t *paged_store;
216 	uint8_t *hashes;
217 	uint8_t *tmp_hashes = __init_start + init_size;
218 	size_t block_size;
219 
220 
221 	TEE_ASSERT(pageable_size % SMALL_PAGE_SIZE == 0);
222 
223 
224 	/* Copy it right after the init area. */
225 	memcpy(tmp_hashes, __data_end + init_size, hash_size);
226 
227 	/*
228 	 * Zero BSS area. Note that globals that would normally would go
229 	 * into BSS which are used before this has to be put into .nozi.*
230 	 * to avoid getting overwritten.
231 	 */
232 	memset(__bss_start, 0, __bss_end - __bss_start);
233 
234 	malloc_init(__heap1_start, __heap1_end - __heap1_start);
235 	malloc_add_pool(__heap2_start, __heap2_end - __heap2_start);
236 
237 	hashes = malloc(hash_size);
238 	EMSG("hash_size %zu", hash_size);
239 	TEE_ASSERT(hashes);
240 	memcpy(hashes, tmp_hashes, hash_size);
241 
242 	/*
243 	 * Need tee_mm_sec_ddr initialized to be able to allocate secure
244 	 * DDR below.
245 	 */
246 	teecore_init_ta_ram();
247 
248 	mm = tee_mm_alloc(&tee_mm_sec_ddr, pageable_size);
249 	TEE_ASSERT(mm);
250 	paged_store = (uint8_t *)tee_mm_get_smem(mm);
251 	/* Copy init part into pageable area */
252 	memcpy(paged_store, __init_start, init_size);
253 	/* Copy pageable part after init part into pageable area */
254 	memcpy(paged_store + init_size, (void *)pageable_part,
255 		__pageable_part_end - __pageable_part_start);
256 
257 	/* Check that hashes of what's in pageable area is OK */
258 	DMSG("Checking hashes of pageable area");
259 	for (n = 0; (n * SMALL_PAGE_SIZE) < pageable_size; n++) {
260 		const uint8_t *hash = hashes + n * TEE_SHA256_HASH_SIZE;
261 		const uint8_t *page = paged_store + n * SMALL_PAGE_SIZE;
262 		TEE_Result res;
263 
264 		DMSG("hash pg_idx %zu hash %p page %p", n, hash, page);
265 		res = hash_sha256_check(hash, page, SMALL_PAGE_SIZE);
266 		if (res != TEE_SUCCESS) {
267 			EMSG("Hash failed for page %zu at %p: res 0x%x",
268 				n, page, res);
269 			panic();
270 		}
271 	}
272 
273 	/*
274 	 * Copy what's not initialized in the last init page. Needed
275 	 * because we're not going fault in the init pages again. We can't
276 	 * fault in pages until we've switched to the new vector by calling
277 	 * thread_init_handlers() below.
278 	 */
279 	if (init_size % SMALL_PAGE_SIZE) {
280 		uint8_t *p;
281 
282 		memcpy(__init_start + init_size, paged_store + init_size,
283 			SMALL_PAGE_SIZE - (init_size % SMALL_PAGE_SIZE));
284 
285 		p = (uint8_t *)(((vaddr_t)__init_start + init_size) &
286 				~SMALL_PAGE_MASK);
287 
288 		cache_maintenance_l1(DCACHE_AREA_CLEAN, p, SMALL_PAGE_SIZE);
289 		cache_maintenance_l1(ICACHE_AREA_INVALIDATE, p,
290 				     SMALL_PAGE_SIZE);
291 	}
292 
293 	/*
294 	 * Inialize the virtual memory pool used for main_mmu_l2_ttb which
295 	 * is supplied to tee_pager_init() below.
296 	 */
297 	block_size = get_block_size();
298 	if (!tee_mm_init(&tee_mm_vcore,
299 			ROUNDDOWN(CFG_TEE_RAM_START, block_size),
300 			ROUNDUP(CFG_TEE_RAM_START + CFG_TEE_RAM_VA_SIZE,
301 				block_size),
302 			SMALL_PAGE_SHIFT, 0))
303 		panic();
304 
305 	/*
306 	 * Claim virtual memory which isn't paged, note that there migth be
307 	 * a gap between tee_mm_vcore.lo and TEE_RAM_START which is also
308 	 * claimed to avoid later allocations to get that memory.
309 	 */
310 	mm = tee_mm_alloc2(&tee_mm_vcore, tee_mm_vcore.lo,
311 			(vaddr_t)(__text_init_start - tee_mm_vcore.lo));
312 	TEE_ASSERT(mm);
313 
314 	/*
315 	 * Allocate virtual memory for the pageable area and let the pager
316 	 * take charge of all the pages already assigned to that memory.
317 	 */
318 	mm = tee_mm_alloc2(&tee_mm_vcore, (vaddr_t)__pageable_start,
319 			   pageable_size);
320 	TEE_ASSERT(mm);
321 	tee_pager_add_area(mm, TEE_PAGER_AREA_RO | TEE_PAGER_AREA_X,
322 			   paged_store, hashes);
323 	tee_pager_add_pages((vaddr_t)__pageable_start,
324 		ROUNDUP(init_size, SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE, false);
325 	tee_pager_add_pages((vaddr_t)__pageable_start +
326 				ROUNDUP(init_size, SMALL_PAGE_SIZE),
327 			(pageable_size - ROUNDUP(init_size, SMALL_PAGE_SIZE)) /
328 				SMALL_PAGE_SIZE, true);
329 
330 }
331 #else
332 static void main_init_runtime(uint32_t pageable_part __unused)
333 {
334 	/*
335 	 * Zero BSS area. Note that globals that would normally would go
336 	 * into BSS which are used before this has to be put into .nozi.*
337 	 * to avoid getting overwritten.
338 	 */
339 	memset(__bss_start, 0, __bss_end - __bss_start);
340 
341 	malloc_init(__heap1_start, __heap1_end - __heap1_start);
342 
343 	/*
344 	 * Initialized at this stage in the pager version of this function
345 	 * above
346 	 */
347 	teecore_init_ta_ram();
348 }
349 #endif
350 
351 static void main_init_primary_helper(uint32_t pageable_part,
352 				     uint32_t nsec_entry)
353 {
354 	/*
355 	 * Mask asynchronous exceptions before switch to the thread vector
356 	 * as the thread handler requires those to be masked while
357 	 * executing with the temporary stack. The thread subsystem also
358 	 * asserts that IRQ is blocked when using most if its functions.
359 	 */
360 	thread_set_exceptions(THREAD_EXCP_ALL);
361 	main_init_cpacr();
362 
363 	main_init_runtime(pageable_part);
364 
365 	DMSG("TEE initializing\n");
366 
367 	thread_init_primary(&handlers);
368 	thread_init_per_cpu();
369 	main_init_sec_mon(nsec_entry);
370 
371 
372 	main_init_gic();
373 	main_init_nsacr();
374 
375 	if (init_teecore() != TEE_SUCCESS)
376 		panic();
377 	DMSG("Primary CPU switching to normal world boot\n");
378 }
379 
380 static void main_init_secondary_helper(uint32_t nsec_entry)
381 {
382 	/*
383 	 * Mask asynchronous exceptions before switch to the thread vector
384 	 * as the thread handler requires those to be masked while
385 	 * executing with the temporary stack. The thread subsystem also
386 	 * asserts that IRQ is blocked when using most if its functions.
387 	 */
388 	thread_set_exceptions(THREAD_EXCP_ALL);
389 
390 	thread_init_per_cpu();
391 	main_init_sec_mon(nsec_entry);
392 	main_init_cpacr();
393 	main_init_nsacr();
394 
395 	DMSG("Secondary CPU Switching to normal world boot\n");
396 }
397 
398 #if defined(CFG_WITH_ARM_TRUSTED_FW)
399 /* called from assembly only */
400 uint32_t *main_init_primary(uint32_t pageable_part);
401 uint32_t *main_init_primary(uint32_t pageable_part)
402 {
403 	main_init_primary_helper(pageable_part, PADDR_INVALID);
404 	return thread_vector_table;
405 }
406 #else
407 /* called from assembly only */
408 void main_init_primary(uint32_t pageable_part, uint32_t nsec_entry);
409 void main_init_primary(uint32_t pageable_part, uint32_t nsec_entry)
410 {
411 	main_init_primary_helper(pageable_part, nsec_entry);
412 }
413 
414 /* called from assembly only */
415 void main_init_secondary(uint32_t nsec_entry);
416 void main_init_secondary(uint32_t nsec_entry)
417 {
418 	main_init_secondary_helper(nsec_entry);
419 }
420 #endif
421 
422 static void main_fiq(void)
423 {
424 	uint32_t iar;
425 
426 	DMSG("enter");
427 
428 	iar = gic_read_iar();
429 
430 	while (pl011_have_rx_data(CONSOLE_UART_BASE)) {
431 		DMSG("cpu %zu: got 0x%x",
432 		     get_core_pos(), pl011_getchar(CONSOLE_UART_BASE));
433 	}
434 
435 	gic_write_eoir(iar);
436 
437 	DMSG("return");
438 }
439 
440 #if defined(CFG_WITH_ARM_TRUSTED_FW)
441 /* called from assembly only */
442 uint32_t main_cpu_on_handler(uint32_t a0, uint32_t a1);
443 uint32_t main_cpu_on_handler(uint32_t a0, uint32_t a1)
444 {
445 	(void)&a0;
446 	(void)&a1;
447 	DMSG("cpu %zu: a0 0x%x", get_core_pos(), a0);
448 	main_init_secondary_helper(PADDR_INVALID);
449 	return 0;
450 }
451 #endif
452 
453 void console_putc(int ch)
454 {
455 	pl011_putc(ch, CONSOLE_UART_BASE);
456 	if (ch == '\n')
457 		pl011_putc('\r', CONSOLE_UART_BASE);
458 }
459 
460 void console_flush(void)
461 {
462 	pl011_flush(CONSOLE_UART_BASE);
463 }
464