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