xref: /optee_os/core/arch/arm/tee/entry_fast.c (revision a1d5c81f8834a9d2c6f4372cce2e59e70e709121)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2015, Linaro Limited
4  * Copyright (c) 2014, STMicroelectronics International N.V.
5  */
6 
7 #include <tee/entry_fast.h>
8 #include <optee_msg.h>
9 #include <sm/optee_smc.h>
10 #include <kernel/boot.h>
11 #include <kernel/tee_l2cc_mutex.h>
12 #include <kernel/virtualization.h>
13 #include <kernel/misc.h>
14 #include <mm/core_mmu.h>
15 
16 #ifdef CFG_CORE_RESERVED_SHM
17 static void tee_entry_get_shm_config(struct thread_smc_args *args)
18 {
19 	args->a0 = OPTEE_SMC_RETURN_OK;
20 	args->a1 = default_nsec_shm_paddr;
21 	args->a2 = default_nsec_shm_size;
22 	/* Should this be TEESMC cache attributes instead? */
23 	args->a3 = core_mmu_is_shm_cached();
24 }
25 #endif
26 
27 static void tee_entry_fastcall_l2cc_mutex(struct thread_smc_args *args)
28 {
29 	TEE_Result ret;
30 #ifdef ARM32
31 	paddr_t pa = 0;
32 
33 	switch (args->a1) {
34 	case OPTEE_SMC_L2CC_MUTEX_GET_ADDR:
35 		ret = tee_get_l2cc_mutex(&pa);
36 		reg_pair_from_64(pa, &args->a2, &args->a3);
37 		break;
38 	case OPTEE_SMC_L2CC_MUTEX_SET_ADDR:
39 		pa = reg_pair_to_64(args->a2, args->a3);
40 		ret = tee_set_l2cc_mutex(&pa);
41 		break;
42 	case OPTEE_SMC_L2CC_MUTEX_ENABLE:
43 		ret = tee_enable_l2cc_mutex();
44 		break;
45 	case OPTEE_SMC_L2CC_MUTEX_DISABLE:
46 		ret = tee_disable_l2cc_mutex();
47 		break;
48 	default:
49 		args->a0 = OPTEE_SMC_RETURN_EBADCMD;
50 		return;
51 	}
52 #else
53 	ret = TEE_ERROR_NOT_SUPPORTED;
54 #endif
55 	if (ret == TEE_ERROR_NOT_SUPPORTED)
56 		args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION;
57 	else if (ret)
58 		args->a0 = OPTEE_SMC_RETURN_EBADADDR;
59 	else
60 		args->a0 = OPTEE_SMC_RETURN_OK;
61 }
62 
63 static void tee_entry_exchange_capabilities(struct thread_smc_args *args)
64 {
65 	bool dyn_shm_en __maybe_unused = false;
66 
67 	/*
68 	 * Currently we ignore OPTEE_SMC_NSEC_CAP_UNIPROCESSOR.
69 	 *
70 	 * The memory mapping of shared memory is defined as normal
71 	 * shared memory for SMP systems and normal memory for UP
72 	 * systems. Currently we map all memory as shared in secure
73 	 * world.
74 	 *
75 	 * When translation tables are created with shared bit cleared for
76 	 * uniprocessor systems we'll need to check
77 	 * OPTEE_SMC_NSEC_CAP_UNIPROCESSOR.
78 	 */
79 
80 	if (args->a1 & ~OPTEE_SMC_NSEC_CAP_UNIPROCESSOR) {
81 		/* Unknown capability. */
82 		args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL;
83 		return;
84 	}
85 
86 	args->a0 = OPTEE_SMC_RETURN_OK;
87 	args->a1 = 0;
88 #ifdef CFG_CORE_RESERVED_SHM
89 	args->a1 |= OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM;
90 #endif
91 #ifdef CFG_VIRTUALIZATION
92 	args->a1 |= OPTEE_SMC_SEC_CAP_VIRTUALIZATION;
93 #endif
94 	args->a1 |= OPTEE_SMC_SEC_CAP_MEMREF_NULL;
95 
96 #if defined(CFG_CORE_DYN_SHM)
97 	dyn_shm_en = core_mmu_nsec_ddr_is_defined();
98 	if (dyn_shm_en)
99 		args->a1 |= OPTEE_SMC_SEC_CAP_DYNAMIC_SHM;
100 #endif
101 
102 	DMSG("Dynamic shared memory is %sabled", dyn_shm_en ? "en" : "dis");
103 }
104 
105 static void tee_entry_disable_shm_cache(struct thread_smc_args *args)
106 {
107 	uint64_t cookie;
108 
109 	if (!thread_disable_prealloc_rpc_cache(&cookie)) {
110 		args->a0 = OPTEE_SMC_RETURN_EBUSY;
111 		return;
112 	}
113 
114 	if (!cookie) {
115 		args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL;
116 		return;
117 	}
118 
119 	args->a0 = OPTEE_SMC_RETURN_OK;
120 	args->a1 = cookie >> 32;
121 	args->a2 = cookie;
122 }
123 
124 static void tee_entry_enable_shm_cache(struct thread_smc_args *args)
125 {
126 	if (thread_enable_prealloc_rpc_cache())
127 		args->a0 = OPTEE_SMC_RETURN_OK;
128 	else
129 		args->a0 = OPTEE_SMC_RETURN_EBUSY;
130 }
131 
132 static void tee_entry_boot_secondary(struct thread_smc_args *args)
133 {
134 #if defined(CFG_BOOT_SECONDARY_REQUEST)
135 	if (!boot_core_release(args->a1, (paddr_t)(args->a3)))
136 		args->a0 = OPTEE_SMC_RETURN_OK;
137 	else
138 		args->a0 = OPTEE_SMC_RETURN_EBADCMD;
139 #else
140 	args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL;
141 #endif
142 }
143 
144 static void tee_entry_get_thread_count(struct thread_smc_args *args)
145 {
146 	args->a0 = OPTEE_SMC_RETURN_OK;
147 	args->a1 = CFG_NUM_THREADS;
148 }
149 
150 #if defined(CFG_VIRTUALIZATION)
151 static void tee_entry_vm_created(struct thread_smc_args *args)
152 {
153 	uint16_t guest_id = args->a1;
154 
155 	/* Only hypervisor can issue this request */
156 	if (args->a7 != HYP_CLNT_ID) {
157 		args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL;
158 		return;
159 	}
160 
161 	args->a0 = virt_guest_created(guest_id);
162 }
163 
164 static void tee_entry_vm_destroyed(struct thread_smc_args *args)
165 {
166 	uint16_t guest_id = args->a1;
167 
168 	/* Only hypervisor can issue this request */
169 	if (args->a7 != HYP_CLNT_ID) {
170 		args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL;
171 		return;
172 	}
173 
174 	args->a0 = virt_guest_destroyed(guest_id);
175 }
176 #endif
177 
178 /* Note: this function is weak to let platforms add special handling */
179 void __weak tee_entry_fast(struct thread_smc_args *args)
180 {
181 	__tee_entry_fast(args);
182 }
183 
184 /*
185  * If tee_entry_fast() is overridden, it's still supposed to call this
186  * function.
187  */
188 void __tee_entry_fast(struct thread_smc_args *args)
189 {
190 	switch (args->a0) {
191 
192 	/* Generic functions */
193 	case OPTEE_SMC_CALLS_COUNT:
194 		tee_entry_get_api_call_count(args);
195 		break;
196 	case OPTEE_SMC_CALLS_UID:
197 		tee_entry_get_api_uuid(args);
198 		break;
199 	case OPTEE_SMC_CALLS_REVISION:
200 		tee_entry_get_api_revision(args);
201 		break;
202 	case OPTEE_SMC_CALL_GET_OS_UUID:
203 		tee_entry_get_os_uuid(args);
204 		break;
205 	case OPTEE_SMC_CALL_GET_OS_REVISION:
206 		tee_entry_get_os_revision(args);
207 		break;
208 
209 	/* OP-TEE specific SMC functions */
210 #ifdef CFG_CORE_RESERVED_SHM
211 	case OPTEE_SMC_GET_SHM_CONFIG:
212 		tee_entry_get_shm_config(args);
213 		break;
214 #endif
215 	case OPTEE_SMC_L2CC_MUTEX:
216 		tee_entry_fastcall_l2cc_mutex(args);
217 		break;
218 	case OPTEE_SMC_EXCHANGE_CAPABILITIES:
219 		tee_entry_exchange_capabilities(args);
220 		break;
221 	case OPTEE_SMC_DISABLE_SHM_CACHE:
222 		tee_entry_disable_shm_cache(args);
223 		break;
224 	case OPTEE_SMC_ENABLE_SHM_CACHE:
225 		tee_entry_enable_shm_cache(args);
226 		break;
227 	case OPTEE_SMC_BOOT_SECONDARY:
228 		tee_entry_boot_secondary(args);
229 		break;
230 	case OPTEE_SMC_GET_THREAD_COUNT:
231 		tee_entry_get_thread_count(args);
232 		break;
233 
234 #if defined(CFG_VIRTUALIZATION)
235 	case OPTEE_SMC_VM_CREATED:
236 		tee_entry_vm_created(args);
237 		break;
238 	case OPTEE_SMC_VM_DESTROYED:
239 		tee_entry_vm_destroyed(args);
240 		break;
241 #endif
242 
243 	default:
244 		args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION;
245 		break;
246 	}
247 }
248 
249 size_t tee_entry_generic_get_api_call_count(void)
250 {
251 	/*
252 	 * All the different calls handled in this file. If the specific
253 	 * target has additional calls it will call this function and
254 	 * add the number of calls the target has added.
255 	 */
256 	size_t ret = 12;
257 
258 #if defined(CFG_VIRTUALIZATION)
259 	ret += 2;
260 #endif
261 
262 	return ret;
263 }
264 
265 void __weak tee_entry_get_api_call_count(struct thread_smc_args *args)
266 {
267 	args->a0 = tee_entry_generic_get_api_call_count();
268 }
269 
270 void __weak tee_entry_get_api_uuid(struct thread_smc_args *args)
271 {
272 	args->a0 = OPTEE_MSG_UID_0;
273 	args->a1 = OPTEE_MSG_UID_1;
274 	args->a2 = OPTEE_MSG_UID_2;
275 	args->a3 = OPTEE_MSG_UID_3;
276 }
277 
278 void __weak tee_entry_get_api_revision(struct thread_smc_args *args)
279 {
280 	args->a0 = OPTEE_MSG_REVISION_MAJOR;
281 	args->a1 = OPTEE_MSG_REVISION_MINOR;
282 }
283 
284 void __weak tee_entry_get_os_uuid(struct thread_smc_args *args)
285 {
286 	args->a0 = OPTEE_MSG_OS_OPTEE_UUID_0;
287 	args->a1 = OPTEE_MSG_OS_OPTEE_UUID_1;
288 	args->a2 = OPTEE_MSG_OS_OPTEE_UUID_2;
289 	args->a3 = OPTEE_MSG_OS_OPTEE_UUID_3;
290 }
291 
292 void __weak tee_entry_get_os_revision(struct thread_smc_args *args)
293 {
294 	args->a0 = CFG_OPTEE_REVISION_MAJOR;
295 	args->a1 = CFG_OPTEE_REVISION_MINOR;
296 	args->a2 = TEE_IMPL_GIT_SHA1;
297 }
298