xref: /optee_os/core/arch/arm/plat-stm/main.c (revision 44bd24c5e3a1540d4e563c82e59309d0e99845ee)
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 #include <stdint.h>
28 #include <string.h>
29 #include <sm/sm.h>
30 #include <sm/tee_mon.h>
31 #include <sm/teesmc.h>
32 #include <sm/teesmc_optee.h>
33 #include <arm.h>
34 #include <kernel/thread.h>
35 #include <kernel/panic.h>
36 #include <kernel/pm_stubs.h>
37 #include <malloc.h>
38 #include <util.h>
39 #include <trace.h>
40 #include <kernel/misc.h>
41 #include <mm/tee_pager.h>
42 #include <mm/core_mmu.h>
43 #include <mm/tee_mmu.h>
44 #include <mm/tee_mmu_defs.h>
45 #include <tee/entry.h>
46 #include <tee/arch_svc.h>
47 #include <console.h>
48 #include <asc.h>
49 #include <assert.h>
50 #include <platform_config.h>
51 
52 extern uint8_t __text_init_start[];
53 extern uint8_t __data_start[];
54 extern uint8_t __data_end[];
55 extern uint8_t __bss_start[];
56 extern uint8_t __bss_end[];
57 extern uint8_t __init_start[];
58 extern uint8_t __init_size[];
59 extern uint8_t __heap1_start[];
60 extern uint8_t __heap1_end[];
61 extern uint8_t __heap2_start[];
62 extern uint8_t __heap2_end[];
63 extern uint8_t __pageable_part_start[];
64 extern uint8_t __pageable_part_end[];
65 extern uint8_t __pageable_start[];
66 extern uint8_t __pageable_end[];
67 
68 static void main_fiq(void);
69 static void main_tee_entry(struct thread_smc_args *args);
70 
71 static const struct thread_handlers handlers = {
72 	.std_smc = main_tee_entry,
73 	.fast_smc = main_tee_entry,
74 	.fiq = main_fiq,
75 	.svc = tee_svc_handler,
76 	.abort = tee_pager_abort_handler,
77 	.cpu_on = pm_panic,
78 	.cpu_off = pm_panic,
79 	.cpu_suspend = pm_panic,
80 	.cpu_resume = pm_panic,
81 	.system_off = pm_panic,
82 	.system_reset = pm_panic,
83 };
84 
85 #define PADDR_INVALID		0xffffffff
86 
87 /* May be overridden in plat-$(PLATFORM)/main.c */
88 void main_init_gic(void);
89 __weak void main_init_gic(void)
90 {
91 }
92 
93 #if defined(CFG_WITH_ARM_TRUSTED_FW)
94 static void init_sec_mon(uint32_t nsec_entry __unused)
95 {
96 	assert(nsec_entry == PADDR_INVALID);
97 	/* Do nothing as we don't have a secure monitor */
98 }
99 #else
100 static void init_sec_mon(uint32_t nsec_entry)
101 {
102 	struct sm_nsec_ctx *nsec_ctx;
103 
104 	assert(nsec_entry != PADDR_INVALID);
105 
106 	/* Initialize secure monitor */
107 	nsec_ctx = sm_get_nsec_ctx();
108 	nsec_ctx->mon_lr = nsec_entry;
109 	nsec_ctx->mon_spsr = CPSR_MODE_SVC | CPSR_I;
110 
111 }
112 #endif
113 
114 #if defined(CFG_WITH_ARM_TRUSTED_FW)
115 static void init_nsacr(void)
116 {
117 }
118 #else
119 static void init_nsacr(void)
120 {
121 	/* Normal world can use CP10 and CP11 (SIMD/VFP) */
122 	write_nsacr(read_nsacr() | NSACR_CP10 | NSACR_CP11);
123 }
124 #endif
125 
126 #ifdef CFG_WITH_VFP
127 static void init_cpacr(void)
128 {
129 	uint32_t cpacr = read_cpacr();
130 
131 	/* Enabled usage of CP10 and CP11 (SIMD/VFP) */
132 	cpacr &= ~CPACR_CP(10, CPACR_CP_ACCESS_FULL);
133 	cpacr |= CPACR_CP(10, CPACR_CP_ACCESS_PL1_ONLY);
134 	cpacr &= ~CPACR_CP(11, CPACR_CP_ACCESS_FULL);
135 	cpacr |= CPACR_CP(11, CPACR_CP_ACCESS_PL1_ONLY);
136 	write_cpacr(cpacr);
137 }
138 #else
139 static void init_cpacr(void)
140 {
141 	/* We're not using VFP/SIMD instructions, leave it disabled */
142 }
143 #endif
144 
145 #ifdef CFG_WITH_PAGER
146 
147 static size_t get_block_size(void)
148 {
149 	struct core_mmu_table_info tbl_info;
150 	unsigned l;
151 
152 	if (!core_mmu_find_table(CFG_TEE_RAM_START, UINT_MAX, &tbl_info))
153 		panic();
154 	l = tbl_info.level - 1;
155 	if (!core_mmu_find_table(CFG_TEE_RAM_START, l, &tbl_info))
156 		panic();
157 	return 1 << tbl_info.shift;
158 }
159 
160 static void init_runtime(uint32_t pageable_part)
161 {
162 	size_t n;
163 	size_t init_size = (size_t)__init_size;
164 	size_t pageable_size = __pageable_end - __pageable_start;
165 	size_t hash_size = (pageable_size / SMALL_PAGE_SIZE) *
166 			   TEE_SHA256_HASH_SIZE;
167 	tee_mm_entry_t *mm;
168 	uint8_t *paged_store;
169 	uint8_t *hashes;
170 	uint8_t *tmp_hashes = __init_start + init_size;
171 	size_t block_size;
172 
173 
174 	TEE_ASSERT(pageable_size % SMALL_PAGE_SIZE == 0);
175 
176 
177 	/* Copy it right after the init area. */
178 	memcpy(tmp_hashes, __data_end + init_size, hash_size);
179 
180 	/*
181 	 * Zero BSS area. Note that globals that would normally would go
182 	 * into BSS which are used before this has to be put into .nozi.*
183 	 * to avoid getting overwritten.
184 	 */
185 	memset(__bss_start, 0, __bss_end - __bss_start);
186 
187 	malloc_init(__heap1_start, __heap1_end - __heap1_start);
188 	malloc_add_pool(__heap2_start, __heap2_end - __heap2_start);
189 
190 	hashes = malloc(hash_size);
191 	EMSG("hash_size %zu", hash_size);
192 	TEE_ASSERT(hashes);
193 	memcpy(hashes, tmp_hashes, hash_size);
194 
195 	/*
196 	 * Need tee_mm_sec_ddr initialized to be able to allocate secure
197 	 * DDR below.
198 	 */
199 	teecore_init_ta_ram();
200 
201 	mm = tee_mm_alloc(&tee_mm_sec_ddr, pageable_size);
202 	TEE_ASSERT(mm);
203 	paged_store = (uint8_t *)tee_mm_get_smem(mm);
204 	/* Copy init part into pageable area */
205 	memcpy(paged_store, __init_start, init_size);
206 	/* Copy pageable part after init part into pageable area */
207 	memcpy(paged_store + init_size, (void *)pageable_part,
208 		__pageable_part_end - __pageable_part_start);
209 
210 	/* Check that hashes of what's in pageable area is OK */
211 	DMSG("Checking hashes of pageable area");
212 	for (n = 0; (n * SMALL_PAGE_SIZE) < pageable_size; n++) {
213 		const uint8_t *hash = hashes + n * TEE_SHA256_HASH_SIZE;
214 		const uint8_t *page = paged_store + n * SMALL_PAGE_SIZE;
215 		TEE_Result res;
216 
217 		DMSG("hash pg_idx %zu hash %p page %p", n, hash, page);
218 		res = hash_sha256_check(hash, page, SMALL_PAGE_SIZE);
219 		if (res != TEE_SUCCESS) {
220 			EMSG("Hash failed for page %zu at %p: res 0x%x",
221 				n, page, res);
222 			panic();
223 		}
224 	}
225 
226 	/*
227 	 * Copy what's not initialized in the last init page. Needed
228 	 * because we're not going fault in the init pages again. We can't
229 	 * fault in pages until we've switched to the new vector by calling
230 	 * thread_init_handlers() below.
231 	 */
232 	if (init_size % SMALL_PAGE_SIZE) {
233 		uint8_t *p;
234 
235 		memcpy(__init_start + init_size, paged_store + init_size,
236 			SMALL_PAGE_SIZE - (init_size % SMALL_PAGE_SIZE));
237 
238 		p = (uint8_t *)(((vaddr_t)__init_start + init_size) &
239 				~SMALL_PAGE_MASK);
240 
241 		cache_maintenance_l1(DCACHE_AREA_CLEAN, p, SMALL_PAGE_SIZE);
242 		cache_maintenance_l1(ICACHE_AREA_INVALIDATE, p,
243 				     SMALL_PAGE_SIZE);
244 	}
245 
246 	/*
247 	 * Initialize the virtual memory pool used for main_mmu_l2_ttb which
248 	 * is supplied to tee_pager_init() below.
249 	 */
250 	block_size = get_block_size();
251 	if (!tee_mm_init(&tee_mm_vcore,
252 			ROUNDDOWN(CFG_TEE_RAM_START, block_size),
253 			ROUNDUP(CFG_TEE_RAM_START + CFG_TEE_RAM_VA_SIZE,
254 				block_size),
255 			SMALL_PAGE_SHIFT, 0))
256 		panic();
257 
258 	/*
259 	 * Claim virtual memory which isn't paged, note that there migth be
260 	 * a gap between tee_mm_vcore.lo and TEE_RAM_START which is also
261 	 * claimed to avoid later allocations to get that memory.
262 	 */
263 	mm = tee_mm_alloc2(&tee_mm_vcore, tee_mm_vcore.lo,
264 			(vaddr_t)(__text_init_start - tee_mm_vcore.lo));
265 	TEE_ASSERT(mm);
266 
267 	/*
268 	 * Allocate virtual memory for the pageable area and let the pager
269 	 * take charge of all the pages already assigned to that memory.
270 	 */
271 	mm = tee_mm_alloc2(&tee_mm_vcore, (vaddr_t)__pageable_start,
272 			   pageable_size);
273 	TEE_ASSERT(mm);
274 	tee_pager_add_area(mm, TEE_PAGER_AREA_RO | TEE_PAGER_AREA_X,
275 			   paged_store, hashes);
276 	tee_pager_add_pages((vaddr_t)__pageable_start,
277 		ROUNDUP(init_size, SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE, false);
278 	tee_pager_add_pages((vaddr_t)__pageable_start +
279 				ROUNDUP(init_size, SMALL_PAGE_SIZE),
280 			(pageable_size - ROUNDUP(init_size, SMALL_PAGE_SIZE)) /
281 				SMALL_PAGE_SIZE, true);
282 
283 }
284 #else
285 static void init_runtime(uint32_t pageable_part __unused)
286 {
287 	/*
288 	 * Zero BSS area. Note that globals that would normally would go
289 	 * into BSS which are used before this has to be put into .nozi.*
290 	 * to avoid getting overwritten.
291 	 */
292 	memset(__bss_start, 0, __bss_end - __bss_start);
293 
294 	malloc_init(__heap1_start, __heap1_end - __heap1_start);
295 
296 	/*
297 	 * Initialized at this stage in the pager version of this function
298 	 * above
299 	 */
300 	teecore_init_ta_ram();
301 }
302 #endif
303 
304 static void init_primary_helper(uint32_t nsec_entry)
305 {
306 	/*
307 	 * Mask asynchronous exceptions before switch to the thread vector
308 	 * as the thread handler requires those to be masked while
309 	 * executing with the temporary stack. The thread subsystem also
310 	 * asserts that IRQ is blocked when using most if its functions.
311 	 */
312 	thread_set_exceptions(THREAD_EXCP_ALL);
313 	init_cpacr();
314 
315 	init_runtime(0);
316 
317 	DMSG("TEE initializing\n");
318 
319 	thread_init_primary(&handlers);
320 	thread_init_per_cpu();
321 	init_sec_mon(nsec_entry);
322 
323 
324 	main_init_gic();
325 	init_nsacr();
326 }
327 
328 static void init_secondary_helper(uint32_t nsec_entry)
329 {
330 	/*
331 	 * Mask asynchronous exceptions before switch to the thread vector
332 	 * as the thread handler requires those to be masked while
333 	 * executing with the temporary stack. The thread subsystem also
334 	 * asserts that IRQ is blocked when using most if its functions.
335 	 */
336 	thread_set_exceptions(THREAD_EXCP_ALL);
337 
338 	thread_init_per_cpu();
339 	init_sec_mon(nsec_entry);
340 	init_cpacr();
341 	init_nsacr();
342 
343 	DMSG("Secondary CPU Switching to normal world boot\n");
344 }
345 
346 #if defined(CFG_WITH_ARM_TRUSTED_FW)
347 uint32_t *generic_boot_init_primary(uint32_t pageable_part)
348 {
349 	init_primary_helper(pageable_part, PADDR_INVALID);
350 	return thread_vector_table;
351 }
352 
353 uint32_t generic_boot_cpu_on_handler(uint32_t a0 __unused, uint32_t a1 __unused)
354 {
355 	DMSG("cpu %zu: a0 0x%x", get_core_pos(), a0);
356 	init_secondary_helper(PADDR_INVALID);
357 	return 0;
358 }
359 #else
360 void generic_boot_init_primary(uint32_t nsec_entry);
361 void generic_boot_init_primary(uint32_t nsec_entry)
362 {
363 	init_primary_helper(nsec_entry);
364 }
365 
366 void generic_boot_init_secondary(uint32_t nsec_entry);
367 void generic_boot_init_secondary(uint32_t nsec_entry)
368 {
369 	init_secondary_helper(nsec_entry);
370 }
371 #endif
372 
373 static void main_fiq(void)
374 {
375 	panic();
376 }
377 
378 static void main_tee_entry(struct thread_smc_args *args)
379 {
380 	/* TODO move to main_init() */
381 	if (init_teecore() != TEE_SUCCESS)
382 		panic();
383 
384 	tee_entry(args);
385 }
386 
387 void console_putc(int ch)
388 {
389 	__asc_xmit_char((char)ch);
390 }
391 
392 void console_flush(void)
393 {
394 	__asc_flush();
395 }
396