2 * Copyright (c) 2015, Linaro Limited
4 * Copyright (c) 2014, STMicroelectronics International N.V.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
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.
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.
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>
38 static void tee_entry_get_shm_config(struct thread_smc_args *args)
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();
47 static void tee_entry_fastcall_l2cc_mutex(struct thread_smc_args *args)
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);
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);
62 case OPTEE_SMC_L2CC_MUTEX_ENABLE:
63 ret = tee_enable_l2cc_mutex();
65 case OPTEE_SMC_L2CC_MUTEX_DISABLE:
66 ret = tee_disable_l2cc_mutex();
69 args->a0 = OPTEE_SMC_RETURN_EBADCMD;
73 ret = TEE_ERROR_NOT_SUPPORTED;
75 if (ret == TEE_ERROR_NOT_SUPPORTED)
76 args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION;
78 args->a0 = OPTEE_SMC_RETURN_EBADADDR;
80 args->a0 = OPTEE_SMC_RETURN_OK;
83 static void tee_entry_exchange_capabilities(struct thread_smc_args *args)
86 * Currently we ignore OPTEE_SMC_NSEC_CAP_UNIPROCESSOR.
88 * The memory mapping of shared memory is defined as normal
89 * shared memory for SMP systems and normal memory for UP
90 * systems. Currently we map all memory as shared in secure
93 * When translation tables are created with shared bit cleared for
94 * uniprocessor systems we'll need to check
95 * OPTEE_SMC_NSEC_CAP_UNIPROCESSOR.
98 if (args->a1 & ~OPTEE_SMC_NSEC_CAP_UNIPROCESSOR) {
99 /* Unknown capability. */
100 args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL;
104 args->a0 = OPTEE_SMC_RETURN_OK;
105 args->a1 = OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM;
108 static void tee_entry_disable_shm_cache(struct thread_smc_args *args)
112 if (!thread_disable_prealloc_rpc_cache(&cookie)) {
113 args->a0 = OPTEE_SMC_RETURN_EBUSY;
118 args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL;
122 args->a0 = OPTEE_SMC_RETURN_OK;
123 args->a1 = cookie >> 32;
127 static void tee_entry_enable_shm_cache(struct thread_smc_args *args)
129 if (thread_enable_prealloc_rpc_cache())
130 args->a0 = OPTEE_SMC_RETURN_OK;
132 args->a0 = OPTEE_SMC_RETURN_EBUSY;
135 static void tee_entry_boot_secondary(struct thread_smc_args *args)
137 #if defined(CFG_BOOT_SECONDARY_REQUEST)
138 if (!generic_boot_core_release(args->a1, (paddr_t)(args->a3)))
139 args->a0 = OPTEE_SMC_RETURN_OK;
141 args->a0 = OPTEE_SMC_RETURN_EBADCMD;
143 args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL;
147 void tee_entry_fast(struct thread_smc_args *args)
151 /* Generic functions */
152 case OPTEE_SMC_CALLS_COUNT:
153 tee_entry_get_api_call_count(args);
155 case OPTEE_SMC_CALLS_UID:
156 tee_entry_get_api_uuid(args);
158 case OPTEE_SMC_CALLS_REVISION:
159 tee_entry_get_api_revision(args);
161 case OPTEE_SMC_CALL_GET_OS_UUID:
162 tee_entry_get_os_uuid(args);
164 case OPTEE_SMC_CALL_GET_OS_REVISION:
165 tee_entry_get_os_revision(args);
168 /* OP-TEE specific SMC functions */
169 case OPTEE_SMC_GET_SHM_CONFIG:
170 tee_entry_get_shm_config(args);
172 case OPTEE_SMC_L2CC_MUTEX:
173 tee_entry_fastcall_l2cc_mutex(args);
175 case OPTEE_SMC_EXCHANGE_CAPABILITIES:
176 tee_entry_exchange_capabilities(args);
178 case OPTEE_SMC_DISABLE_SHM_CACHE:
179 tee_entry_disable_shm_cache(args);
181 case OPTEE_SMC_ENABLE_SHM_CACHE:
182 tee_entry_enable_shm_cache(args);
184 case OPTEE_SMC_BOOT_SECONDARY:
185 tee_entry_boot_secondary(args);
189 args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION;
194 size_t tee_entry_generic_get_api_call_count(void)
197 * All the different calls handled in this file. If the specific
198 * target has additional calls it will call this function and
199 * add the number of calls the target has added.
204 void __weak tee_entry_get_api_call_count(struct thread_smc_args *args)
206 args->a0 = tee_entry_generic_get_api_call_count();
209 void __weak tee_entry_get_api_uuid(struct thread_smc_args *args)
211 args->a0 = OPTEE_MSG_UID_0;
212 args->a1 = OPTEE_MSG_UID_1;
213 args->a2 = OPTEE_MSG_UID_2;
214 args->a3 = OPTEE_MSG_UID_3;
217 void __weak tee_entry_get_api_revision(struct thread_smc_args *args)
219 args->a0 = OPTEE_MSG_REVISION_MAJOR;
220 args->a1 = OPTEE_MSG_REVISION_MINOR;
223 void __weak tee_entry_get_os_uuid(struct thread_smc_args *args)
225 args->a0 = OPTEE_MSG_OS_OPTEE_UUID_0;
226 args->a1 = OPTEE_MSG_OS_OPTEE_UUID_1;
227 args->a2 = OPTEE_MSG_OS_OPTEE_UUID_2;
228 args->a3 = OPTEE_MSG_OS_OPTEE_UUID_3;
231 void __weak tee_entry_get_os_revision(struct thread_smc_args *args)
233 args->a0 = CFG_OPTEE_REVISION_MAJOR;
234 args->a1 = CFG_OPTEE_REVISION_MINOR;