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