xref: /optee_os/core/arch/arm/plat-stm/main.c (revision c61c04b837302c854a3c9f650118dd7be548302b)
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 <malloc.h>
37 #include <util.h>
38 #include <trace.h>
39 #include <kernel/misc.h>
40 #include <mm/tee_pager.h>
41 #include <mm/core_mmu.h>
42 #include <mm/tee_mmu.h>
43 #include <mm/tee_mmu_defs.h>
44 #include <tee/entry.h>
45 #include <tee/arch_svc.h>
46 #include <console.h>
47 #include <asc.h>
48 #include <kernel/tee_l2cc_mutex.h>
49 #include <assert.h>
50 #include <platform_config.h>
51 
52 /* teecore heap address/size is defined in scatter file */
53 extern unsigned char teecore_heap_start;
54 extern unsigned char teecore_heap_end;
55 
56 
57 static void main_fiq(void);
58 static void main_tee_entry(struct thread_smc_args *args);
59 static uint32_t main_default_pm_handler(uint32_t a0, uint32_t a1);
60 
61 static const struct thread_handlers handlers = {
62 	.std_smc = main_tee_entry,
63 	.fast_smc = main_tee_entry,
64 	.fiq = main_fiq,
65 	.svc = tee_svc_handler,
66 	.abort = tee_pager_abort_handler,
67 	.cpu_on = main_default_pm_handler,
68 	.cpu_off = main_default_pm_handler,
69 	.cpu_suspend = main_default_pm_handler,
70 	.cpu_resume = main_default_pm_handler,
71 	.system_off = main_default_pm_handler,
72 	.system_reset = main_default_pm_handler,
73 };
74 
75 void main_init(uint32_t nsec_entry); /* called from assembly only */
76 void main_init(uint32_t nsec_entry)
77 {
78 	struct sm_nsec_ctx *nsec_ctx;
79 	size_t pos = get_core_pos();
80 
81 	/*
82 	 * Mask IRQ and FIQ before switch to the thread vector as the
83 	 * thread handler requires IRQ and FIQ to be masked while executing
84 	 * with the temporary stack. The thread subsystem also asserts that
85 	 * IRQ is blocked when using most if its functions.
86 	 */
87 	write_cpsr(read_cpsr() | CPSR_F | CPSR_I);
88 
89 	if (pos == 0)
90 		thread_init_primary(&handlers);
91 
92 	thread_init_per_cpu();
93 
94 	/* Initialize secure monitor */
95 	nsec_ctx = sm_get_nsec_ctx();
96 	nsec_ctx->mon_lr = nsec_entry;
97 	nsec_ctx->mon_spsr = CPSR_MODE_SVC | CPSR_I;
98 
99 	if (pos == 0) {
100 		unsigned long a, s;
101 		/* core malloc pool init */
102 #ifdef CFG_TEE_MALLOC_START
103 		a = CFG_TEE_MALLOC_START;
104 		s = CFG_TEE_MALLOC_SIZE;
105 #else
106 		a = (unsigned long)&teecore_heap_start;
107 		s = (unsigned long)&teecore_heap_end;
108 		a = ((a + 1) & ~0x0FFFF) + 0x10000;	/* 64kB aligned */
109 		s = s & ~0x0FFFF;	/* 64kB aligned */
110 		s = s - a;
111 #endif
112 		malloc_init((void *)a, s);
113 
114 		teecore_init_ta_ram();
115 	}
116 }
117 
118 static void main_fiq(void)
119 {
120 	panic();
121 }
122 
123 static uint32_t main_default_pm_handler(uint32_t a0, uint32_t a1)
124 {
125 	/*
126 	 * This function is not supported in this configuration, and
127 	 * should never be called. Panic to catch unintended calls.
128 	 */
129 	(void)&a0;
130 	(void)&a1;
131 	panic();
132 	return 1;
133 }
134 
135 static void main_tee_entry(struct thread_smc_args *args)
136 {
137 	/*
138 	 * This function first catches all ST specific SMC functions
139 	 * if none matches, the generic tee_entry is called.
140 	 */
141 	int ret;
142 
143 	/* TODO move to main_init() */
144 	if (init_teecore() != TEE_SUCCESS)
145 		panic();
146 
147 	if (args->a0 == TEESMC32_OPTEE_FASTCALL_GET_SHM_CONFIG) {
148 		args->a0 = TEESMC_RETURN_OK;
149 		args->a1 = default_nsec_shm_paddr;
150 		args->a2 = default_nsec_shm_size;
151 		/* Should this be TEESMC cache attributes instead? */
152 		args->a3 = core_mmu_is_shm_cached();
153 		return;
154 	}
155 
156 	if (args->a0 == TEESMC32_OPTEE_FASTCALL_L2CC_MUTEX) {
157 		switch (args->a1) {
158 		case TEESMC_OPTEE_L2CC_MUTEX_GET_ADDR:
159 			ret = tee_l2cc_mutex_configure(
160 					SERVICEID_GET_L2CC_MUTEX, &args->a2);
161 			break;
162 		case TEESMC_OPTEE_L2CC_MUTEX_SET_ADDR:
163 			ret = tee_l2cc_mutex_configure(
164 					SERVICEID_SET_L2CC_MUTEX, &args->a2);
165 			break;
166 		case TEESMC_OPTEE_L2CC_MUTEX_ENABLE:
167 			ret = tee_l2cc_mutex_configure(
168 					SERVICEID_ENABLE_L2CC_MUTEX, NULL);
169 			break;
170 		case TEESMC_OPTEE_L2CC_MUTEX_DISABLE:
171 			ret = tee_l2cc_mutex_configure(
172 					SERVICEID_DISABLE_L2CC_MUTEX, NULL);
173 			break;
174 		default:
175 			args->a0 = TEESMC_RETURN_EBADCMD;
176 			return;
177 		}
178 		if (ret)
179 			args->a0 = TEESMC_RETURN_EBADADDR;
180 		else
181 			args->a0 = TEESMC_RETURN_OK;
182 		return;
183 	}
184 
185 	tee_entry(args);
186 }
187 
188 
189 /* Override weak function in tee/entry.c */
190 void tee_entry_get_api_call_count(struct thread_smc_args *args)
191 {
192 	args->a0 = tee_entry_generic_get_api_call_count() + 2;
193 }
194 
195 /* Override weak function in tee/entry.c */
196 void tee_entry_get_api_uuid(struct thread_smc_args *args)
197 {
198 	args->a0 = TEESMC_OPTEE_UID_R0;
199 	args->a1 = TEESMC_OPTEE_UID_R1;
200 	args->a2 = TEESMC_OPTEE_UID_R2;
201 	args->a3 = TEESMC_OPTEE_UID32_R3;
202 }
203 
204 /* Override weak function in tee/entry.c */
205 void tee_entry_get_api_revision(struct thread_smc_args *args)
206 {
207 	args->a0 = TEESMC_OPTEE_REVISION_MAJOR;
208 	args->a1 = TEESMC_OPTEE_REVISION_MINOR;
209 }
210 
211 /* Override weak function in tee/entry.c */
212 void tee_entry_get_os_uuid(struct thread_smc_args *args)
213 {
214 	args->a0 = TEESMC_OS_OPTEE_UUID_R0;
215 	args->a1 = TEESMC_OS_OPTEE_UUID_R1;
216 	args->a2 = TEESMC_OS_OPTEE_UUID_R2;
217 	args->a3 = TEESMC_OS_OPTEE_UUID_R3;
218 }
219 
220 /* Override weak function in tee/entry.c */
221 void tee_entry_get_os_revision(struct thread_smc_args *args)
222 {
223 	args->a0 = TEESMC_OS_OPTEE_REVISION_MAJOR;
224 	args->a1 = TEESMC_OS_OPTEE_REVISION_MINOR;
225 }
226 
227 /* ttbr1 for teecore mapping: 16kB, fixed addr. */
228 extern uint8_t *SEC_MMU_TTB_FLD;
229 /* ttbr0 for TA mapping (default was 128kB) */
230 extern uint8_t *SEC_TA_MMU_TTB_FLD;
231 
232 paddr_t core_mmu_get_main_ttb_pa(void)
233 {
234 	/* Note that this depends on flat mapping of TEE Core */
235 	paddr_t pa = (paddr_t)core_mmu_get_main_ttb_va();
236 
237 	TEE_ASSERT(!(pa & ~TEE_MMU_TTB_L1_MASK));
238 	return pa;
239 }
240 
241 vaddr_t core_mmu_get_main_ttb_va(void)
242 {
243 	return (vaddr_t)&SEC_MMU_TTB_FLD;
244 }
245 
246 paddr_t core_mmu_get_ul1_ttb_pa(void)
247 {
248 	/* Note that this depends on flat mapping of TEE Core */
249 	paddr_t pa = (paddr_t)core_mmu_get_ul1_ttb_va();
250 	TEE_ASSERT(!(pa & ~TEE_MMU_TTB_UL1_MASK));
251 	return pa;
252 }
253 
254 vaddr_t core_mmu_get_ul1_ttb_va(void)
255 {
256 	return (vaddr_t)&SEC_TA_MMU_TTB_FLD;
257 }
258 
259 void console_putc(int ch)
260 {
261 	__asc_xmit_char((char)ch);
262 }
263 
264 void console_flush(void)
265 {
266 	__asc_flush();
267 }
268 
269 /* L2 translation table(s) for teecore mapping: fixed addr. */
270 extern uint8_t *SEC_MMU_L2_TTB_FLD;
271 extern uint8_t *SEC_MMU_L2_TTB_END;
272 
273 void *core_mmu_alloc_l2(struct tee_mmap_region *mm)
274 {
275 	/* Can't have this in .bss since it's not initialized yet */
276 	static size_t l2_offs __attribute__((section(".data")));
277 	const size_t l2_size = SEC_MMU_L2_TTB_END - SEC_MMU_L2_TTB_FLD;
278 	const size_t l2_va_size = TEE_MMU_L2_NUM_ENTRIES * SMALL_PAGE_SIZE;
279 	size_t l2_va_space = ((l2_size - l2_offs) / TEE_MMU_L2_SIZE) *
280 				l2_va_size;
281 
282 	if (l2_offs)
283 		return NULL;
284 	if (mm->size > l2_va_space)
285 		return NULL;
286 	l2_offs += ROUNDUP(mm->size, l2_va_size) / l2_va_size;
287 	return SEC_MMU_L2_TTB_FLD;
288 }
289