0001
0002
0003
0004
0005
0006 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0007
0008 #include <linux/arm_ffa.h>
0009 #include <linux/errno.h>
0010 #include <linux/scatterlist.h>
0011 #include <linux/sched.h>
0012 #include <linux/slab.h>
0013 #include <linux/string.h>
0014 #include <linux/tee_drv.h>
0015 #include <linux/types.h>
0016 #include "optee_private.h"
0017 #include "optee_ffa.h"
0018 #include "optee_rpc_cmd.h"
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 struct shm_rhash {
0041 struct tee_shm *shm;
0042 u64 global_id;
0043 struct rhash_head linkage;
0044 };
0045
0046 static void rh_free_fn(void *ptr, void *arg)
0047 {
0048 kfree(ptr);
0049 }
0050
0051 static const struct rhashtable_params shm_rhash_params = {
0052 .head_offset = offsetof(struct shm_rhash, linkage),
0053 .key_len = sizeof(u64),
0054 .key_offset = offsetof(struct shm_rhash, global_id),
0055 .automatic_shrinking = true,
0056 };
0057
0058 static struct tee_shm *optee_shm_from_ffa_handle(struct optee *optee,
0059 u64 global_id)
0060 {
0061 struct tee_shm *shm = NULL;
0062 struct shm_rhash *r;
0063
0064 mutex_lock(&optee->ffa.mutex);
0065 r = rhashtable_lookup_fast(&optee->ffa.global_ids, &global_id,
0066 shm_rhash_params);
0067 if (r)
0068 shm = r->shm;
0069 mutex_unlock(&optee->ffa.mutex);
0070
0071 return shm;
0072 }
0073
0074 static int optee_shm_add_ffa_handle(struct optee *optee, struct tee_shm *shm,
0075 u64 global_id)
0076 {
0077 struct shm_rhash *r;
0078 int rc;
0079
0080 r = kmalloc(sizeof(*r), GFP_KERNEL);
0081 if (!r)
0082 return -ENOMEM;
0083 r->shm = shm;
0084 r->global_id = global_id;
0085
0086 mutex_lock(&optee->ffa.mutex);
0087 rc = rhashtable_lookup_insert_fast(&optee->ffa.global_ids, &r->linkage,
0088 shm_rhash_params);
0089 mutex_unlock(&optee->ffa.mutex);
0090
0091 if (rc)
0092 kfree(r);
0093
0094 return rc;
0095 }
0096
0097 static int optee_shm_rem_ffa_handle(struct optee *optee, u64 global_id)
0098 {
0099 struct shm_rhash *r;
0100 int rc = -ENOENT;
0101
0102 mutex_lock(&optee->ffa.mutex);
0103 r = rhashtable_lookup_fast(&optee->ffa.global_ids, &global_id,
0104 shm_rhash_params);
0105 if (r)
0106 rc = rhashtable_remove_fast(&optee->ffa.global_ids,
0107 &r->linkage, shm_rhash_params);
0108 mutex_unlock(&optee->ffa.mutex);
0109
0110 if (!rc)
0111 kfree(r);
0112
0113 return rc;
0114 }
0115
0116
0117
0118
0119
0120
0121
0122
0123 static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
0124 u32 attr, const struct optee_msg_param *mp)
0125 {
0126 struct tee_shm *shm = NULL;
0127 u64 offs_high = 0;
0128 u64 offs_low = 0;
0129
0130 p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
0131 attr - OPTEE_MSG_ATTR_TYPE_FMEM_INPUT;
0132 p->u.memref.size = mp->u.fmem.size;
0133
0134 if (mp->u.fmem.global_id != OPTEE_MSG_FMEM_INVALID_GLOBAL_ID)
0135 shm = optee_shm_from_ffa_handle(optee, mp->u.fmem.global_id);
0136 p->u.memref.shm = shm;
0137
0138 if (shm) {
0139 offs_low = mp->u.fmem.offs_low;
0140 offs_high = mp->u.fmem.offs_high;
0141 }
0142 p->u.memref.shm_offs = offs_low | offs_high << 32;
0143 }
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155 static int optee_ffa_from_msg_param(struct optee *optee,
0156 struct tee_param *params, size_t num_params,
0157 const struct optee_msg_param *msg_params)
0158 {
0159 size_t n;
0160
0161 for (n = 0; n < num_params; n++) {
0162 struct tee_param *p = params + n;
0163 const struct optee_msg_param *mp = msg_params + n;
0164 u32 attr = mp->attr & OPTEE_MSG_ATTR_TYPE_MASK;
0165
0166 switch (attr) {
0167 case OPTEE_MSG_ATTR_TYPE_NONE:
0168 p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
0169 memset(&p->u, 0, sizeof(p->u));
0170 break;
0171 case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
0172 case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
0173 case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
0174 optee_from_msg_param_value(p, attr, mp);
0175 break;
0176 case OPTEE_MSG_ATTR_TYPE_FMEM_INPUT:
0177 case OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT:
0178 case OPTEE_MSG_ATTR_TYPE_FMEM_INOUT:
0179 from_msg_param_ffa_mem(optee, p, attr, mp);
0180 break;
0181 default:
0182 return -EINVAL;
0183 }
0184 }
0185
0186 return 0;
0187 }
0188
0189 static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
0190 const struct tee_param *p)
0191 {
0192 struct tee_shm *shm = p->u.memref.shm;
0193
0194 mp->attr = OPTEE_MSG_ATTR_TYPE_FMEM_INPUT + p->attr -
0195 TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
0196
0197 if (shm) {
0198 u64 shm_offs = p->u.memref.shm_offs;
0199
0200 mp->u.fmem.internal_offs = shm->offset;
0201
0202 mp->u.fmem.offs_low = shm_offs;
0203 mp->u.fmem.offs_high = shm_offs >> 32;
0204
0205 if (mp->u.fmem.offs_high != shm_offs >> 32)
0206 return -EINVAL;
0207
0208 mp->u.fmem.global_id = shm->sec_world_id;
0209 } else {
0210 memset(&mp->u, 0, sizeof(mp->u));
0211 mp->u.fmem.global_id = OPTEE_MSG_FMEM_INVALID_GLOBAL_ID;
0212 }
0213 mp->u.fmem.size = p->u.memref.size;
0214
0215 return 0;
0216 }
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227 static int optee_ffa_to_msg_param(struct optee *optee,
0228 struct optee_msg_param *msg_params,
0229 size_t num_params,
0230 const struct tee_param *params)
0231 {
0232 size_t n;
0233
0234 for (n = 0; n < num_params; n++) {
0235 const struct tee_param *p = params + n;
0236 struct optee_msg_param *mp = msg_params + n;
0237
0238 switch (p->attr) {
0239 case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
0240 mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
0241 memset(&mp->u, 0, sizeof(mp->u));
0242 break;
0243 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
0244 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
0245 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
0246 optee_to_msg_param_value(mp, p);
0247 break;
0248 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
0249 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
0250 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
0251 if (to_msg_param_ffa_mem(mp, p))
0252 return -EINVAL;
0253 break;
0254 default:
0255 return -EINVAL;
0256 }
0257 }
0258
0259 return 0;
0260 }
0261
0262
0263
0264
0265
0266
0267
0268
0269 static int optee_ffa_shm_register(struct tee_context *ctx, struct tee_shm *shm,
0270 struct page **pages, size_t num_pages,
0271 unsigned long start)
0272 {
0273 struct optee *optee = tee_get_drvdata(ctx->teedev);
0274 const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_ops;
0275 struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
0276 struct ffa_mem_region_attributes mem_attr = {
0277 .receiver = ffa_dev->vm_id,
0278 .attrs = FFA_MEM_RW,
0279 };
0280 struct ffa_mem_ops_args args = {
0281 .use_txbuf = true,
0282 .attrs = &mem_attr,
0283 .nattrs = 1,
0284 };
0285 struct sg_table sgt;
0286 int rc;
0287
0288 rc = optee_check_mem_type(start, num_pages);
0289 if (rc)
0290 return rc;
0291
0292 rc = sg_alloc_table_from_pages(&sgt, pages, num_pages, 0,
0293 num_pages * PAGE_SIZE, GFP_KERNEL);
0294 if (rc)
0295 return rc;
0296 args.sg = sgt.sgl;
0297 rc = ffa_ops->memory_share(ffa_dev, &args);
0298 sg_free_table(&sgt);
0299 if (rc)
0300 return rc;
0301
0302 rc = optee_shm_add_ffa_handle(optee, shm, args.g_handle);
0303 if (rc) {
0304 ffa_ops->memory_reclaim(args.g_handle, 0);
0305 return rc;
0306 }
0307
0308 shm->sec_world_id = args.g_handle;
0309
0310 return 0;
0311 }
0312
0313 static int optee_ffa_shm_unregister(struct tee_context *ctx,
0314 struct tee_shm *shm)
0315 {
0316 struct optee *optee = tee_get_drvdata(ctx->teedev);
0317 const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_ops;
0318 struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
0319 u64 global_handle = shm->sec_world_id;
0320 struct ffa_send_direct_data data = {
0321 .data0 = OPTEE_FFA_UNREGISTER_SHM,
0322 .data1 = (u32)global_handle,
0323 .data2 = (u32)(global_handle >> 32)
0324 };
0325 int rc;
0326
0327 optee_shm_rem_ffa_handle(optee, global_handle);
0328 shm->sec_world_id = 0;
0329
0330 rc = ffa_ops->sync_send_receive(ffa_dev, &data);
0331 if (rc)
0332 pr_err("Unregister SHM id 0x%llx rc %d\n", global_handle, rc);
0333
0334 rc = ffa_ops->memory_reclaim(global_handle, 0);
0335 if (rc)
0336 pr_err("mem_reclaim: 0x%llx %d", global_handle, rc);
0337
0338 return rc;
0339 }
0340
0341 static int optee_ffa_shm_unregister_supp(struct tee_context *ctx,
0342 struct tee_shm *shm)
0343 {
0344 struct optee *optee = tee_get_drvdata(ctx->teedev);
0345 const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_ops;
0346 u64 global_handle = shm->sec_world_id;
0347 int rc;
0348
0349
0350
0351
0352
0353
0354
0355 optee_shm_rem_ffa_handle(optee, global_handle);
0356 rc = ffa_ops->memory_reclaim(global_handle, 0);
0357 if (rc)
0358 pr_err("mem_reclaim: 0x%llx %d", global_handle, rc);
0359
0360 shm->sec_world_id = 0;
0361
0362 return rc;
0363 }
0364
0365
0366
0367
0368
0369
0370
0371
0372 static int pool_ffa_op_alloc(struct tee_shm_pool *pool,
0373 struct tee_shm *shm, size_t size, size_t align)
0374 {
0375 return optee_pool_op_alloc_helper(pool, shm, size, align,
0376 optee_ffa_shm_register);
0377 }
0378
0379 static void pool_ffa_op_free(struct tee_shm_pool *pool,
0380 struct tee_shm *shm)
0381 {
0382 optee_pool_op_free_helper(pool, shm, optee_ffa_shm_unregister);
0383 }
0384
0385 static void pool_ffa_op_destroy_pool(struct tee_shm_pool *pool)
0386 {
0387 kfree(pool);
0388 }
0389
0390 static const struct tee_shm_pool_ops pool_ffa_ops = {
0391 .alloc = pool_ffa_op_alloc,
0392 .free = pool_ffa_op_free,
0393 .destroy_pool = pool_ffa_op_destroy_pool,
0394 };
0395
0396
0397
0398
0399
0400
0401
0402 static struct tee_shm_pool *optee_ffa_shm_pool_alloc_pages(void)
0403 {
0404 struct tee_shm_pool *pool = kzalloc(sizeof(*pool), GFP_KERNEL);
0405
0406 if (!pool)
0407 return ERR_PTR(-ENOMEM);
0408
0409 pool->ops = &pool_ffa_ops;
0410
0411 return pool;
0412 }
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424 static void handle_ffa_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
0425 struct optee *optee,
0426 struct optee_msg_arg *arg)
0427 {
0428 struct tee_shm *shm;
0429
0430 if (arg->num_params != 1 ||
0431 arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) {
0432 arg->ret = TEEC_ERROR_BAD_PARAMETERS;
0433 return;
0434 }
0435
0436 switch (arg->params[0].u.value.a) {
0437 case OPTEE_RPC_SHM_TYPE_APPL:
0438 shm = optee_rpc_cmd_alloc_suppl(ctx, arg->params[0].u.value.b);
0439 break;
0440 case OPTEE_RPC_SHM_TYPE_KERNEL:
0441 shm = tee_shm_alloc_priv_buf(optee->ctx,
0442 arg->params[0].u.value.b);
0443 break;
0444 default:
0445 arg->ret = TEEC_ERROR_BAD_PARAMETERS;
0446 return;
0447 }
0448
0449 if (IS_ERR(shm)) {
0450 arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
0451 return;
0452 }
0453
0454 arg->params[0] = (struct optee_msg_param){
0455 .attr = OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT,
0456 .u.fmem.size = tee_shm_get_size(shm),
0457 .u.fmem.global_id = shm->sec_world_id,
0458 .u.fmem.internal_offs = shm->offset,
0459 };
0460
0461 arg->ret = TEEC_SUCCESS;
0462 }
0463
0464 static void handle_ffa_rpc_func_cmd_shm_free(struct tee_context *ctx,
0465 struct optee *optee,
0466 struct optee_msg_arg *arg)
0467 {
0468 struct tee_shm *shm;
0469
0470 if (arg->num_params != 1 ||
0471 arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT)
0472 goto err_bad_param;
0473
0474 shm = optee_shm_from_ffa_handle(optee, arg->params[0].u.value.b);
0475 if (!shm)
0476 goto err_bad_param;
0477 switch (arg->params[0].u.value.a) {
0478 case OPTEE_RPC_SHM_TYPE_APPL:
0479 optee_rpc_cmd_free_suppl(ctx, shm);
0480 break;
0481 case OPTEE_RPC_SHM_TYPE_KERNEL:
0482 tee_shm_free(shm);
0483 break;
0484 default:
0485 goto err_bad_param;
0486 }
0487 arg->ret = TEEC_SUCCESS;
0488 return;
0489
0490 err_bad_param:
0491 arg->ret = TEEC_ERROR_BAD_PARAMETERS;
0492 }
0493
0494 static void handle_ffa_rpc_func_cmd(struct tee_context *ctx,
0495 struct optee *optee,
0496 struct optee_msg_arg *arg)
0497 {
0498 arg->ret_origin = TEEC_ORIGIN_COMMS;
0499 switch (arg->cmd) {
0500 case OPTEE_RPC_CMD_SHM_ALLOC:
0501 handle_ffa_rpc_func_cmd_shm_alloc(ctx, optee, arg);
0502 break;
0503 case OPTEE_RPC_CMD_SHM_FREE:
0504 handle_ffa_rpc_func_cmd_shm_free(ctx, optee, arg);
0505 break;
0506 default:
0507 optee_rpc_cmd(ctx, optee, arg);
0508 }
0509 }
0510
0511 static void optee_handle_ffa_rpc(struct tee_context *ctx, struct optee *optee,
0512 u32 cmd, struct optee_msg_arg *arg)
0513 {
0514 switch (cmd) {
0515 case OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD:
0516 handle_ffa_rpc_func_cmd(ctx, optee, arg);
0517 break;
0518 case OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT:
0519
0520 break;
0521 default:
0522 pr_warn("Unknown RPC func 0x%x\n", cmd);
0523 break;
0524 }
0525 }
0526
0527 static int optee_ffa_yielding_call(struct tee_context *ctx,
0528 struct ffa_send_direct_data *data,
0529 struct optee_msg_arg *rpc_arg)
0530 {
0531 struct optee *optee = tee_get_drvdata(ctx->teedev);
0532 const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_ops;
0533 struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
0534 struct optee_call_waiter w;
0535 u32 cmd = data->data0;
0536 u32 w4 = data->data1;
0537 u32 w5 = data->data2;
0538 u32 w6 = data->data3;
0539 int rc;
0540
0541
0542 optee_cq_wait_init(&optee->call_queue, &w);
0543 while (true) {
0544 rc = ffa_ops->sync_send_receive(ffa_dev, data);
0545 if (rc)
0546 goto done;
0547
0548 switch ((int)data->data0) {
0549 case TEEC_SUCCESS:
0550 break;
0551 case TEEC_ERROR_BUSY:
0552 if (cmd == OPTEE_FFA_YIELDING_CALL_RESUME) {
0553 rc = -EIO;
0554 goto done;
0555 }
0556
0557
0558
0559
0560
0561 optee_cq_wait_for_completion(&optee->call_queue, &w);
0562 data->data0 = cmd;
0563 data->data1 = w4;
0564 data->data2 = w5;
0565 data->data3 = w6;
0566 continue;
0567 default:
0568 rc = -EIO;
0569 goto done;
0570 }
0571
0572 if (data->data1 == OPTEE_FFA_YIELDING_CALL_RETURN_DONE)
0573 goto done;
0574
0575
0576
0577
0578
0579
0580
0581
0582 cond_resched();
0583 optee_handle_ffa_rpc(ctx, optee, data->data1, rpc_arg);
0584 cmd = OPTEE_FFA_YIELDING_CALL_RESUME;
0585 data->data0 = cmd;
0586 data->data1 = 0;
0587 data->data2 = 0;
0588 data->data3 = 0;
0589 }
0590 done:
0591
0592
0593
0594
0595 optee_cq_wait_final(&optee->call_queue, &w);
0596
0597 return rc;
0598 }
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612 static int optee_ffa_do_call_with_arg(struct tee_context *ctx,
0613 struct tee_shm *shm, u_int offs)
0614 {
0615 struct ffa_send_direct_data data = {
0616 .data0 = OPTEE_FFA_YIELDING_CALL_WITH_ARG,
0617 .data1 = (u32)shm->sec_world_id,
0618 .data2 = (u32)(shm->sec_world_id >> 32),
0619 .data3 = offs,
0620 };
0621 struct optee_msg_arg *arg;
0622 unsigned int rpc_arg_offs;
0623 struct optee_msg_arg *rpc_arg;
0624
0625
0626
0627
0628
0629
0630
0631 if (shm->offset)
0632 return -EINVAL;
0633
0634 arg = tee_shm_get_va(shm, offs);
0635 if (IS_ERR(arg))
0636 return PTR_ERR(arg);
0637
0638 rpc_arg_offs = OPTEE_MSG_GET_ARG_SIZE(arg->num_params);
0639 rpc_arg = tee_shm_get_va(shm, offs + rpc_arg_offs);
0640 if (IS_ERR(rpc_arg))
0641 return PTR_ERR(rpc_arg);
0642
0643 return optee_ffa_yielding_call(ctx, &data, rpc_arg);
0644 }
0645
0646
0647
0648
0649
0650
0651
0652
0653
0654 static bool optee_ffa_api_is_compatbile(struct ffa_device *ffa_dev,
0655 const struct ffa_dev_ops *ops)
0656 {
0657 struct ffa_send_direct_data data = { OPTEE_FFA_GET_API_VERSION };
0658 int rc;
0659
0660 ops->mode_32bit_set(ffa_dev);
0661
0662 rc = ops->sync_send_receive(ffa_dev, &data);
0663 if (rc) {
0664 pr_err("Unexpected error %d\n", rc);
0665 return false;
0666 }
0667 if (data.data0 != OPTEE_FFA_VERSION_MAJOR ||
0668 data.data1 < OPTEE_FFA_VERSION_MINOR) {
0669 pr_err("Incompatible OP-TEE API version %lu.%lu",
0670 data.data0, data.data1);
0671 return false;
0672 }
0673
0674 data = (struct ffa_send_direct_data){ OPTEE_FFA_GET_OS_VERSION };
0675 rc = ops->sync_send_receive(ffa_dev, &data);
0676 if (rc) {
0677 pr_err("Unexpected error %d\n", rc);
0678 return false;
0679 }
0680 if (data.data2)
0681 pr_info("revision %lu.%lu (%08lx)",
0682 data.data0, data.data1, data.data2);
0683 else
0684 pr_info("revision %lu.%lu", data.data0, data.data1);
0685
0686 return true;
0687 }
0688
0689 static bool optee_ffa_exchange_caps(struct ffa_device *ffa_dev,
0690 const struct ffa_dev_ops *ops,
0691 u32 *sec_caps,
0692 unsigned int *rpc_param_count)
0693 {
0694 struct ffa_send_direct_data data = { OPTEE_FFA_EXCHANGE_CAPABILITIES };
0695 int rc;
0696
0697 rc = ops->sync_send_receive(ffa_dev, &data);
0698 if (rc) {
0699 pr_err("Unexpected error %d", rc);
0700 return false;
0701 }
0702 if (data.data0) {
0703 pr_err("Unexpected exchange error %lu", data.data0);
0704 return false;
0705 }
0706
0707 *rpc_param_count = (u8)data.data1;
0708 *sec_caps = data.data2;
0709
0710 return true;
0711 }
0712
0713 static void optee_ffa_get_version(struct tee_device *teedev,
0714 struct tee_ioctl_version_data *vers)
0715 {
0716 struct tee_ioctl_version_data v = {
0717 .impl_id = TEE_IMPL_ID_OPTEE,
0718 .impl_caps = TEE_OPTEE_CAP_TZ,
0719 .gen_caps = TEE_GEN_CAP_GP | TEE_GEN_CAP_REG_MEM |
0720 TEE_GEN_CAP_MEMREF_NULL,
0721 };
0722
0723 *vers = v;
0724 }
0725
0726 static int optee_ffa_open(struct tee_context *ctx)
0727 {
0728 return optee_open(ctx, true);
0729 }
0730
0731 static const struct tee_driver_ops optee_ffa_clnt_ops = {
0732 .get_version = optee_ffa_get_version,
0733 .open = optee_ffa_open,
0734 .release = optee_release,
0735 .open_session = optee_open_session,
0736 .close_session = optee_close_session,
0737 .invoke_func = optee_invoke_func,
0738 .cancel_req = optee_cancel_req,
0739 .shm_register = optee_ffa_shm_register,
0740 .shm_unregister = optee_ffa_shm_unregister,
0741 };
0742
0743 static const struct tee_desc optee_ffa_clnt_desc = {
0744 .name = DRIVER_NAME "-ffa-clnt",
0745 .ops = &optee_ffa_clnt_ops,
0746 .owner = THIS_MODULE,
0747 };
0748
0749 static const struct tee_driver_ops optee_ffa_supp_ops = {
0750 .get_version = optee_ffa_get_version,
0751 .open = optee_ffa_open,
0752 .release = optee_release_supp,
0753 .supp_recv = optee_supp_recv,
0754 .supp_send = optee_supp_send,
0755 .shm_register = optee_ffa_shm_register,
0756 .shm_unregister = optee_ffa_shm_unregister_supp,
0757 };
0758
0759 static const struct tee_desc optee_ffa_supp_desc = {
0760 .name = DRIVER_NAME "-ffa-supp",
0761 .ops = &optee_ffa_supp_ops,
0762 .owner = THIS_MODULE,
0763 .flags = TEE_DESC_PRIVILEGED,
0764 };
0765
0766 static const struct optee_ops optee_ffa_ops = {
0767 .do_call_with_arg = optee_ffa_do_call_with_arg,
0768 .to_msg_param = optee_ffa_to_msg_param,
0769 .from_msg_param = optee_ffa_from_msg_param,
0770 };
0771
0772 static void optee_ffa_remove(struct ffa_device *ffa_dev)
0773 {
0774 struct optee *optee = ffa_dev_get_drvdata(ffa_dev);
0775
0776 optee_remove_common(optee);
0777
0778 mutex_destroy(&optee->ffa.mutex);
0779 rhashtable_free_and_destroy(&optee->ffa.global_ids, rh_free_fn, NULL);
0780
0781 kfree(optee);
0782 }
0783
0784 static int optee_ffa_probe(struct ffa_device *ffa_dev)
0785 {
0786 const struct ffa_dev_ops *ffa_ops;
0787 unsigned int rpc_param_count;
0788 struct tee_shm_pool *pool;
0789 struct tee_device *teedev;
0790 struct tee_context *ctx;
0791 u32 arg_cache_flags = 0;
0792 struct optee *optee;
0793 u32 sec_caps;
0794 int rc;
0795
0796 ffa_ops = ffa_dev_ops_get(ffa_dev);
0797 if (!ffa_ops) {
0798 pr_warn("failed \"method\" init: ffa\n");
0799 return -ENOENT;
0800 }
0801
0802 if (!optee_ffa_api_is_compatbile(ffa_dev, ffa_ops))
0803 return -EINVAL;
0804
0805 if (!optee_ffa_exchange_caps(ffa_dev, ffa_ops, &sec_caps,
0806 &rpc_param_count))
0807 return -EINVAL;
0808 if (sec_caps & OPTEE_FFA_SEC_CAP_ARG_OFFSET)
0809 arg_cache_flags |= OPTEE_SHM_ARG_SHARED;
0810
0811 optee = kzalloc(sizeof(*optee), GFP_KERNEL);
0812 if (!optee)
0813 return -ENOMEM;
0814
0815 pool = optee_ffa_shm_pool_alloc_pages();
0816 if (IS_ERR(pool)) {
0817 rc = PTR_ERR(pool);
0818 goto err_free_optee;
0819 }
0820 optee->pool = pool;
0821
0822 optee->ops = &optee_ffa_ops;
0823 optee->ffa.ffa_dev = ffa_dev;
0824 optee->ffa.ffa_ops = ffa_ops;
0825 optee->rpc_param_count = rpc_param_count;
0826
0827 teedev = tee_device_alloc(&optee_ffa_clnt_desc, NULL, optee->pool,
0828 optee);
0829 if (IS_ERR(teedev)) {
0830 rc = PTR_ERR(teedev);
0831 goto err_free_pool;
0832 }
0833 optee->teedev = teedev;
0834
0835 teedev = tee_device_alloc(&optee_ffa_supp_desc, NULL, optee->pool,
0836 optee);
0837 if (IS_ERR(teedev)) {
0838 rc = PTR_ERR(teedev);
0839 goto err_unreg_teedev;
0840 }
0841 optee->supp_teedev = teedev;
0842
0843 rc = tee_device_register(optee->teedev);
0844 if (rc)
0845 goto err_unreg_supp_teedev;
0846
0847 rc = tee_device_register(optee->supp_teedev);
0848 if (rc)
0849 goto err_unreg_supp_teedev;
0850
0851 rc = rhashtable_init(&optee->ffa.global_ids, &shm_rhash_params);
0852 if (rc)
0853 goto err_unreg_supp_teedev;
0854 mutex_init(&optee->ffa.mutex);
0855 mutex_init(&optee->call_queue.mutex);
0856 INIT_LIST_HEAD(&optee->call_queue.waiters);
0857 optee_supp_init(&optee->supp);
0858 optee_shm_arg_cache_init(optee, arg_cache_flags);
0859 ffa_dev_set_drvdata(ffa_dev, optee);
0860 ctx = teedev_open(optee->teedev);
0861 if (IS_ERR(ctx)) {
0862 rc = PTR_ERR(ctx);
0863 goto err_rhashtable_free;
0864 }
0865 optee->ctx = ctx;
0866 rc = optee_notif_init(optee, OPTEE_DEFAULT_MAX_NOTIF_VALUE);
0867 if (rc)
0868 goto err_close_ctx;
0869
0870 rc = optee_enumerate_devices(PTA_CMD_GET_DEVICES);
0871 if (rc)
0872 goto err_unregister_devices;
0873
0874 pr_info("initialized driver\n");
0875 return 0;
0876
0877 err_unregister_devices:
0878 optee_unregister_devices();
0879 optee_notif_uninit(optee);
0880 err_close_ctx:
0881 teedev_close_context(ctx);
0882 err_rhashtable_free:
0883 rhashtable_free_and_destroy(&optee->ffa.global_ids, rh_free_fn, NULL);
0884 optee_supp_uninit(&optee->supp);
0885 mutex_destroy(&optee->call_queue.mutex);
0886 mutex_destroy(&optee->ffa.mutex);
0887 err_unreg_supp_teedev:
0888 tee_device_unregister(optee->supp_teedev);
0889 err_unreg_teedev:
0890 tee_device_unregister(optee->teedev);
0891 err_free_pool:
0892 tee_shm_pool_free(pool);
0893 err_free_optee:
0894 kfree(optee);
0895 return rc;
0896 }
0897
0898 static const struct ffa_device_id optee_ffa_device_id[] = {
0899
0900 { UUID_INIT(0x486178e0, 0xe7f8, 0x11e3,
0901 0xbc, 0x5e, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b) },
0902 {}
0903 };
0904
0905 static struct ffa_driver optee_ffa_driver = {
0906 .name = "optee",
0907 .probe = optee_ffa_probe,
0908 .remove = optee_ffa_remove,
0909 .id_table = optee_ffa_device_id,
0910 };
0911
0912 int optee_ffa_abi_register(void)
0913 {
0914 if (IS_REACHABLE(CONFIG_ARM_FFA_TRANSPORT))
0915 return ffa_register(&optee_ffa_driver);
0916 else
0917 return -EOPNOTSUPP;
0918 }
0919
0920 void optee_ffa_abi_unregister(void)
0921 {
0922 if (IS_REACHABLE(CONFIG_ARM_FFA_TRANSPORT))
0923 ffa_unregister(&optee_ffa_driver);
0924 }