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/virtualization.h> 13 #include <kernel/misc.h> 14 #include <mm/core_mmu.h> 15 16 #ifdef CFG_CORE_RESERVED_SHM 17 static void tee_entry_get_shm_config(struct thread_smc_args *args) 18 { 19 args->a0 = OPTEE_SMC_RETURN_OK; 20 args->a1 = default_nsec_shm_paddr; 21 args->a2 = default_nsec_shm_size; 22 /* Should this be TEESMC cache attributes instead? */ 23 args->a3 = core_mmu_is_shm_cached(); 24 } 25 #endif 26 27 static void tee_entry_fastcall_l2cc_mutex(struct thread_smc_args *args) 28 { 29 TEE_Result ret; 30 #ifdef ARM32 31 paddr_t pa = 0; 32 33 switch (args->a1) { 34 case OPTEE_SMC_L2CC_MUTEX_GET_ADDR: 35 ret = tee_get_l2cc_mutex(&pa); 36 reg_pair_from_64(pa, &args->a2, &args->a3); 37 break; 38 case OPTEE_SMC_L2CC_MUTEX_SET_ADDR: 39 pa = reg_pair_to_64(args->a2, args->a3); 40 ret = tee_set_l2cc_mutex(&pa); 41 break; 42 case OPTEE_SMC_L2CC_MUTEX_ENABLE: 43 ret = tee_enable_l2cc_mutex(); 44 break; 45 case OPTEE_SMC_L2CC_MUTEX_DISABLE: 46 ret = tee_disable_l2cc_mutex(); 47 break; 48 default: 49 args->a0 = OPTEE_SMC_RETURN_EBADCMD; 50 return; 51 } 52 #else 53 ret = TEE_ERROR_NOT_SUPPORTED; 54 #endif 55 if (ret == TEE_ERROR_NOT_SUPPORTED) 56 args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION; 57 else if (ret) 58 args->a0 = OPTEE_SMC_RETURN_EBADADDR; 59 else 60 args->a0 = OPTEE_SMC_RETURN_OK; 61 } 62 63 static void tee_entry_exchange_capabilities(struct thread_smc_args *args) 64 { 65 bool dyn_shm_en __maybe_unused = false; 66 67 /* 68 * Currently we ignore OPTEE_SMC_NSEC_CAP_UNIPROCESSOR. 69 * 70 * The memory mapping of shared memory is defined as normal 71 * shared memory for SMP systems and normal memory for UP 72 * systems. Currently we map all memory as shared in secure 73 * world. 74 * 75 * When translation tables are created with shared bit cleared for 76 * uniprocessor systems we'll need to check 77 * OPTEE_SMC_NSEC_CAP_UNIPROCESSOR. 78 */ 79 80 if (args->a1 & ~OPTEE_SMC_NSEC_CAP_UNIPROCESSOR) { 81 /* Unknown capability. */ 82 args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL; 83 return; 84 } 85 86 args->a0 = OPTEE_SMC_RETURN_OK; 87 args->a1 = 0; 88 #ifdef CFG_CORE_RESERVED_SHM 89 args->a1 |= OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM; 90 #endif 91 #ifdef CFG_VIRTUALIZATION 92 args->a1 |= OPTEE_SMC_SEC_CAP_VIRTUALIZATION; 93 #endif 94 95 #if defined(CFG_CORE_DYN_SHM) 96 dyn_shm_en = core_mmu_nsec_ddr_is_defined(); 97 if (dyn_shm_en) 98 args->a1 |= OPTEE_SMC_SEC_CAP_DYNAMIC_SHM; 99 #endif 100 101 DMSG("Dynamic shared memory is %sabled", dyn_shm_en ? "en" : "dis"); 102 } 103 104 static void tee_entry_disable_shm_cache(struct thread_smc_args *args) 105 { 106 uint64_t cookie; 107 108 if (!thread_disable_prealloc_rpc_cache(&cookie)) { 109 args->a0 = OPTEE_SMC_RETURN_EBUSY; 110 return; 111 } 112 113 if (!cookie) { 114 args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL; 115 return; 116 } 117 118 args->a0 = OPTEE_SMC_RETURN_OK; 119 args->a1 = cookie >> 32; 120 args->a2 = cookie; 121 } 122 123 static void tee_entry_enable_shm_cache(struct thread_smc_args *args) 124 { 125 if (thread_enable_prealloc_rpc_cache()) 126 args->a0 = OPTEE_SMC_RETURN_OK; 127 else 128 args->a0 = OPTEE_SMC_RETURN_EBUSY; 129 } 130 131 static void tee_entry_boot_secondary(struct thread_smc_args *args) 132 { 133 #if defined(CFG_BOOT_SECONDARY_REQUEST) 134 if (!generic_boot_core_release(args->a1, (paddr_t)(args->a3))) 135 args->a0 = OPTEE_SMC_RETURN_OK; 136 else 137 args->a0 = OPTEE_SMC_RETURN_EBADCMD; 138 #else 139 args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL; 140 #endif 141 } 142 143 static void tee_entry_get_thread_count(struct thread_smc_args *args) 144 { 145 args->a0 = OPTEE_SMC_RETURN_OK; 146 args->a1 = CFG_NUM_THREADS; 147 } 148 149 #if defined(CFG_VIRTUALIZATION) 150 static void tee_entry_vm_created(struct thread_smc_args *args) 151 { 152 uint16_t guest_id = args->a1; 153 154 /* Only hypervisor can issue this request */ 155 if (args->a7 != HYP_CLNT_ID) { 156 args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL; 157 return; 158 } 159 160 args->a0 = virt_guest_created(guest_id); 161 } 162 163 static void tee_entry_vm_destroyed(struct thread_smc_args *args) 164 { 165 uint16_t guest_id = args->a1; 166 167 /* Only hypervisor can issue this request */ 168 if (args->a7 != HYP_CLNT_ID) { 169 args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL; 170 return; 171 } 172 173 args->a0 = virt_guest_destroyed(guest_id); 174 } 175 #endif 176 177 /* Note: this function is weak to let platforms add special handling */ 178 void __weak tee_entry_fast(struct thread_smc_args *args) 179 { 180 __tee_entry_fast(args); 181 } 182 183 /* 184 * If tee_entry_fast() is overridden, it's still supposed to call this 185 * function. 186 */ 187 void __tee_entry_fast(struct thread_smc_args *args) 188 { 189 switch (args->a0) { 190 191 /* Generic functions */ 192 case OPTEE_SMC_CALLS_COUNT: 193 tee_entry_get_api_call_count(args); 194 break; 195 case OPTEE_SMC_CALLS_UID: 196 tee_entry_get_api_uuid(args); 197 break; 198 case OPTEE_SMC_CALLS_REVISION: 199 tee_entry_get_api_revision(args); 200 break; 201 case OPTEE_SMC_CALL_GET_OS_UUID: 202 tee_entry_get_os_uuid(args); 203 break; 204 case OPTEE_SMC_CALL_GET_OS_REVISION: 205 tee_entry_get_os_revision(args); 206 break; 207 208 /* OP-TEE specific SMC functions */ 209 #ifdef CFG_CORE_RESERVED_SHM 210 case OPTEE_SMC_GET_SHM_CONFIG: 211 tee_entry_get_shm_config(args); 212 break; 213 #endif 214 case OPTEE_SMC_L2CC_MUTEX: 215 tee_entry_fastcall_l2cc_mutex(args); 216 break; 217 case OPTEE_SMC_EXCHANGE_CAPABILITIES: 218 tee_entry_exchange_capabilities(args); 219 break; 220 case OPTEE_SMC_DISABLE_SHM_CACHE: 221 tee_entry_disable_shm_cache(args); 222 break; 223 case OPTEE_SMC_ENABLE_SHM_CACHE: 224 tee_entry_enable_shm_cache(args); 225 break; 226 case OPTEE_SMC_BOOT_SECONDARY: 227 tee_entry_boot_secondary(args); 228 break; 229 case OPTEE_SMC_GET_THREAD_COUNT: 230 tee_entry_get_thread_count(args); 231 break; 232 233 #if defined(CFG_VIRTUALIZATION) 234 case OPTEE_SMC_VM_CREATED: 235 tee_entry_vm_created(args); 236 break; 237 case OPTEE_SMC_VM_DESTROYED: 238 tee_entry_vm_destroyed(args); 239 break; 240 #endif 241 242 default: 243 args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION; 244 break; 245 } 246 } 247 248 size_t tee_entry_generic_get_api_call_count(void) 249 { 250 /* 251 * All the different calls handled in this file. If the specific 252 * target has additional calls it will call this function and 253 * add the number of calls the target has added. 254 */ 255 size_t ret = 12; 256 257 #if defined(CFG_VIRTUALIZATION) 258 ret += 2; 259 #endif 260 261 return ret; 262 } 263 264 void __weak tee_entry_get_api_call_count(struct thread_smc_args *args) 265 { 266 args->a0 = tee_entry_generic_get_api_call_count(); 267 } 268 269 void __weak tee_entry_get_api_uuid(struct thread_smc_args *args) 270 { 271 args->a0 = OPTEE_MSG_UID_0; 272 args->a1 = OPTEE_MSG_UID_1; 273 args->a2 = OPTEE_MSG_UID_2; 274 args->a3 = OPTEE_MSG_UID_3; 275 } 276 277 void __weak tee_entry_get_api_revision(struct thread_smc_args *args) 278 { 279 args->a0 = OPTEE_MSG_REVISION_MAJOR; 280 args->a1 = OPTEE_MSG_REVISION_MINOR; 281 } 282 283 void __weak tee_entry_get_os_uuid(struct thread_smc_args *args) 284 { 285 args->a0 = OPTEE_MSG_OS_OPTEE_UUID_0; 286 args->a1 = OPTEE_MSG_OS_OPTEE_UUID_1; 287 args->a2 = OPTEE_MSG_OS_OPTEE_UUID_2; 288 args->a3 = OPTEE_MSG_OS_OPTEE_UUID_3; 289 } 290 291 void __weak tee_entry_get_os_revision(struct thread_smc_args *args) 292 { 293 args->a0 = CFG_OPTEE_REVISION_MAJOR; 294 args->a1 = CFG_OPTEE_REVISION_MINOR; 295 args->a2 = TEE_IMPL_GIT_SHA1; 296 } 297