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