Skip to content

Commit 53a107c

Browse files
lorcjenswi-linaro
authored andcommitted
tee: optee: add registered buffers handling into RPC calls
With latest changes to OP-TEE we can use any buffers as a shared memory. Thus, it is possible for supplicant to provide part of own memory when OP-TEE asks to allocate a shared buffer. This patch adds support for such feature into RPC handling code. Now when OP-TEE asks supplicant to allocate shared buffer, supplicant can use TEE_IOC_SHM_REGISTER to provide such buffer. RPC handler is aware of this, so it will pass list of allocated pages to OP-TEE. Signed-off-by: Volodymyr Babchuk <[email protected]> [jw: fix parenthesis alignment in free_pages_list()] Signed-off-by: Jens Wiklander <[email protected]>
1 parent 64cf9d8 commit 53a107c

File tree

4 files changed

+102
-11
lines changed

4 files changed

+102
-11
lines changed

drivers/tee/optee/call.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg)
136136
struct optee *optee = tee_get_drvdata(ctx->teedev);
137137
struct optee_call_waiter w;
138138
struct optee_rpc_param param = { };
139+
struct optee_call_ctx call_ctx = { };
139140
u32 ret;
140141

141142
param.a0 = OPTEE_SMC_CALL_WITH_ARG;
@@ -160,13 +161,14 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg)
160161
param.a1 = res.a1;
161162
param.a2 = res.a2;
162163
param.a3 = res.a3;
163-
optee_handle_rpc(ctx, &param);
164+
optee_handle_rpc(ctx, &param, &call_ctx);
164165
} else {
165166
ret = res.a0;
166167
break;
167168
}
168169
}
169170

171+
optee_rpc_finalize_call(&call_ctx);
170172
/*
171173
* We're done with our thread in secure world, if there's any
172174
* thread waiters wake up one.
@@ -602,3 +604,18 @@ int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm)
602604
tee_shm_free(shm_arg);
603605
return rc;
604606
}
607+
608+
int optee_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm,
609+
struct page **pages, size_t num_pages)
610+
{
611+
/*
612+
* We don't want to register supplicant memory in OP-TEE.
613+
* Instead information about it will be passed in RPC code.
614+
*/
615+
return 0;
616+
}
617+
618+
int optee_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm)
619+
{
620+
return 0;
621+
}

drivers/tee/optee/core.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,8 @@ static const struct tee_driver_ops optee_supp_ops = {
331331
.release = optee_release,
332332
.supp_recv = optee_supp_recv,
333333
.supp_send = optee_supp_send,
334+
.shm_register = optee_shm_register_supp,
335+
.shm_unregister = optee_shm_unregister_supp,
334336
};
335337

336338
static const struct tee_desc optee_supp_desc = {

drivers/tee/optee/optee_private.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,16 @@ struct optee_rpc_param {
130130
u32 a7;
131131
};
132132

133-
void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param);
133+
/* Holds context that is preserved during one STD call */
134+
struct optee_call_ctx {
135+
/* information about pages list used in last allocation */
136+
void *pages_list;
137+
size_t num_entries;
138+
};
139+
140+
void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param,
141+
struct optee_call_ctx *call_ctx);
142+
void optee_rpc_finalize_call(struct optee_call_ctx *call_ctx);
134143

135144
void optee_wait_queue_init(struct optee_wait_queue *wq);
136145
void optee_wait_queue_exit(struct optee_wait_queue *wq);
@@ -164,6 +173,10 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
164173
struct page **pages, size_t num_pages);
165174
int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm);
166175

176+
int optee_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm,
177+
struct page **pages, size_t num_pages);
178+
int optee_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm);
179+
167180
int optee_from_msg_param(struct tee_param *params, size_t num_params,
168181
const struct optee_msg_param *msg_params);
169182
int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,

drivers/tee/optee/rpc.c

Lines changed: 68 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,8 @@ static struct tee_shm *cmd_alloc_suppl(struct tee_context *ctx, size_t sz)
200200
}
201201

202202
static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
203-
struct optee_msg_arg *arg)
203+
struct optee_msg_arg *arg,
204+
struct optee_call_ctx *call_ctx)
204205
{
205206
phys_addr_t pa;
206207
struct tee_shm *shm;
@@ -245,10 +246,49 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
245246
goto bad;
246247
}
247248

248-
arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT;
249-
arg->params[0].u.tmem.buf_ptr = pa;
250-
arg->params[0].u.tmem.size = sz;
251-
arg->params[0].u.tmem.shm_ref = (unsigned long)shm;
249+
sz = tee_shm_get_size(shm);
250+
251+
if (tee_shm_is_registered(shm)) {
252+
struct page **pages;
253+
u64 *pages_list;
254+
size_t page_num;
255+
256+
pages = tee_shm_get_pages(shm, &page_num);
257+
if (!pages || !page_num) {
258+
arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
259+
goto bad;
260+
}
261+
262+
pages_list = optee_allocate_pages_list(page_num);
263+
if (!pages_list) {
264+
arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
265+
goto bad;
266+
}
267+
268+
call_ctx->pages_list = pages_list;
269+
call_ctx->num_entries = page_num;
270+
271+
arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT |
272+
OPTEE_MSG_ATTR_NONCONTIG;
273+
/*
274+
* In the least bits of u.tmem.buf_ptr we store buffer offset
275+
* from 4k page, as described in OP-TEE ABI.
276+
*/
277+
arg->params[0].u.tmem.buf_ptr = virt_to_phys(pages_list) |
278+
(tee_shm_get_page_offset(shm) &
279+
(OPTEE_MSG_NONCONTIG_PAGE_SIZE - 1));
280+
arg->params[0].u.tmem.size = tee_shm_get_size(shm);
281+
arg->params[0].u.tmem.shm_ref = (unsigned long)shm;
282+
283+
optee_fill_pages_list(pages_list, pages, page_num,
284+
tee_shm_get_page_offset(shm));
285+
} else {
286+
arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT;
287+
arg->params[0].u.tmem.buf_ptr = pa;
288+
arg->params[0].u.tmem.size = sz;
289+
arg->params[0].u.tmem.shm_ref = (unsigned long)shm;
290+
}
291+
252292
arg->ret = TEEC_SUCCESS;
253293
return;
254294
bad:
@@ -307,8 +347,24 @@ static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx,
307347
arg->ret = TEEC_SUCCESS;
308348
}
309349

350+
static void free_pages_list(struct optee_call_ctx *call_ctx)
351+
{
352+
if (call_ctx->pages_list) {
353+
optee_free_pages_list(call_ctx->pages_list,
354+
call_ctx->num_entries);
355+
call_ctx->pages_list = NULL;
356+
call_ctx->num_entries = 0;
357+
}
358+
}
359+
360+
void optee_rpc_finalize_call(struct optee_call_ctx *call_ctx)
361+
{
362+
free_pages_list(call_ctx);
363+
}
364+
310365
static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee,
311-
struct tee_shm *shm)
366+
struct tee_shm *shm,
367+
struct optee_call_ctx *call_ctx)
312368
{
313369
struct optee_msg_arg *arg;
314370

@@ -329,7 +385,8 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee,
329385
handle_rpc_func_cmd_wait(arg);
330386
break;
331387
case OPTEE_MSG_RPC_CMD_SHM_ALLOC:
332-
handle_rpc_func_cmd_shm_alloc(ctx, arg);
388+
free_pages_list(call_ctx);
389+
handle_rpc_func_cmd_shm_alloc(ctx, arg, call_ctx);
333390
break;
334391
case OPTEE_MSG_RPC_CMD_SHM_FREE:
335392
handle_rpc_func_cmd_shm_free(ctx, arg);
@@ -343,10 +400,12 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee,
343400
* optee_handle_rpc() - handle RPC from secure world
344401
* @ctx: context doing the RPC
345402
* @param: value of registers for the RPC
403+
* @call_ctx: call context. Preserved during one OP-TEE invocation
346404
*
347405
* Result of RPC is written back into @param.
348406
*/
349-
void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param)
407+
void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param,
408+
struct optee_call_ctx *call_ctx)
350409
{
351410
struct tee_device *teedev = ctx->teedev;
352411
struct optee *optee = tee_get_drvdata(teedev);
@@ -381,7 +440,7 @@ void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param)
381440
break;
382441
case OPTEE_SMC_RPC_FUNC_CMD:
383442
shm = reg_pair_to_ptr(param->a1, param->a2);
384-
handle_rpc_func_cmd(ctx, optee, shm);
443+
handle_rpc_func_cmd(ctx, optee, shm, call_ctx);
385444
break;
386445
default:
387446
pr_warn("Unknown RPC func 0x%x\n",

0 commit comments

Comments
 (0)