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