xref: /optee_os/core/arch/arm/tee/entry_fast.c (revision 18c5148d357e51235bc842b7826ff6e8da109902)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2015, Linaro Limited
4  * Copyright (c) 2014, STMicroelectronics International N.V.
5  */
6 
7 #include <tee/entry_fast.h>
8 #include <optee_msg.h>
9 #include <sm/optee_smc.h>
10 #include <kernel/generic_boot.h>
11 #include <kernel/tee_l2cc_mutex.h>
12 #include <kernel/misc.h>
13 #include <mm/core_mmu.h>
14 
15 static void tee_entry_get_shm_config(struct thread_smc_args *args)
16 {
17 	args->a0 = OPTEE_SMC_RETURN_OK;
18 	args->a1 = default_nsec_shm_paddr;
19 	args->a2 = default_nsec_shm_size;
20 	/* Should this be TEESMC cache attributes instead? */
21 	args->a3 = core_mmu_is_shm_cached();
22 }
23 
24 static void tee_entry_fastcall_l2cc_mutex(struct thread_smc_args *args)
25 {
26 	TEE_Result ret;
27 #ifdef ARM32
28 	paddr_t pa = 0;
29 
30 	switch (args->a1) {
31 	case OPTEE_SMC_L2CC_MUTEX_GET_ADDR:
32 		ret = tee_get_l2cc_mutex(&pa);
33 		reg_pair_from_64(pa, &args->a2, &args->a3);
34 		break;
35 	case OPTEE_SMC_L2CC_MUTEX_SET_ADDR:
36 		pa = reg_pair_to_64(args->a2, args->a3);
37 		ret = tee_set_l2cc_mutex(&pa);
38 		break;
39 	case OPTEE_SMC_L2CC_MUTEX_ENABLE:
40 		ret = tee_enable_l2cc_mutex();
41 		break;
42 	case OPTEE_SMC_L2CC_MUTEX_DISABLE:
43 		ret = tee_disable_l2cc_mutex();
44 		break;
45 	default:
46 		args->a0 = OPTEE_SMC_RETURN_EBADCMD;
47 		return;
48 	}
49 #else
50 	ret = TEE_ERROR_NOT_SUPPORTED;
51 #endif
52 	if (ret == TEE_ERROR_NOT_SUPPORTED)
53 		args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION;
54 	else if (ret)
55 		args->a0 = OPTEE_SMC_RETURN_EBADADDR;
56 	else
57 		args->a0 = OPTEE_SMC_RETURN_OK;
58 }
59 
60 static void tee_entry_exchange_capabilities(struct thread_smc_args *args)
61 {
62 	bool dyn_shm_en = false;
63 
64 	/*
65 	 * Currently we ignore OPTEE_SMC_NSEC_CAP_UNIPROCESSOR.
66 	 *
67 	 * The memory mapping of shared memory is defined as normal
68 	 * shared memory for SMP systems and normal memory for UP
69 	 * systems. Currently we map all memory as shared in secure
70 	 * world.
71 	 *
72 	 * When translation tables are created with shared bit cleared for
73 	 * uniprocessor systems we'll need to check
74 	 * OPTEE_SMC_NSEC_CAP_UNIPROCESSOR.
75 	 */
76 
77 	if (args->a1 & ~OPTEE_SMC_NSEC_CAP_UNIPROCESSOR) {
78 		/* Unknown capability. */
79 		args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL;
80 		return;
81 	}
82 
83 	args->a0 = OPTEE_SMC_RETURN_OK;
84 	args->a1 = OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM;
85 
86 #if defined(CFG_DYN_SHM_CAP)
87 	dyn_shm_en = core_mmu_nsec_ddr_is_defined();
88 	if (dyn_shm_en)
89 		args->a1 |= OPTEE_SMC_SEC_CAP_DYNAMIC_SHM;
90 #endif
91 
92 	IMSG("Dynamic shared memory is %sabled", dyn_shm_en ? "en" : "dis");
93 }
94 
95 static void tee_entry_disable_shm_cache(struct thread_smc_args *args)
96 {
97 	uint64_t cookie;
98 
99 	if (!thread_disable_prealloc_rpc_cache(&cookie)) {
100 		args->a0 = OPTEE_SMC_RETURN_EBUSY;
101 		return;
102 	}
103 
104 	if (!cookie) {
105 		args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL;
106 		return;
107 	}
108 
109 	args->a0 = OPTEE_SMC_RETURN_OK;
110 	args->a1 = cookie >> 32;
111 	args->a2 = cookie;
112 }
113 
114 static void tee_entry_enable_shm_cache(struct thread_smc_args *args)
115 {
116 	if (thread_enable_prealloc_rpc_cache())
117 		args->a0 = OPTEE_SMC_RETURN_OK;
118 	else
119 		args->a0 = OPTEE_SMC_RETURN_EBUSY;
120 }
121 
122 static void tee_entry_boot_secondary(struct thread_smc_args *args)
123 {
124 #if defined(CFG_BOOT_SECONDARY_REQUEST)
125 	if (!generic_boot_core_release(args->a1, (paddr_t)(args->a3)))
126 		args->a0 = OPTEE_SMC_RETURN_OK;
127 	else
128 		args->a0 = OPTEE_SMC_RETURN_EBADCMD;
129 #else
130 	args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL;
131 #endif
132 }
133 
134 void tee_entry_fast(struct thread_smc_args *args)
135 {
136 	switch (args->a0) {
137 
138 	/* Generic functions */
139 	case OPTEE_SMC_CALLS_COUNT:
140 		tee_entry_get_api_call_count(args);
141 		break;
142 	case OPTEE_SMC_CALLS_UID:
143 		tee_entry_get_api_uuid(args);
144 		break;
145 	case OPTEE_SMC_CALLS_REVISION:
146 		tee_entry_get_api_revision(args);
147 		break;
148 	case OPTEE_SMC_CALL_GET_OS_UUID:
149 		tee_entry_get_os_uuid(args);
150 		break;
151 	case OPTEE_SMC_CALL_GET_OS_REVISION:
152 		tee_entry_get_os_revision(args);
153 		break;
154 
155 	/* OP-TEE specific SMC functions */
156 	case OPTEE_SMC_GET_SHM_CONFIG:
157 		tee_entry_get_shm_config(args);
158 		break;
159 	case OPTEE_SMC_L2CC_MUTEX:
160 		tee_entry_fastcall_l2cc_mutex(args);
161 		break;
162 	case OPTEE_SMC_EXCHANGE_CAPABILITIES:
163 		tee_entry_exchange_capabilities(args);
164 		break;
165 	case OPTEE_SMC_DISABLE_SHM_CACHE:
166 		tee_entry_disable_shm_cache(args);
167 		break;
168 	case OPTEE_SMC_ENABLE_SHM_CACHE:
169 		tee_entry_enable_shm_cache(args);
170 		break;
171 	case OPTEE_SMC_BOOT_SECONDARY:
172 		tee_entry_boot_secondary(args);
173 		break;
174 
175 	default:
176 		args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION;
177 		break;
178 	}
179 }
180 
181 size_t tee_entry_generic_get_api_call_count(void)
182 {
183 	/*
184 	 * All the different calls handled in this file. If the specific
185 	 * target has additional calls it will call this function and
186 	 * add the number of calls the target has added.
187 	 */
188 	return 11;
189 }
190 
191 void __weak tee_entry_get_api_call_count(struct thread_smc_args *args)
192 {
193 	args->a0 = tee_entry_generic_get_api_call_count();
194 }
195 
196 void __weak tee_entry_get_api_uuid(struct thread_smc_args *args)
197 {
198 	args->a0 = OPTEE_MSG_UID_0;
199 	args->a1 = OPTEE_MSG_UID_1;
200 	args->a2 = OPTEE_MSG_UID_2;
201 	args->a3 = OPTEE_MSG_UID_3;
202 }
203 
204 void __weak tee_entry_get_api_revision(struct thread_smc_args *args)
205 {
206 	args->a0 = OPTEE_MSG_REVISION_MAJOR;
207 	args->a1 = OPTEE_MSG_REVISION_MINOR;
208 }
209 
210 void __weak tee_entry_get_os_uuid(struct thread_smc_args *args)
211 {
212 	args->a0 = OPTEE_MSG_OS_OPTEE_UUID_0;
213 	args->a1 = OPTEE_MSG_OS_OPTEE_UUID_1;
214 	args->a2 = OPTEE_MSG_OS_OPTEE_UUID_2;
215 	args->a3 = OPTEE_MSG_OS_OPTEE_UUID_3;
216 }
217 
218 void __weak tee_entry_get_os_revision(struct thread_smc_args *args)
219 {
220 	args->a0 = CFG_OPTEE_REVISION_MAJOR;
221 	args->a1 = CFG_OPTEE_REVISION_MINOR;
222 	args->a2 = TEE_IMPL_GIT_SHA1;
223 }
224