xref: /optee_os/core/arch/arm/tee/entry_fast.c (revision 1bb929836182ecb96d2d9d268daa807c67596396)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2015, Linaro Limited
4  * All rights reserved.
5  * Copyright (c) 2014, STMicroelectronics International N.V.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice,
12  * this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include <tee/entry_fast.h>
32 #include <optee_msg.h>
33 #include <sm/optee_smc.h>
34 #include <kernel/generic_boot.h>
35 #include <kernel/tee_l2cc_mutex.h>
36 #include <kernel/misc.h>
37 #include <mm/core_mmu.h>
38 
39 static void tee_entry_get_shm_config(struct thread_smc_args *args)
40 {
41 	args->a0 = OPTEE_SMC_RETURN_OK;
42 	args->a1 = default_nsec_shm_paddr;
43 	args->a2 = default_nsec_shm_size;
44 	/* Should this be TEESMC cache attributes instead? */
45 	args->a3 = core_mmu_is_shm_cached();
46 }
47 
48 static void tee_entry_fastcall_l2cc_mutex(struct thread_smc_args *args)
49 {
50 	TEE_Result ret;
51 #ifdef ARM32
52 	paddr_t pa = 0;
53 
54 	switch (args->a1) {
55 	case OPTEE_SMC_L2CC_MUTEX_GET_ADDR:
56 		ret = tee_get_l2cc_mutex(&pa);
57 		reg_pair_from_64(pa, &args->a2, &args->a3);
58 		break;
59 	case OPTEE_SMC_L2CC_MUTEX_SET_ADDR:
60 		pa = reg_pair_to_64(args->a2, args->a3);
61 		ret = tee_set_l2cc_mutex(&pa);
62 		break;
63 	case OPTEE_SMC_L2CC_MUTEX_ENABLE:
64 		ret = tee_enable_l2cc_mutex();
65 		break;
66 	case OPTEE_SMC_L2CC_MUTEX_DISABLE:
67 		ret = tee_disable_l2cc_mutex();
68 		break;
69 	default:
70 		args->a0 = OPTEE_SMC_RETURN_EBADCMD;
71 		return;
72 	}
73 #else
74 	ret = TEE_ERROR_NOT_SUPPORTED;
75 #endif
76 	if (ret == TEE_ERROR_NOT_SUPPORTED)
77 		args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION;
78 	else if (ret)
79 		args->a0 = OPTEE_SMC_RETURN_EBADADDR;
80 	else
81 		args->a0 = OPTEE_SMC_RETURN_OK;
82 }
83 
84 static void tee_entry_exchange_capabilities(struct thread_smc_args *args)
85 {
86 	bool dyn_shm_en = false;
87 
88 	/*
89 	 * Currently we ignore OPTEE_SMC_NSEC_CAP_UNIPROCESSOR.
90 	 *
91 	 * The memory mapping of shared memory is defined as normal
92 	 * shared memory for SMP systems and normal memory for UP
93 	 * systems. Currently we map all memory as shared in secure
94 	 * world.
95 	 *
96 	 * When translation tables are created with shared bit cleared for
97 	 * uniprocessor systems we'll need to check
98 	 * OPTEE_SMC_NSEC_CAP_UNIPROCESSOR.
99 	 */
100 
101 	if (args->a1 & ~OPTEE_SMC_NSEC_CAP_UNIPROCESSOR) {
102 		/* Unknown capability. */
103 		args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL;
104 		return;
105 	}
106 
107 	args->a0 = OPTEE_SMC_RETURN_OK;
108 	args->a1 = OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM;
109 
110 #if defined(CFG_DYN_SHM_CAP)
111 	dyn_shm_en = core_mmu_nsec_ddr_is_defined();
112 	if (dyn_shm_en)
113 		args->a1 |= OPTEE_SMC_SEC_CAP_DYNAMIC_SHM;
114 #endif
115 
116 	IMSG("Dynamic shared memory is %sabled", dyn_shm_en ? "en" : "dis");
117 }
118 
119 static void tee_entry_disable_shm_cache(struct thread_smc_args *args)
120 {
121 	uint64_t cookie;
122 
123 	if (!thread_disable_prealloc_rpc_cache(&cookie)) {
124 		args->a0 = OPTEE_SMC_RETURN_EBUSY;
125 		return;
126 	}
127 
128 	if (!cookie) {
129 		args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL;
130 		return;
131 	}
132 
133 	args->a0 = OPTEE_SMC_RETURN_OK;
134 	args->a1 = cookie >> 32;
135 	args->a2 = cookie;
136 }
137 
138 static void tee_entry_enable_shm_cache(struct thread_smc_args *args)
139 {
140 	if (thread_enable_prealloc_rpc_cache())
141 		args->a0 = OPTEE_SMC_RETURN_OK;
142 	else
143 		args->a0 = OPTEE_SMC_RETURN_EBUSY;
144 }
145 
146 static void tee_entry_boot_secondary(struct thread_smc_args *args)
147 {
148 #if defined(CFG_BOOT_SECONDARY_REQUEST)
149 	if (!generic_boot_core_release(args->a1, (paddr_t)(args->a3)))
150 		args->a0 = OPTEE_SMC_RETURN_OK;
151 	else
152 		args->a0 = OPTEE_SMC_RETURN_EBADCMD;
153 #else
154 	args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL;
155 #endif
156 }
157 
158 void tee_entry_fast(struct thread_smc_args *args)
159 {
160 	switch (args->a0) {
161 
162 	/* Generic functions */
163 	case OPTEE_SMC_CALLS_COUNT:
164 		tee_entry_get_api_call_count(args);
165 		break;
166 	case OPTEE_SMC_CALLS_UID:
167 		tee_entry_get_api_uuid(args);
168 		break;
169 	case OPTEE_SMC_CALLS_REVISION:
170 		tee_entry_get_api_revision(args);
171 		break;
172 	case OPTEE_SMC_CALL_GET_OS_UUID:
173 		tee_entry_get_os_uuid(args);
174 		break;
175 	case OPTEE_SMC_CALL_GET_OS_REVISION:
176 		tee_entry_get_os_revision(args);
177 		break;
178 
179 	/* OP-TEE specific SMC functions */
180 	case OPTEE_SMC_GET_SHM_CONFIG:
181 		tee_entry_get_shm_config(args);
182 		break;
183 	case OPTEE_SMC_L2CC_MUTEX:
184 		tee_entry_fastcall_l2cc_mutex(args);
185 		break;
186 	case OPTEE_SMC_EXCHANGE_CAPABILITIES:
187 		tee_entry_exchange_capabilities(args);
188 		break;
189 	case OPTEE_SMC_DISABLE_SHM_CACHE:
190 		tee_entry_disable_shm_cache(args);
191 		break;
192 	case OPTEE_SMC_ENABLE_SHM_CACHE:
193 		tee_entry_enable_shm_cache(args);
194 		break;
195 	case OPTEE_SMC_BOOT_SECONDARY:
196 		tee_entry_boot_secondary(args);
197 		break;
198 
199 	default:
200 		args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION;
201 		break;
202 	}
203 }
204 
205 size_t tee_entry_generic_get_api_call_count(void)
206 {
207 	/*
208 	 * All the different calls handled in this file. If the specific
209 	 * target has additional calls it will call this function and
210 	 * add the number of calls the target has added.
211 	 */
212 	return 9;
213 }
214 
215 void __weak tee_entry_get_api_call_count(struct thread_smc_args *args)
216 {
217 	args->a0 = tee_entry_generic_get_api_call_count();
218 }
219 
220 void __weak tee_entry_get_api_uuid(struct thread_smc_args *args)
221 {
222 	args->a0 = OPTEE_MSG_UID_0;
223 	args->a1 = OPTEE_MSG_UID_1;
224 	args->a2 = OPTEE_MSG_UID_2;
225 	args->a3 = OPTEE_MSG_UID_3;
226 }
227 
228 void __weak tee_entry_get_api_revision(struct thread_smc_args *args)
229 {
230 	args->a0 = OPTEE_MSG_REVISION_MAJOR;
231 	args->a1 = OPTEE_MSG_REVISION_MINOR;
232 }
233 
234 void __weak tee_entry_get_os_uuid(struct thread_smc_args *args)
235 {
236 	args->a0 = OPTEE_MSG_OS_OPTEE_UUID_0;
237 	args->a1 = OPTEE_MSG_OS_OPTEE_UUID_1;
238 	args->a2 = OPTEE_MSG_OS_OPTEE_UUID_2;
239 	args->a3 = OPTEE_MSG_OS_OPTEE_UUID_3;
240 }
241 
242 void __weak tee_entry_get_os_revision(struct thread_smc_args *args)
243 {
244 	args->a0 = CFG_OPTEE_REVISION_MAJOR;
245 	args->a1 = CFG_OPTEE_REVISION_MINOR;
246 	args->a2 = TEE_IMPL_GIT_SHA1;
247 }
248