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