Received: by 2002:a05:6a10:206:0:0:0:0 with SMTP id 6csp727720pxj; Wed, 16 Jun 2021 12:08:49 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwN5w3O+T0Hwb7G6c1kM8f/7XE9WpRuKSLDVwyjOKaZ9bGE6pAGk0/yD+vlSxMFYck3kX4k X-Received: by 2002:a17:906:b74a:: with SMTP id fx10mr1050689ejb.248.1623870529661; Wed, 16 Jun 2021 12:08:49 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1623870529; cv=none; d=google.com; s=arc-20160816; b=QNbtHLNZVXdM17imAurmjtrwaAkT0EsfsiEMTn5mcFTQ+g1x38yxGLtat13UMqZILh DeTeiJ3ho8IsMY7AhRVnMO9csmcv19ZTPaerEHyoTOyy49L62HBSxTbae1lhRUubZHyq ZOY+XVjWOB7vt/BVp41imCBRZaw+ZMRCOrSiJJKSRcxiPn/PWtRlS0UsURUU3Iam59Eb lLjfpP4UCZfUXKjm5ZScXp1/ZThfRKIOMFGtK1MUKFltN6U+6fZeogYNkAaLEiQAKf/8 LKal/yUfzPHMMDzAO8mzFK8h0SrDTj8L21lcVXSYD6V3Gd4sYC1l/+kgnErLswuBiV0X 5tXA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:subject:message-id:date:from:in-reply-to :references:mime-version:dkim-signature; bh=VyCBocDZOkSlZ3/u4uBoRdZ5lUQFO7OQRGC9zsUUqHU=; b=OkHUO0UATz8ldHGdsvDoc5XhBZytbZBAFKBsFm9yxbVEyMLWL/goGSVIqq7SaGz7sp F4H+dt5aiZBjVyk8pvij9O9w9EqYCFsdwKKLW2vR4Y8xZqH5lBlrR6FkPJtVNLxepaUS 5MStbiKU2I0ooYqRmrPcKHK5oBEMOrFj8NXXCmImIW7jGLf3vKhhmYTrs/cPde+Q3IuJ P3OlcFuhncZ+0CssCOG8ePCQyitbzXT7hCFzpy7v4bdrArqLruvpT9qd3aFmm3WTSRYC 2A7MJBLW0MmTsbfgcDZO//Gt0zRvBFeWf8kPkiR4qnVksHxFDh7SGtV8lS867ESz1TfY Oudg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=bF0xp0Bh; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id a5si3029530edr.176.2021.06.16.12.08.24; Wed, 16 Jun 2021 12:08:49 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=bF0xp0Bh; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233834AbhFPOK7 (ORCPT + 99 others); Wed, 16 Jun 2021 10:10:59 -0400 Received: from mail.kernel.org ([198.145.29.99]:50998 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233825AbhFPOK6 (ORCPT ); Wed, 16 Jun 2021 10:10:58 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 8A01761356; Wed, 16 Jun 2021 14:08:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1623852532; bh=rQC5ozp6rwvdThR70lipI8/AG6qXwR3DpzMThbUquVE=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=bF0xp0BhCVzN8RW6zSAe1xG3KJGTWHvtsFvYjVNIDu2Y7e+PbKc3OrfHpTA3fu5f0 4guDHlltSQTb+XisP5fjRsAwUZmy6Zwdun0mH0sz7rg0RiXOy+OWqn4bAnm3Puyo+3 689AC4U01ht4bClbF1B4hl+g9qeJfFRjxxUAvWHOdrF9r7ptg+aMPQXl2exiNjO4Hi MLgxl76omGV9Ri8m4tLrh4QhSXE1u512vdcgsaG1JMvb803wgwL8ldHANYufjwNqva ZotGFFhmb9RPdE57CL2U2I/DTkv7YZtV9YGMt/SEgLK+nJo4Auw/WooyLdoHG8t2Ov jutLEkcwAW8kA== Received: by mail-ot1-f41.google.com with SMTP id w23-20020a9d5a970000b02903d0ef989477so2562572oth.9; Wed, 16 Jun 2021 07:08:52 -0700 (PDT) X-Gm-Message-State: AOAM531SfH/M4GW+MD/ZiAcGit/BuM8h1w2my6GgPEc7r7R5/hCu3Two 3r/Vij7Yl4vSaIXyhQVFK3ieSVMw1C5W2q2DV84= X-Received: by 2002:a05:6830:1d63:: with SMTP id l3mr91877oti.108.1623852531769; Wed, 16 Jun 2021 07:08:51 -0700 (PDT) MIME-Version: 1.0 References: <20210616103649.2662395-1-jens.wiklander@linaro.org> <20210616103649.2662395-8-jens.wiklander@linaro.org> In-Reply-To: <20210616103649.2662395-8-jens.wiklander@linaro.org> From: Ard Biesheuvel Date: Wed, 16 Jun 2021 16:08:40 +0200 X-Gmail-Original-Message-ID: Message-ID: Subject: Re: [PATCH v2 7/7] optee: add asynchronous notifications To: Jens Wiklander Cc: Linux Kernel Mailing List , Linux ARM , op-tee@lists.trustedfirmware.org, "open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS" , Linux Doc Mailing List , Jerome Forissier , Etienne Carriere , Sumit Garg , Vincent Guittot , Rob Herring , Jonathan Corbet , Marc Zyngier Content-Type: text/plain; charset="UTF-8" Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, 16 Jun 2021 at 12:37, Jens Wiklander wrote: > > Adds support for asynchronous notifications from secure world to normal > world. This allows a design with a top half and bottom half type of > driver where the top half runs in secure interrupt context and a > notifications tells normal world to schedule a yielding call to do the > bottom half processing. > > The protocol is defined in optee_msg.h optee_rpc_cmd.h and optee_smc.h. > > A notification consists of a 32-bit value which normal world can > retrieve using a fastcall into secure world. The value > OPTEE_SMC_ASYNC_NOTIF_VALUE_DO_BOTTOM_HALF (0) has a special meaning. > When this value is sent it means that normal world is supposed to make a > yielding call OPTEE_MSG_CMD_DO_BOTTOM_HALF. > > Notification capability is negotiated while the driver is initialized. > If both sides supports these notifications then they are enabled. > > An interrupt is used to notify the driver that there are asynchronous > notifications pending. The maximum needed notification value is > communicated at this stage. This allows scaling up when needed. > > Signed-off-by: Jens Wiklander Acked-by: Ard Biesheuvel > --- > drivers/tee/optee/call.c | 27 ++++++++ > drivers/tee/optee/core.c | 82 +++++++++++++++------- > drivers/tee/optee/notif.c | 109 ++++++++++++++++++++++++++++-- > drivers/tee/optee/optee_msg.h | 9 +++ > drivers/tee/optee/optee_private.h | 6 +- > drivers/tee/optee/optee_smc.h | 75 +++++++++++++++++++- > 6 files changed, 276 insertions(+), 32 deletions(-) > > diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c > index 6132cc8d014c..9da66acac828 100644 > --- a/drivers/tee/optee/call.c > +++ b/drivers/tee/optee/call.c > @@ -390,6 +390,33 @@ int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session) > return 0; > } > > +static int simple_call_with_arg(struct tee_context *ctx, u32 cmd) > +{ > + struct optee_msg_arg *msg_arg; > + phys_addr_t msg_parg; > + struct tee_shm *shm; > + > + shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg); > + if (IS_ERR(shm)) > + return PTR_ERR(shm); > + > + msg_arg->cmd = cmd; > + optee_do_call_with_arg(ctx, msg_parg); > + > + tee_shm_free(shm); > + return 0; > +} > + > +int optee_do_bottom_half(struct tee_context *ctx) > +{ > + return simple_call_with_arg(ctx, OPTEE_MSG_CMD_DO_BOTTOM_HALF); > +} > + > +int optee_stop_async_notif(struct tee_context *ctx) > +{ > + return simple_call_with_arg(ctx, OPTEE_MSG_CMD_STOP_ASYNC_NOTIF); > +} > + > /** > * optee_enable_shm_cache() - Enables caching of some shared memory allocation > * in OP-TEE > diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c > index 2272696ac986..e3c80505cc88 100644 > --- a/drivers/tee/optee/core.c > +++ b/drivers/tee/optee/core.c > @@ -7,9 +7,12 @@ > > #include > #include > +#include > #include > +#include > #include > #include > +#include > #include > #include > #include > @@ -353,6 +356,17 @@ static const struct tee_desc optee_supp_desc = { > .flags = TEE_DESC_PRIVILEGED, > }; > > +static int enable_async_notif(optee_invoke_fn *invoke_fn) > +{ > + struct arm_smccc_res res; > + > + invoke_fn(OPTEE_SMC_ENABLE_ASYNC_NOTIF, 0, 0, 0, 0, 0, 0, 0, &res); > + > + if (res.a0) > + return -EINVAL; > + return 0; > +} > + > static bool optee_msg_api_uid_is_optee_api(optee_invoke_fn *invoke_fn) > { > struct arm_smccc_res res; > @@ -402,7 +416,7 @@ static bool optee_msg_api_revision_is_compatible(optee_invoke_fn *invoke_fn) > } > > static bool optee_msg_exchange_capabilities(optee_invoke_fn *invoke_fn, > - u32 *sec_caps) > + u32 *sec_caps, u32 *max_notif_value) > { > union { > struct arm_smccc_res smccc; > @@ -425,6 +439,7 @@ static bool optee_msg_exchange_capabilities(optee_invoke_fn *invoke_fn, > return false; > > *sec_caps = res.result.capabilities; > + *max_notif_value = res.result.max_notif_value; > return true; > } > > @@ -609,6 +624,7 @@ static int optee_probe(struct platform_device *pdev) > struct optee *optee = NULL; > void *memremaped_shm = NULL; > struct tee_device *teedev; > + u32 max_notif_value; > u32 sec_caps; > int rc; > > @@ -628,7 +644,8 @@ static int optee_probe(struct platform_device *pdev) > return -EINVAL; > } > > - if (!optee_msg_exchange_capabilities(invoke_fn, &sec_caps)) { > + if (!optee_msg_exchange_capabilities(invoke_fn, &sec_caps, > + &max_notif_value)) { > pr_warn("capabilities mismatch\n"); > return -EINVAL; > } > @@ -651,7 +668,7 @@ static int optee_probe(struct platform_device *pdev) > optee = kzalloc(sizeof(*optee), GFP_KERNEL); > if (!optee) { > rc = -ENOMEM; > - goto err; > + goto err_free_pool; > } > > optee->invoke_fn = invoke_fn; > @@ -660,24 +677,24 @@ static int optee_probe(struct platform_device *pdev) > teedev = tee_device_alloc(&optee_desc, NULL, pool, optee); > if (IS_ERR(teedev)) { > rc = PTR_ERR(teedev); > - goto err; > + goto err_free_optee; > } > optee->teedev = teedev; > > teedev = tee_device_alloc(&optee_supp_desc, NULL, pool, optee); > if (IS_ERR(teedev)) { > rc = PTR_ERR(teedev); > - goto err; > + goto err_unreg_teedev; > } > optee->supp_teedev = teedev; > > rc = tee_device_register(optee->teedev); > if (rc) > - goto err; > + goto err_unreg_supp_teedev; > > rc = tee_device_register(optee->supp_teedev); > if (rc) > - goto err; > + goto err_unreg_supp_teedev; > > mutex_init(&optee->call_queue.mutex); > INIT_LIST_HEAD(&optee->call_queue.waiters); > @@ -687,10 +704,30 @@ static int optee_probe(struct platform_device *pdev) > > platform_set_drvdata(pdev, optee); > > - rc = optee_notif_init(optee, 255); > - if (rc) { > - optee_remove(pdev); > - return rc; > + if (sec_caps & OPTEE_SMC_SEC_CAP_ASYNC_NOTIF) { > + unsigned int irq; > + > + rc = platform_get_irq(pdev, 0); > + if (rc < 0) { > + pr_err("platform_get_irq: ret %d\n", rc); > + goto err_unreg_supp_teedev; > + } > + irq = rc; > + > + rc = optee_notif_init(optee, max_notif_value, irq); > + if (rc) { > + irq_dispose_mapping(irq); > + optee_remove(pdev); > + return rc; > + } > + enable_async_notif(optee->invoke_fn); > + pr_info("Asynchronous notifications enabled\n"); > + } else { > + rc = optee_notif_init(optee, 255, 0); > + if (rc) { > + optee_remove(pdev); > + return rc; > + } > } > > optee_enable_shm_cache(optee); > @@ -706,20 +743,15 @@ static int optee_probe(struct platform_device *pdev) > > pr_info("initialized driver\n"); > return 0; > -err: > - if (optee) { > - /* > - * tee_device_unregister() is safe to call even if the > - * devices hasn't been registered with > - * tee_device_register() yet. > - */ > - tee_device_unregister(optee->supp_teedev); > - tee_device_unregister(optee->teedev); > - kfree(optee); > - } > - if (pool) > - tee_shm_pool_free(pool); > - if (memremaped_shm) > +err_unreg_supp_teedev: > + tee_device_unregister(optee->supp_teedev); > +err_unreg_teedev: > + tee_device_unregister(optee->teedev); > +err_free_optee: > + kfree(optee); > +err_free_pool: > + tee_shm_pool_free(pool); > + if (optee->memremaped_shm) > memunmap(memremaped_shm); > return rc; > } > diff --git a/drivers/tee/optee/notif.c b/drivers/tee/optee/notif.c > index a28fa03dcd0e..ecfa82797695 100644 > --- a/drivers/tee/optee/notif.c > +++ b/drivers/tee/optee/notif.c > @@ -7,10 +7,14 @@ > > #include > #include > +#include > +#include > #include > #include > #include > #include "optee_private.h" > +#include "optee_smc.h" > +#include "optee_rpc_cmd.h" > > struct notif_entry { > struct list_head link; > @@ -18,6 +22,54 @@ struct notif_entry { > u_int key; > }; > > +static u32 get_async_notif_value(optee_invoke_fn *invoke_fn, bool *value_valid, > + bool *value_pending) > +{ > + struct arm_smccc_res res; > + > + invoke_fn(OPTEE_SMC_GET_ASYNC_NOTIF_VALUE, 0, 0, 0, 0, 0, 0, 0, &res); > + > + if (res.a0) > + return 0; > + *value_valid = (res.a2 & OPTEE_SMC_ASYNC_NOTIF_VALUE_VALID); > + *value_pending = (res.a2 & OPTEE_SMC_ASYNC_NOTIF_VALUE_PENDING); > + return res.a1; > +} > + > +static irqreturn_t notif_irq_handler(int irq, void *dev_id) > +{ > + struct optee *optee = dev_id; > + bool do_bottom_half = false; > + bool value_valid; > + bool value_pending; > + u32 value; > + > + do { > + value = get_async_notif_value(optee->invoke_fn, &value_valid, > + &value_pending); > + if (!value_valid) > + break; > + > + if (value == OPTEE_SMC_ASYNC_NOTIF_VALUE_DO_BOTTOM_HALF) > + do_bottom_half = true; > + else > + optee_notif_send(optee, value); > + } while (value_pending); > + > + if (do_bottom_half) > + return IRQ_WAKE_THREAD; > + return IRQ_HANDLED; > +} > + > +static irqreturn_t notif_irq_thread_fn(int irq, void *dev_id) > +{ > + struct optee *optee = dev_id; > + > + optee_do_bottom_half(optee->notif.ctx); > + > + return IRQ_HANDLED; > +} > + > static bool have_key(struct optee *optee, u_int key) > { > struct notif_entry *entry; > @@ -106,20 +158,69 @@ int optee_notif_send(struct optee *optee, u_int key) > return 0; > } > > -int optee_notif_init(struct optee *optee, u_int max_key) > +int optee_notif_init(struct optee *optee, u_int max_key, u_int irq) > { > + struct tee_context *ctx; > + int rc; > + > + if (irq) { > + ctx = tee_dev_open_helper(optee->teedev); > + if (IS_ERR(ctx)) > + return PTR_ERR(ctx); > + > + optee->notif.ctx = ctx; > + } > + > spin_lock_init(&optee->notif.lock); > INIT_LIST_HEAD(&optee->notif.db); > optee->notif.bitmap = bitmap_zalloc(max_key, GFP_KERNEL); > - if (!optee->notif.bitmap) > - return -ENOMEM; > - > + if (!optee->notif.bitmap) { > + rc = -ENOMEM; > + goto err_put_ctx; > + } > optee->notif.max_key = max_key; > > + if (irq) { > + rc = request_threaded_irq(irq, notif_irq_handler, > + notif_irq_thread_fn, > + 0, "optee_notification", optee); > + if (rc) > + goto err_free_bitmap; > + > + optee->notif.irq = irq; > + } > + > return 0; > + > +err_free_bitmap: > + kfree(optee->notif.bitmap); > +err_put_ctx: > + tee_dev_ctx_put(optee->notif.ctx); > + optee->notif.ctx = NULL; > + > + return rc; > } > > void optee_notif_uninit(struct optee *optee) > { > + if (optee->notif.ctx) { > + optee_stop_async_notif(optee->notif.ctx); > + if (optee->notif.irq) { > + free_irq(optee->notif.irq, optee); > + irq_dispose_mapping(optee->notif.irq); > + } > + > + /* > + * The thread normally working with optee->notif.ctx was > + * stopped with free_irq() above. > + * > + * Note we're not using teedev_close_context() or > + * tee_client_close_context() since we have already called > + * tee_device_put() while initializing to avoid a circular > + * reference counting. > + */ > + tee_dev_ctx_put(optee->notif.ctx); > + } > + > kfree(optee->notif.bitmap); > } > diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h > index 81ff593ac4ec..35970932de34 100644 > --- a/drivers/tee/optee/optee_msg.h > +++ b/drivers/tee/optee/optee_msg.h > @@ -291,6 +291,13 @@ struct optee_msg_arg { > * [in] param[0].u.rmem.shm_ref holds shared memory reference > * [in] param[0].u.rmem.offs 0 > * [in] param[0].u.rmem.size 0 > + * > + * OPTEE_MSG_CMD_DO_BOTTOM_HALF does the scheduled bottom half processing > + * of a driver. > + * > + * OPTEE_MSG_CMD_STOP_ASYNC_NOTIF informs secure world that from now is > + * normal world unable to process asynchronous notifications. Typically > + * used when the driver is shut down. > */ > #define OPTEE_MSG_CMD_OPEN_SESSION 0 > #define OPTEE_MSG_CMD_INVOKE_COMMAND 1 > @@ -298,6 +305,8 @@ struct optee_msg_arg { > #define OPTEE_MSG_CMD_CANCEL 3 > #define OPTEE_MSG_CMD_REGISTER_SHM 4 > #define OPTEE_MSG_CMD_UNREGISTER_SHM 5 > +#define OPTEE_MSG_CMD_DO_BOTTOM_HALF 6 > +#define OPTEE_MSG_CMD_STOP_ASYNC_NOTIF 7 > #define OPTEE_MSG_FUNCID_CALL_WITH_ARG 0x0004 > > #endif /* _OPTEE_MSG_H */ > diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h > index 7dc058d008b2..62365912a70b 100644 > --- a/drivers/tee/optee/optee_private.h > +++ b/drivers/tee/optee/optee_private.h > @@ -37,6 +37,8 @@ struct optee_call_queue { > > struct optee_notif { > u_int max_key; > + unsigned int irq; > + struct tee_context *ctx; > /* Serializes access to the elements below in this struct */ > spinlock_t lock; > struct list_head db; > @@ -132,7 +134,7 @@ void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param, > struct optee_call_ctx *call_ctx); > void optee_rpc_finalize_call(struct optee_call_ctx *call_ctx); > > -int optee_notif_init(struct optee *optee, u_int max_key); > +int optee_notif_init(struct optee *optee, u_int max_key, u_int irq); > void optee_notif_uninit(struct optee *optee); > int optee_notif_wait(struct optee *optee, u_int key); > int optee_notif_send(struct optee *optee, u_int key); > @@ -159,6 +161,8 @@ 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); > int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session); > +int optee_do_bottom_half(struct tee_context *ctx); > +int optee_stop_async_notif(struct tee_context *ctx); > > void optee_enable_shm_cache(struct optee *optee); > void optee_disable_shm_cache(struct optee *optee); > diff --git a/drivers/tee/optee/optee_smc.h b/drivers/tee/optee/optee_smc.h > index 80eb763a8a80..c6eec6b6febf 100644 > --- a/drivers/tee/optee/optee_smc.h > +++ b/drivers/tee/optee/optee_smc.h > @@ -107,6 +107,12 @@ struct optee_smc_call_get_os_revision_result { > /* > * Call with struct optee_msg_arg as argument > * > + * When calling this function normal world has a few responsibilities: > + * 1. It must be able to handle eventual RPCs > + * 2. Non-secure interrupts should not be masked > + * 3. If asynchronous notifications has be negotiated successfully, then > + * asynchronous notifications should be unmasked during this call. > + * > * Call register usage: > * a0 SMC Function ID, OPTEE_SMC*CALL_WITH_ARG > * a1 Upper 32 bits of a 64-bit physical pointer to a struct optee_msg_arg > @@ -195,7 +201,8 @@ struct optee_smc_get_shm_config_result { > * Normal return register usage: > * a0 OPTEE_SMC_RETURN_OK > * a1 bitfield of secure world capabilities OPTEE_SMC_SEC_CAP_* > - * a2-7 Preserved > + * a2 The maximum secure world notification number > + * a3-7 Preserved > * > * Error return register usage: > * a0 OPTEE_SMC_RETURN_ENOTAVAIL, can't use the capabilities from normal world > @@ -218,6 +225,8 @@ struct optee_smc_get_shm_config_result { > #define OPTEE_SMC_SEC_CAP_VIRTUALIZATION BIT(3) > /* Secure world supports Shared Memory with a NULL reference */ > #define OPTEE_SMC_SEC_CAP_MEMREF_NULL BIT(4) > +/* Secure world supports asynchronous notification of normal world */ > +#define OPTEE_SMC_SEC_CAP_ASYNC_NOTIF BIT(5) > > #define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES 9 > #define OPTEE_SMC_EXCHANGE_CAPABILITIES \ > @@ -226,8 +235,8 @@ struct optee_smc_get_shm_config_result { > struct optee_smc_exchange_capabilities_result { > unsigned long status; > unsigned long capabilities; > + unsigned long max_notif_value; > unsigned long reserved0; > - unsigned long reserved1; > }; > > /* > @@ -319,6 +328,68 @@ struct optee_smc_disable_shm_cache_result { > #define OPTEE_SMC_GET_THREAD_COUNT \ > OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_THREAD_COUNT) > > +/* > + * Inform OP-TEE that normal world is able to receive asynchronous > + * notifications. > + * > + * Call requests usage: > + * a0 SMC Function ID, OPTEE_SMC_ENABLE_ASYNC_NOTIF > + * a1-6 Not used > + * a7 Hypervisor Client ID register > + * > + * Normal return register usage: > + * a0 OPTEE_SMC_RETURN_OK > + * a1-7 Preserved > + * > + * Not supported return register usage: > + * a0 OPTEE_SMC_RETURN_ENOTAVAIL > + * a1-7 Preserved > + */ > +#define OPTEE_SMC_FUNCID_ENABLE_ASYNC_NOTIF 16 > +#define OPTEE_SMC_ENABLE_ASYNC_NOTIF \ > + OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_ENABLE_ASYNC_NOTIF) > + > +/* > + * Retrieve a value of notifications pended since the last call of this > + * function. > + * > + * OP-TEE keeps a records of all posted values. When an interrupts is > + * received which indicates that there are posed values this function > + * should be called until all pended values has been retrieved. When a > + * value is retrieved it's cleared from the record in secure world. > + * > + * Call requests usage: > + * a0 SMC Function ID, OPTEE_SMC_GET_ASYNC_NOTIF_VALUE > + * a1-6 Not used > + * a7 Hypervisor Client ID register > + * > + * Normal return register usage: > + * a0 OPTEE_SMC_RETURN_OK > + * a1 value > + * a2 Bit[0]: OPTEE_SMC_ASYNC_NOTIF_VALUE_VALID if the value in a1 is > + * valid, else 0 if no values where pending > + * a2 Bit[1]: OPTEE_SMC_ASYNC_NOTIF_VALUE_PENDING if another value is > + * pending, else 0. > + * Bit[31:2]: MBZ > + * a3-7 Preserved > + * > + * Not supported return register usage: > + * a0 OPTEE_SMC_RETURN_ENOTAVAIL > + * a1-7 Preserved > + */ > +#define OPTEE_SMC_ASYNC_NOTIF_VALUE_VALID BIT(0) > +#define OPTEE_SMC_ASYNC_NOTIF_VALUE_PENDING BIT(1) > + > +/* > + * Notification that OP-TEE expects a yielding call to do some bottom half > + * work in a driver. > + */ > +#define OPTEE_SMC_ASYNC_NOTIF_VALUE_DO_BOTTOM_HALF 0 > + > +#define OPTEE_SMC_FUNCID_GET_ASYNC_NOTIF_VALUE 17 > +#define OPTEE_SMC_GET_ASYNC_NOTIF_VALUE \ > + OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_ASYNC_NOTIF_VALUE) > + > /* > * Resume from RPC (for example after processing a foreign interrupt) > * > -- > 2.31.1 >