xref: /kernel/linux/linux-5.10/drivers/tee/optee/rpc.c (revision 8c2ecf20)
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (c) 2015-2016, Linaro Limited
4 */
5
6#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7
8#include <linux/delay.h>
9#include <linux/device.h>
10#include <linux/i2c.h>
11#include <linux/slab.h>
12#include <linux/tee_drv.h>
13#include "optee_private.h"
14#include "optee_smc.h"
15
16struct wq_entry {
17	struct list_head link;
18	struct completion c;
19	u32 key;
20};
21
22void optee_wait_queue_init(struct optee_wait_queue *priv)
23{
24	mutex_init(&priv->mu);
25	INIT_LIST_HEAD(&priv->db);
26}
27
28void optee_wait_queue_exit(struct optee_wait_queue *priv)
29{
30	mutex_destroy(&priv->mu);
31}
32
33static void handle_rpc_func_cmd_get_time(struct optee_msg_arg *arg)
34{
35	struct timespec64 ts;
36
37	if (arg->num_params != 1)
38		goto bad;
39	if ((arg->params[0].attr & OPTEE_MSG_ATTR_TYPE_MASK) !=
40			OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT)
41		goto bad;
42
43	ktime_get_real_ts64(&ts);
44	arg->params[0].u.value.a = ts.tv_sec;
45	arg->params[0].u.value.b = ts.tv_nsec;
46
47	arg->ret = TEEC_SUCCESS;
48	return;
49bad:
50	arg->ret = TEEC_ERROR_BAD_PARAMETERS;
51}
52
53#if IS_REACHABLE(CONFIG_I2C)
54static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx,
55					     struct optee_msg_arg *arg)
56{
57	struct tee_param *params;
58	struct i2c_adapter *adapter;
59	struct i2c_msg msg = { };
60	size_t i;
61	int ret = -EOPNOTSUPP;
62	u8 attr[] = {
63		TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT,
64		TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT,
65		TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT,
66		TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT,
67	};
68
69	if (arg->num_params != ARRAY_SIZE(attr)) {
70		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
71		return;
72	}
73
74	params = kmalloc_array(arg->num_params, sizeof(struct tee_param),
75			       GFP_KERNEL);
76	if (!params) {
77		arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
78		return;
79	}
80
81	if (optee_from_msg_param(params, arg->num_params, arg->params))
82		goto bad;
83
84	for (i = 0; i < arg->num_params; i++) {
85		if (params[i].attr != attr[i])
86			goto bad;
87	}
88
89	adapter = i2c_get_adapter(params[0].u.value.b);
90	if (!adapter)
91		goto bad;
92
93	if (params[1].u.value.a & OPTEE_MSG_RPC_CMD_I2C_FLAGS_TEN_BIT) {
94		if (!i2c_check_functionality(adapter,
95					     I2C_FUNC_10BIT_ADDR)) {
96			i2c_put_adapter(adapter);
97			goto bad;
98		}
99
100		msg.flags = I2C_M_TEN;
101	}
102
103	msg.addr = params[0].u.value.c;
104	msg.buf  = params[2].u.memref.shm->kaddr;
105	msg.len  = params[2].u.memref.size;
106
107	switch (params[0].u.value.a) {
108	case OPTEE_MSG_RPC_CMD_I2C_TRANSFER_RD:
109		msg.flags |= I2C_M_RD;
110		break;
111	case OPTEE_MSG_RPC_CMD_I2C_TRANSFER_WR:
112		break;
113	default:
114		i2c_put_adapter(adapter);
115		goto bad;
116	}
117
118	ret = i2c_transfer(adapter, &msg, 1);
119
120	if (ret < 0) {
121		arg->ret = TEEC_ERROR_COMMUNICATION;
122	} else {
123		params[3].u.value.a = msg.len;
124		if (optee_to_msg_param(arg->params, arg->num_params, params))
125			arg->ret = TEEC_ERROR_BAD_PARAMETERS;
126		else
127			arg->ret = TEEC_SUCCESS;
128	}
129
130	i2c_put_adapter(adapter);
131	kfree(params);
132	return;
133bad:
134	kfree(params);
135	arg->ret = TEEC_ERROR_BAD_PARAMETERS;
136}
137#else
138static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx,
139					     struct optee_msg_arg *arg)
140{
141	arg->ret = TEEC_ERROR_NOT_SUPPORTED;
142}
143#endif
144
145static struct wq_entry *wq_entry_get(struct optee_wait_queue *wq, u32 key)
146{
147	struct wq_entry *w;
148
149	mutex_lock(&wq->mu);
150
151	list_for_each_entry(w, &wq->db, link)
152		if (w->key == key)
153			goto out;
154
155	w = kmalloc(sizeof(*w), GFP_KERNEL);
156	if (w) {
157		init_completion(&w->c);
158		w->key = key;
159		list_add_tail(&w->link, &wq->db);
160	}
161out:
162	mutex_unlock(&wq->mu);
163	return w;
164}
165
166static void wq_sleep(struct optee_wait_queue *wq, u32 key)
167{
168	struct wq_entry *w = wq_entry_get(wq, key);
169
170	if (w) {
171		wait_for_completion(&w->c);
172		mutex_lock(&wq->mu);
173		list_del(&w->link);
174		mutex_unlock(&wq->mu);
175		kfree(w);
176	}
177}
178
179static void wq_wakeup(struct optee_wait_queue *wq, u32 key)
180{
181	struct wq_entry *w = wq_entry_get(wq, key);
182
183	if (w)
184		complete(&w->c);
185}
186
187static void handle_rpc_func_cmd_wq(struct optee *optee,
188				   struct optee_msg_arg *arg)
189{
190	if (arg->num_params != 1)
191		goto bad;
192
193	if ((arg->params[0].attr & OPTEE_MSG_ATTR_TYPE_MASK) !=
194			OPTEE_MSG_ATTR_TYPE_VALUE_INPUT)
195		goto bad;
196
197	switch (arg->params[0].u.value.a) {
198	case OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP:
199		wq_sleep(&optee->wait_queue, arg->params[0].u.value.b);
200		break;
201	case OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP:
202		wq_wakeup(&optee->wait_queue, arg->params[0].u.value.b);
203		break;
204	default:
205		goto bad;
206	}
207
208	arg->ret = TEEC_SUCCESS;
209	return;
210bad:
211	arg->ret = TEEC_ERROR_BAD_PARAMETERS;
212}
213
214static void handle_rpc_func_cmd_wait(struct optee_msg_arg *arg)
215{
216	u32 msec_to_wait;
217
218	if (arg->num_params != 1)
219		goto bad;
220
221	if ((arg->params[0].attr & OPTEE_MSG_ATTR_TYPE_MASK) !=
222			OPTEE_MSG_ATTR_TYPE_VALUE_INPUT)
223		goto bad;
224
225	msec_to_wait = arg->params[0].u.value.a;
226
227	/* Go to interruptible sleep */
228	msleep_interruptible(msec_to_wait);
229
230	arg->ret = TEEC_SUCCESS;
231	return;
232bad:
233	arg->ret = TEEC_ERROR_BAD_PARAMETERS;
234}
235
236static void handle_rpc_supp_cmd(struct tee_context *ctx,
237				struct optee_msg_arg *arg)
238{
239	struct tee_param *params;
240
241	arg->ret_origin = TEEC_ORIGIN_COMMS;
242
243	params = kmalloc_array(arg->num_params, sizeof(struct tee_param),
244			       GFP_KERNEL);
245	if (!params) {
246		arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
247		return;
248	}
249
250	if (optee_from_msg_param(params, arg->num_params, arg->params)) {
251		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
252		goto out;
253	}
254
255	arg->ret = optee_supp_thrd_req(ctx, arg->cmd, arg->num_params, params);
256
257	if (optee_to_msg_param(arg->params, arg->num_params, params))
258		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
259out:
260	kfree(params);
261}
262
263static struct tee_shm *cmd_alloc_suppl(struct tee_context *ctx, size_t sz)
264{
265	u32 ret;
266	struct tee_param param;
267	struct optee *optee = tee_get_drvdata(ctx->teedev);
268	struct tee_shm *shm;
269
270	param.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
271	param.u.value.a = OPTEE_MSG_RPC_SHM_TYPE_APPL;
272	param.u.value.b = sz;
273	param.u.value.c = 0;
274
275	ret = optee_supp_thrd_req(ctx, OPTEE_MSG_RPC_CMD_SHM_ALLOC, 1, &param);
276	if (ret)
277		return ERR_PTR(-ENOMEM);
278
279	mutex_lock(&optee->supp.mutex);
280	/* Increases count as secure world doesn't have a reference */
281	shm = tee_shm_get_from_id(optee->supp.ctx, param.u.value.c);
282	mutex_unlock(&optee->supp.mutex);
283	return shm;
284}
285
286static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
287					  struct optee *optee,
288					  struct optee_msg_arg *arg,
289					  struct optee_call_ctx *call_ctx)
290{
291	phys_addr_t pa;
292	struct tee_shm *shm;
293	size_t sz;
294	size_t n;
295
296	arg->ret_origin = TEEC_ORIGIN_COMMS;
297
298	if (!arg->num_params ||
299	    arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) {
300		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
301		return;
302	}
303
304	for (n = 1; n < arg->num_params; n++) {
305		if (arg->params[n].attr != OPTEE_MSG_ATTR_TYPE_NONE) {
306			arg->ret = TEEC_ERROR_BAD_PARAMETERS;
307			return;
308		}
309	}
310
311	sz = arg->params[0].u.value.b;
312	switch (arg->params[0].u.value.a) {
313	case OPTEE_MSG_RPC_SHM_TYPE_APPL:
314		shm = cmd_alloc_suppl(ctx, sz);
315		break;
316	case OPTEE_MSG_RPC_SHM_TYPE_KERNEL:
317		shm = tee_shm_alloc(optee->ctx, sz,
318				    TEE_SHM_MAPPED | TEE_SHM_PRIV);
319		break;
320	default:
321		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
322		return;
323	}
324
325	if (IS_ERR(shm)) {
326		arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
327		return;
328	}
329
330	if (tee_shm_get_pa(shm, 0, &pa)) {
331		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
332		goto bad;
333	}
334
335	sz = tee_shm_get_size(shm);
336
337	if (tee_shm_is_registered(shm)) {
338		struct page **pages;
339		u64 *pages_list;
340		size_t page_num;
341
342		pages = tee_shm_get_pages(shm, &page_num);
343		if (!pages || !page_num) {
344			arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
345			goto bad;
346		}
347
348		pages_list = optee_allocate_pages_list(page_num);
349		if (!pages_list) {
350			arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
351			goto bad;
352		}
353
354		call_ctx->pages_list = pages_list;
355		call_ctx->num_entries = page_num;
356
357		arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT |
358				      OPTEE_MSG_ATTR_NONCONTIG;
359		/*
360		 * In the least bits of u.tmem.buf_ptr we store buffer offset
361		 * from 4k page, as described in OP-TEE ABI.
362		 */
363		arg->params[0].u.tmem.buf_ptr = virt_to_phys(pages_list) |
364			(tee_shm_get_page_offset(shm) &
365			 (OPTEE_MSG_NONCONTIG_PAGE_SIZE - 1));
366		arg->params[0].u.tmem.size = tee_shm_get_size(shm);
367		arg->params[0].u.tmem.shm_ref = (unsigned long)shm;
368
369		optee_fill_pages_list(pages_list, pages, page_num,
370				      tee_shm_get_page_offset(shm));
371	} else {
372		arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT;
373		arg->params[0].u.tmem.buf_ptr = pa;
374		arg->params[0].u.tmem.size = sz;
375		arg->params[0].u.tmem.shm_ref = (unsigned long)shm;
376	}
377
378	arg->ret = TEEC_SUCCESS;
379	return;
380bad:
381	tee_shm_free(shm);
382}
383
384static void cmd_free_suppl(struct tee_context *ctx, struct tee_shm *shm)
385{
386	struct tee_param param;
387
388	param.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
389	param.u.value.a = OPTEE_MSG_RPC_SHM_TYPE_APPL;
390	param.u.value.b = tee_shm_get_id(shm);
391	param.u.value.c = 0;
392
393	/*
394	 * Match the tee_shm_get_from_id() in cmd_alloc_suppl() as secure
395	 * world has released its reference.
396	 *
397	 * It's better to do this before sending the request to supplicant
398	 * as we'd like to let the process doing the initial allocation to
399	 * do release the last reference too in order to avoid stacking
400	 * many pending fput() on the client process. This could otherwise
401	 * happen if secure world does many allocate and free in a single
402	 * invoke.
403	 */
404	tee_shm_put(shm);
405
406	optee_supp_thrd_req(ctx, OPTEE_MSG_RPC_CMD_SHM_FREE, 1, &param);
407}
408
409static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx,
410					 struct optee_msg_arg *arg)
411{
412	struct tee_shm *shm;
413
414	arg->ret_origin = TEEC_ORIGIN_COMMS;
415
416	if (arg->num_params != 1 ||
417	    arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) {
418		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
419		return;
420	}
421
422	shm = (struct tee_shm *)(unsigned long)arg->params[0].u.value.b;
423	switch (arg->params[0].u.value.a) {
424	case OPTEE_MSG_RPC_SHM_TYPE_APPL:
425		cmd_free_suppl(ctx, shm);
426		break;
427	case OPTEE_MSG_RPC_SHM_TYPE_KERNEL:
428		tee_shm_free(shm);
429		break;
430	default:
431		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
432	}
433	arg->ret = TEEC_SUCCESS;
434}
435
436static void free_pages_list(struct optee_call_ctx *call_ctx)
437{
438	if (call_ctx->pages_list) {
439		optee_free_pages_list(call_ctx->pages_list,
440				      call_ctx->num_entries);
441		call_ctx->pages_list = NULL;
442		call_ctx->num_entries = 0;
443	}
444}
445
446void optee_rpc_finalize_call(struct optee_call_ctx *call_ctx)
447{
448	free_pages_list(call_ctx);
449}
450
451static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee,
452				struct tee_shm *shm,
453				struct optee_call_ctx *call_ctx)
454{
455	struct optee_msg_arg *arg;
456
457	arg = tee_shm_get_va(shm, 0);
458	if (IS_ERR(arg)) {
459		pr_err("%s: tee_shm_get_va %p failed\n", __func__, shm);
460		return;
461	}
462
463	switch (arg->cmd) {
464	case OPTEE_MSG_RPC_CMD_GET_TIME:
465		handle_rpc_func_cmd_get_time(arg);
466		break;
467	case OPTEE_MSG_RPC_CMD_WAIT_QUEUE:
468		handle_rpc_func_cmd_wq(optee, arg);
469		break;
470	case OPTEE_MSG_RPC_CMD_SUSPEND:
471		handle_rpc_func_cmd_wait(arg);
472		break;
473	case OPTEE_MSG_RPC_CMD_SHM_ALLOC:
474		free_pages_list(call_ctx);
475		handle_rpc_func_cmd_shm_alloc(ctx, optee, arg, call_ctx);
476		break;
477	case OPTEE_MSG_RPC_CMD_SHM_FREE:
478		handle_rpc_func_cmd_shm_free(ctx, arg);
479		break;
480	case OPTEE_MSG_RPC_CMD_I2C_TRANSFER:
481		handle_rpc_func_cmd_i2c_transfer(ctx, arg);
482		break;
483	default:
484		handle_rpc_supp_cmd(ctx, arg);
485	}
486}
487
488/**
489 * optee_handle_rpc() - handle RPC from secure world
490 * @ctx:	context doing the RPC
491 * @param:	value of registers for the RPC
492 * @call_ctx:	call context. Preserved during one OP-TEE invocation
493 *
494 * Result of RPC is written back into @param.
495 */
496void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param,
497		      struct optee_call_ctx *call_ctx)
498{
499	struct tee_device *teedev = ctx->teedev;
500	struct optee *optee = tee_get_drvdata(teedev);
501	struct tee_shm *shm;
502	phys_addr_t pa;
503
504	switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) {
505	case OPTEE_SMC_RPC_FUNC_ALLOC:
506		shm = tee_shm_alloc(optee->ctx, param->a1,
507				    TEE_SHM_MAPPED | TEE_SHM_PRIV);
508		if (!IS_ERR(shm) && !tee_shm_get_pa(shm, 0, &pa)) {
509			reg_pair_from_64(&param->a1, &param->a2, pa);
510			reg_pair_from_64(&param->a4, &param->a5,
511					 (unsigned long)shm);
512		} else {
513			param->a1 = 0;
514			param->a2 = 0;
515			param->a4 = 0;
516			param->a5 = 0;
517		}
518		break;
519	case OPTEE_SMC_RPC_FUNC_FREE:
520		shm = reg_pair_to_ptr(param->a1, param->a2);
521		tee_shm_free(shm);
522		break;
523	case OPTEE_SMC_RPC_FUNC_FOREIGN_INTR:
524		/*
525		 * A foreign interrupt was raised while secure world was
526		 * executing, since they are handled in Linux a dummy RPC is
527		 * performed to let Linux take the interrupt through the normal
528		 * vector.
529		 */
530		break;
531	case OPTEE_SMC_RPC_FUNC_CMD:
532		shm = reg_pair_to_ptr(param->a1, param->a2);
533		handle_rpc_func_cmd(ctx, optee, shm, call_ctx);
534		break;
535	default:
536		pr_warn("Unknown RPC func 0x%x\n",
537			(u32)OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0));
538		break;
539	}
540
541	param->a0 = OPTEE_SMC_CALL_RETURN_FROM_RPC;
542}
543