Skip to content

Commit 4602c58

Browse files
committed
optee: refactor driver with internal callbacks
The OP-TEE driver is refactored with three internal callbacks replacing direct calls to optee_from_msg_param(), optee_to_msg_param() and optee_do_call_with_arg(). These functions a central to communicating with OP-TEE in secure world by using the SMC Calling Convention directly. This refactoring makes room for using other primitives to communicate with OP-TEE in secure world while being able to reuse as much as possible from the present driver. Reviewed-by: Sumit Garg <[email protected]> Signed-off-by: Jens Wiklander <[email protected]>
1 parent c0ab6db commit 4602c58

File tree

4 files changed

+182
-106
lines changed

4 files changed

+182
-106
lines changed

drivers/tee/optee/call.c

Lines changed: 42 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-License-Identifier: GPL-2.0-only
22
/*
3-
* Copyright (c) 2015, Linaro Limited
3+
* Copyright (c) 2015-2021, Linaro Limited
44
*/
55
#include <linux/arm-smccc.h>
66
#include <linux/device.h>
@@ -118,20 +118,25 @@ static struct optee_session *find_session(struct optee_context_data *ctxdata,
118118
/**
119119
* optee_do_call_with_arg() - Do an SMC to OP-TEE in secure world
120120
* @ctx: calling context
121-
* @parg: physical address of message to pass to secure world
121+
* @arg: shared memory holding the message to pass to secure world
122122
*
123123
* Does and SMC to OP-TEE in secure world and handles eventual resulting
124124
* Remote Procedure Calls (RPC) from OP-TEE.
125125
*
126126
* Returns return code from secure world, 0 is OK
127127
*/
128-
u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg)
128+
int optee_do_call_with_arg(struct tee_context *ctx, struct tee_shm *arg)
129129
{
130130
struct optee *optee = tee_get_drvdata(ctx->teedev);
131131
struct optee_call_waiter w;
132132
struct optee_rpc_param param = { };
133133
struct optee_call_ctx call_ctx = { };
134-
u32 ret;
134+
phys_addr_t parg;
135+
int rc;
136+
137+
rc = tee_shm_get_pa(arg, 0, &parg);
138+
if (rc)
139+
return rc;
135140

136141
param.a0 = OPTEE_SMC_CALL_WITH_ARG;
137142
reg_pair_from_64(&param.a1, &param.a2, parg);
@@ -160,7 +165,7 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg)
160165
param.a3 = res.a3;
161166
optee_handle_rpc(ctx, &param, &call_ctx);
162167
} else {
163-
ret = res.a0;
168+
rc = res.a0;
164169
break;
165170
}
166171
}
@@ -172,14 +177,12 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg)
172177
*/
173178
optee_cq_wait_final(&optee->call_queue, &w);
174179

175-
return ret;
180+
return rc;
176181
}
177182

178183
static struct tee_shm *get_msg_arg(struct tee_context *ctx, size_t num_params,
179-
struct optee_msg_arg **msg_arg,
180-
phys_addr_t *msg_parg)
184+
struct optee_msg_arg **msg_arg)
181185
{
182-
int rc;
183186
struct tee_shm *shm;
184187
struct optee_msg_arg *ma;
185188

@@ -190,22 +193,13 @@ static struct tee_shm *get_msg_arg(struct tee_context *ctx, size_t num_params,
190193

191194
ma = tee_shm_get_va(shm, 0);
192195
if (IS_ERR(ma)) {
193-
rc = PTR_ERR(ma);
194-
goto out;
196+
tee_shm_free(shm);
197+
return (void *)ma;
195198
}
196199

197-
rc = tee_shm_get_pa(shm, 0, msg_parg);
198-
if (rc)
199-
goto out;
200-
201200
memset(ma, 0, OPTEE_MSG_GET_ARG_SIZE(num_params));
202201
ma->num_params = num_params;
203202
*msg_arg = ma;
204-
out:
205-
if (rc) {
206-
tee_shm_free(shm);
207-
return ERR_PTR(rc);
208-
}
209203

210204
return shm;
211205
}
@@ -214,16 +208,16 @@ int optee_open_session(struct tee_context *ctx,
214208
struct tee_ioctl_open_session_arg *arg,
215209
struct tee_param *param)
216210
{
211+
struct optee *optee = tee_get_drvdata(ctx->teedev);
217212
struct optee_context_data *ctxdata = ctx->data;
218213
int rc;
219214
struct tee_shm *shm;
220215
struct optee_msg_arg *msg_arg;
221-
phys_addr_t msg_parg;
222216
struct optee_session *sess = NULL;
223217
uuid_t client_uuid;
224218

225219
/* +2 for the meta parameters added below */
226-
shm = get_msg_arg(ctx, arg->num_params + 2, &msg_arg, &msg_parg);
220+
shm = get_msg_arg(ctx, arg->num_params + 2, &msg_arg);
227221
if (IS_ERR(shm))
228222
return PTR_ERR(shm);
229223

@@ -247,7 +241,8 @@ int optee_open_session(struct tee_context *ctx,
247241
goto out;
248242
export_uuid(msg_arg->params[1].u.octets, &client_uuid);
249243

250-
rc = optee_to_msg_param(msg_arg->params + 2, arg->num_params, param);
244+
rc = optee->ops->to_msg_param(optee, msg_arg->params + 2,
245+
arg->num_params, param);
251246
if (rc)
252247
goto out;
253248

@@ -257,7 +252,7 @@ int optee_open_session(struct tee_context *ctx,
257252
goto out;
258253
}
259254

260-
if (optee_do_call_with_arg(ctx, msg_parg)) {
255+
if (optee->ops->do_call_with_arg(ctx, shm)) {
261256
msg_arg->ret = TEEC_ERROR_COMMUNICATION;
262257
msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
263258
}
@@ -272,7 +267,8 @@ int optee_open_session(struct tee_context *ctx,
272267
kfree(sess);
273268
}
274269

275-
if (optee_from_msg_param(param, arg->num_params, msg_arg->params + 2)) {
270+
if (optee->ops->from_msg_param(optee, param, arg->num_params,
271+
msg_arg->params + 2)) {
276272
arg->ret = TEEC_ERROR_COMMUNICATION;
277273
arg->ret_origin = TEEC_ORIGIN_COMMS;
278274
/* Close session again to avoid leakage */
@@ -291,16 +287,16 @@ int optee_open_session(struct tee_context *ctx,
291287
int optee_close_session_helper(struct tee_context *ctx, u32 session)
292288
{
293289
struct tee_shm *shm;
290+
struct optee *optee = tee_get_drvdata(ctx->teedev);
294291
struct optee_msg_arg *msg_arg;
295-
phys_addr_t msg_parg;
296292

297-
shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg);
293+
shm = get_msg_arg(ctx, 0, &msg_arg);
298294
if (IS_ERR(shm))
299295
return PTR_ERR(shm);
300296

301297
msg_arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
302298
msg_arg->session = session;
303-
optee_do_call_with_arg(ctx, msg_parg);
299+
optee->ops->do_call_with_arg(ctx, shm);
304300

305301
tee_shm_free(shm);
306302

@@ -328,10 +324,10 @@ int optee_close_session(struct tee_context *ctx, u32 session)
328324
int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
329325
struct tee_param *param)
330326
{
327+
struct optee *optee = tee_get_drvdata(ctx->teedev);
331328
struct optee_context_data *ctxdata = ctx->data;
332329
struct tee_shm *shm;
333330
struct optee_msg_arg *msg_arg;
334-
phys_addr_t msg_parg;
335331
struct optee_session *sess;
336332
int rc;
337333

@@ -342,24 +338,26 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
342338
if (!sess)
343339
return -EINVAL;
344340

345-
shm = get_msg_arg(ctx, arg->num_params, &msg_arg, &msg_parg);
341+
shm = get_msg_arg(ctx, arg->num_params, &msg_arg);
346342
if (IS_ERR(shm))
347343
return PTR_ERR(shm);
348344
msg_arg->cmd = OPTEE_MSG_CMD_INVOKE_COMMAND;
349345
msg_arg->func = arg->func;
350346
msg_arg->session = arg->session;
351347
msg_arg->cancel_id = arg->cancel_id;
352348

353-
rc = optee_to_msg_param(msg_arg->params, arg->num_params, param);
349+
rc = optee->ops->to_msg_param(optee, msg_arg->params, arg->num_params,
350+
param);
354351
if (rc)
355352
goto out;
356353

357-
if (optee_do_call_with_arg(ctx, msg_parg)) {
354+
if (optee->ops->do_call_with_arg(ctx, shm)) {
358355
msg_arg->ret = TEEC_ERROR_COMMUNICATION;
359356
msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
360357
}
361358

362-
if (optee_from_msg_param(param, arg->num_params, msg_arg->params)) {
359+
if (optee->ops->from_msg_param(optee, param, arg->num_params,
360+
msg_arg->params)) {
363361
msg_arg->ret = TEEC_ERROR_COMMUNICATION;
364362
msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
365363
}
@@ -373,10 +371,10 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
373371

374372
int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session)
375373
{
374+
struct optee *optee = tee_get_drvdata(ctx->teedev);
376375
struct optee_context_data *ctxdata = ctx->data;
377376
struct tee_shm *shm;
378377
struct optee_msg_arg *msg_arg;
379-
phys_addr_t msg_parg;
380378
struct optee_session *sess;
381379

382380
/* Check that the session is valid */
@@ -386,14 +384,14 @@ int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session)
386384
if (!sess)
387385
return -EINVAL;
388386

389-
shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg);
387+
shm = get_msg_arg(ctx, 0, &msg_arg);
390388
if (IS_ERR(shm))
391389
return PTR_ERR(shm);
392390

393391
msg_arg->cmd = OPTEE_MSG_CMD_CANCEL;
394392
msg_arg->session = session;
395393
msg_arg->cancel_id = cancel_id;
396-
optee_do_call_with_arg(ctx, msg_parg);
394+
optee->ops->do_call_with_arg(ctx, shm);
397395

398396
tee_shm_free(shm);
399397
return 0;
@@ -622,10 +620,10 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
622620
struct page **pages, size_t num_pages,
623621
unsigned long start)
624622
{
625-
struct tee_shm *shm_arg = NULL;
623+
struct optee *optee = tee_get_drvdata(ctx->teedev);
626624
struct optee_msg_arg *msg_arg;
625+
struct tee_shm *shm_arg;
627626
u64 *pages_list;
628-
phys_addr_t msg_parg;
629627
int rc;
630628

631629
if (!num_pages)
@@ -639,7 +637,7 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
639637
if (!pages_list)
640638
return -ENOMEM;
641639

642-
shm_arg = get_msg_arg(ctx, 1, &msg_arg, &msg_parg);
640+
shm_arg = get_msg_arg(ctx, 1, &msg_arg);
643641
if (IS_ERR(shm_arg)) {
644642
rc = PTR_ERR(shm_arg);
645643
goto out;
@@ -660,7 +658,7 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
660658
msg_arg->params->u.tmem.buf_ptr = virt_to_phys(pages_list) |
661659
(tee_shm_get_page_offset(shm) & (OPTEE_MSG_NONCONTIG_PAGE_SIZE - 1));
662660

663-
if (optee_do_call_with_arg(ctx, msg_parg) ||
661+
if (optee->ops->do_call_with_arg(ctx, shm_arg) ||
664662
msg_arg->ret != TEEC_SUCCESS)
665663
rc = -EINVAL;
666664

@@ -672,12 +670,12 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
672670

673671
int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm)
674672
{
675-
struct tee_shm *shm_arg;
673+
struct optee *optee = tee_get_drvdata(ctx->teedev);
676674
struct optee_msg_arg *msg_arg;
677-
phys_addr_t msg_parg;
675+
struct tee_shm *shm_arg;
678676
int rc = 0;
679677

680-
shm_arg = get_msg_arg(ctx, 1, &msg_arg, &msg_parg);
678+
shm_arg = get_msg_arg(ctx, 1, &msg_arg);
681679
if (IS_ERR(shm_arg))
682680
return PTR_ERR(shm_arg);
683681

@@ -686,7 +684,7 @@ int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm)
686684
msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
687685
msg_arg->params[0].u.rmem.shm_ref = (unsigned long)shm;
688686

689-
if (optee_do_call_with_arg(ctx, msg_parg) ||
687+
if (optee->ops->do_call_with_arg(ctx, shm_arg) ||
690688
msg_arg->ret != TEEC_SUCCESS)
691689
rc = -EINVAL;
692690
tee_shm_free(shm_arg);

0 commit comments

Comments
 (0)