xref: /optee_os/core/arch/arm/tee/entry_fast.c (revision a31f13fbe554136fa2314c7daf1af9d8b0b0ad8d)
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/tee_l2cc_mutex.h>
34 #include <kernel/panic.h>
35 #include <kernel/misc.h>
36 #include <mm/core_mmu.h>
37 
38 #include <assert.h>
39 
40 static void tee_entry_get_shm_config(struct thread_smc_args *args)
41 {
42 	args->a0 = OPTEE_SMC_RETURN_OK;
43 	args->a1 = default_nsec_shm_paddr;
44 	args->a2 = default_nsec_shm_size;
45 	/* Should this be TEESMC cache attributes instead? */
46 	args->a3 = core_mmu_is_shm_cached();
47 }
48 
49 static void tee_entry_fastcall_l2cc_mutex(struct thread_smc_args *args)
50 {
51 	TEE_Result ret;
52 #ifdef ARM32
53 	paddr_t pa = 0;
54 
55 	switch (args->a1) {
56 	case OPTEE_SMC_L2CC_MUTEX_GET_ADDR:
57 		ret = tee_get_l2cc_mutex(&pa);
58 		reg_pair_from_64(pa, &args->a2, &args->a3);
59 		break;
60 	case OPTEE_SMC_L2CC_MUTEX_SET_ADDR:
61 		pa = reg_pair_to_64(args->a2, args->a3);
62 		ret = tee_set_l2cc_mutex(&pa);
63 		break;
64 	case OPTEE_SMC_L2CC_MUTEX_ENABLE:
65 		ret = tee_enable_l2cc_mutex();
66 		break;
67 	case OPTEE_SMC_L2CC_MUTEX_DISABLE:
68 		ret = tee_disable_l2cc_mutex();
69 		break;
70 	default:
71 		args->a0 = OPTEE_SMC_RETURN_EBADCMD;
72 		return;
73 	}
74 #else
75 	ret = TEE_ERROR_NOT_SUPPORTED;
76 #endif
77 	if (ret == TEE_ERROR_NOT_SUPPORTED)
78 		args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION;
79 	else if (ret)
80 		args->a0 = OPTEE_SMC_RETURN_EBADADDR;
81 	else
82 		args->a0 = OPTEE_SMC_RETURN_OK;
83 }
84 
85 static void tee_entry_exchange_capabilities(struct thread_smc_args *args)
86 {
87 	if (args->a1) {
88 		/*
89 		 * Either unknown capability or
90 		 * OPTEE_SMC_NSEC_CAP_UNIPROCESSOR, in either case we can't
91 		 * deal with it.
92 		 *
93 		 * The memory mapping of shared memory is defined as normal
94 		 * shared memory for SMP systems and normal memory for UP
95 		 * systems. Currently we map all memory as shared in secure
96 		 * world.
97 		 */
98 		args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL;
99 		return;
100 	}
101 
102 	args->a0 = OPTEE_SMC_RETURN_OK;
103 	args->a1 = OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM;
104 }
105 
106 static void tee_entry_disable_shm_cache(struct thread_smc_args *args)
107 {
108 	uint64_t cookie;
109 
110 	if (!thread_disable_prealloc_rpc_cache(&cookie)) {
111 		args->a0 = OPTEE_SMC_RETURN_EBUSY;
112 		return;
113 	}
114 
115 	if (!cookie) {
116 		args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL;
117 		return;
118 	}
119 
120 	args->a0 = OPTEE_SMC_RETURN_OK;
121 	args->a1 = cookie >> 32;
122 	args->a2 = cookie;
123 }
124 
125 static void tee_entry_enable_shm_cache(struct thread_smc_args *args)
126 {
127 	if (thread_enable_prealloc_rpc_cache())
128 		args->a0 = OPTEE_SMC_RETURN_OK;
129 	else
130 		args->a0 = OPTEE_SMC_RETURN_EBUSY;
131 }
132 
133 void tee_entry_fast(struct thread_smc_args *args)
134 {
135 	switch (args->a0) {
136 
137 	/* Generic functions */
138 	case OPTEE_SMC_CALLS_COUNT:
139 		tee_entry_get_api_call_count(args);
140 		break;
141 	case OPTEE_SMC_CALLS_UID:
142 		tee_entry_get_api_uuid(args);
143 		break;
144 	case OPTEE_SMC_CALLS_REVISION:
145 		tee_entry_get_api_revision(args);
146 		break;
147 	case OPTEE_SMC_CALL_GET_OS_UUID:
148 		tee_entry_get_os_uuid(args);
149 		break;
150 	case OPTEE_SMC_CALL_GET_OS_REVISION:
151 		tee_entry_get_os_revision(args);
152 		break;
153 
154 	/* OP-TEE specific SMC functions */
155 	case OPTEE_SMC_GET_SHM_CONFIG:
156 		tee_entry_get_shm_config(args);
157 		break;
158 	case OPTEE_SMC_L2CC_MUTEX:
159 		tee_entry_fastcall_l2cc_mutex(args);
160 		break;
161 	case OPTEE_SMC_EXCHANGE_CAPABILITIES:
162 		tee_entry_exchange_capabilities(args);
163 		break;
164 	case OPTEE_SMC_DISABLE_SHM_CACHE:
165 		tee_entry_disable_shm_cache(args);
166 		break;
167 	case OPTEE_SMC_ENABLE_SHM_CACHE:
168 		tee_entry_enable_shm_cache(args);
169 		break;
170 
171 	default:
172 		args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION;
173 		break;
174 	}
175 }
176 
177 size_t tee_entry_generic_get_api_call_count(void)
178 {
179 	/*
180 	 * All the different calls handled in this file. If the specific
181 	 * target has additional calls it will call this function and
182 	 * add the number of calls the target has added.
183 	 */
184 	return 9;
185 }
186 
187 void __weak tee_entry_get_api_call_count(struct thread_smc_args *args)
188 {
189 	args->a0 = tee_entry_generic_get_api_call_count();
190 }
191 
192 void __weak tee_entry_get_api_uuid(struct thread_smc_args *args)
193 {
194 	args->a0 = OPTEE_MSG_UID_0;
195 	args->a1 = OPTEE_MSG_UID_1;
196 	args->a2 = OPTEE_MSG_UID_2;
197 	args->a3 = OPTEE_MSG_UID_3;
198 }
199 
200 void __weak tee_entry_get_api_revision(struct thread_smc_args *args)
201 {
202 	args->a0 = OPTEE_MSG_REVISION_MAJOR;
203 	args->a1 = OPTEE_MSG_REVISION_MINOR;
204 }
205 
206 void __weak tee_entry_get_os_uuid(struct thread_smc_args *args)
207 {
208 	args->a0 = OPTEE_MSG_OS_OPTEE_UUID_0;
209 	args->a1 = OPTEE_MSG_OS_OPTEE_UUID_1;
210 	args->a2 = OPTEE_MSG_OS_OPTEE_UUID_2;
211 	args->a3 = OPTEE_MSG_OS_OPTEE_UUID_3;
212 }
213 
214 void __weak tee_entry_get_os_revision(struct thread_smc_args *args)
215 {
216 	args->a0 = CFG_OPTEE_REVISION_MAJOR;
217 	args->a1 = CFG_OPTEE_REVISION_MINOR;
218 }
219