blob: faf6cd022038606e480f26f7b141a4907ead66ac [file] [log] [blame]
Brad Bishopbec4ebc2022-08-03 09:55:16 -04001From 5665ffd3fb8e94003abc1c0c05c9fa30d4028b67 Mon Sep 17 00:00:00 2001
2From: Jens Wiklander <jens.wiklander@linaro.org>
3Date: Thu, 25 Mar 2021 15:08:53 +0100
4Subject: [PATCH 19/22] optee: add FF-A support
5
6Adds support for using FF-A [1] as transport to the OP-TEE driver.
7
8Introduces struct optee_msg_param_fmem which carries all information
9needed when OP-TEE is calling FFA_MEM_RETRIEVE_REQ to get the shared
10memory reference mapped by the hypervisor in S-EL2. Register usage is
11also updated to include the information needed.
12
13The FF-A part of this driver is enabled if CONFIG_ARM_FFA_TRANSPORT is
14enabled.
15
16[1] https://developer.arm.com/documentation/den0077/latest
17Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
18
19Upstream-Status: Pending [Not submitted to upstream yet]
20---
21 drivers/tee/optee/call.c | 212 ++++++++++++-
22 drivers/tee/optee/core.c | 486 +++++++++++++++++++++++++++++-
23 drivers/tee/optee/optee_ffa.h | 153 ++++++++++
24 drivers/tee/optee/optee_msg.h | 27 +-
25 drivers/tee/optee/optee_private.h | 52 ++++
26 drivers/tee/optee/rpc.c | 118 ++++++++
27 6 files changed, 1040 insertions(+), 8 deletions(-)
28 create mode 100644 drivers/tee/optee/optee_ffa.h
29
30diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
31index e7b93153252c..cf91a81a242a 100644
32--- a/drivers/tee/optee/call.c
33+++ b/drivers/tee/optee/call.c
34@@ -3,15 +3,18 @@
35 * Copyright (c) 2015-2021, Linaro Limited
36 */
37 #include <linux/arm-smccc.h>
38+#include <linux/arm_ffa.h>
39 #include <linux/device.h>
40 #include <linux/err.h>
41 #include <linux/errno.h>
42 #include <linux/mm.h>
43 #include <linux/sched.h>
44+#include <linux/scatterlist.h>
45 #include <linux/slab.h>
46 #include <linux/tee_drv.h>
47 #include <linux/types.h>
48 #include <linux/uaccess.h>
49+#include "optee_ffa.h"
50 #include "optee_private.h"
51 #include "optee_smc.h"
52
53@@ -180,11 +183,21 @@ int optee_do_call_with_arg(struct tee_context *ctx, struct tee_shm *arg)
54 static struct tee_shm *get_msg_arg(struct tee_context *ctx, size_t num_params,
55 struct optee_msg_arg **msg_arg)
56 {
57+ struct optee *optee = tee_get_drvdata(ctx->teedev);
58+ size_t sz = OPTEE_MSG_GET_ARG_SIZE(num_params);
59 struct tee_shm *shm;
60 struct optee_msg_arg *ma;
61
62- shm = tee_shm_alloc(ctx, OPTEE_MSG_GET_ARG_SIZE(num_params),
63- TEE_SHM_MAPPED);
64+ /*
65+ * rpc_arg_count is set to the number of allocated parameters in
66+ * the RPC argument struct if a second MSG arg struct is expected.
67+ * The second arg struct will then be used for RPC. So far only
68+ * enabled when using FF-A as transport layer.
69+ */
70+ if (optee->rpc_arg_count)
71+ sz += OPTEE_MSG_GET_ARG_SIZE(optee->rpc_arg_count);
72+
73+ shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED);
74 if (IS_ERR(shm))
75 return shm;
76
77@@ -673,3 +686,198 @@ int optee_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm)
78 {
79 return 0;
80 }
81+
82+#ifdef CONFIG_ARM_FFA_TRANSPORT
83+static int optee_ffa_yielding_call(struct tee_context *ctx,
84+ struct ffa_send_direct_data *data,
85+ struct optee_msg_arg *rpc_arg)
86+{
87+ struct optee *optee = tee_get_drvdata(ctx->teedev);
88+ const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_ops;
89+ struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
90+ struct optee_call_waiter w;
91+ u32 cmd = data->data0;
92+ u32 w4 = data->data1;
93+ u32 w5 = data->data2;
94+ u32 w6 = data->data3;
95+ int rc;
96+
97+ /* Initialize waiter */
98+ optee_cq_wait_init(&optee->call_queue, &w);
99+ while (true) {
100+ rc = ffa_ops->sync_send_receive(ffa_dev, data);
101+ if (rc)
102+ goto done;
103+
104+ switch ((int)data->data0) {
105+ case TEEC_SUCCESS:
106+ break;
107+ case TEEC_ERROR_BUSY:
108+ if (cmd == OPTEE_FFA_YIELDING_CALL_RESUME) {
109+ rc = -EIO;
110+ goto done;
111+ }
112+
113+ /*
114+ * Out of threads in secure world, wait for a thread
115+ * become available.
116+ */
117+ optee_cq_wait_for_completion(&optee->call_queue, &w);
118+ data->data0 = cmd;
119+ data->data1 = w4;
120+ data->data2 = w5;
121+ data->data3 = w6;
122+ continue;
123+ default:
124+ rc = -EIO;
125+ goto done;
126+ }
127+
128+ if (data->data1 == OPTEE_FFA_YIELDING_CALL_RETURN_DONE)
129+ goto done;
130+
131+ /*
132+ * OP-TEE has returned with a RPC request.
133+ *
134+ * Note that data->data4 (passed in register w7) is already
135+ * filled in by ffa_ops->sync_send_receive() returning
136+ * above.
137+ */
138+ cond_resched();
139+ optee_handle_ffa_rpc(ctx, data->data1, rpc_arg);
140+ cmd = OPTEE_FFA_YIELDING_CALL_RESUME;
141+ data->data0 = cmd;
142+ data->data1 = 0;
143+ data->data2 = 0;
144+ data->data3 = 0;
145+ }
146+done:
147+ /*
148+ * We're done with our thread in secure world, if there's any
149+ * thread waiters wake up one.
150+ */
151+ optee_cq_wait_final(&optee->call_queue, &w);
152+
153+ return rc;
154+}
155+
156+/**
157+ * optee_ffa_do_call_with_arg() - Do a FF-A call to enter OP-TEE in secure world
158+ * @ctx: calling context
159+ * @shm: shared memory holding the message to pass to secure world
160+ *
161+ * Does a FF-A call to OP-TEE in secure world and handles eventual resulting
162+ * Remote Procedure Calls (RPC) from OP-TEE.
163+ *
164+ * Returns return code from FF-A, 0 is OK
165+ */
166+
167+int optee_ffa_do_call_with_arg(struct tee_context *ctx, struct tee_shm *shm)
168+{
169+ struct ffa_send_direct_data data = {
170+ .data0 = OPTEE_FFA_YIELDING_CALL_WITH_ARG,
171+ .data1 = (u32)shm->sec_world_id,
172+ .data2 = (u32)(shm->sec_world_id >> 32),
173+ .data3 = shm->offset,
174+ };
175+ struct optee_msg_arg *arg = tee_shm_get_va(shm, 0);
176+ unsigned int rpc_arg_offs = OPTEE_MSG_GET_ARG_SIZE(arg->num_params);
177+ struct optee_msg_arg *rpc_arg = tee_shm_get_va(shm, rpc_arg_offs);
178+
179+ return optee_ffa_yielding_call(ctx, &data, rpc_arg);
180+}
181+
182+int optee_ffa_shm_register(struct tee_context *ctx, struct tee_shm *shm,
183+ struct page **pages, size_t num_pages,
184+ unsigned long start)
185+{
186+ struct optee *optee = tee_get_drvdata(ctx->teedev);
187+ const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_ops;
188+ struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
189+ struct ffa_mem_region_attributes mem_attr = {
190+ .receiver = ffa_dev->vm_id,
191+ .attrs = FFA_MEM_RW,
192+ };
193+ struct ffa_mem_ops_args args = {
194+ .use_txbuf = true,
195+ .attrs = &mem_attr,
196+ .nattrs = 1,
197+ };
198+ struct sg_table sgt;
199+ int rc;
200+
201+ rc = check_mem_type(start, num_pages);
202+ if (rc)
203+ return rc;
204+
205+ rc = sg_alloc_table_from_pages(&sgt, pages, num_pages, 0,
206+ num_pages * PAGE_SIZE, GFP_KERNEL);
207+ if (rc)
208+ return rc;
209+ args.sg = sgt.sgl;
210+ rc = ffa_ops->memory_share(ffa_dev, &args);
211+ sg_free_table(&sgt);
212+ if (rc)
213+ return rc;
214+
215+ rc = optee_shm_add_ffa_handle(optee, shm, args.g_handle);
216+ if (rc) {
217+ ffa_ops->memory_reclaim(args.g_handle, 0);
218+ return rc;
219+ }
220+
221+ shm->sec_world_id = args.g_handle;
222+
223+ return 0;
224+}
225+
226+int optee_ffa_shm_unregister(struct tee_context *ctx, struct tee_shm *shm)
227+{
228+ struct optee *optee = tee_get_drvdata(ctx->teedev);
229+ const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_ops;
230+ struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
231+ u64 global_handle = shm->sec_world_id;
232+ struct ffa_send_direct_data data = {
233+ .data0 = OPTEE_FFA_UNREGISTER_SHM,
234+ .data1 = (u32)global_handle,
235+ .data2 = (u32)(global_handle >> 32)
236+ };
237+ int rc;
238+
239+ optee_shm_rem_ffa_handle(optee, global_handle);
240+ shm->sec_world_id = 0;
241+
242+ rc = ffa_ops->sync_send_receive(ffa_dev, &data);
243+ if (rc)
244+ pr_err("Unregister SHM id 0x%llx rc %d\n", global_handle, rc);
245+
246+ rc = ffa_ops->memory_reclaim(global_handle, 0);
247+ if (rc)
248+ pr_err("mem_reclain: 0x%llx %d", global_handle, rc);
249+
250+ return rc;
251+}
252+
253+int optee_ffa_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm)
254+{
255+ struct optee *optee = tee_get_drvdata(ctx->teedev);
256+ const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_ops;
257+ u64 global_handle = shm->sec_world_id;
258+ int rc;
259+
260+ /*
261+ * We're skipping the OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM call
262+ * since this is OP-TEE freeing via RPC so it has already retired
263+ * this ID.
264+ */
265+
266+ optee_shm_rem_ffa_handle(optee, global_handle);
267+ rc = ffa_ops->memory_reclaim(global_handle, 0);
268+ if (rc)
269+ pr_err("mem_reclain: 0x%llx %d", global_handle, rc);
270+
271+ shm->sec_world_id = 0;
272+
273+ return rc;
274+}
275+#endif /*CONFIG_ARM_FFA_TRANSPORT*/
276diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
277index ab602bb8e14a..b9719c60dc48 100644
278--- a/drivers/tee/optee/core.c
279+++ b/drivers/tee/optee/core.c
280@@ -6,6 +6,7 @@
281 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
282
283 #include <linux/arm-smccc.h>
284+#include <linux/arm_ffa.h>
285 #include <linux/errno.h>
286 #include <linux/io.h>
287 #include <linux/module.h>
288@@ -20,6 +21,7 @@
289 #include <linux/workqueue.h>
290 #include "optee_private.h"
291 #include "optee_smc.h"
292+#include "optee_ffa.h"
293 #include "shm_pool.h"
294
295 #define DRIVER_NAME "optee"
296@@ -299,10 +301,9 @@ static int optee_open(struct tee_context *ctx)
297 mutex_init(&ctxdata->mutex);
298 INIT_LIST_HEAD(&ctxdata->sess_list);
299
300- if (optee->sec_caps & OPTEE_SMC_SEC_CAP_MEMREF_NULL)
301- ctx->cap_memref_null = true;
302- else
303- ctx->cap_memref_null = false;
304+ ctx->cap_memref_null = optee_is_ffa_based(optee) ||
305+ (optee->sec_caps &
306+ OPTEE_SMC_SEC_CAP_MEMREF_NULL);
307
308 ctx->data = ctxdata;
309 return 0;
310@@ -567,6 +568,472 @@ optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm)
311 return rc;
312 }
313
314+#ifdef CONFIG_ARM_FFA_TRANSPORT
315+static void optee_ffa_get_version(struct tee_device *teedev,
316+ struct tee_ioctl_version_data *vers)
317+{
318+ struct tee_ioctl_version_data v = {
319+ .impl_id = TEE_IMPL_ID_OPTEE,
320+ .impl_caps = TEE_OPTEE_CAP_TZ,
321+ .gen_caps = TEE_GEN_CAP_GP | TEE_GEN_CAP_REG_MEM |
322+ TEE_GEN_CAP_MEMREF_NULL,
323+ };
324+
325+ *vers = v;
326+}
327+
328+struct shm_rhash {
329+ struct tee_shm *shm;
330+ u64 global_id;
331+ struct rhash_head linkage;
332+};
333+
334+static void rh_free_fn(void *ptr, void *arg)
335+{
336+ kfree(ptr);
337+}
338+
339+static const struct rhashtable_params shm_rhash_params = {
340+ .head_offset = offsetof(struct shm_rhash, linkage),
341+ .key_len = sizeof(u64),
342+ .key_offset = offsetof(struct shm_rhash, global_id),
343+ .automatic_shrinking = true,
344+};
345+
346+struct tee_shm *optee_shm_from_ffa_handle(struct optee *optee, u64 global_id)
347+{
348+ struct tee_shm *shm = NULL;
349+ struct shm_rhash *r;
350+
351+ mutex_lock(&optee->ffa.mutex);
352+ r = rhashtable_lookup_fast(&optee->ffa.global_ids, &global_id,
353+ shm_rhash_params);
354+ if (r)
355+ shm = r->shm;
356+ mutex_unlock(&optee->ffa.mutex);
357+
358+ return shm;
359+}
360+
361+int optee_shm_add_ffa_handle(struct optee *optee, struct tee_shm *shm,
362+ u64 global_id)
363+{
364+ struct shm_rhash *r;
365+ int rc;
366+
367+ r = kmalloc(sizeof(*r), GFP_KERNEL);
368+ if (!r)
369+ return -ENOMEM;
370+ r->shm = shm;
371+ r->global_id = global_id;
372+
373+ mutex_lock(&optee->ffa.mutex);
374+ rc = rhashtable_lookup_insert_fast(&optee->ffa.global_ids, &r->linkage,
375+ shm_rhash_params);
376+ mutex_unlock(&optee->ffa.mutex);
377+
378+ if (rc)
379+ kfree(r);
380+
381+ return rc;
382+}
383+
384+int optee_shm_rem_ffa_handle(struct optee *optee, u64 global_id)
385+{
386+ struct shm_rhash *r;
387+ int rc = -ENOENT;
388+
389+ mutex_lock(&optee->ffa.mutex);
390+ r = rhashtable_lookup_fast(&optee->ffa.global_ids, &global_id,
391+ shm_rhash_params);
392+ if (r)
393+ rc = rhashtable_remove_fast(&optee->ffa.global_ids,
394+ &r->linkage, shm_rhash_params);
395+ mutex_unlock(&optee->ffa.mutex);
396+
397+ if (!rc)
398+ kfree(r);
399+
400+ return rc;
401+}
402+
403+static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
404+ u32 attr, const struct optee_msg_param *mp)
405+{
406+ struct tee_shm *shm = NULL;
407+ u64 offs_high = 0;
408+ u64 offs_low = 0;
409+
410+ p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
411+ attr - OPTEE_MSG_ATTR_TYPE_FMEM_INPUT;
412+ p->u.memref.size = mp->u.fmem.size;
413+
414+ if (mp->u.fmem.global_id != OPTEE_MSG_FMEM_INVALID_GLOBAL_ID)
415+ shm = optee_shm_from_ffa_handle(optee, mp->u.fmem.global_id);
416+ p->u.memref.shm = shm;
417+
418+ if (shm) {
419+ offs_low = mp->u.fmem.offs_low;
420+ offs_high = mp->u.fmem.offs_high;
421+ }
422+ p->u.memref.shm_offs = offs_low | offs_high << 32;
423+}
424+
425+/**
426+ * optee_ffa_from_msg_param() - convert from OPTEE_MSG parameters to
427+ * struct tee_param
428+ * @optee: main service struct
429+ * @params: subsystem internal parameter representation
430+ * @num_params: number of elements in the parameter arrays
431+ * @msg_params: OPTEE_MSG parameters
432+ *
433+ * Returns 0 on success or <0 on failure
434+ */
435+static int optee_ffa_from_msg_param(struct optee *optee,
436+ struct tee_param *params, size_t num_params,
437+ const struct optee_msg_param *msg_params)
438+{
439+ size_t n;
440+
441+ for (n = 0; n < num_params; n++) {
442+ struct tee_param *p = params + n;
443+ const struct optee_msg_param *mp = msg_params + n;
444+ u32 attr = mp->attr & OPTEE_MSG_ATTR_TYPE_MASK;
445+
446+ switch (attr) {
447+ case OPTEE_MSG_ATTR_TYPE_NONE:
448+ p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
449+ memset(&p->u, 0, sizeof(p->u));
450+ break;
451+ case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
452+ case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
453+ case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
454+ from_msg_param_value(p, attr, mp);
455+ break;
456+ case OPTEE_MSG_ATTR_TYPE_FMEM_INPUT:
457+ case OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT:
458+ case OPTEE_MSG_ATTR_TYPE_FMEM_INOUT:
459+ from_msg_param_ffa_mem(optee, p, attr, mp);
460+ break;
461+ default:
462+ return -EINVAL;
463+ }
464+ }
465+
466+ return 0;
467+}
468+
469+static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
470+ const struct tee_param *p)
471+{
472+ struct tee_shm *shm = p->u.memref.shm;
473+
474+ mp->attr = OPTEE_MSG_ATTR_TYPE_FMEM_INPUT + p->attr -
475+ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
476+
477+ if (shm) {
478+ u64 shm_offs = p->u.memref.shm_offs;
479+
480+ mp->u.fmem.internal_offs = shm->offset;
481+
482+ mp->u.fmem.offs_low = shm_offs;
483+ mp->u.fmem.offs_high = shm_offs >> 32;
484+ /* Check that the entire offset could be stored. */
485+ if (mp->u.fmem.offs_high != shm_offs >> 32)
486+ return -EINVAL;
487+
488+ mp->u.fmem.global_id = shm->sec_world_id;
489+ } else {
490+ memset(&mp->u, 0, sizeof(mp->u));
491+ mp->u.fmem.global_id = OPTEE_MSG_FMEM_INVALID_GLOBAL_ID;
492+ }
493+ mp->u.fmem.size = p->u.memref.size;
494+
495+ return 0;
496+}
497+
498+/**
499+ * optee_ffa_to_msg_param() - convert from struct tee_params to OPTEE_MSG
500+ * parameters
501+ * @optee: main service struct
502+ * @msg_params: OPTEE_MSG parameters
503+ * @num_params: number of elements in the parameter arrays
504+ * @params: subsystem itnernal parameter representation
505+ * Returns 0 on success or <0 on failure
506+ */
507+static int optee_ffa_to_msg_param(struct optee *optee,
508+ struct optee_msg_param *msg_params,
509+ size_t num_params,
510+ const struct tee_param *params)
511+{
512+ size_t n;
513+
514+ for (n = 0; n < num_params; n++) {
515+ const struct tee_param *p = params + n;
516+ struct optee_msg_param *mp = msg_params + n;
517+
518+ switch (p->attr) {
519+ case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
520+ mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
521+ memset(&mp->u, 0, sizeof(mp->u));
522+ break;
523+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
524+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
525+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
526+ to_msg_param_value(mp, p);
527+ break;
528+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
529+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
530+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
531+ if (to_msg_param_ffa_mem(mp, p))
532+ return -EINVAL;
533+ break;
534+ default:
535+ return -EINVAL;
536+ }
537+ }
538+
539+ return 0;
540+}
541+
542+static bool optee_ffa_api_is_compatbile(struct ffa_device *ffa_dev,
543+ const struct ffa_dev_ops *ops)
544+{
545+ struct ffa_send_direct_data data = { OPTEE_FFA_GET_API_VERSION };
546+ int rc;
547+
548+ ops->mode_32bit_set(ffa_dev);
549+
550+ rc = ops->sync_send_receive(ffa_dev, &data);
551+ if (rc) {
552+ pr_err("Unexpected error %d\n", rc);
553+ return false;
554+ }
555+ if (data.data0 != OPTEE_FFA_VERSION_MAJOR ||
556+ data.data1 < OPTEE_FFA_VERSION_MINOR) {
557+ pr_err("Incompatible OP-TEE API version %lu.%lu",
558+ data.data0, data.data1);
559+ return false;
560+ }
561+
562+ data = (struct ffa_send_direct_data){ OPTEE_FFA_GET_OS_VERSION };
563+ rc = ops->sync_send_receive(ffa_dev, &data);
564+ if (rc) {
565+ pr_err("Unexpected error %d\n", rc);
566+ return false;
567+ }
568+ if (data.data2)
569+ pr_info("revision %lu.%lu (%08lx)",
570+ data.data0, data.data1, data.data2);
571+ else
572+ pr_info("revision %lu.%lu", data.data0, data.data1);
573+
574+ return true;
575+}
576+
577+static bool optee_ffa_exchange_caps(struct ffa_device *ffa_dev,
578+ const struct ffa_dev_ops *ops,
579+ u32 *sec_caps, unsigned int *rpc_arg_count)
580+{
581+ struct ffa_send_direct_data data = { OPTEE_FFA_EXCHANGE_CAPABILITIES };
582+ int rc;
583+
584+ rc = ops->sync_send_receive(ffa_dev, &data);
585+ if (rc) {
586+ pr_err("Unexpected error %d", rc);
587+ return false;
588+ }
589+ if (data.data0) {
590+ pr_err("Unexpected exchange error %lu", data.data0);
591+ return false;
592+ }
593+
594+ *sec_caps = 0;
595+ *rpc_arg_count = (u8)data.data1;
596+
597+ return true;
598+}
599+
600+static struct tee_shm_pool *optee_ffa_config_dyn_shm(void)
601+{
602+ struct tee_shm_pool_mgr *priv_mgr;
603+ struct tee_shm_pool_mgr *dmabuf_mgr;
604+ void *rc;
605+
606+ rc = optee_ffa_shm_pool_alloc_pages();
607+ if (IS_ERR(rc))
608+ return rc;
609+ priv_mgr = rc;
610+
611+ rc = optee_ffa_shm_pool_alloc_pages();
612+ if (IS_ERR(rc)) {
613+ tee_shm_pool_mgr_destroy(priv_mgr);
614+ return rc;
615+ }
616+ dmabuf_mgr = rc;
617+
618+ rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr);
619+ if (IS_ERR(rc)) {
620+ tee_shm_pool_mgr_destroy(priv_mgr);
621+ tee_shm_pool_mgr_destroy(dmabuf_mgr);
622+ }
623+
624+ return rc;
625+}
626+
627+static const struct tee_driver_ops optee_ffa_clnt_ops = {
628+ .get_version = optee_ffa_get_version,
629+ .open = optee_open,
630+ .release = optee_release,
631+ .open_session = optee_open_session,
632+ .close_session = optee_close_session,
633+ .invoke_func = optee_invoke_func,
634+ .cancel_req = optee_cancel_req,
635+ .shm_register = optee_ffa_shm_register,
636+ .shm_unregister = optee_ffa_shm_unregister,
637+};
638+
639+static const struct tee_desc optee_ffa_clnt_desc = {
640+ .name = DRIVER_NAME "ffa-clnt",
641+ .ops = &optee_ffa_clnt_ops,
642+ .owner = THIS_MODULE,
643+};
644+
645+static const struct tee_driver_ops optee_ffa_supp_ops = {
646+ .get_version = optee_ffa_get_version,
647+ .open = optee_open,
648+ .release = optee_release_supp,
649+ .supp_recv = optee_supp_recv,
650+ .supp_send = optee_supp_send,
651+ .shm_register = optee_ffa_shm_register, /* same as for clnt ops */
652+ .shm_unregister = optee_ffa_shm_unregister_supp,
653+};
654+
655+static const struct tee_desc optee_ffa_supp_desc = {
656+ .name = DRIVER_NAME "ffa-supp",
657+ .ops = &optee_ffa_supp_ops,
658+ .owner = THIS_MODULE,
659+ .flags = TEE_DESC_PRIVILEGED,
660+};
661+
662+static const struct optee_ops optee_ffa_ops = {
663+ .do_call_with_arg = optee_ffa_do_call_with_arg,
664+ .to_msg_param = optee_ffa_to_msg_param,
665+ .from_msg_param = optee_ffa_from_msg_param,
666+};
667+
668+static void optee_ffa_remove(struct ffa_device *ffa_dev)
669+{
670+ (void)ffa_dev;
671+}
672+
673+static int optee_ffa_probe(struct ffa_device *ffa_dev)
674+{
675+ const struct ffa_dev_ops *ffa_ops;
676+ unsigned int rpc_arg_count;
677+ struct tee_device *teedev;
678+ struct optee *optee;
679+ u32 sec_caps;
680+ int rc;
681+
682+ ffa_ops = ffa_dev_ops_get(ffa_dev);
683+ if (!ffa_ops) {
684+ pr_warn("failed \"method\" init: ffa\n");
685+ return -ENOENT;
686+ }
687+
688+ if (!optee_ffa_api_is_compatbile(ffa_dev, ffa_ops))
689+ return -EINVAL;
690+
691+ if (!optee_ffa_exchange_caps(ffa_dev, ffa_ops, &sec_caps,
692+ &rpc_arg_count))
693+ return -EINVAL;
694+
695+ optee = kzalloc(sizeof(*optee), GFP_KERNEL);
696+ if (!optee) {
697+ rc = -ENOMEM;
698+ goto err;
699+ }
700+ optee->pool = optee_ffa_config_dyn_shm();
701+ if (IS_ERR(optee->pool)) {
702+ rc = PTR_ERR(optee->pool);
703+ optee->pool = NULL;
704+ goto err;
705+ }
706+
707+ optee->ops = &optee_ffa_ops;
708+ optee->ffa.ffa_dev = ffa_dev;
709+ optee->ffa.ffa_ops = ffa_ops;
710+ optee->sec_caps = sec_caps;
711+ optee->rpc_arg_count = rpc_arg_count;
712+
713+ teedev = tee_device_alloc(&optee_ffa_clnt_desc, NULL, optee->pool,
714+ optee);
715+ if (IS_ERR(teedev)) {
716+ rc = PTR_ERR(teedev);
717+ goto err;
718+ }
719+ optee->teedev = teedev;
720+
721+ teedev = tee_device_alloc(&optee_ffa_supp_desc, NULL, optee->pool,
722+ optee);
723+ if (IS_ERR(teedev)) {
724+ rc = PTR_ERR(teedev);
725+ goto err;
726+ }
727+ optee->supp_teedev = teedev;
728+
729+ rc = tee_device_register(optee->teedev);
730+ if (rc)
731+ goto err;
732+
733+ rc = tee_device_register(optee->supp_teedev);
734+ if (rc)
735+ goto err;
736+
737+ rc = rhashtable_init(&optee->ffa.global_ids, &shm_rhash_params);
738+ if (rc)
739+ goto err;
740+ mutex_init(&optee->ffa.mutex);
741+ mutex_init(&optee->call_queue.mutex);
742+ INIT_LIST_HEAD(&optee->call_queue.waiters);
743+ optee_wait_queue_init(&optee->wait_queue);
744+ optee_supp_init(&optee->supp);
745+ ffa_dev_set_drvdata(ffa_dev, optee);
746+
747+ pr_info("initialized driver\n");
748+ return 0;
749+err:
750+ /*
751+ * tee_device_unregister() is safe to call even if the
752+ * devices hasn't been registered with
753+ * tee_device_register() yet.
754+ */
755+ tee_device_unregister(optee->supp_teedev);
756+ tee_device_unregister(optee->teedev);
757+ if (optee->pool)
758+ tee_shm_pool_free(optee->pool);
759+ kfree(optee);
760+ return rc;
761+}
762+
763+static const struct ffa_device_id optee_ffa_device_id[] = {
764+ /* 486178e0-e7f8-11e3-bc5e0002a5d5c51b */
765+ { UUID_INIT(0x486178e0, 0xe7f8, 0x11e3,
766+ 0xbc, 0x5e, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b) },
767+ {}
768+};
769+
770+static struct ffa_driver optee_ffa_driver = {
771+ .name = "optee",
772+ .probe = optee_ffa_probe,
773+ .remove = optee_ffa_remove,
774+ .id_table = optee_ffa_device_id,
775+};
776+
777+module_ffa_driver(optee_ffa_driver);
778+#endif /*CONFIG_ARM_FFA_TRANSPORT*/
779+
780 /* Simple wrapper functions to be able to use a function pointer */
781 static void optee_smccc_smc(unsigned long a0, unsigned long a1,
782 unsigned long a2, unsigned long a3,
783@@ -615,7 +1082,8 @@ static int optee_remove(struct platform_device *pdev)
784 * reference counters and also avoid wild pointers in secure world
785 * into the old shared memory range.
786 */
787- optee_disable_shm_cache(optee);
788+ if (!optee_is_ffa_based(optee))
789+ optee_disable_shm_cache(optee);
790
791 /*
792 * The two devices have to be unregistered before we can free the
793@@ -631,6 +1099,14 @@ static int optee_remove(struct platform_device *pdev)
794 optee_supp_uninit(&optee->supp);
795 mutex_destroy(&optee->call_queue.mutex);
796
797+#ifdef CONFIG_ARM_FFA_TRANSPORT
798+ if (optee->ffa.ffa_ops) {
799+ mutex_destroy(&optee->ffa.mutex);
800+ rhashtable_free_and_destroy(&optee->ffa.global_ids,
801+ rh_free_fn, NULL);
802+ }
803+#endif /*CONFIG_ARM_FFA_TRANSPORT*/
804+
805 kfree(optee);
806
807 return 0;
808diff --git a/drivers/tee/optee/optee_ffa.h b/drivers/tee/optee/optee_ffa.h
809new file mode 100644
810index 000000000000..ee3a03fc392c
811--- /dev/null
812+++ b/drivers/tee/optee/optee_ffa.h
813@@ -0,0 +1,153 @@
814+/* SPDX-License-Identifier: BSD-2-Clause */
815+/*
816+ * Copyright (c) 2019-2021, Linaro Limited
817+ */
818+
819+/*
820+ * This file is exported by OP-TEE and is kept in sync between secure world
821+ * and normal world drivers. We're using ARM FF-A 1.0 specification.
822+ */
823+
824+#ifndef __OPTEE_FFA_H
825+#define __OPTEE_FFA_H
826+
827+#include <linux/arm_ffa.h>
828+
829+/*
830+ * Normal world sends requests with FFA_MSG_SEND_DIRECT_REQ and
831+ * responses are returned with FFA_MSG_SEND_DIRECT_RESP for normal
832+ * messages.
833+ *
834+ * All requests with FFA_MSG_SEND_DIRECT_REQ and FFA_MSG_SEND_DIRECT_RESP
835+ * are using the AArch32 SMC calling convention with register usage as
836+ * defined in FF-A specification:
837+ * w0: Function ID (0x8400006F or 0x84000070)
838+ * w1: Source/Destination IDs
839+ * w2: Reserved (MBZ)
840+ * w3-w7: Implementation defined, free to be used below
841+ */
842+
843+#define OPTEE_FFA_VERSION_MAJOR 1
844+#define OPTEE_FFA_VERSION_MINOR 0
845+
846+#define OPTEE_FFA_BLOCKING_CALL(id) (id)
847+#define OPTEE_FFA_YIELDING_CALL_BIT 31
848+#define OPTEE_FFA_YIELDING_CALL(id) ((id) | BIT(OPTEE_FFA_YIELDING_CALL_BIT))
849+
850+/*
851+ * Returns the API version implemented, currently follows the FF-A version.
852+ * Call register usage:
853+ * w3: Service ID, OPTEE_FFA_GET_API_VERSION
854+ * w4-w7: Not used (MBZ)
855+ *
856+ * Return register usage:
857+ * w3: OPTEE_FFA_VERSION_MAJOR
858+ * w4: OPTEE_FFA_VERSION_MINOR
859+ * w5-w7: Not used (MBZ)
860+ */
861+#define OPTEE_FFA_GET_API_VERSION OPTEE_FFA_BLOCKING_CALL(0)
862+
863+/*
864+ * Returns the revision of OP-TEE.
865+ *
866+ * Used by non-secure world to figure out which version of the Trusted OS
867+ * is installed. Note that the returned revision is the revision of the
868+ * Trusted OS, not of the API.
869+ *
870+ * Call register usage:
871+ * w3: Service ID, OPTEE_FFA_GET_OS_VERSION
872+ * w4-w7: Unused (MBZ)
873+ *
874+ * Return register usage:
875+ * w3: CFG_OPTEE_REVISION_MAJOR
876+ * w4: CFG_OPTEE_REVISION_MINOR
877+ * w5: TEE_IMPL_GIT_SHA1 (or zero if not supported)
878+ */
879+#define OPTEE_FFA_GET_OS_VERSION OPTEE_FFA_BLOCKING_CALL(1)
880+
881+/*
882+ * Exchange capabilities between normal world and secure world.
883+ *
884+ * Currently there are no defined capabilities. When features are added new
885+ * capabilities may be added.
886+ *
887+ * Call register usage:
888+ * w3: Service ID, OPTEE_FFA_EXCHANGE_CAPABILITIES
889+ * w4-w7: Note used (MBZ)
890+ *
891+ * Return register usage:
892+ * w3: Error code, 0 on success
893+ * w4: Bit[7:0]: Number of parameters needed for RPC to be supplied
894+ * as the second MSG arg struct for
895+ * OPTEE_FFA_YIELDING_CALL_WITH_ARG.
896+ * Bit[31:8]: Reserved (MBZ)
897+ * w5-w7: Note used (MBZ)
898+ */
899+#define OPTEE_FFA_EXCHANGE_CAPABILITIES OPTEE_FFA_BLOCKING_CALL(2)
900+
901+/*
902+ * Unregister shared memory
903+ *
904+ * Call register usage:
905+ * w3: Service ID, OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM
906+ * w4: Shared memory handle, lower bits
907+ * w5: Shared memory handle, higher bits
908+ * w6-w7: Not used (MBZ)
909+ *
910+ * Return register usage:
911+ * w3: Error code, 0 on success
912+ * w4-w7: Note used (MBZ)
913+ */
914+#define OPTEE_FFA_UNREGISTER_SHM OPTEE_FFA_BLOCKING_CALL(3)
915+
916+/*
917+ * Call with struct optee_msg_arg as argument in the supplied shared memory
918+ * with a zero internal offset and normal cached memory attributes.
919+ * Register usage:
920+ * w3: Service ID, OPTEE_FFA_YIELDING_CALL_WITH_ARG
921+ * w4: Lower 32 bits of a 64-bit Shared memory handle
922+ * w5: Upper 32 bits of a 64-bit Shared memory handle
923+ * w6: Offset into shared memory pointing to a struct optee_msg_arg
924+ * right after the parameters of this struct (at offset
925+ * OPTEE_MSG_GET_ARG_SIZE(num_params) follows a struct optee_msg_arg
926+ * for RPC, this struct has reserved space for the number of RPC
927+ * parameters as returned by OPTEE_FFA_EXCHANGE_CAPABILITIES.
928+ * w7: Not used (MBZ)
929+ * Resume from RPC. Register usage:
930+ * w3: Service ID, OPTEE_FFA_YIELDING_CALL_RESUME
931+ * w4-w6: Not used (MBZ)
932+ * w7: Resume info
933+ *
934+ * Normal return (yielding call is completed). Register usage:
935+ * w3: Error code, 0 on success
936+ * w4: OPTEE_FFA_YIELDING_CALL_RETURN_DONE
937+ * w5-w7: Not used (MBZ)
938+ *
939+ * RPC interrupt return (RPC from secure world). Register usage:
940+ * w3: Error code == 0
941+ * w4: Any defined RPC code but OPTEE_FFA_YIELDING_CALL_RETURN_DONE
942+ * w5-w6: Not used (MBZ)
943+ * w7: Resume info
944+ *
945+ * Possible error codes in register w3:
946+ * 0: Success
947+ * FFA_DENIED: w4 isn't one of OPTEE_FFA_YIELDING_CALL_START
948+ * OPTEE_FFA_YIELDING_CALL_RESUME
949+ *
950+ * Possible error codes for OPTEE_FFA_YIELDING_CALL_START,
951+ * FFA_BUSY: Number of OP-TEE OS threads exceeded,
952+ * try again later
953+ * FFA_DENIED: RPC shared memory object not found
954+ * FFA_INVALID_PARAMETER: Bad shared memory handle or offset into the memory
955+ *
956+ * Possible error codes for OPTEE_FFA_YIELDING_CALL_RESUME
957+ * FFA_INVALID_PARAMETER: Bad resume info
958+ */
959+#define OPTEE_FFA_YIELDING_CALL_WITH_ARG OPTEE_FFA_YIELDING_CALL(0)
960+#define OPTEE_FFA_YIELDING_CALL_RESUME OPTEE_FFA_YIELDING_CALL(1)
961+
962+#define OPTEE_FFA_YIELDING_CALL_RETURN_DONE 0
963+#define OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD 1
964+#define OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT 2
965+
966+#endif /*__OPTEE_FFA_H*/
967diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h
968index 5bef6a0165db..1ee943980c68 100644
969--- a/drivers/tee/optee/optee_msg.h
970+++ b/drivers/tee/optee/optee_msg.h
971@@ -28,6 +28,9 @@
972 #define OPTEE_MSG_ATTR_TYPE_RMEM_INPUT 0x5
973 #define OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT 0x6
974 #define OPTEE_MSG_ATTR_TYPE_RMEM_INOUT 0x7
975+#define OPTEE_MSG_ATTR_TYPE_FMEM_INPUT OPTEE_MSG_ATTR_TYPE_RMEM_INPUT
976+#define OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT
977+#define OPTEE_MSG_ATTR_TYPE_FMEM_INOUT OPTEE_MSG_ATTR_TYPE_RMEM_INOUT
978 #define OPTEE_MSG_ATTR_TYPE_TMEM_INPUT 0x9
979 #define OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT 0xa
980 #define OPTEE_MSG_ATTR_TYPE_TMEM_INOUT 0xb
981@@ -96,6 +99,8 @@
982 */
983 #define OPTEE_MSG_NONCONTIG_PAGE_SIZE 4096
984
985+#define OPTEE_MSG_FMEM_INVALID_GLOBAL_ID 0xffffffffffffffff
986+
987 /**
988 * struct optee_msg_param_tmem - temporary memory reference parameter
989 * @buf_ptr: Address of the buffer
990@@ -127,6 +132,23 @@ struct optee_msg_param_rmem {
991 u64 shm_ref;
992 };
993
994+/**
995+ * struct optee_msg_param_fmem - ffa memory reference parameter
996+ * @offs_lower: Lower bits of offset into shared memory reference
997+ * @offs_upper: Upper bits of offset into shared memory reference
998+ * @internal_offs: Internal offset into the first page of shared memory
999+ * reference
1000+ * @size: Size of the buffer
1001+ * @global_id: Global identifier of Shared memory
1002+ */
1003+struct optee_msg_param_fmem {
1004+ u32 offs_low;
1005+ u16 offs_high;
1006+ u16 internal_offs;
1007+ u64 size;
1008+ u64 global_id;
1009+};
1010+
1011 /**
1012 * struct optee_msg_param_value - opaque value parameter
1013 *
1014@@ -143,13 +165,15 @@ struct optee_msg_param_value {
1015 * @attr: attributes
1016 * @tmem: parameter by temporary memory reference
1017 * @rmem: parameter by registered memory reference
1018+ * @fmem: parameter by ffa registered memory reference
1019 * @value: parameter by opaque value
1020 * @octets: parameter by octet string
1021 *
1022 * @attr & OPTEE_MSG_ATTR_TYPE_MASK indicates if tmem, rmem or value is used in
1023 * the union. OPTEE_MSG_ATTR_TYPE_VALUE_* indicates value or octets,
1024 * OPTEE_MSG_ATTR_TYPE_TMEM_* indicates @tmem and
1025- * OPTEE_MSG_ATTR_TYPE_RMEM_* indicates @rmem,
1026+ * OPTEE_MSG_ATTR_TYPE_RMEM_* or the alias PTEE_MSG_ATTR_TYPE_FMEM_* indicates
1027+ * @rmem or @fmem depending on the conduit.
1028 * OPTEE_MSG_ATTR_TYPE_NONE indicates that none of the members are used.
1029 */
1030 struct optee_msg_param {
1031@@ -157,6 +181,7 @@ struct optee_msg_param {
1032 union {
1033 struct optee_msg_param_tmem tmem;
1034 struct optee_msg_param_rmem rmem;
1035+ struct optee_msg_param_fmem fmem;
1036 struct optee_msg_param_value value;
1037 u8 octets[24];
1038 } u;
1039diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
1040index c5741e96e967..1ffe74e66d15 100644
1041--- a/drivers/tee/optee/optee_private.h
1042+++ b/drivers/tee/optee/optee_private.h
1043@@ -7,6 +7,7 @@
1044 #define OPTEE_PRIVATE_H
1045
1046 #include <linux/arm-smccc.h>
1047+#include <linux/rhashtable.h>
1048 #include <linux/semaphore.h>
1049 #include <linux/tee_drv.h>
1050 #include <linux/types.h>
1051@@ -20,6 +21,7 @@
1052 #define TEEC_ERROR_NOT_SUPPORTED 0xFFFF000A
1053 #define TEEC_ERROR_COMMUNICATION 0xFFFF000E
1054 #define TEEC_ERROR_OUT_OF_MEMORY 0xFFFF000C
1055+#define TEEC_ERROR_BUSY 0xFFFF000D
1056 #define TEEC_ERROR_SHORT_BUFFER 0xFFFF0010
1057
1058 #define TEEC_ORIGIN_COMMS 0x00000002
1059@@ -66,6 +68,22 @@ struct optee_supp {
1060 struct completion reqs_c;
1061 };
1062
1063+/**
1064+ * struct optee_ffa_data - FFA communication struct
1065+ * @ffa_dev FFA device, contains the destination id, the id of
1066+ * OP-TEE in secure world
1067+ * @ffa_ops FFA operations
1068+ * @mutex Serializes access to @global_ids
1069+ * @global_ids FF-A shared memory global handle translation
1070+ */
1071+struct optee_ffa {
1072+ struct ffa_device *ffa_dev;
1073+ const struct ffa_dev_ops *ffa_ops;
1074+ /* Serializes access to @global_ids */
1075+ struct mutex mutex;
1076+ struct rhashtable global_ids;
1077+};
1078+
1079 struct optee;
1080
1081 /**
1082@@ -113,11 +131,15 @@ struct optee {
1083 struct tee_device *teedev;
1084 const struct optee_ops *ops;
1085 optee_invoke_fn *invoke_fn;
1086+#ifdef CONFIG_ARM_FFA_TRANSPORT
1087+ struct optee_ffa ffa;
1088+#endif
1089 struct optee_call_queue call_queue;
1090 struct optee_wait_queue wait_queue;
1091 struct optee_supp supp;
1092 struct tee_shm_pool *pool;
1093 void *memremaped_shm;
1094+ unsigned int rpc_arg_count;
1095 u32 sec_caps;
1096 bool scan_bus_done;
1097 struct workqueue_struct *scan_bus_wq;
1098@@ -206,6 +228,36 @@ void optee_fill_pages_list(u64 *dst, struct page **pages, int num_pages,
1099 #define PTA_CMD_GET_DEVICES_SUPP 0x1
1100 int optee_enumerate_devices(u32 func);
1101
1102+int optee_shm_add_ffa_handle(struct optee *optee, struct tee_shm *shm,
1103+ u64 global_id);
1104+int optee_shm_rem_ffa_handle(struct optee *optee, u64 global_id);
1105+
1106+struct tee_shm *optee_shm_from_ffa_handle(struct optee *optee, u64 global_id);
1107+
1108+int optee_ffa_shm_register(struct tee_context *ctx, struct tee_shm *shm,
1109+ struct page **pages, size_t num_pages,
1110+ unsigned long start);
1111+int optee_ffa_shm_unregister(struct tee_context *ctx, struct tee_shm *shm);
1112+int optee_ffa_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm,
1113+ struct page **pages, size_t num_pages,
1114+ unsigned long start);
1115+int optee_ffa_shm_unregister_supp(struct tee_context *ctx,
1116+ struct tee_shm *shm);
1117+
1118+int optee_ffa_do_call_with_arg(struct tee_context *ctx, struct tee_shm *arg);
1119+int optee_ffa_rpc_shm_register(struct tee_context *ctx, struct tee_shm *shm);
1120+void optee_handle_ffa_rpc(struct tee_context *ctx, u32 cmd,
1121+ struct optee_msg_arg *arg);
1122+
1123+static inline bool optee_is_ffa_based(struct optee *optee)
1124+{
1125+#ifdef CONFIG_ARM_FFA_TRANSPORT
1126+ return optee->ffa.ffa_ops;
1127+#else
1128+ return false;
1129+#endif
1130+}
1131+
1132 /*
1133 * Small helpers
1134 */
1135diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c
1136index 39562fb6841e..865a9ab3cf65 100644
1137--- a/drivers/tee/optee/rpc.c
1138+++ b/drivers/tee/optee/rpc.c
1139@@ -10,6 +10,7 @@
1140 #include <linux/i2c.h>
1141 #include <linux/slab.h>
1142 #include <linux/tee_drv.h>
1143+#include "optee_ffa.h"
1144 #include "optee_private.h"
1145 #include "optee_smc.h"
1146 #include "optee_rpc_cmd.h"
1147@@ -543,3 +544,120 @@ void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param,
1148
1149 param->a0 = OPTEE_SMC_CALL_RETURN_FROM_RPC;
1150 }
1151+
1152+#ifdef CONFIG_ARM_FFA_TRANSPORT
1153+static void handle_ffa_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
1154+ struct optee_msg_arg *arg)
1155+{
1156+ struct tee_shm *shm;
1157+
1158+ if (arg->num_params != 1 ||
1159+ arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) {
1160+ arg->ret = TEEC_ERROR_BAD_PARAMETERS;
1161+ return;
1162+ }
1163+
1164+ switch (arg->params[0].u.value.a) {
1165+ case OPTEE_RPC_SHM_TYPE_APPL:
1166+ shm = cmd_alloc_suppl(ctx, arg->params[0].u.value.b);
1167+ break;
1168+ case OPTEE_RPC_SHM_TYPE_KERNEL:
1169+ shm = tee_shm_alloc(ctx, arg->params[0].u.value.b,
1170+ TEE_SHM_MAPPED);
1171+ break;
1172+ default:
1173+ arg->ret = TEEC_ERROR_BAD_PARAMETERS;
1174+ return;
1175+ }
1176+
1177+ if (IS_ERR(shm)) {
1178+ arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
1179+ return;
1180+ }
1181+
1182+ arg->params[0] = (struct optee_msg_param){
1183+ .attr = OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT,
1184+ .u.fmem.size = tee_shm_get_size(shm),
1185+ .u.fmem.global_id = shm->sec_world_id,
1186+ .u.fmem.internal_offs = shm->offset,
1187+ };
1188+
1189+ arg->ret = TEEC_SUCCESS;
1190+}
1191+
1192+static void handle_ffa_rpc_func_cmd_shm_free(struct tee_context *ctx,
1193+ struct optee *optee,
1194+ struct optee_msg_arg *arg)
1195+{
1196+ struct tee_shm *shm;
1197+
1198+ if (arg->num_params != 1 ||
1199+ arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT)
1200+ goto err_bad_param;
1201+
1202+ shm = optee_shm_from_ffa_handle(optee, arg->params[0].u.value.b);
1203+ if (!shm)
1204+ goto err_bad_param;
1205+ switch (arg->params[0].u.value.a) {
1206+ case OPTEE_RPC_SHM_TYPE_APPL:
1207+ cmd_free_suppl(ctx, shm);
1208+ break;
1209+ case OPTEE_RPC_SHM_TYPE_KERNEL:
1210+ tee_shm_free(shm);
1211+ break;
1212+ default:
1213+ goto err_bad_param;
1214+ }
1215+ arg->ret = TEEC_SUCCESS;
1216+ return;
1217+
1218+err_bad_param:
1219+ arg->ret = TEEC_ERROR_BAD_PARAMETERS;
1220+}
1221+
1222+static void handle_ffa_rpc_func_cmd(struct tee_context *ctx,
1223+ struct optee_msg_arg *arg)
1224+{
1225+ struct optee *optee = tee_get_drvdata(ctx->teedev);
1226+
1227+ arg->ret_origin = TEEC_ORIGIN_COMMS;
1228+ switch (arg->cmd) {
1229+ case OPTEE_RPC_CMD_GET_TIME:
1230+ handle_rpc_func_cmd_get_time(arg);
1231+ break;
1232+ case OPTEE_RPC_CMD_WAIT_QUEUE:
1233+ handle_rpc_func_cmd_wq(optee, arg);
1234+ break;
1235+ case OPTEE_RPC_CMD_SUSPEND:
1236+ handle_rpc_func_cmd_wait(arg);
1237+ break;
1238+ case OPTEE_RPC_CMD_SHM_ALLOC:
1239+ handle_ffa_rpc_func_cmd_shm_alloc(ctx, arg);
1240+ break;
1241+ case OPTEE_RPC_CMD_SHM_FREE:
1242+ handle_ffa_rpc_func_cmd_shm_free(ctx, optee, arg);
1243+ break;
1244+ case OPTEE_RPC_CMD_I2C_TRANSFER:
1245+ handle_rpc_func_cmd_i2c_transfer(ctx, arg);
1246+ break;
1247+ default:
1248+ handle_rpc_supp_cmd(ctx, optee, arg);
1249+ }
1250+}
1251+
1252+void optee_handle_ffa_rpc(struct tee_context *ctx, u32 cmd,
1253+ struct optee_msg_arg *arg)
1254+{
1255+ switch (cmd) {
1256+ case OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD:
1257+ handle_ffa_rpc_func_cmd(ctx, arg);
1258+ break;
1259+ case OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT:
1260+ /* Interrupt delivered by now */
1261+ break;
1262+ default:
1263+ pr_warn("Unknown RPC func 0x%x\n", cmd);
1264+ break;
1265+ }
1266+}
1267+#endif /*CONFIG_ARM_FFA_TRANSPORT*/
1268--
12692.17.1
1270