1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2015, Linaro Limited 4 * All rights reserved. 5 * Copyright (c) 2014, STMicroelectronics International N.V. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright notice, 12 * this list of conditions and the following disclaimer. 13 * 14 * 2. Redistributions in binary form must reproduce the above copyright notice, 15 * this list of conditions and the following disclaimer in the documentation 16 * and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <tee/entry_fast.h> 32 #include <optee_msg.h> 33 #include <sm/optee_smc.h> 34 #include <kernel/generic_boot.h> 35 #include <kernel/tee_l2cc_mutex.h> 36 #include <kernel/misc.h> 37 #include <mm/core_mmu.h> 38 39 static void tee_entry_get_shm_config(struct thread_smc_args *args) 40 { 41 args->a0 = OPTEE_SMC_RETURN_OK; 42 args->a1 = default_nsec_shm_paddr; 43 args->a2 = default_nsec_shm_size; 44 /* Should this be TEESMC cache attributes instead? */ 45 args->a3 = core_mmu_is_shm_cached(); 46 } 47 48 static void tee_entry_fastcall_l2cc_mutex(struct thread_smc_args *args) 49 { 50 TEE_Result ret; 51 #ifdef ARM32 52 paddr_t pa = 0; 53 54 switch (args->a1) { 55 case OPTEE_SMC_L2CC_MUTEX_GET_ADDR: 56 ret = tee_get_l2cc_mutex(&pa); 57 reg_pair_from_64(pa, &args->a2, &args->a3); 58 break; 59 case OPTEE_SMC_L2CC_MUTEX_SET_ADDR: 60 pa = reg_pair_to_64(args->a2, args->a3); 61 ret = tee_set_l2cc_mutex(&pa); 62 break; 63 case OPTEE_SMC_L2CC_MUTEX_ENABLE: 64 ret = tee_enable_l2cc_mutex(); 65 break; 66 case OPTEE_SMC_L2CC_MUTEX_DISABLE: 67 ret = tee_disable_l2cc_mutex(); 68 break; 69 default: 70 args->a0 = OPTEE_SMC_RETURN_EBADCMD; 71 return; 72 } 73 #else 74 ret = TEE_ERROR_NOT_SUPPORTED; 75 #endif 76 if (ret == TEE_ERROR_NOT_SUPPORTED) 77 args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION; 78 else if (ret) 79 args->a0 = OPTEE_SMC_RETURN_EBADADDR; 80 else 81 args->a0 = OPTEE_SMC_RETURN_OK; 82 } 83 84 static void tee_entry_exchange_capabilities(struct thread_smc_args *args) 85 { 86 bool dyn_shm_en = false; 87 88 /* 89 * Currently we ignore OPTEE_SMC_NSEC_CAP_UNIPROCESSOR. 90 * 91 * The memory mapping of shared memory is defined as normal 92 * shared memory for SMP systems and normal memory for UP 93 * systems. Currently we map all memory as shared in secure 94 * world. 95 * 96 * When translation tables are created with shared bit cleared for 97 * uniprocessor systems we'll need to check 98 * OPTEE_SMC_NSEC_CAP_UNIPROCESSOR. 99 */ 100 101 if (args->a1 & ~OPTEE_SMC_NSEC_CAP_UNIPROCESSOR) { 102 /* Unknown capability. */ 103 args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL; 104 return; 105 } 106 107 args->a0 = OPTEE_SMC_RETURN_OK; 108 args->a1 = OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM; 109 110 #if defined(CFG_DYN_SHM_CAP) 111 dyn_shm_en = core_mmu_nsec_ddr_is_defined(); 112 if (dyn_shm_en) 113 args->a1 |= OPTEE_SMC_SEC_CAP_DYNAMIC_SHM; 114 #endif 115 116 IMSG("Dynamic shared memory is %sabled", dyn_shm_en ? "en" : "dis"); 117 } 118 119 static void tee_entry_disable_shm_cache(struct thread_smc_args *args) 120 { 121 uint64_t cookie; 122 123 if (!thread_disable_prealloc_rpc_cache(&cookie)) { 124 args->a0 = OPTEE_SMC_RETURN_EBUSY; 125 return; 126 } 127 128 if (!cookie) { 129 args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL; 130 return; 131 } 132 133 args->a0 = OPTEE_SMC_RETURN_OK; 134 args->a1 = cookie >> 32; 135 args->a2 = cookie; 136 } 137 138 static void tee_entry_enable_shm_cache(struct thread_smc_args *args) 139 { 140 if (thread_enable_prealloc_rpc_cache()) 141 args->a0 = OPTEE_SMC_RETURN_OK; 142 else 143 args->a0 = OPTEE_SMC_RETURN_EBUSY; 144 } 145 146 static void tee_entry_boot_secondary(struct thread_smc_args *args) 147 { 148 #if defined(CFG_BOOT_SECONDARY_REQUEST) 149 if (!generic_boot_core_release(args->a1, (paddr_t)(args->a3))) 150 args->a0 = OPTEE_SMC_RETURN_OK; 151 else 152 args->a0 = OPTEE_SMC_RETURN_EBADCMD; 153 #else 154 args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL; 155 #endif 156 } 157 158 void tee_entry_fast(struct thread_smc_args *args) 159 { 160 switch (args->a0) { 161 162 /* Generic functions */ 163 case OPTEE_SMC_CALLS_COUNT: 164 tee_entry_get_api_call_count(args); 165 break; 166 case OPTEE_SMC_CALLS_UID: 167 tee_entry_get_api_uuid(args); 168 break; 169 case OPTEE_SMC_CALLS_REVISION: 170 tee_entry_get_api_revision(args); 171 break; 172 case OPTEE_SMC_CALL_GET_OS_UUID: 173 tee_entry_get_os_uuid(args); 174 break; 175 case OPTEE_SMC_CALL_GET_OS_REVISION: 176 tee_entry_get_os_revision(args); 177 break; 178 179 /* OP-TEE specific SMC functions */ 180 case OPTEE_SMC_GET_SHM_CONFIG: 181 tee_entry_get_shm_config(args); 182 break; 183 case OPTEE_SMC_L2CC_MUTEX: 184 tee_entry_fastcall_l2cc_mutex(args); 185 break; 186 case OPTEE_SMC_EXCHANGE_CAPABILITIES: 187 tee_entry_exchange_capabilities(args); 188 break; 189 case OPTEE_SMC_DISABLE_SHM_CACHE: 190 tee_entry_disable_shm_cache(args); 191 break; 192 case OPTEE_SMC_ENABLE_SHM_CACHE: 193 tee_entry_enable_shm_cache(args); 194 break; 195 case OPTEE_SMC_BOOT_SECONDARY: 196 tee_entry_boot_secondary(args); 197 break; 198 199 default: 200 args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION; 201 break; 202 } 203 } 204 205 size_t tee_entry_generic_get_api_call_count(void) 206 { 207 /* 208 * All the different calls handled in this file. If the specific 209 * target has additional calls it will call this function and 210 * add the number of calls the target has added. 211 */ 212 return 9; 213 } 214 215 void __weak tee_entry_get_api_call_count(struct thread_smc_args *args) 216 { 217 args->a0 = tee_entry_generic_get_api_call_count(); 218 } 219 220 void __weak tee_entry_get_api_uuid(struct thread_smc_args *args) 221 { 222 args->a0 = OPTEE_MSG_UID_0; 223 args->a1 = OPTEE_MSG_UID_1; 224 args->a2 = OPTEE_MSG_UID_2; 225 args->a3 = OPTEE_MSG_UID_3; 226 } 227 228 void __weak tee_entry_get_api_revision(struct thread_smc_args *args) 229 { 230 args->a0 = OPTEE_MSG_REVISION_MAJOR; 231 args->a1 = OPTEE_MSG_REVISION_MINOR; 232 } 233 234 void __weak tee_entry_get_os_uuid(struct thread_smc_args *args) 235 { 236 args->a0 = OPTEE_MSG_OS_OPTEE_UUID_0; 237 args->a1 = OPTEE_MSG_OS_OPTEE_UUID_1; 238 args->a2 = OPTEE_MSG_OS_OPTEE_UUID_2; 239 args->a3 = OPTEE_MSG_OS_OPTEE_UUID_3; 240 } 241 242 void __weak tee_entry_get_os_revision(struct thread_smc_args *args) 243 { 244 args->a0 = CFG_OPTEE_REVISION_MAJOR; 245 args->a1 = CFG_OPTEE_REVISION_MINOR; 246 args->a2 = TEE_IMPL_GIT_SHA1; 247 } 248