1 /* 2 * Copyright (c) 2015-2016, Linaro Limited 3 * 4 * This software is licensed under the terms of the GNU General Public 5 * License version 2, as published by the Free Software Foundation, and 6 * may be copied, distributed, and modified under those terms. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 */ 14 15 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 16 17 #include <linux/delay.h> 18 #include <linux/device.h> 19 #include <linux/slab.h> 20 #include <linux/tee_drv.h> 21 #include "optee_private.h" 22 #include "optee_smc.h" 23 24 struct wq_entry { 25 struct list_head link; 26 struct completion c; 27 u32 key; 28 }; 29 30 void optee_wait_queue_init(struct optee_wait_queue *priv) 31 { 32 mutex_init(&priv->mu); 33 INIT_LIST_HEAD(&priv->db); 34 } 35 36 void optee_wait_queue_exit(struct optee_wait_queue *priv) 37 { 38 mutex_destroy(&priv->mu); 39 } 40 41 static void handle_rpc_func_cmd_get_time(struct optee_msg_arg *arg) 42 { 43 struct timespec64 ts; 44 45 if (arg->num_params != 1) 46 goto bad; 47 if ((arg->params[0].attr & OPTEE_MSG_ATTR_TYPE_MASK) != 48 OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT) 49 goto bad; 50 51 getnstimeofday64(&ts); 52 arg->params[0].u.value.a = ts.tv_sec; 53 arg->params[0].u.value.b = ts.tv_nsec; 54 55 arg->ret = TEEC_SUCCESS; 56 return; 57 bad: 58 arg->ret = TEEC_ERROR_BAD_PARAMETERS; 59 } 60 61 static struct wq_entry *wq_entry_get(struct optee_wait_queue *wq, u32 key) 62 { 63 struct wq_entry *w; 64 65 mutex_lock(&wq->mu); 66 67 list_for_each_entry(w, &wq->db, link) 68 if (w->key == key) 69 goto out; 70 71 w = kmalloc(sizeof(*w), GFP_KERNEL); 72 if (w) { 73 init_completion(&w->c); 74 w->key = key; 75 list_add_tail(&w->link, &wq->db); 76 } 77 out: 78 mutex_unlock(&wq->mu); 79 return w; 80 } 81 82 static void wq_sleep(struct optee_wait_queue *wq, u32 key) 83 { 84 struct wq_entry *w = wq_entry_get(wq, key); 85 86 if (w) { 87 wait_for_completion(&w->c); 88 mutex_lock(&wq->mu); 89 list_del(&w->link); 90 mutex_unlock(&wq->mu); 91 kfree(w); 92 } 93 } 94 95 static void wq_wakeup(struct optee_wait_queue *wq, u32 key) 96 { 97 struct wq_entry *w = wq_entry_get(wq, key); 98 99 if (w) 100 complete(&w->c); 101 } 102 103 static void handle_rpc_func_cmd_wq(struct optee *optee, 104 struct optee_msg_arg *arg) 105 { 106 if (arg->num_params != 1) 107 goto bad; 108 109 if ((arg->params[0].attr & OPTEE_MSG_ATTR_TYPE_MASK) != 110 OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) 111 goto bad; 112 113 switch (arg->params[0].u.value.a) { 114 case OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP: 115 wq_sleep(&optee->wait_queue, arg->params[0].u.value.b); 116 break; 117 case OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP: 118 wq_wakeup(&optee->wait_queue, arg->params[0].u.value.b); 119 break; 120 default: 121 goto bad; 122 } 123 124 arg->ret = TEEC_SUCCESS; 125 return; 126 bad: 127 arg->ret = TEEC_ERROR_BAD_PARAMETERS; 128 } 129 130 static void handle_rpc_func_cmd_wait(struct optee_msg_arg *arg) 131 { 132 u32 msec_to_wait; 133 134 if (arg->num_params != 1) 135 goto bad; 136 137 if ((arg->params[0].attr & OPTEE_MSG_ATTR_TYPE_MASK) != 138 OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) 139 goto bad; 140 141 msec_to_wait = arg->params[0].u.value.a; 142 143 /* Go to interruptible sleep */ 144 msleep_interruptible(msec_to_wait); 145 146 arg->ret = TEEC_SUCCESS; 147 return; 148 bad: 149 arg->ret = TEEC_ERROR_BAD_PARAMETERS; 150 } 151 152 static void handle_rpc_supp_cmd(struct tee_context *ctx, 153 struct optee_msg_arg *arg) 154 { 155 struct tee_param *params; 156 157 arg->ret_origin = TEEC_ORIGIN_COMMS; 158 159 params = kmalloc_array(arg->num_params, sizeof(struct tee_param), 160 GFP_KERNEL); 161 if (!params) { 162 arg->ret = TEEC_ERROR_OUT_OF_MEMORY; 163 return; 164 } 165 166 if (optee_from_msg_param(params, arg->num_params, arg->params)) { 167 arg->ret = TEEC_ERROR_BAD_PARAMETERS; 168 goto out; 169 } 170 171 arg->ret = optee_supp_thrd_req(ctx, arg->cmd, arg->num_params, params); 172 173 if (optee_to_msg_param(arg->params, arg->num_params, params)) 174 arg->ret = TEEC_ERROR_BAD_PARAMETERS; 175 out: 176 kfree(params); 177 } 178 179 static struct tee_shm *cmd_alloc_suppl(struct tee_context *ctx, size_t sz) 180 { 181 u32 ret; 182 struct tee_param param; 183 struct optee *optee = tee_get_drvdata(ctx->teedev); 184 struct tee_shm *shm; 185 186 param.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT; 187 param.u.value.a = OPTEE_MSG_RPC_SHM_TYPE_APPL; 188 param.u.value.b = sz; 189 param.u.value.c = 0; 190 191 ret = optee_supp_thrd_req(ctx, OPTEE_MSG_RPC_CMD_SHM_ALLOC, 1, ¶m); 192 if (ret) 193 return ERR_PTR(-ENOMEM); 194 195 mutex_lock(&optee->supp.ctx_mutex); 196 /* Increases count as secure world doesn't have a reference */ 197 shm = tee_shm_get_from_id(optee->supp.ctx, param.u.value.c); 198 mutex_unlock(&optee->supp.ctx_mutex); 199 return shm; 200 } 201 202 static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx, 203 struct optee_msg_arg *arg) 204 { 205 phys_addr_t pa; 206 struct tee_shm *shm; 207 size_t sz; 208 size_t n; 209 210 arg->ret_origin = TEEC_ORIGIN_COMMS; 211 212 if (!arg->num_params || 213 arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) { 214 arg->ret = TEEC_ERROR_BAD_PARAMETERS; 215 return; 216 } 217 218 for (n = 1; n < arg->num_params; n++) { 219 if (arg->params[n].attr != OPTEE_MSG_ATTR_TYPE_NONE) { 220 arg->ret = TEEC_ERROR_BAD_PARAMETERS; 221 return; 222 } 223 } 224 225 sz = arg->params[0].u.value.b; 226 switch (arg->params[0].u.value.a) { 227 case OPTEE_MSG_RPC_SHM_TYPE_APPL: 228 shm = cmd_alloc_suppl(ctx, sz); 229 break; 230 case OPTEE_MSG_RPC_SHM_TYPE_KERNEL: 231 shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED); 232 break; 233 default: 234 arg->ret = TEEC_ERROR_BAD_PARAMETERS; 235 return; 236 } 237 238 if (IS_ERR(shm)) { 239 arg->ret = TEEC_ERROR_OUT_OF_MEMORY; 240 return; 241 } 242 243 if (tee_shm_get_pa(shm, 0, &pa)) { 244 arg->ret = TEEC_ERROR_BAD_PARAMETERS; 245 goto bad; 246 } 247 248 arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT; 249 arg->params[0].u.tmem.buf_ptr = pa; 250 arg->params[0].u.tmem.size = sz; 251 arg->params[0].u.tmem.shm_ref = (unsigned long)shm; 252 arg->ret = TEEC_SUCCESS; 253 return; 254 bad: 255 tee_shm_free(shm); 256 } 257 258 static void cmd_free_suppl(struct tee_context *ctx, struct tee_shm *shm) 259 { 260 struct tee_param param; 261 262 param.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT; 263 param.u.value.a = OPTEE_MSG_RPC_SHM_TYPE_APPL; 264 param.u.value.b = tee_shm_get_id(shm); 265 param.u.value.c = 0; 266 267 /* 268 * Match the tee_shm_get_from_id() in cmd_alloc_suppl() as secure 269 * world has released its reference. 270 * 271 * It's better to do this before sending the request to supplicant 272 * as we'd like to let the process doing the initial allocation to 273 * do release the last reference too in order to avoid stacking 274 * many pending fput() on the client process. This could otherwise 275 * happen if secure world does many allocate and free in a single 276 * invoke. 277 */ 278 tee_shm_put(shm); 279 280 optee_supp_thrd_req(ctx, OPTEE_MSG_RPC_CMD_SHM_FREE, 1, ¶m); 281 } 282 283 static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx, 284 struct optee_msg_arg *arg) 285 { 286 struct tee_shm *shm; 287 288 arg->ret_origin = TEEC_ORIGIN_COMMS; 289 290 if (arg->num_params != 1 || 291 arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) { 292 arg->ret = TEEC_ERROR_BAD_PARAMETERS; 293 return; 294 } 295 296 shm = (struct tee_shm *)(unsigned long)arg->params[0].u.value.b; 297 switch (arg->params[0].u.value.a) { 298 case OPTEE_MSG_RPC_SHM_TYPE_APPL: 299 cmd_free_suppl(ctx, shm); 300 break; 301 case OPTEE_MSG_RPC_SHM_TYPE_KERNEL: 302 tee_shm_free(shm); 303 break; 304 default: 305 arg->ret = TEEC_ERROR_BAD_PARAMETERS; 306 } 307 arg->ret = TEEC_SUCCESS; 308 } 309 310 static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee, 311 struct tee_shm *shm) 312 { 313 struct optee_msg_arg *arg; 314 315 arg = tee_shm_get_va(shm, 0); 316 if (IS_ERR(arg)) { 317 pr_err("%s: tee_shm_get_va %p failed\n", __func__, shm); 318 return; 319 } 320 321 switch (arg->cmd) { 322 case OPTEE_MSG_RPC_CMD_GET_TIME: 323 handle_rpc_func_cmd_get_time(arg); 324 break; 325 case OPTEE_MSG_RPC_CMD_WAIT_QUEUE: 326 handle_rpc_func_cmd_wq(optee, arg); 327 break; 328 case OPTEE_MSG_RPC_CMD_SUSPEND: 329 handle_rpc_func_cmd_wait(arg); 330 break; 331 case OPTEE_MSG_RPC_CMD_SHM_ALLOC: 332 handle_rpc_func_cmd_shm_alloc(ctx, arg); 333 break; 334 case OPTEE_MSG_RPC_CMD_SHM_FREE: 335 handle_rpc_func_cmd_shm_free(ctx, arg); 336 break; 337 default: 338 handle_rpc_supp_cmd(ctx, arg); 339 } 340 } 341 342 /** 343 * optee_handle_rpc() - handle RPC from secure world 344 * @ctx: context doing the RPC 345 * @param: value of registers for the RPC 346 * 347 * Result of RPC is written back into @param. 348 */ 349 void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param) 350 { 351 struct tee_device *teedev = ctx->teedev; 352 struct optee *optee = tee_get_drvdata(teedev); 353 struct tee_shm *shm; 354 phys_addr_t pa; 355 356 switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) { 357 case OPTEE_SMC_RPC_FUNC_ALLOC: 358 shm = tee_shm_alloc(ctx, param->a1, TEE_SHM_MAPPED); 359 if (!IS_ERR(shm) && !tee_shm_get_pa(shm, 0, &pa)) { 360 reg_pair_from_64(¶m->a1, ¶m->a2, pa); 361 reg_pair_from_64(¶m->a4, ¶m->a5, 362 (unsigned long)shm); 363 } else { 364 param->a1 = 0; 365 param->a2 = 0; 366 param->a4 = 0; 367 param->a5 = 0; 368 } 369 break; 370 case OPTEE_SMC_RPC_FUNC_FREE: 371 shm = reg_pair_to_ptr(param->a1, param->a2); 372 tee_shm_free(shm); 373 break; 374 case OPTEE_SMC_RPC_FUNC_FOREIGN_INTR: 375 /* 376 * A foreign interrupt was raised while secure world was 377 * executing, since they are handled in Linux a dummy RPC is 378 * performed to let Linux take the interrupt through the normal 379 * vector. 380 */ 381 break; 382 case OPTEE_SMC_RPC_FUNC_CMD: 383 shm = reg_pair_to_ptr(param->a1, param->a2); 384 handle_rpc_func_cmd(ctx, optee, shm); 385 break; 386 default: 387 pr_warn("Unknown RPC func 0x%x\n", 388 (u32)OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)); 389 break; 390 } 391 392 param->a0 = OPTEE_SMC_CALL_RETURN_FROM_RPC; 393 } 394