1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (c) 2023, Arm Limited
4 */
5
6 #include <linux/arm_ffa.h>
7 #include <linux/err.h>
8 #include <linux/errno.h>
9 #include <linux/kernel.h>
10 #include <linux/limits.h>
11 #include <linux/mm.h>
12 #include <linux/module.h>
13 #include <linux/scatterlist.h>
14 #include <linux/slab.h>
15 #include <linux/tee_core.h>
16 #include <linux/types.h>
17 #include <linux/uuid.h>
18 #include <linux/xarray.h>
19 #include "tstee_private.h"
20
21 #define FFA_DIRECT_REQ_ARG_NUM 5
22 #define FFA_INVALID_MEM_HANDLE U64_MAX
23
arg_list_to_ffa_data(const u32 * args,struct ffa_send_direct_data * data)24 static void arg_list_to_ffa_data(const u32 *args,
25 struct ffa_send_direct_data *data)
26 {
27 data->data0 = args[0];
28 data->data1 = args[1];
29 data->data2 = args[2];
30 data->data3 = args[3];
31 data->data4 = args[4];
32 }
33
arg_list_from_ffa_data(const struct ffa_send_direct_data * data,u32 * args)34 static void arg_list_from_ffa_data(const struct ffa_send_direct_data *data,
35 u32 *args)
36 {
37 args[0] = lower_32_bits(data->data0);
38 args[1] = lower_32_bits(data->data1);
39 args[2] = lower_32_bits(data->data2);
40 args[3] = lower_32_bits(data->data3);
41 args[4] = lower_32_bits(data->data4);
42 }
43
tstee_get_version(struct tee_device * teedev,struct tee_ioctl_version_data * vers)44 static void tstee_get_version(struct tee_device *teedev,
45 struct tee_ioctl_version_data *vers)
46 {
47 struct tstee *tstee = tee_get_drvdata(teedev);
48 struct tee_ioctl_version_data v = {
49 .impl_id = TEE_IMPL_ID_TSTEE,
50 /* FF-A endpoint ID only uses the lower 16 bits */
51 .impl_caps = lower_16_bits(tstee->ffa_dev->vm_id),
52 .gen_caps = 0,
53 };
54
55 *vers = v;
56 }
57
tstee_open(struct tee_context * ctx)58 static int tstee_open(struct tee_context *ctx)
59 {
60 struct ts_context_data *ctxdata;
61
62 ctxdata = kzalloc(sizeof(*ctxdata), GFP_KERNEL);
63 if (!ctxdata)
64 return -ENOMEM;
65
66 xa_init_flags(&ctxdata->sess_list, XA_FLAGS_ALLOC);
67
68 ctx->data = ctxdata;
69
70 return 0;
71 }
72
tstee_release(struct tee_context * ctx)73 static void tstee_release(struct tee_context *ctx)
74 {
75 struct ts_context_data *ctxdata = ctx->data;
76 struct ts_session *sess;
77 unsigned long idx;
78
79 if (!ctxdata)
80 return;
81
82 xa_for_each(&ctxdata->sess_list, idx, sess) {
83 xa_erase(&ctxdata->sess_list, idx);
84 kfree(sess);
85 }
86
87 xa_destroy(&ctxdata->sess_list);
88
89 kfree(ctxdata);
90 ctx->data = NULL;
91 }
92
tstee_open_session(struct tee_context * ctx,struct tee_ioctl_open_session_arg * arg,struct tee_param * param __always_unused)93 static int tstee_open_session(struct tee_context *ctx,
94 struct tee_ioctl_open_session_arg *arg,
95 struct tee_param *param __always_unused)
96 {
97 struct tstee *tstee = tee_get_drvdata(ctx->teedev);
98 struct ffa_device *ffa_dev = tstee->ffa_dev;
99 struct ts_context_data *ctxdata = ctx->data;
100 struct ffa_send_direct_data ffa_data;
101 struct ts_session *sess = NULL;
102 u32 ffa_args[FFA_DIRECT_REQ_ARG_NUM] = {};
103 u32 sess_id;
104 int rc;
105
106 ffa_args[TS_RPC_CTRL_REG] =
107 TS_RPC_CTRL_PACK_IFACE_OPCODE(TS_RPC_MGMT_IFACE_ID,
108 TS_RPC_OP_SERVICE_INFO);
109
110 memcpy(ffa_args + TS_RPC_SERVICE_INFO_UUID0, arg->uuid, UUID_SIZE);
111
112 arg_list_to_ffa_data(ffa_args, &ffa_data);
113 rc = ffa_dev->ops->msg_ops->sync_send_receive(ffa_dev, &ffa_data);
114 if (rc)
115 return rc;
116
117 arg_list_from_ffa_data(&ffa_data, ffa_args);
118
119 if (ffa_args[TS_RPC_SERVICE_INFO_RPC_STATUS] != TS_RPC_OK)
120 return -ENODEV;
121
122 if (ffa_args[TS_RPC_SERVICE_INFO_IFACE] > U8_MAX)
123 return -EINVAL;
124
125 sess = kzalloc(sizeof(*sess), GFP_KERNEL);
126 if (!sess)
127 return -ENOMEM;
128
129 sess->iface_id = ffa_args[TS_RPC_SERVICE_INFO_IFACE];
130
131 rc = xa_alloc(&ctxdata->sess_list, &sess_id, sess, xa_limit_32b,
132 GFP_KERNEL);
133 if (rc) {
134 kfree(sess);
135 return rc;
136 }
137
138 arg->session = sess_id;
139 arg->ret = 0;
140
141 return 0;
142 }
143
tstee_close_session(struct tee_context * ctx,u32 session)144 static int tstee_close_session(struct tee_context *ctx, u32 session)
145 {
146 struct ts_context_data *ctxdata = ctx->data;
147 struct ts_session *sess;
148
149 /* Calls xa_lock() internally */
150 sess = xa_erase(&ctxdata->sess_list, session);
151 if (!sess)
152 return -EINVAL;
153
154 kfree(sess);
155
156 return 0;
157 }
158
tstee_invoke_func(struct tee_context * ctx,struct tee_ioctl_invoke_arg * arg,struct tee_param * param)159 static int tstee_invoke_func(struct tee_context *ctx,
160 struct tee_ioctl_invoke_arg *arg,
161 struct tee_param *param)
162 {
163 struct tstee *tstee = tee_get_drvdata(ctx->teedev);
164 struct ffa_device *ffa_dev = tstee->ffa_dev;
165 struct ts_context_data *ctxdata = ctx->data;
166 struct ffa_send_direct_data ffa_data;
167 struct tee_shm *shm = NULL;
168 struct ts_session *sess;
169 u32 req_len, ffa_args[FFA_DIRECT_REQ_ARG_NUM] = {};
170 int shm_id, rc;
171 u8 iface_id;
172 u64 handle;
173 u16 opcode;
174
175 xa_lock(&ctxdata->sess_list);
176 sess = xa_load(&ctxdata->sess_list, arg->session);
177
178 /*
179 * Do this while holding the lock to make sure that the session wasn't
180 * closed meanwhile
181 */
182 if (sess)
183 iface_id = sess->iface_id;
184
185 xa_unlock(&ctxdata->sess_list);
186 if (!sess)
187 return -EINVAL;
188
189 opcode = lower_16_bits(arg->func);
190 shm_id = lower_32_bits(param[0].u.value.a);
191 req_len = lower_32_bits(param[0].u.value.b);
192
193 if (shm_id != 0) {
194 shm = tee_shm_get_from_id(ctx, shm_id);
195 if (IS_ERR(shm))
196 return PTR_ERR(shm);
197
198 if (shm->size < req_len) {
199 dev_err(&ffa_dev->dev,
200 "request doesn't fit into shared memory buffer\n");
201 rc = -EINVAL;
202 goto out;
203 }
204
205 handle = shm->sec_world_id;
206 } else {
207 handle = FFA_INVALID_MEM_HANDLE;
208 }
209
210 ffa_args[TS_RPC_CTRL_REG] = TS_RPC_CTRL_PACK_IFACE_OPCODE(iface_id,
211 opcode);
212 ffa_args[TS_RPC_SERVICE_MEM_HANDLE_LSW] = lower_32_bits(handle);
213 ffa_args[TS_RPC_SERVICE_MEM_HANDLE_MSW] = upper_32_bits(handle);
214 ffa_args[TS_RPC_SERVICE_REQ_LEN] = req_len;
215 ffa_args[TS_RPC_SERVICE_CLIENT_ID] = 0;
216
217 arg_list_to_ffa_data(ffa_args, &ffa_data);
218 rc = ffa_dev->ops->msg_ops->sync_send_receive(ffa_dev, &ffa_data);
219 if (rc)
220 goto out;
221
222 arg_list_from_ffa_data(&ffa_data, ffa_args);
223
224 if (ffa_args[TS_RPC_SERVICE_RPC_STATUS] != TS_RPC_OK) {
225 dev_err(&ffa_dev->dev, "invoke_func rpc status: %d\n",
226 ffa_args[TS_RPC_SERVICE_RPC_STATUS]);
227 rc = -EINVAL;
228 goto out;
229 }
230
231 arg->ret = ffa_args[TS_RPC_SERVICE_STATUS];
232 if (shm && shm->size >= ffa_args[TS_RPC_SERVICE_RESP_LEN])
233 param[0].u.value.a = ffa_args[TS_RPC_SERVICE_RESP_LEN];
234
235 out:
236 if (shm)
237 tee_shm_put(shm);
238
239 return rc;
240 }
241
tstee_shm_register(struct tee_context * ctx,struct tee_shm * shm,struct page ** pages,size_t num_pages,unsigned long start __always_unused)242 static int tstee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
243 struct page **pages, size_t num_pages,
244 unsigned long start __always_unused)
245 {
246 struct tstee *tstee = tee_get_drvdata(ctx->teedev);
247 struct ffa_device *ffa_dev = tstee->ffa_dev;
248 struct ffa_mem_region_attributes mem_attr = {
249 .receiver = tstee->ffa_dev->vm_id,
250 .attrs = FFA_MEM_RW,
251 .flag = 0,
252 };
253 struct ffa_mem_ops_args mem_args = {
254 .attrs = &mem_attr,
255 .use_txbuf = true,
256 .nattrs = 1,
257 .flags = 0,
258 };
259 struct ffa_send_direct_data ffa_data;
260 struct sg_table sgt;
261 u32 ffa_args[FFA_DIRECT_REQ_ARG_NUM] = {};
262 int rc;
263
264 rc = sg_alloc_table_from_pages(&sgt, pages, num_pages, 0,
265 num_pages * PAGE_SIZE, GFP_KERNEL);
266 if (rc)
267 return rc;
268
269 mem_args.sg = sgt.sgl;
270 rc = ffa_dev->ops->mem_ops->memory_share(&mem_args);
271 sg_free_table(&sgt);
272 if (rc)
273 return rc;
274
275 shm->sec_world_id = mem_args.g_handle;
276
277 ffa_args[TS_RPC_CTRL_REG] =
278 TS_RPC_CTRL_PACK_IFACE_OPCODE(TS_RPC_MGMT_IFACE_ID,
279 TS_RPC_OP_RETRIEVE_MEM);
280 ffa_args[TS_RPC_RETRIEVE_MEM_HANDLE_LSW] =
281 lower_32_bits(shm->sec_world_id);
282 ffa_args[TS_RPC_RETRIEVE_MEM_HANDLE_MSW] =
283 upper_32_bits(shm->sec_world_id);
284 ffa_args[TS_RPC_RETRIEVE_MEM_TAG_LSW] = 0;
285 ffa_args[TS_RPC_RETRIEVE_MEM_TAG_MSW] = 0;
286
287 arg_list_to_ffa_data(ffa_args, &ffa_data);
288 rc = ffa_dev->ops->msg_ops->sync_send_receive(ffa_dev, &ffa_data);
289 if (rc) {
290 (void)ffa_dev->ops->mem_ops->memory_reclaim(shm->sec_world_id,
291 0);
292 return rc;
293 }
294
295 arg_list_from_ffa_data(&ffa_data, ffa_args);
296
297 if (ffa_args[TS_RPC_RETRIEVE_MEM_RPC_STATUS] != TS_RPC_OK) {
298 dev_err(&ffa_dev->dev, "shm_register rpc status: %d\n",
299 ffa_args[TS_RPC_RETRIEVE_MEM_RPC_STATUS]);
300 ffa_dev->ops->mem_ops->memory_reclaim(shm->sec_world_id, 0);
301 return -EINVAL;
302 }
303
304 return 0;
305 }
306
tstee_shm_unregister(struct tee_context * ctx,struct tee_shm * shm)307 static int tstee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm)
308 {
309 struct tstee *tstee = tee_get_drvdata(ctx->teedev);
310 struct ffa_device *ffa_dev = tstee->ffa_dev;
311 struct ffa_send_direct_data ffa_data;
312 u32 ffa_args[FFA_DIRECT_REQ_ARG_NUM] = {};
313 int rc;
314
315 ffa_args[TS_RPC_CTRL_REG] =
316 TS_RPC_CTRL_PACK_IFACE_OPCODE(TS_RPC_MGMT_IFACE_ID,
317 TS_RPC_OP_RELINQ_MEM);
318 ffa_args[TS_RPC_RELINQ_MEM_HANDLE_LSW] =
319 lower_32_bits(shm->sec_world_id);
320 ffa_args[TS_RPC_RELINQ_MEM_HANDLE_MSW] =
321 upper_32_bits(shm->sec_world_id);
322
323 arg_list_to_ffa_data(ffa_args, &ffa_data);
324 rc = ffa_dev->ops->msg_ops->sync_send_receive(ffa_dev, &ffa_data);
325 if (rc)
326 return rc;
327 arg_list_from_ffa_data(&ffa_data, ffa_args);
328
329 if (ffa_args[TS_RPC_RELINQ_MEM_RPC_STATUS] != TS_RPC_OK) {
330 dev_err(&ffa_dev->dev, "shm_unregister rpc status: %d\n",
331 ffa_args[TS_RPC_RELINQ_MEM_RPC_STATUS]);
332 return -EINVAL;
333 }
334
335 rc = ffa_dev->ops->mem_ops->memory_reclaim(shm->sec_world_id, 0);
336
337 return rc;
338 }
339
340 static const struct tee_driver_ops tstee_ops = {
341 .get_version = tstee_get_version,
342 .open = tstee_open,
343 .release = tstee_release,
344 .open_session = tstee_open_session,
345 .close_session = tstee_close_session,
346 .invoke_func = tstee_invoke_func,
347 };
348
349 static const struct tee_desc tstee_desc = {
350 .name = "tstee-clnt",
351 .ops = &tstee_ops,
352 .owner = THIS_MODULE,
353 };
354
pool_op_alloc(struct tee_shm_pool * pool,struct tee_shm * shm,size_t size,size_t align)355 static int pool_op_alloc(struct tee_shm_pool *pool, struct tee_shm *shm,
356 size_t size, size_t align)
357 {
358 return tee_dyn_shm_alloc_helper(shm, size, align, tstee_shm_register);
359 }
360
pool_op_free(struct tee_shm_pool * pool,struct tee_shm * shm)361 static void pool_op_free(struct tee_shm_pool *pool, struct tee_shm *shm)
362 {
363 tee_dyn_shm_free_helper(shm, tstee_shm_unregister);
364 }
365
pool_op_destroy_pool(struct tee_shm_pool * pool)366 static void pool_op_destroy_pool(struct tee_shm_pool *pool)
367 {
368 kfree(pool);
369 }
370
371 static const struct tee_shm_pool_ops pool_ops = {
372 .alloc = pool_op_alloc,
373 .free = pool_op_free,
374 .destroy_pool = pool_op_destroy_pool,
375 };
376
tstee_create_shm_pool(void)377 static struct tee_shm_pool *tstee_create_shm_pool(void)
378 {
379 struct tee_shm_pool *pool = kzalloc(sizeof(*pool), GFP_KERNEL);
380
381 if (!pool)
382 return ERR_PTR(-ENOMEM);
383
384 pool->ops = &pool_ops;
385
386 return pool;
387 }
388
tstee_check_rpc_compatible(struct ffa_device * ffa_dev)389 static bool tstee_check_rpc_compatible(struct ffa_device *ffa_dev)
390 {
391 struct ffa_send_direct_data ffa_data;
392 u32 ffa_args[FFA_DIRECT_REQ_ARG_NUM] = {};
393
394 ffa_args[TS_RPC_CTRL_REG] =
395 TS_RPC_CTRL_PACK_IFACE_OPCODE(TS_RPC_MGMT_IFACE_ID,
396 TS_RPC_OP_GET_VERSION);
397
398 arg_list_to_ffa_data(ffa_args, &ffa_data);
399 if (ffa_dev->ops->msg_ops->sync_send_receive(ffa_dev, &ffa_data))
400 return false;
401
402 arg_list_from_ffa_data(&ffa_data, ffa_args);
403
404 return ffa_args[TS_RPC_GET_VERSION_RESP] == TS_RPC_PROTOCOL_VERSION;
405 }
406
tstee_probe(struct ffa_device * ffa_dev)407 static int tstee_probe(struct ffa_device *ffa_dev)
408 {
409 struct tstee *tstee;
410 int rc;
411
412 ffa_dev->ops->msg_ops->mode_32bit_set(ffa_dev);
413
414 if (!tstee_check_rpc_compatible(ffa_dev))
415 return -EINVAL;
416
417 tstee = kzalloc(sizeof(*tstee), GFP_KERNEL);
418 if (!tstee)
419 return -ENOMEM;
420
421 tstee->ffa_dev = ffa_dev;
422
423 tstee->pool = tstee_create_shm_pool();
424 if (IS_ERR(tstee->pool)) {
425 rc = PTR_ERR(tstee->pool);
426 tstee->pool = NULL;
427 goto err_free_tstee;
428 }
429
430 tstee->teedev = tee_device_alloc(&tstee_desc, NULL, tstee->pool, tstee);
431 if (IS_ERR(tstee->teedev)) {
432 rc = PTR_ERR(tstee->teedev);
433 tstee->teedev = NULL;
434 goto err_free_pool;
435 }
436
437 rc = tee_device_register(tstee->teedev);
438 if (rc)
439 goto err_unreg_teedev;
440
441 ffa_dev_set_drvdata(ffa_dev, tstee);
442
443 return 0;
444
445 err_unreg_teedev:
446 tee_device_unregister(tstee->teedev);
447 err_free_pool:
448 tee_shm_pool_free(tstee->pool);
449 err_free_tstee:
450 kfree(tstee);
451 return rc;
452 }
453
tstee_remove(struct ffa_device * ffa_dev)454 static void tstee_remove(struct ffa_device *ffa_dev)
455 {
456 struct tstee *tstee = ffa_dev->dev.driver_data;
457
458 tee_device_unregister(tstee->teedev);
459 tee_shm_pool_free(tstee->pool);
460 kfree(tstee);
461 }
462
463 static const struct ffa_device_id tstee_device_ids[] = {
464 /* TS RPC protocol UUID: bdcd76d7-825e-4751-963b-86d4f84943ac */
465 { TS_RPC_UUID },
466 {}
467 };
468
469 static struct ffa_driver tstee_driver = {
470 .name = "arm_tstee",
471 .probe = tstee_probe,
472 .remove = tstee_remove,
473 .id_table = tstee_device_ids,
474 };
475
476 module_ffa_driver(tstee_driver);
477
478 MODULE_AUTHOR("Balint Dobszay <balint.dobszay@arm.com>");
479 MODULE_DESCRIPTION("Arm Trusted Services TEE driver");
480 MODULE_LICENSE("GPL");
481