diff options
author | Arnd Bergmann <arnd@arndb.de> | 2023-12-22 10:42:19 +0000 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2023-12-22 10:42:19 +0000 |
commit | 9d0e3c5a3d89bbd77c671a84301c38e0a71bfa14 (patch) | |
tree | 73109355b77f7737c971b1972dc25bbfed678645 | |
parent | 60cc77704eb23558c46a4428792515e48273dde0 (diff) | |
parent | 4b391c9c37646f25118355f414b9e6d9fefe782f (diff) |
Merge tag 'system-thread-for-v6.8' of https://git.linaro.org/people/jens.wiklander/linux-tee into soc/drivers
OP-TEE add reserved system thread
Add support for a reserved system thread in the SMC-ABI of the OP-TEE driver.
SCMI with OP-TEE transport uses this to guarantee that it will always have
a thread available in the secure world.
* tag 'system-thread-for-v6.8' of https://git.linaro.org/people/jens.wiklander/linux-tee:
firmware: arm_scmi: optee: use optee system invocation
tee: optee: support tracking system threads
tee: system session
tee: optee: system thread call property
Link: https://lore.kernel.org/r/20231211102600.GA571787@rayden
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r-- | drivers/firmware/arm_scmi/optee.c | 4 | ||||
-rw-r--r-- | drivers/tee/optee/call.c | 130 | ||||
-rw-r--r-- | drivers/tee/optee/core.c | 5 | ||||
-rw-r--r-- | drivers/tee/optee/ffa_abi.c | 14 | ||||
-rw-r--r-- | drivers/tee/optee/optee_private.h | 29 | ||||
-rw-r--r-- | drivers/tee/optee/smc_abi.c | 32 | ||||
-rw-r--r-- | drivers/tee/tee_core.c | 8 | ||||
-rw-r--r-- | include/linux/tee_drv.h | 16 |
8 files changed, 211 insertions, 27 deletions
diff --git a/drivers/firmware/arm_scmi/optee.c b/drivers/firmware/arm_scmi/optee.c index e123de6e8c67..25bfb465484d 100644 --- a/drivers/firmware/arm_scmi/optee.c +++ b/drivers/firmware/arm_scmi/optee.c @@ -440,6 +440,10 @@ static int scmi_optee_chan_setup(struct scmi_chan_info *cinfo, struct device *de if (ret) goto err_free_shm; + ret = tee_client_system_session(scmi_optee_private->tee_ctx, channel->tee_session); + if (ret) + dev_warn(dev, "Could not switch to system session, do best effort\n"); + ret = get_channel(channel); if (ret) goto err_close_sess; diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c index df5fb5410b72..b04c49c69619 100644 --- a/drivers/tee/optee/call.c +++ b/drivers/tee/optee/call.c @@ -39,9 +39,29 @@ struct optee_shm_arg_entry { DECLARE_BITMAP(map, MAX_ARG_COUNT_PER_ENTRY); }; +void optee_cq_init(struct optee_call_queue *cq, int thread_count) +{ + mutex_init(&cq->mutex); + INIT_LIST_HEAD(&cq->waiters); + + /* + * If cq->total_thread_count is 0 then we're not trying to keep + * track of how many free threads we have, instead we're relying on + * the secure world to tell us when we're out of thread and have to + * wait for another thread to become available. + */ + cq->total_thread_count = thread_count; + cq->free_thread_count = thread_count; +} + void optee_cq_wait_init(struct optee_call_queue *cq, - struct optee_call_waiter *w) + struct optee_call_waiter *w, bool sys_thread) { + unsigned int free_thread_threshold; + bool need_wait = false; + + memset(w, 0, sizeof(*w)); + /* * We're preparing to make a call to secure world. In case we can't * allocate a thread in secure world we'll end up waiting in @@ -60,8 +80,38 @@ void optee_cq_wait_init(struct optee_call_queue *cq, */ init_completion(&w->c); list_add_tail(&w->list_node, &cq->waiters); + w->sys_thread = sys_thread; + + if (cq->total_thread_count) { + if (sys_thread || !cq->sys_thread_req_count) + free_thread_threshold = 0; + else + free_thread_threshold = 1; + + if (cq->free_thread_count > free_thread_threshold) + cq->free_thread_count--; + else + need_wait = true; + } mutex_unlock(&cq->mutex); + + while (need_wait) { + optee_cq_wait_for_completion(cq, w); + mutex_lock(&cq->mutex); + + if (sys_thread || !cq->sys_thread_req_count) + free_thread_threshold = 0; + else + free_thread_threshold = 1; + + if (cq->free_thread_count > free_thread_threshold) { + cq->free_thread_count--; + need_wait = false; + } + + mutex_unlock(&cq->mutex); + } } void optee_cq_wait_for_completion(struct optee_call_queue *cq, @@ -83,6 +133,14 @@ static void optee_cq_complete_one(struct optee_call_queue *cq) { struct optee_call_waiter *w; + /* Wake a waiting system session if any, prior to a normal session */ + list_for_each_entry(w, &cq->waiters, list_node) { + if (w->sys_thread && !completion_done(&w->c)) { + complete(&w->c); + return; + } + } + list_for_each_entry(w, &cq->waiters, list_node) { if (!completion_done(&w->c)) { complete(&w->c); @@ -104,6 +162,8 @@ void optee_cq_wait_final(struct optee_call_queue *cq, /* Get out of the list */ list_del(&w->list_node); + cq->free_thread_count++; + /* Wake up one eventual waiting task */ optee_cq_complete_one(cq); @@ -119,6 +179,28 @@ void optee_cq_wait_final(struct optee_call_queue *cq, mutex_unlock(&cq->mutex); } +/* Count registered system sessions to reserved a system thread or not */ +static bool optee_cq_incr_sys_thread_count(struct optee_call_queue *cq) +{ + if (cq->total_thread_count <= 1) + return false; + + mutex_lock(&cq->mutex); + cq->sys_thread_req_count++; + mutex_unlock(&cq->mutex); + + return true; +} + +static void optee_cq_decr_sys_thread_count(struct optee_call_queue *cq) +{ + mutex_lock(&cq->mutex); + cq->sys_thread_req_count--; + /* If there's someone waiting, let it resume */ + optee_cq_complete_one(cq); + mutex_unlock(&cq->mutex); +} + /* Requires the filpstate mutex to be held */ static struct optee_session *find_session(struct optee_context_data *ctxdata, u32 session_id) @@ -328,7 +410,8 @@ int optee_open_session(struct tee_context *ctx, goto out; } - if (optee->ops->do_call_with_arg(ctx, shm, offs)) { + if (optee->ops->do_call_with_arg(ctx, shm, offs, + sess->use_sys_thread)) { msg_arg->ret = TEEC_ERROR_COMMUNICATION; msg_arg->ret_origin = TEEC_ORIGIN_COMMS; } @@ -360,7 +443,29 @@ out: return rc; } -int optee_close_session_helper(struct tee_context *ctx, u32 session) +int optee_system_session(struct tee_context *ctx, u32 session) +{ + struct optee *optee = tee_get_drvdata(ctx->teedev); + struct optee_context_data *ctxdata = ctx->data; + struct optee_session *sess; + int rc = -EINVAL; + + mutex_lock(&ctxdata->mutex); + + sess = find_session(ctxdata, session); + if (sess && (sess->use_sys_thread || + optee_cq_incr_sys_thread_count(&optee->call_queue))) { + sess->use_sys_thread = true; + rc = 0; + } + + mutex_unlock(&ctxdata->mutex); + + return rc; +} + +int optee_close_session_helper(struct tee_context *ctx, u32 session, + bool system_thread) { struct optee *optee = tee_get_drvdata(ctx->teedev); struct optee_shm_arg_entry *entry; @@ -374,10 +479,13 @@ int optee_close_session_helper(struct tee_context *ctx, u32 session) msg_arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION; msg_arg->session = session; - optee->ops->do_call_with_arg(ctx, shm, offs); + optee->ops->do_call_with_arg(ctx, shm, offs, system_thread); optee_free_msg_arg(ctx, entry, offs); + if (system_thread) + optee_cq_decr_sys_thread_count(&optee->call_queue); + return 0; } @@ -385,6 +493,7 @@ int optee_close_session(struct tee_context *ctx, u32 session) { struct optee_context_data *ctxdata = ctx->data; struct optee_session *sess; + bool system_thread; /* Check that the session is valid and remove it from the list */ mutex_lock(&ctxdata->mutex); @@ -394,9 +503,10 @@ int optee_close_session(struct tee_context *ctx, u32 session) mutex_unlock(&ctxdata->mutex); if (!sess) return -EINVAL; + system_thread = sess->use_sys_thread; kfree(sess); - return optee_close_session_helper(ctx, session); + return optee_close_session_helper(ctx, session, system_thread); } int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg, @@ -408,12 +518,15 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg, struct optee_msg_arg *msg_arg; struct optee_session *sess; struct tee_shm *shm; + bool system_thread; u_int offs; int rc; /* Check that the session is valid */ mutex_lock(&ctxdata->mutex); sess = find_session(ctxdata, arg->session); + if (sess) + system_thread = sess->use_sys_thread; mutex_unlock(&ctxdata->mutex); if (!sess) return -EINVAL; @@ -432,7 +545,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg, if (rc) goto out; - if (optee->ops->do_call_with_arg(ctx, shm, offs)) { + if (optee->ops->do_call_with_arg(ctx, shm, offs, system_thread)) { msg_arg->ret = TEEC_ERROR_COMMUNICATION; msg_arg->ret_origin = TEEC_ORIGIN_COMMS; } @@ -457,12 +570,15 @@ int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session) struct optee_shm_arg_entry *entry; struct optee_msg_arg *msg_arg; struct optee_session *sess; + bool system_thread; struct tee_shm *shm; u_int offs; /* Check that the session is valid */ mutex_lock(&ctxdata->mutex); sess = find_session(ctxdata, session); + if (sess) + system_thread = sess->use_sys_thread; mutex_unlock(&ctxdata->mutex); if (!sess) return -EINVAL; @@ -474,7 +590,7 @@ int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session) msg_arg->cmd = OPTEE_MSG_CMD_CANCEL; msg_arg->session = session; msg_arg->cancel_id = cancel_id; - optee->ops->do_call_with_arg(ctx, shm, offs); + optee->ops->do_call_with_arg(ctx, shm, offs, system_thread); optee_free_msg_arg(ctx, entry, offs); return 0; diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index 2a258bd3b6b5..d01ca47f7bde 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -129,7 +129,8 @@ int optee_open(struct tee_context *ctx, bool cap_memref_null) static void optee_release_helper(struct tee_context *ctx, int (*close_session)(struct tee_context *ctx, - u32 session)) + u32 session, + bool system_thread)) { struct optee_context_data *ctxdata = ctx->data; struct optee_session *sess; @@ -141,7 +142,7 @@ static void optee_release_helper(struct tee_context *ctx, list_for_each_entry_safe(sess, sess_tmp, &ctxdata->sess_list, list_node) { list_del(&sess->list_node); - close_session(ctx, sess->session_id); + close_session(ctx, sess->session_id, sess->use_sys_thread); kfree(sess); } kfree(ctxdata); diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c index 0828240f27e6..d73396ed5b93 100644 --- a/drivers/tee/optee/ffa_abi.c +++ b/drivers/tee/optee/ffa_abi.c @@ -528,7 +528,8 @@ static void optee_handle_ffa_rpc(struct tee_context *ctx, struct optee *optee, static int optee_ffa_yielding_call(struct tee_context *ctx, struct ffa_send_direct_data *data, - struct optee_msg_arg *rpc_arg) + struct optee_msg_arg *rpc_arg, + bool system_thread) { struct optee *optee = tee_get_drvdata(ctx->teedev); struct ffa_device *ffa_dev = optee->ffa.ffa_dev; @@ -541,7 +542,7 @@ static int optee_ffa_yielding_call(struct tee_context *ctx, int rc; /* Initialize waiter */ - optee_cq_wait_init(&optee->call_queue, &w); + optee_cq_wait_init(&optee->call_queue, &w, system_thread); while (true) { rc = msg_ops->sync_send_receive(ffa_dev, data); if (rc) @@ -604,6 +605,7 @@ done: * @ctx: calling context * @shm: shared memory holding the message to pass to secure world * @offs: offset of the message in @shm + * @system_thread: true if caller requests TEE system thread support * * Does a FF-A call to OP-TEE in secure world and handles eventual resulting * Remote Procedure Calls (RPC) from OP-TEE. @@ -612,7 +614,8 @@ done: */ static int optee_ffa_do_call_with_arg(struct tee_context *ctx, - struct tee_shm *shm, u_int offs) + struct tee_shm *shm, u_int offs, + bool system_thread) { struct ffa_send_direct_data data = { .data0 = OPTEE_FFA_YIELDING_CALL_WITH_ARG, @@ -642,7 +645,7 @@ static int optee_ffa_do_call_with_arg(struct tee_context *ctx, if (IS_ERR(rpc_arg)) return PTR_ERR(rpc_arg); - return optee_ffa_yielding_call(ctx, &data, rpc_arg); + return optee_ffa_yielding_call(ctx, &data, rpc_arg, system_thread); } /* @@ -850,8 +853,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev) if (rc) goto err_unreg_supp_teedev; mutex_init(&optee->ffa.mutex); - mutex_init(&optee->call_queue.mutex); - INIT_LIST_HEAD(&optee->call_queue.waiters); + optee_cq_init(&optee->call_queue, 0); optee_supp_init(&optee->supp); optee_shm_arg_cache_init(optee, arg_cache_flags); ffa_dev_set_drvdata(ffa_dev, optee); diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h index 6bb5cae09688..7832ccefe6d0 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -40,15 +40,33 @@ typedef void (optee_invoke_fn)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, struct arm_smccc_res *); +/* + * struct optee_call_waiter - TEE entry may need to wait for a free TEE thread + * @list_node Reference in waiters list + * @c Waiting completion reference + * @sys_thread True if waiter belongs to a system thread + */ struct optee_call_waiter { struct list_head list_node; struct completion c; + bool sys_thread; }; +/* + * struct optee_call_queue - OP-TEE call queue management + * @mutex Serializes access to this struct + * @waiters List of threads waiting to enter OP-TEE + * @total_thread_count Overall number of thread context in OP-TEE or 0 + * @free_thread_count Number of threads context free in OP-TEE + * @sys_thread_req_count Number of registered system thread sessions + */ struct optee_call_queue { /* Serializes access to this struct */ struct mutex mutex; struct list_head waiters; + int total_thread_count; + int free_thread_count; + int sys_thread_req_count; }; struct optee_notif { @@ -154,7 +172,8 @@ struct optee; */ struct optee_ops { int (*do_call_with_arg)(struct tee_context *ctx, - struct tee_shm *shm_arg, u_int offs); + struct tee_shm *shm_arg, u_int offs, + bool system_thread); int (*to_msg_param)(struct optee *optee, struct optee_msg_param *msg_params, size_t num_params, const struct tee_param *params); @@ -204,6 +223,7 @@ struct optee { struct optee_session { struct list_head list_node; u32 session_id; + bool use_sys_thread; }; struct optee_context_data { @@ -250,7 +270,9 @@ int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params, int optee_open_session(struct tee_context *ctx, struct tee_ioctl_open_session_arg *arg, struct tee_param *param); -int optee_close_session_helper(struct tee_context *ctx, u32 session); +int optee_system_session(struct tee_context *ctx, u32 session); +int optee_close_session_helper(struct tee_context *ctx, u32 session, + bool system_thread); int optee_close_session(struct tee_context *ctx, u32 session); int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg, struct tee_param *param); @@ -298,8 +320,9 @@ static inline void optee_to_msg_param_value(struct optee_msg_param *mp, mp->u.value.c = p->u.value.c; } +void optee_cq_init(struct optee_call_queue *cq, int thread_count); void optee_cq_wait_init(struct optee_call_queue *cq, - struct optee_call_waiter *w); + struct optee_call_waiter *w, bool sys_thread); void optee_cq_wait_for_completion(struct optee_call_queue *cq, struct optee_call_waiter *w); void optee_cq_wait_final(struct optee_call_queue *cq, diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c index d5b28fd35d66..3b60acc15cf0 100644 --- a/drivers/tee/optee/smc_abi.c +++ b/drivers/tee/optee/smc_abi.c @@ -283,7 +283,7 @@ static void optee_enable_shm_cache(struct optee *optee) struct optee_call_waiter w; /* We need to retry until secure world isn't busy. */ - optee_cq_wait_init(&optee->call_queue, &w); + optee_cq_wait_init(&optee->call_queue, &w, false); while (true) { struct arm_smccc_res res; @@ -308,7 +308,7 @@ static void __optee_disable_shm_cache(struct optee *optee, bool is_mapped) struct optee_call_waiter w; /* We need to retry until secure world isn't busy. */ - optee_cq_wait_init(&optee->call_queue, &w); + optee_cq_wait_init(&optee->call_queue, &w, false); while (true) { union { struct arm_smccc_res smccc; @@ -507,7 +507,7 @@ static int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm, msg_arg->params->u.tmem.buf_ptr = virt_to_phys(pages_list) | (tee_shm_get_page_offset(shm) & (OPTEE_MSG_NONCONTIG_PAGE_SIZE - 1)); - if (optee->ops->do_call_with_arg(ctx, shm_arg, 0) || + if (optee->ops->do_call_with_arg(ctx, shm_arg, 0, false) || msg_arg->ret != TEEC_SUCCESS) rc = -EINVAL; @@ -550,7 +550,7 @@ static int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm) msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT; msg_arg->params[0].u.rmem.shm_ref = (unsigned long)shm; - if (optee->ops->do_call_with_arg(ctx, shm_arg, 0) || + if (optee->ops->do_call_with_arg(ctx, shm_arg, 0, false) || msg_arg->ret != TEEC_SUCCESS) rc = -EINVAL; out: @@ -878,6 +878,7 @@ static void optee_handle_rpc(struct tee_context *ctx, * @ctx: calling context * @shm: shared memory holding the message to pass to secure world * @offs: offset of the message in @shm + * @system_thread: true if caller requests TEE system thread support * * Does and SMC to OP-TEE in secure world and handles eventual resulting * Remote Procedure Calls (RPC) from OP-TEE. @@ -885,7 +886,8 @@ static void optee_handle_rpc(struct tee_context *ctx, * Returns return code from secure world, 0 is OK */ static int optee_smc_do_call_with_arg(struct tee_context *ctx, - struct tee_shm *shm, u_int offs) + struct tee_shm *shm, u_int offs, + bool system_thread) { struct optee *optee = tee_get_drvdata(ctx->teedev); struct optee_call_waiter w; @@ -926,7 +928,7 @@ static int optee_smc_do_call_with_arg(struct tee_context *ctx, reg_pair_from_64(¶m.a1, ¶m.a2, parg); } /* Initialize waiter */ - optee_cq_wait_init(&optee->call_queue, &w); + optee_cq_wait_init(&optee->call_queue, &w, system_thread); while (true) { struct arm_smccc_res res; @@ -977,7 +979,7 @@ static int simple_call_with_arg(struct tee_context *ctx, u32 cmd) return PTR_ERR(msg_arg); msg_arg->cmd = cmd; - optee_smc_do_call_with_arg(ctx, shm, offs); + optee_smc_do_call_with_arg(ctx, shm, offs, false); optee_free_msg_arg(ctx, entry, offs); return 0; @@ -1210,6 +1212,7 @@ static const struct tee_driver_ops optee_clnt_ops = { .release = optee_release, .open_session = optee_open_session, .close_session = optee_close_session, + .system_session = optee_system_session, .invoke_func = optee_invoke_func, .cancel_req = optee_cancel_req, .shm_register = optee_shm_register, @@ -1357,6 +1360,16 @@ static bool optee_msg_exchange_capabilities(optee_invoke_fn *invoke_fn, return true; } +static unsigned int optee_msg_get_thread_count(optee_invoke_fn *invoke_fn) +{ + struct arm_smccc_res res; + + invoke_fn(OPTEE_SMC_GET_THREAD_COUNT, 0, 0, 0, 0, 0, 0, 0, &res); + if (res.a0) + return 0; + return res.a1; +} + static struct tee_shm_pool * optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm) { @@ -1609,6 +1622,7 @@ static int optee_probe(struct platform_device *pdev) struct optee *optee = NULL; void *memremaped_shm = NULL; unsigned int rpc_param_count; + unsigned int thread_count; struct tee_device *teedev; struct tee_context *ctx; u32 max_notif_value; @@ -1636,6 +1650,7 @@ static int optee_probe(struct platform_device *pdev) return -EINVAL; } + thread_count = optee_msg_get_thread_count(invoke_fn); if (!optee_msg_exchange_capabilities(invoke_fn, &sec_caps, &max_notif_value, &rpc_param_count)) { @@ -1725,8 +1740,7 @@ static int optee_probe(struct platform_device *pdev) if (rc) goto err_unreg_supp_teedev; - mutex_init(&optee->call_queue.mutex); - INIT_LIST_HEAD(&optee->call_queue.waiters); + optee_cq_init(&optee->call_queue, thread_count); optee_supp_init(&optee->supp); optee->smc.memremaped_shm = memremaped_shm; optee->pool = pool; diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index 5ddfd5d9ac7f..792d6fae4354 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -1173,6 +1173,14 @@ int tee_client_close_session(struct tee_context *ctx, u32 session) } EXPORT_SYMBOL_GPL(tee_client_close_session); +int tee_client_system_session(struct tee_context *ctx, u32 session) +{ + if (!ctx->teedev->desc->ops->system_session) + return -EINVAL; + return ctx->teedev->desc->ops->system_session(ctx, session); +} +EXPORT_SYMBOL_GPL(tee_client_system_session); + int tee_client_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg, struct tee_param *param) diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index 17eb1c5205d3..911ddf92dcee 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -84,6 +84,7 @@ struct tee_param { * @release: release this open file * @open_session: open a new session * @close_session: close a session + * @system_session: declare session as a system session * @invoke_func: invoke a trusted function * @cancel_req: request cancel of an ongoing invoke or open * @supp_recv: called for supplicant to get a command @@ -100,6 +101,7 @@ struct tee_driver_ops { struct tee_ioctl_open_session_arg *arg, struct tee_param *param); int (*close_session)(struct tee_context *ctx, u32 session); + int (*system_session)(struct tee_context *ctx, u32 session); int (*invoke_func)(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg, struct tee_param *param); @@ -430,6 +432,20 @@ int tee_client_open_session(struct tee_context *ctx, int tee_client_close_session(struct tee_context *ctx, u32 session); /** + * tee_client_system_session() - Declare session as a system session + * @ctx: TEE Context + * @session: Session id + * + * This function requests TEE to provision an entry context ready to use for + * that session only. The provisioned entry context is used for command + * invocation and session closure, not for command cancelling requests. + * TEE releases the provisioned context upon session closure. + * + * Return < 0 on error else 0 if an entry context has been provisioned. + */ +int tee_client_system_session(struct tee_context *ctx, u32 session); + +/** * tee_client_invoke_func() - Invoke a function in a Trusted Application * @ctx: TEE Context * @arg: Invoke arguments, see description of |