1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (c) 2021, 2023 Linaro Limited
4 */
5
6 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7
8 #include <linux/arm_ffa.h>
9 #include <linux/errno.h>
10 #include <linux/rpmb.h>
11 #include <linux/scatterlist.h>
12 #include <linux/sched.h>
13 #include <linux/slab.h>
14 #include <linux/string.h>
15 #include <linux/tee_core.h>
16 #include <linux/types.h>
17 #include "optee_private.h"
18 #include "optee_ffa.h"
19 #include "optee_rpc_cmd.h"
20
21 /*
22 * This file implement the FF-A ABI used when communicating with secure world
23 * OP-TEE OS via FF-A.
24 * This file is divided into the following sections:
25 * 1. Maintain a hash table for lookup of a global FF-A memory handle
26 * 2. Convert between struct tee_param and struct optee_msg_param
27 * 3. Low level support functions to register shared memory in secure world
28 * 4. Dynamic shared memory pool based on alloc_pages()
29 * 5. Do a normal scheduled call into secure world
30 * 6. Driver initialization.
31 */
32
33 /*
34 * 1. Maintain a hash table for lookup of a global FF-A memory handle
35 *
36 * FF-A assigns a global memory handle for each piece shared memory.
37 * This handle is then used when communicating with secure world.
38 *
39 * Main functions are optee_shm_add_ffa_handle() and optee_shm_rem_ffa_handle()
40 */
41 struct shm_rhash {
42 struct tee_shm *shm;
43 u64 global_id;
44 struct rhash_head linkage;
45 };
46
rh_free_fn(void * ptr,void * arg)47 static void rh_free_fn(void *ptr, void *arg)
48 {
49 kfree(ptr);
50 }
51
52 static const struct rhashtable_params shm_rhash_params = {
53 .head_offset = offsetof(struct shm_rhash, linkage),
54 .key_len = sizeof(u64),
55 .key_offset = offsetof(struct shm_rhash, global_id),
56 .automatic_shrinking = true,
57 };
58
optee_shm_from_ffa_handle(struct optee * optee,u64 global_id)59 static struct tee_shm *optee_shm_from_ffa_handle(struct optee *optee,
60 u64 global_id)
61 {
62 struct tee_shm *shm = NULL;
63 struct shm_rhash *r;
64
65 mutex_lock(&optee->ffa.mutex);
66 r = rhashtable_lookup_fast(&optee->ffa.global_ids, &global_id,
67 shm_rhash_params);
68 if (r)
69 shm = r->shm;
70 mutex_unlock(&optee->ffa.mutex);
71
72 return shm;
73 }
74
optee_shm_add_ffa_handle(struct optee * optee,struct tee_shm * shm,u64 global_id)75 static int optee_shm_add_ffa_handle(struct optee *optee, struct tee_shm *shm,
76 u64 global_id)
77 {
78 struct shm_rhash *r;
79 int rc;
80
81 r = kmalloc_obj(*r);
82 if (!r)
83 return -ENOMEM;
84 r->shm = shm;
85 r->global_id = global_id;
86
87 mutex_lock(&optee->ffa.mutex);
88 rc = rhashtable_lookup_insert_fast(&optee->ffa.global_ids, &r->linkage,
89 shm_rhash_params);
90 mutex_unlock(&optee->ffa.mutex);
91
92 if (rc)
93 kfree(r);
94
95 return rc;
96 }
97
optee_shm_rem_ffa_handle(struct optee * optee,u64 global_id)98 static int optee_shm_rem_ffa_handle(struct optee *optee, u64 global_id)
99 {
100 struct shm_rhash *r;
101 int rc = -ENOENT;
102
103 mutex_lock(&optee->ffa.mutex);
104 r = rhashtable_lookup_fast(&optee->ffa.global_ids, &global_id,
105 shm_rhash_params);
106 if (r)
107 rc = rhashtable_remove_fast(&optee->ffa.global_ids,
108 &r->linkage, shm_rhash_params);
109 mutex_unlock(&optee->ffa.mutex);
110
111 if (!rc)
112 kfree(r);
113
114 return rc;
115 }
116
117 /*
118 * 2. Convert between struct tee_param and struct optee_msg_param
119 *
120 * optee_ffa_from_msg_param() and optee_ffa_to_msg_param() are the main
121 * functions.
122 */
123
from_msg_param_ffa_mem(struct optee * optee,struct tee_param * p,u32 attr,const struct optee_msg_param * mp)124 static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
125 u32 attr, const struct optee_msg_param *mp)
126 {
127 struct tee_shm *shm = NULL;
128 u64 offs_high = 0;
129 u64 offs_low = 0;
130
131 p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
132 attr - OPTEE_MSG_ATTR_TYPE_FMEM_INPUT;
133 p->u.memref.size = mp->u.fmem.size;
134
135 if (mp->u.fmem.global_id != OPTEE_MSG_FMEM_INVALID_GLOBAL_ID)
136 shm = optee_shm_from_ffa_handle(optee, mp->u.fmem.global_id);
137 p->u.memref.shm = shm;
138
139 if (shm) {
140 offs_low = mp->u.fmem.offs_low;
141 offs_high = mp->u.fmem.offs_high;
142 }
143 p->u.memref.shm_offs = offs_low | offs_high << 32;
144 }
145
146 /**
147 * optee_ffa_from_msg_param() - convert from OPTEE_MSG parameters to
148 * struct tee_param
149 * @optee: main service struct
150 * @params: subsystem internal parameter representation
151 * @num_params: number of elements in the parameter arrays
152 * @msg_params: OPTEE_MSG parameters
153 *
154 * Returns 0 on success or <0 on failure
155 */
optee_ffa_from_msg_param(struct optee * optee,struct tee_param * params,size_t num_params,const struct optee_msg_param * msg_params)156 static int optee_ffa_from_msg_param(struct optee *optee,
157 struct tee_param *params, size_t num_params,
158 const struct optee_msg_param *msg_params)
159 {
160 size_t n;
161
162 for (n = 0; n < num_params; n++) {
163 struct tee_param *p = params + n;
164 const struct optee_msg_param *mp = msg_params + n;
165 u32 attr = mp->attr & OPTEE_MSG_ATTR_TYPE_MASK;
166
167 switch (attr) {
168 case OPTEE_MSG_ATTR_TYPE_NONE:
169 p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
170 memset(&p->u, 0, sizeof(p->u));
171 break;
172 case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
173 case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
174 case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
175 optee_from_msg_param_value(p, attr, mp);
176 break;
177 case OPTEE_MSG_ATTR_TYPE_FMEM_INPUT:
178 case OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT:
179 case OPTEE_MSG_ATTR_TYPE_FMEM_INOUT:
180 from_msg_param_ffa_mem(optee, p, attr, mp);
181 break;
182 default:
183 return -EINVAL;
184 }
185 }
186
187 return 0;
188 }
189
to_msg_param_ffa_mem(struct optee_msg_param * mp,const struct tee_param * p)190 static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
191 const struct tee_param *p)
192 {
193 struct tee_shm *shm = p->u.memref.shm;
194
195 mp->attr = OPTEE_MSG_ATTR_TYPE_FMEM_INPUT + p->attr -
196 TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
197
198 if (shm) {
199 u64 shm_offs = p->u.memref.shm_offs;
200
201 mp->u.fmem.internal_offs = tee_shm_get_page_offset(shm) &
202 (FFA_PAGE_SIZE - 1);
203
204 mp->u.fmem.offs_low = shm_offs;
205 mp->u.fmem.offs_high = shm_offs >> 32;
206 /* Check that the entire offset could be stored. */
207 if (mp->u.fmem.offs_high != shm_offs >> 32)
208 return -EINVAL;
209
210 mp->u.fmem.global_id = shm->sec_world_id;
211 } else {
212 memset(&mp->u, 0, sizeof(mp->u));
213 mp->u.fmem.global_id = OPTEE_MSG_FMEM_INVALID_GLOBAL_ID;
214 }
215 mp->u.fmem.size = p->u.memref.size;
216
217 return 0;
218 }
219
220 /**
221 * optee_ffa_to_msg_param() - convert from struct tee_params to OPTEE_MSG
222 * parameters
223 * @optee: main service struct
224 * @msg_params: OPTEE_MSG parameters
225 * @num_params: number of elements in the parameter arrays
226 * @params: subsystem itnernal parameter representation
227 * Returns 0 on success or <0 on failure
228 */
optee_ffa_to_msg_param(struct optee * optee,struct optee_msg_param * msg_params,size_t num_params,const struct tee_param * params)229 static int optee_ffa_to_msg_param(struct optee *optee,
230 struct optee_msg_param *msg_params,
231 size_t num_params,
232 const struct tee_param *params)
233 {
234 size_t n;
235
236 for (n = 0; n < num_params; n++) {
237 const struct tee_param *p = params + n;
238 struct optee_msg_param *mp = msg_params + n;
239
240 switch (p->attr) {
241 case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
242 mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
243 memset(&mp->u, 0, sizeof(mp->u));
244 break;
245 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
246 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
247 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
248 optee_to_msg_param_value(mp, p);
249 break;
250 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
251 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
252 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
253 if (to_msg_param_ffa_mem(mp, p))
254 return -EINVAL;
255 break;
256 default:
257 return -EINVAL;
258 }
259 }
260
261 return 0;
262 }
263
264 /*
265 * 3. Low level support functions to register shared memory in secure world
266 *
267 * Functions to register and unregister shared memory both for normal
268 * clients and for tee-supplicant.
269 */
270
optee_ffa_shm_register(struct tee_context * ctx,struct tee_shm * shm,struct page ** pages,size_t num_pages,unsigned long start)271 static int optee_ffa_shm_register(struct tee_context *ctx, struct tee_shm *shm,
272 struct page **pages, size_t num_pages,
273 unsigned long start)
274 {
275 struct optee *optee = tee_get_drvdata(ctx->teedev);
276 struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
277 const struct ffa_mem_ops *mem_ops = ffa_dev->ops->mem_ops;
278 struct ffa_mem_region_attributes mem_attr = {
279 .receiver = ffa_dev->vm_id,
280 .attrs = FFA_MEM_RW,
281 };
282 struct ffa_mem_ops_args args = {
283 .use_txbuf = true,
284 .attrs = &mem_attr,
285 .nattrs = 1,
286 };
287 struct sg_table sgt;
288 size_t ffa_offs;
289 int rc;
290
291 if (!num_pages)
292 return -EINVAL;
293
294 rc = optee_check_mem_type(start, num_pages);
295 if (rc)
296 return rc;
297
298 /*
299 * Start the FF-A descriptor at the 4 KiB page containing the shared
300 * buffer, skipping unused leading 4 KiB pages when PAGE_SIZE is
301 * larger. Same approach as optee_fill_pages_list() in the SMC ABI.
302 * This leaves only the offset into that 4 KiB page for internal_offs.
303 */
304 ffa_offs = round_down(tee_shm_get_page_offset(shm), FFA_PAGE_SIZE);
305 rc = sg_alloc_table_from_pages(&sgt, pages, num_pages, ffa_offs,
306 num_pages * PAGE_SIZE - ffa_offs,
307 GFP_KERNEL);
308 if (rc)
309 return rc;
310 args.sg = sgt.sgl;
311 rc = mem_ops->memory_share(&args);
312 sg_free_table(&sgt);
313 if (rc)
314 return rc;
315
316 rc = optee_shm_add_ffa_handle(optee, shm, args.g_handle);
317 if (rc) {
318 mem_ops->memory_reclaim(args.g_handle, 0);
319 return rc;
320 }
321
322 shm->sec_world_id = args.g_handle;
323
324 return 0;
325 }
326
optee_ffa_shm_unregister(struct tee_context * ctx,struct tee_shm * shm)327 static int optee_ffa_shm_unregister(struct tee_context *ctx,
328 struct tee_shm *shm)
329 {
330 struct optee *optee = tee_get_drvdata(ctx->teedev);
331 struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
332 const struct ffa_msg_ops *msg_ops = ffa_dev->ops->msg_ops;
333 const struct ffa_mem_ops *mem_ops = ffa_dev->ops->mem_ops;
334 u64 global_handle = shm->sec_world_id;
335 struct ffa_send_direct_data data = {
336 .data0 = OPTEE_FFA_UNREGISTER_SHM,
337 .data1 = (u32)global_handle,
338 .data2 = (u32)(global_handle >> 32)
339 };
340 int rc;
341
342 optee_shm_rem_ffa_handle(optee, global_handle);
343 shm->sec_world_id = 0;
344
345 rc = msg_ops->sync_send_receive(ffa_dev, &data);
346 if (rc)
347 pr_err("Unregister SHM id 0x%llx rc %d\n", global_handle, rc);
348
349 rc = mem_ops->memory_reclaim(global_handle, 0);
350 if (rc)
351 pr_err("mem_reclaim: 0x%llx %d", global_handle, rc);
352
353 return rc;
354 }
355
optee_ffa_shm_unregister_supp(struct tee_context * ctx,struct tee_shm * shm)356 static int optee_ffa_shm_unregister_supp(struct tee_context *ctx,
357 struct tee_shm *shm)
358 {
359 struct optee *optee = tee_get_drvdata(ctx->teedev);
360 const struct ffa_mem_ops *mem_ops;
361 u64 global_handle = shm->sec_world_id;
362 int rc;
363
364 /*
365 * We're skipping the OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM call
366 * since this is OP-TEE freeing via RPC so it has already retired
367 * this ID.
368 */
369
370 optee_shm_rem_ffa_handle(optee, global_handle);
371 mem_ops = optee->ffa.ffa_dev->ops->mem_ops;
372 rc = mem_ops->memory_reclaim(global_handle, 0);
373 if (rc)
374 pr_err("mem_reclaim: 0x%llx %d", global_handle, rc);
375
376 shm->sec_world_id = 0;
377
378 return rc;
379 }
380
381 /*
382 * 4. Dynamic shared memory pool based on alloc_pages()
383 *
384 * Implements an OP-TEE specific shared memory pool.
385 * The main function is optee_ffa_shm_pool_alloc_pages().
386 */
387
pool_ffa_op_alloc(struct tee_shm_pool * pool,struct tee_shm * shm,size_t size,size_t align)388 static int pool_ffa_op_alloc(struct tee_shm_pool *pool,
389 struct tee_shm *shm, size_t size, size_t align)
390 {
391 return tee_dyn_shm_alloc_helper(shm, size, align,
392 optee_ffa_shm_register);
393 }
394
pool_ffa_op_free(struct tee_shm_pool * pool,struct tee_shm * shm)395 static void pool_ffa_op_free(struct tee_shm_pool *pool,
396 struct tee_shm *shm)
397 {
398 tee_dyn_shm_free_helper(shm, optee_ffa_shm_unregister);
399 }
400
pool_ffa_op_destroy_pool(struct tee_shm_pool * pool)401 static void pool_ffa_op_destroy_pool(struct tee_shm_pool *pool)
402 {
403 kfree(pool);
404 }
405
406 static const struct tee_shm_pool_ops pool_ffa_ops = {
407 .alloc = pool_ffa_op_alloc,
408 .free = pool_ffa_op_free,
409 .destroy_pool = pool_ffa_op_destroy_pool,
410 };
411
412 /**
413 * optee_ffa_shm_pool_alloc_pages() - create page-based allocator pool
414 *
415 * This pool is used with OP-TEE over FF-A. In this case command buffers
416 * and such are allocated from kernel's own memory.
417 */
optee_ffa_shm_pool_alloc_pages(void)418 static struct tee_shm_pool *optee_ffa_shm_pool_alloc_pages(void)
419 {
420 struct tee_shm_pool *pool = kzalloc_obj(*pool);
421
422 if (!pool)
423 return ERR_PTR(-ENOMEM);
424
425 pool->ops = &pool_ffa_ops;
426
427 return pool;
428 }
429
430 /*
431 * 5. Do a normal scheduled call into secure world
432 *
433 * The function optee_ffa_do_call_with_arg() performs a normal scheduled
434 * call into secure world. During this call may normal world request help
435 * from normal world using RPCs, Remote Procedure Calls. This includes
436 * delivery of non-secure interrupts to for instance allow rescheduling of
437 * the current task.
438 */
439
handle_ffa_rpc_func_cmd_shm_alloc(struct tee_context * ctx,struct optee * optee,struct optee_msg_arg * arg)440 static void handle_ffa_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
441 struct optee *optee,
442 struct optee_msg_arg *arg)
443 {
444 struct tee_shm *shm;
445
446 if (arg->num_params != 1 ||
447 arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) {
448 arg->ret = TEEC_ERROR_BAD_PARAMETERS;
449 return;
450 }
451
452 switch (arg->params[0].u.value.a) {
453 case OPTEE_RPC_SHM_TYPE_APPL:
454 shm = optee_rpc_cmd_alloc_suppl(ctx, arg->params[0].u.value.b);
455 break;
456 case OPTEE_RPC_SHM_TYPE_KERNEL:
457 shm = tee_shm_alloc_priv_buf(optee->ctx,
458 arg->params[0].u.value.b);
459 break;
460 default:
461 arg->ret = TEEC_ERROR_BAD_PARAMETERS;
462 return;
463 }
464
465 if (IS_ERR(shm)) {
466 arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
467 return;
468 }
469
470 arg->params[0] = (struct optee_msg_param){
471 .attr = OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT,
472 .u.fmem.size = tee_shm_get_size(shm),
473 .u.fmem.global_id = shm->sec_world_id,
474 .u.fmem.internal_offs = tee_shm_get_page_offset(shm) &
475 (FFA_PAGE_SIZE - 1),
476 };
477
478 arg->ret = TEEC_SUCCESS;
479 }
480
handle_ffa_rpc_func_cmd_shm_free(struct tee_context * ctx,struct optee * optee,struct optee_msg_arg * arg)481 static void handle_ffa_rpc_func_cmd_shm_free(struct tee_context *ctx,
482 struct optee *optee,
483 struct optee_msg_arg *arg)
484 {
485 struct tee_shm *shm;
486
487 if (arg->num_params != 1 ||
488 arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT)
489 goto err_bad_param;
490
491 shm = optee_shm_from_ffa_handle(optee, arg->params[0].u.value.b);
492 if (!shm)
493 goto err_bad_param;
494 switch (arg->params[0].u.value.a) {
495 case OPTEE_RPC_SHM_TYPE_APPL:
496 optee_rpc_cmd_free_suppl(ctx, shm);
497 break;
498 case OPTEE_RPC_SHM_TYPE_KERNEL:
499 tee_shm_free(shm);
500 break;
501 default:
502 goto err_bad_param;
503 }
504 arg->ret = TEEC_SUCCESS;
505 return;
506
507 err_bad_param:
508 arg->ret = TEEC_ERROR_BAD_PARAMETERS;
509 }
510
handle_ffa_rpc_func_cmd(struct tee_context * ctx,struct optee * optee,struct optee_msg_arg * arg)511 static void handle_ffa_rpc_func_cmd(struct tee_context *ctx,
512 struct optee *optee,
513 struct optee_msg_arg *arg)
514 {
515 arg->ret_origin = TEEC_ORIGIN_COMMS;
516 switch (arg->cmd) {
517 case OPTEE_RPC_CMD_SHM_ALLOC:
518 handle_ffa_rpc_func_cmd_shm_alloc(ctx, optee, arg);
519 break;
520 case OPTEE_RPC_CMD_SHM_FREE:
521 handle_ffa_rpc_func_cmd_shm_free(ctx, optee, arg);
522 break;
523 default:
524 optee_rpc_cmd(ctx, optee, arg);
525 }
526 }
527
optee_handle_ffa_rpc(struct tee_context * ctx,struct optee * optee,u32 cmd,struct optee_msg_arg * arg)528 static void optee_handle_ffa_rpc(struct tee_context *ctx, struct optee *optee,
529 u32 cmd, struct optee_msg_arg *arg)
530 {
531 switch (cmd) {
532 case OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD:
533 handle_ffa_rpc_func_cmd(ctx, optee, arg);
534 break;
535 case OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT:
536 /* Interrupt delivered by now */
537 break;
538 default:
539 pr_warn("Unknown RPC func 0x%x\n", cmd);
540 break;
541 }
542 }
543
optee_ffa_yielding_call(struct tee_context * ctx,struct ffa_send_direct_data * data,struct optee_msg_arg * rpc_arg,bool system_thread)544 static int optee_ffa_yielding_call(struct tee_context *ctx,
545 struct ffa_send_direct_data *data,
546 struct optee_msg_arg *rpc_arg,
547 bool system_thread)
548 {
549 struct optee *optee = tee_get_drvdata(ctx->teedev);
550 struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
551 const struct ffa_msg_ops *msg_ops = ffa_dev->ops->msg_ops;
552 struct optee_call_waiter w;
553 u32 cmd = data->data0;
554 u32 w4 = data->data1;
555 u32 w5 = data->data2;
556 u32 w6 = data->data3;
557 int rc;
558
559 /* Initialize waiter */
560 optee_cq_wait_init(&optee->call_queue, &w, system_thread);
561 while (true) {
562 rc = msg_ops->sync_send_receive(ffa_dev, data);
563 if (rc)
564 goto done;
565
566 switch ((int)data->data0) {
567 case TEEC_SUCCESS:
568 break;
569 case TEEC_ERROR_BUSY:
570 if (cmd == OPTEE_FFA_YIELDING_CALL_RESUME) {
571 rc = -EIO;
572 goto done;
573 }
574
575 /*
576 * Out of threads in secure world, wait for a thread
577 * become available.
578 */
579 optee_cq_wait_for_completion(&optee->call_queue, &w);
580 data->data0 = cmd;
581 data->data1 = w4;
582 data->data2 = w5;
583 data->data3 = w6;
584 continue;
585 default:
586 rc = -EIO;
587 goto done;
588 }
589
590 if (data->data1 == OPTEE_FFA_YIELDING_CALL_RETURN_DONE)
591 goto done;
592
593 /*
594 * OP-TEE has returned with a RPC request.
595 *
596 * Note that data->data4 (passed in register w7) is already
597 * filled in by ffa_mem_ops->sync_send_receive() returning
598 * above.
599 */
600 cond_resched();
601 optee_handle_ffa_rpc(ctx, optee, data->data1, rpc_arg);
602 cmd = OPTEE_FFA_YIELDING_CALL_RESUME;
603 data->data0 = cmd;
604 data->data1 = 0;
605 data->data2 = 0;
606 data->data3 = 0;
607 }
608 done:
609 /*
610 * We're done with our thread in secure world, if there's any
611 * thread waiters wake up one.
612 */
613 optee_cq_wait_final(&optee->call_queue, &w);
614
615 return rc;
616 }
617
618 /**
619 * optee_ffa_do_call_with_arg() - Do a FF-A call to enter OP-TEE in secure world
620 * @ctx: calling context
621 * @shm: shared memory holding the message to pass to secure world
622 * @offs: offset of the message in @shm
623 * @system_thread: true if caller requests TEE system thread support
624 *
625 * Does a FF-A call to OP-TEE in secure world and handles eventual resulting
626 * Remote Procedure Calls (RPC) from OP-TEE.
627 *
628 * Returns return code from FF-A, 0 is OK
629 */
630
optee_ffa_do_call_with_arg(struct tee_context * ctx,struct tee_shm * shm,u_int offs,bool system_thread)631 static int optee_ffa_do_call_with_arg(struct tee_context *ctx,
632 struct tee_shm *shm, u_int offs,
633 bool system_thread)
634 {
635 struct ffa_send_direct_data data = {
636 .data0 = OPTEE_FFA_YIELDING_CALL_WITH_ARG,
637 .data1 = (u32)shm->sec_world_id,
638 .data2 = (u32)(shm->sec_world_id >> 32),
639 .data3 = offs,
640 };
641 struct optee_msg_arg *arg;
642 unsigned int rpc_arg_offs;
643 struct optee_msg_arg *rpc_arg;
644
645 /*
646 * The shared memory object has to start on a page when passed as
647 * an argument struct. This is also what the shm pool allocator
648 * returns, but check this before calling secure world to catch
649 * eventual errors early in case something changes.
650 */
651 if (shm->offset)
652 return -EINVAL;
653
654 arg = tee_shm_get_va(shm, offs);
655 if (IS_ERR(arg))
656 return PTR_ERR(arg);
657
658 rpc_arg_offs = OPTEE_MSG_GET_ARG_SIZE(arg->num_params);
659 rpc_arg = tee_shm_get_va(shm, offs + rpc_arg_offs);
660 if (IS_ERR(rpc_arg))
661 return PTR_ERR(rpc_arg);
662
663 return optee_ffa_yielding_call(ctx, &data, rpc_arg, system_thread);
664 }
665
do_call_lend_protmem(struct optee * optee,u64 cookie,u32 use_case)666 static int do_call_lend_protmem(struct optee *optee, u64 cookie, u32 use_case)
667 {
668 struct optee_shm_arg_entry *entry;
669 struct optee_msg_arg *msg_arg;
670 struct tee_shm *shm;
671 u_int offs;
672 int rc;
673
674 msg_arg = optee_get_msg_arg(optee->ctx, 1, &entry, &shm, &offs);
675 if (IS_ERR(msg_arg))
676 return PTR_ERR(msg_arg);
677
678 msg_arg->cmd = OPTEE_MSG_CMD_ASSIGN_PROTMEM;
679 msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
680 msg_arg->params[0].u.value.a = cookie;
681 msg_arg->params[0].u.value.b = use_case;
682
683 rc = optee->ops->do_call_with_arg(optee->ctx, shm, offs, false);
684 if (rc)
685 goto out;
686 if (msg_arg->ret != TEEC_SUCCESS) {
687 rc = -EINVAL;
688 goto out;
689 }
690
691 out:
692 optee_free_msg_arg(optee->ctx, entry, offs);
693 return rc;
694 }
695
optee_ffa_lend_protmem(struct optee * optee,struct tee_shm * protmem,u32 * mem_attrs,unsigned int ma_count,u32 use_case)696 static int optee_ffa_lend_protmem(struct optee *optee, struct tee_shm *protmem,
697 u32 *mem_attrs, unsigned int ma_count,
698 u32 use_case)
699 {
700 struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
701 const struct ffa_mem_ops *mem_ops = ffa_dev->ops->mem_ops;
702 const struct ffa_msg_ops *msg_ops = ffa_dev->ops->msg_ops;
703 struct ffa_send_direct_data data;
704 struct ffa_mem_region_attributes *mem_attr;
705 struct ffa_mem_ops_args args = {
706 .use_txbuf = true,
707 .tag = use_case,
708 };
709 struct page *page;
710 struct scatterlist sgl;
711 unsigned int n;
712 int rc;
713
714 mem_attr = kzalloc_objs(*mem_attr, ma_count);
715 if (!mem_attr)
716 return -ENOMEM;
717
718 for (n = 0; n < ma_count; n++) {
719 mem_attr[n].receiver = mem_attrs[n] & U16_MAX;
720 mem_attr[n].attrs = mem_attrs[n] >> 16;
721 }
722 args.attrs = mem_attr;
723 args.nattrs = ma_count;
724
725 page = phys_to_page(protmem->paddr);
726 sg_init_table(&sgl, 1);
727 sg_set_page(&sgl, page, protmem->size, 0);
728
729 args.sg = &sgl;
730 rc = mem_ops->memory_lend(&args);
731 kfree(mem_attr);
732 if (rc)
733 return rc;
734
735 rc = do_call_lend_protmem(optee, args.g_handle, use_case);
736 if (rc)
737 goto err_reclaim;
738
739 rc = optee_shm_add_ffa_handle(optee, protmem, args.g_handle);
740 if (rc)
741 goto err_unreg;
742
743 protmem->sec_world_id = args.g_handle;
744
745 return 0;
746
747 err_unreg:
748 data = (struct ffa_send_direct_data){
749 .data0 = OPTEE_FFA_RELEASE_PROTMEM,
750 .data1 = (u32)args.g_handle,
751 .data2 = (u32)(args.g_handle >> 32),
752 };
753 msg_ops->sync_send_receive(ffa_dev, &data);
754 err_reclaim:
755 mem_ops->memory_reclaim(args.g_handle, 0);
756 return rc;
757 }
758
optee_ffa_reclaim_protmem(struct optee * optee,struct tee_shm * protmem)759 static int optee_ffa_reclaim_protmem(struct optee *optee,
760 struct tee_shm *protmem)
761 {
762 struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
763 const struct ffa_msg_ops *msg_ops = ffa_dev->ops->msg_ops;
764 const struct ffa_mem_ops *mem_ops = ffa_dev->ops->mem_ops;
765 u64 global_handle = protmem->sec_world_id;
766 struct ffa_send_direct_data data = {
767 .data0 = OPTEE_FFA_RELEASE_PROTMEM,
768 .data1 = (u32)global_handle,
769 .data2 = (u32)(global_handle >> 32)
770 };
771 int rc;
772
773 optee_shm_rem_ffa_handle(optee, global_handle);
774 protmem->sec_world_id = 0;
775
776 rc = msg_ops->sync_send_receive(ffa_dev, &data);
777 if (rc)
778 pr_err("Release SHM id 0x%llx rc %d\n", global_handle, rc);
779
780 rc = mem_ops->memory_reclaim(global_handle, 0);
781 if (rc)
782 pr_err("mem_reclaim: 0x%llx %d", global_handle, rc);
783
784 return rc;
785 }
786
787 /*
788 * 6. Driver initialization
789 *
790 * During driver inititialization is the OP-TEE Secure Partition is probed
791 * to find out which features it supports so the driver can be initialized
792 * with a matching configuration.
793 */
794
optee_ffa_get_os_revision(struct ffa_device * ffa_dev,const struct ffa_ops * ops,struct optee_revision * revision)795 static bool optee_ffa_get_os_revision(struct ffa_device *ffa_dev,
796 const struct ffa_ops *ops,
797 struct optee_revision *revision)
798 {
799 const struct ffa_msg_ops *msg_ops = ops->msg_ops;
800 struct ffa_send_direct_data data = {
801 .data0 = OPTEE_FFA_GET_OS_VERSION,
802 };
803 int rc;
804
805 msg_ops->mode_32bit_set(ffa_dev);
806
807 rc = msg_ops->sync_send_receive(ffa_dev, &data);
808 if (rc) {
809 pr_err("Unexpected error %d\n", rc);
810 return false;
811 }
812
813 if (revision) {
814 revision->os_major = data.data0;
815 revision->os_minor = data.data1;
816 revision->os_build_id = data.data2;
817 }
818
819 if (data.data2)
820 pr_info("revision %lu.%lu (%08lx)",
821 data.data0, data.data1, data.data2);
822 else
823 pr_info("revision %lu.%lu", data.data0, data.data1);
824
825 return true;
826 }
827
optee_ffa_api_is_compatible(struct ffa_device * ffa_dev,const struct ffa_ops * ops)828 static bool optee_ffa_api_is_compatible(struct ffa_device *ffa_dev,
829 const struct ffa_ops *ops)
830 {
831 const struct ffa_msg_ops *msg_ops = ops->msg_ops;
832 struct ffa_send_direct_data data = {
833 .data0 = OPTEE_FFA_GET_API_VERSION,
834 };
835 int rc;
836
837 msg_ops->mode_32bit_set(ffa_dev);
838
839 rc = msg_ops->sync_send_receive(ffa_dev, &data);
840 if (rc) {
841 pr_err("Unexpected error %d\n", rc);
842 return false;
843 }
844 if (data.data0 != OPTEE_FFA_VERSION_MAJOR ||
845 data.data1 < OPTEE_FFA_VERSION_MINOR) {
846 pr_err("Incompatible OP-TEE API version %lu.%lu",
847 data.data0, data.data1);
848 return false;
849 }
850
851 return true;
852 }
853
optee_ffa_exchange_caps(struct ffa_device * ffa_dev,const struct ffa_ops * ops,u32 * sec_caps,unsigned int * rpc_param_count,unsigned int * max_notif_value)854 static bool optee_ffa_exchange_caps(struct ffa_device *ffa_dev,
855 const struct ffa_ops *ops,
856 u32 *sec_caps,
857 unsigned int *rpc_param_count,
858 unsigned int *max_notif_value)
859 {
860 struct ffa_send_direct_data data = {
861 .data0 = OPTEE_FFA_EXCHANGE_CAPABILITIES,
862 };
863 int rc;
864
865 rc = ops->msg_ops->sync_send_receive(ffa_dev, &data);
866 if (rc) {
867 pr_err("Unexpected error %d", rc);
868 return false;
869 }
870 if (data.data0) {
871 pr_err("Unexpected exchange error %lu", data.data0);
872 return false;
873 }
874
875 *rpc_param_count = (u8)data.data1;
876 *sec_caps = data.data2;
877 if (data.data3)
878 *max_notif_value = data.data3;
879 else
880 *max_notif_value = OPTEE_DEFAULT_MAX_NOTIF_VALUE;
881
882 return true;
883 }
884
notif_work_fn(struct work_struct * work)885 static void notif_work_fn(struct work_struct *work)
886 {
887 struct optee_ffa *optee_ffa = container_of(work, struct optee_ffa,
888 notif_work);
889 struct optee *optee = container_of(optee_ffa, struct optee, ffa);
890
891 optee_do_bottom_half(optee->ctx);
892 }
893
notif_callback(int notify_id,void * cb_data)894 static void notif_callback(int notify_id, void *cb_data)
895 {
896 struct optee *optee = cb_data;
897
898 if (notify_id == optee->ffa.bottom_half_value)
899 queue_work(optee->ffa.notif_wq, &optee->ffa.notif_work);
900 else
901 optee_notif_send(optee, notify_id);
902 }
903
enable_async_notif(struct optee * optee)904 static int enable_async_notif(struct optee *optee)
905 {
906 struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
907 struct ffa_send_direct_data data = {
908 .data0 = OPTEE_FFA_ENABLE_ASYNC_NOTIF,
909 .data1 = optee->ffa.bottom_half_value,
910 };
911 int rc;
912
913 rc = ffa_dev->ops->msg_ops->sync_send_receive(ffa_dev, &data);
914 if (rc)
915 return rc;
916 return data.data0;
917 }
918
optee_ffa_get_version(struct tee_device * teedev,struct tee_ioctl_version_data * vers)919 static void optee_ffa_get_version(struct tee_device *teedev,
920 struct tee_ioctl_version_data *vers)
921 {
922 struct tee_ioctl_version_data v = {
923 .impl_id = TEE_IMPL_ID_OPTEE,
924 .impl_caps = TEE_OPTEE_CAP_TZ,
925 .gen_caps = TEE_GEN_CAP_GP | TEE_GEN_CAP_REG_MEM |
926 TEE_GEN_CAP_MEMREF_NULL,
927 };
928
929 *vers = v;
930 }
931
optee_ffa_open(struct tee_context * ctx)932 static int optee_ffa_open(struct tee_context *ctx)
933 {
934 return optee_open(ctx, true);
935 }
936
937 static const struct tee_driver_ops optee_ffa_clnt_ops = {
938 .get_version = optee_ffa_get_version,
939 .get_tee_revision = optee_get_revision,
940 .open = optee_ffa_open,
941 .release = optee_release,
942 .open_session = optee_open_session,
943 .close_session = optee_close_session,
944 .invoke_func = optee_invoke_func,
945 .cancel_req = optee_cancel_req,
946 .shm_register = optee_ffa_shm_register,
947 .shm_unregister = optee_ffa_shm_unregister,
948 };
949
950 static const struct tee_desc optee_ffa_clnt_desc = {
951 .name = DRIVER_NAME "-ffa-clnt",
952 .ops = &optee_ffa_clnt_ops,
953 .owner = THIS_MODULE,
954 };
955
956 static const struct tee_driver_ops optee_ffa_supp_ops = {
957 .get_version = optee_ffa_get_version,
958 .get_tee_revision = optee_get_revision,
959 .open = optee_ffa_open,
960 .release = optee_release_supp,
961 .supp_recv = optee_supp_recv,
962 .supp_send = optee_supp_send,
963 .shm_register = optee_ffa_shm_register, /* same as for clnt ops */
964 .shm_unregister = optee_ffa_shm_unregister_supp,
965 };
966
967 static const struct tee_desc optee_ffa_supp_desc = {
968 .name = DRIVER_NAME "-ffa-supp",
969 .ops = &optee_ffa_supp_ops,
970 .owner = THIS_MODULE,
971 .flags = TEE_DESC_PRIVILEGED,
972 };
973
974 static const struct optee_ops optee_ffa_ops = {
975 .do_call_with_arg = optee_ffa_do_call_with_arg,
976 .to_msg_param = optee_ffa_to_msg_param,
977 .from_msg_param = optee_ffa_from_msg_param,
978 .lend_protmem = optee_ffa_lend_protmem,
979 .reclaim_protmem = optee_ffa_reclaim_protmem,
980 };
981
optee_ffa_remove(struct ffa_device * ffa_dev)982 static void optee_ffa_remove(struct ffa_device *ffa_dev)
983 {
984 struct optee *optee = ffa_dev_get_drvdata(ffa_dev);
985 u32 bottom_half_id = optee->ffa.bottom_half_value;
986
987 if (bottom_half_id != U32_MAX) {
988 ffa_dev->ops->notifier_ops->notify_relinquish(ffa_dev,
989 bottom_half_id);
990 destroy_workqueue(optee->ffa.notif_wq);
991 }
992 optee_remove_common(optee);
993
994 mutex_destroy(&optee->ffa.mutex);
995 rhashtable_free_and_destroy(&optee->ffa.global_ids, rh_free_fn, NULL);
996
997 kfree(optee);
998 }
999
optee_ffa_async_notif_init(struct ffa_device * ffa_dev,struct optee * optee)1000 static int optee_ffa_async_notif_init(struct ffa_device *ffa_dev,
1001 struct optee *optee)
1002 {
1003 bool is_per_vcpu = false;
1004 u32 notif_id = 0;
1005 int rc;
1006
1007 INIT_WORK(&optee->ffa.notif_work, notif_work_fn);
1008 optee->ffa.notif_wq = create_workqueue("optee_notification");
1009 if (!optee->ffa.notif_wq) {
1010 rc = -EINVAL;
1011 goto err;
1012 }
1013
1014 while (true) {
1015 rc = ffa_dev->ops->notifier_ops->notify_request(ffa_dev,
1016 is_per_vcpu,
1017 notif_callback,
1018 optee,
1019 notif_id);
1020 if (!rc)
1021 break;
1022 /*
1023 * -EACCES means that the notification ID was
1024 * already bound, try the next one as long as we
1025 * haven't reached the max. Any other error is a
1026 * permanent error, so skip asynchronous
1027 * notifications in that case.
1028 */
1029 if (rc != -EACCES)
1030 goto err_wq;
1031 notif_id++;
1032 if (notif_id >= OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE)
1033 goto err_wq;
1034 }
1035 optee->ffa.bottom_half_value = notif_id;
1036
1037 rc = enable_async_notif(optee);
1038 if (rc < 0)
1039 goto err_rel;
1040
1041 return 0;
1042 err_rel:
1043 ffa_dev->ops->notifier_ops->notify_relinquish(ffa_dev, notif_id);
1044 err_wq:
1045 destroy_workqueue(optee->ffa.notif_wq);
1046 err:
1047 optee->ffa.bottom_half_value = U32_MAX;
1048
1049 return rc;
1050 }
1051
optee_ffa_protmem_pool_init(struct optee * optee,u32 sec_caps)1052 static int optee_ffa_protmem_pool_init(struct optee *optee, u32 sec_caps)
1053 {
1054 enum tee_dma_heap_id id = TEE_DMA_HEAP_SECURE_VIDEO_PLAY;
1055 struct tee_protmem_pool *pool;
1056 int rc = 0;
1057
1058 if (sec_caps & OPTEE_FFA_SEC_CAP_PROTMEM) {
1059 pool = optee_protmem_alloc_dyn_pool(optee, id);
1060 if (IS_ERR(pool))
1061 return PTR_ERR(pool);
1062
1063 rc = tee_device_register_dma_heap(optee->teedev, id, pool);
1064 if (rc)
1065 pool->ops->destroy_pool(pool);
1066 }
1067
1068 return rc;
1069 }
1070
optee_ffa_probe(struct ffa_device * ffa_dev)1071 static int optee_ffa_probe(struct ffa_device *ffa_dev)
1072 {
1073 const struct ffa_notifier_ops *notif_ops;
1074 const struct ffa_ops *ffa_ops;
1075 unsigned int max_notif_value;
1076 unsigned int rpc_param_count;
1077 struct tee_shm_pool *pool;
1078 struct tee_device *teedev;
1079 struct tee_context *ctx;
1080 u32 arg_cache_flags = 0;
1081 struct optee *optee;
1082 u32 sec_caps;
1083 int rc;
1084
1085 ffa_ops = ffa_dev->ops;
1086 notif_ops = ffa_ops->notifier_ops;
1087
1088 if (!optee_ffa_api_is_compatible(ffa_dev, ffa_ops))
1089 return -EINVAL;
1090
1091 if (!optee_ffa_exchange_caps(ffa_dev, ffa_ops, &sec_caps,
1092 &rpc_param_count, &max_notif_value))
1093 return -EINVAL;
1094 if (sec_caps & OPTEE_FFA_SEC_CAP_ARG_OFFSET)
1095 arg_cache_flags |= OPTEE_SHM_ARG_SHARED;
1096
1097 optee = kzalloc_obj(*optee);
1098 if (!optee)
1099 return -ENOMEM;
1100
1101 if (!optee_ffa_get_os_revision(ffa_dev, ffa_ops, &optee->revision)) {
1102 rc = -EINVAL;
1103 goto err_free_optee;
1104 }
1105
1106 pool = optee_ffa_shm_pool_alloc_pages();
1107 if (IS_ERR(pool)) {
1108 rc = PTR_ERR(pool);
1109 goto err_free_optee;
1110 }
1111 optee->pool = pool;
1112
1113 optee->ops = &optee_ffa_ops;
1114 optee->ffa.ffa_dev = ffa_dev;
1115 optee->ffa.bottom_half_value = U32_MAX;
1116 optee->rpc_param_count = rpc_param_count;
1117
1118 if (IS_REACHABLE(CONFIG_RPMB) &&
1119 (sec_caps & OPTEE_FFA_SEC_CAP_RPMB_PROBE))
1120 optee->in_kernel_rpmb_routing = true;
1121
1122 teedev = tee_device_alloc(&optee_ffa_clnt_desc, NULL, optee->pool,
1123 optee);
1124 if (IS_ERR(teedev)) {
1125 rc = PTR_ERR(teedev);
1126 goto err_free_shm_pool;
1127 }
1128 optee->teedev = teedev;
1129
1130 teedev = tee_device_alloc(&optee_ffa_supp_desc, NULL, optee->pool,
1131 optee);
1132 if (IS_ERR(teedev)) {
1133 rc = PTR_ERR(teedev);
1134 goto err_unreg_teedev;
1135 }
1136 optee->supp_teedev = teedev;
1137
1138 optee_set_dev_group(optee);
1139
1140 rc = rhashtable_init(&optee->ffa.global_ids, &shm_rhash_params);
1141 if (rc)
1142 goto err_unreg_supp_teedev;
1143 mutex_init(&optee->ffa.mutex);
1144 optee_cq_init(&optee->call_queue, 0);
1145 optee_supp_init(&optee->supp);
1146 optee_shm_arg_cache_init(optee, arg_cache_flags);
1147 mutex_init(&optee->rpmb_dev_mutex);
1148 ffa_dev_set_drvdata(ffa_dev, optee);
1149 ctx = teedev_open(optee->teedev);
1150 if (IS_ERR(ctx)) {
1151 rc = PTR_ERR(ctx);
1152 goto err_rhashtable_free;
1153 }
1154 optee->ctx = ctx;
1155 rc = optee_notif_init(optee, OPTEE_DEFAULT_MAX_NOTIF_VALUE);
1156 if (rc)
1157 goto err_close_ctx;
1158 if (sec_caps & OPTEE_FFA_SEC_CAP_ASYNC_NOTIF) {
1159 rc = optee_ffa_async_notif_init(ffa_dev, optee);
1160 if (rc < 0)
1161 pr_err("Failed to initialize async notifications: %d",
1162 rc);
1163 }
1164
1165 if (optee_ffa_protmem_pool_init(optee, sec_caps))
1166 pr_info("Protected memory service not available\n");
1167
1168 rc = tee_device_register(optee->teedev);
1169 if (rc)
1170 goto err_unregister_devices;
1171
1172 rc = tee_device_register(optee->supp_teedev);
1173 if (rc)
1174 goto err_unregister_devices;
1175
1176 rc = optee_enumerate_devices(PTA_CMD_GET_DEVICES);
1177 if (rc)
1178 goto err_unregister_devices;
1179
1180 INIT_WORK(&optee->rpmb_scan_bus_work, optee_bus_scan_rpmb);
1181 optee->rpmb_intf.notifier_call = optee_rpmb_intf_rdev;
1182 blocking_notifier_chain_register(&optee_rpmb_intf_added,
1183 &optee->rpmb_intf);
1184 pr_info("initialized driver\n");
1185 return 0;
1186
1187 err_unregister_devices:
1188 optee_unregister_devices();
1189 if (optee->ffa.bottom_half_value != U32_MAX)
1190 notif_ops->notify_relinquish(ffa_dev,
1191 optee->ffa.bottom_half_value);
1192 optee_notif_uninit(optee);
1193 err_close_ctx:
1194 teedev_close_context(ctx);
1195 err_rhashtable_free:
1196 rhashtable_free_and_destroy(&optee->ffa.global_ids, rh_free_fn, NULL);
1197 rpmb_dev_put(optee->rpmb_dev);
1198 mutex_destroy(&optee->rpmb_dev_mutex);
1199 optee_supp_uninit(&optee->supp);
1200 mutex_destroy(&optee->call_queue.mutex);
1201 mutex_destroy(&optee->ffa.mutex);
1202 err_unreg_supp_teedev:
1203 tee_device_unregister(optee->supp_teedev);
1204 err_unreg_teedev:
1205 tee_device_unregister(optee->teedev);
1206 err_free_shm_pool:
1207 tee_shm_pool_free(pool);
1208 err_free_optee:
1209 kfree(optee);
1210 return rc;
1211 }
1212
1213 static const struct ffa_device_id optee_ffa_device_id[] = {
1214 /* 486178e0-e7f8-11e3-bc5e0002a5d5c51b */
1215 { UUID_INIT(0x486178e0, 0xe7f8, 0x11e3,
1216 0xbc, 0x5e, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b) },
1217 {}
1218 };
1219
1220 static struct ffa_driver optee_ffa_driver = {
1221 .name = "optee",
1222 .probe = optee_ffa_probe,
1223 .remove = optee_ffa_remove,
1224 .id_table = optee_ffa_device_id,
1225 };
1226
optee_ffa_abi_register(void)1227 int optee_ffa_abi_register(void)
1228 {
1229 if (IS_REACHABLE(CONFIG_ARM_FFA_TRANSPORT))
1230 return ffa_register(&optee_ffa_driver);
1231 else
1232 return -EOPNOTSUPP;
1233 }
1234
optee_ffa_abi_unregister(void)1235 void optee_ffa_abi_unregister(void)
1236 {
1237 if (IS_REACHABLE(CONFIG_ARM_FFA_TRANSPORT))
1238 ffa_unregister(&optee_ffa_driver);
1239 }
1240