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