From nobody Mon Jun 22 15:43:44 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6B2F3C433FE for ; Mon, 21 Mar 2022 13:04:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347701AbiCUNFY (ORCPT ); Mon, 21 Mar 2022 09:05:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56158 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347685AbiCUNFU (ORCPT ); Mon, 21 Mar 2022 09:05:20 -0400 Received: from mail-lf1-x133.google.com (mail-lf1-x133.google.com [IPv6:2a00:1450:4864:20::133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7616011A00 for ; Mon, 21 Mar 2022 06:03:54 -0700 (PDT) Received: by mail-lf1-x133.google.com with SMTP id bt26so24475611lfb.3 for ; Mon, 21 Mar 2022 06:03:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=86psb8kPn4M1qHzNjl7a471DNz143YZ1CZe8yVwqHQk=; b=MZUi50SU3X1QiEt6eexLrwpbhToWV7FokIX44P2Zx5tZM4Gxgf8FGqmAMSynY0csS6 ib7J7JUObbOTWIOz4HA2GD04z1Vo7Fv8UmE1gXVEbPDNtrzru7f+3rSUWml05mgtJqmx cn43SDW38HkLw2lD8627WiENyV8aQydMnRbzYqkTUvVAjGl0rQZJZJiYeXlU/FCKcp0d aq419H6wZind4UdWlv8b0t2KtDlYiSthE3ecbVFAybtz9pULCrnkt9ZsuRkfqULOD6Ra +1pb9R9UTsoNdBoKL0MYcfJnRWRIskc86zyg0KIIPTeVLU5450n4SeUKE34zVy8YIKUs s9VQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=86psb8kPn4M1qHzNjl7a471DNz143YZ1CZe8yVwqHQk=; b=OLJYemygjE81fK15aGYbtz4FqWo1teiWCE8dfHOr99v4MtlS+yYvC/1Zws1TFe/gcJ 1ONGermQLbX0DoEJAfKjoS4ad7Itig41/U0Zma0MGrfYq101hCd3Js+yXAOw+aAMffsg /b7CfvFR02aC7PkVIydhLhqek0eF+WP3oukVxnScwYkXoT1LrVWk+9Pj+BuUErApt0TO OE48tvCF3Dum7A7VfVbi5SFlpb/IZHk+Vg2MO9p69zwct1/Aw6NUUgJYtr9ldbv8Z5rL RZMLQDCQhmAJiU4NNLftFwg83PV3XbcRj++EPvzg3lzqUXztt54yEwNRH1qMzxmiBWzn ncDA== X-Gm-Message-State: AOAM53223fxsK8GOk7rZKZ0dFcci81SoGtM33pMSoHf0EQ45x+t0MEYf pZ6BemcWBuukTBua5g3QJaUnZLrwrkF5Yw== X-Google-Smtp-Source: ABdhPJwhDZguVWPogpCGYKoMEAwtip8urqaIuhszw8dc4AwNWLn+GAVav2oryEAtcT0n8bKfiij+Wg== X-Received: by 2002:a05:6512:16a2:b0:448:1fbb:8ca1 with SMTP id bu34-20020a05651216a200b004481fbb8ca1mr14832890lfb.125.1647867832136; Mon, 21 Mar 2022 06:03:52 -0700 (PDT) Received: from jade.urgonet (h-79-136-84-253.A175.priv.bahnhof.se. [79.136.84.253]) by smtp.gmail.com with ESMTPSA id t27-20020a2e8e7b000000b00247f32b572asm2067738ljk.19.2022.03.21.06.03.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Mar 2022 06:03:51 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, op-tee@lists.trustedfirmware.org Cc: Sumit Garg , Jens Wiklander Subject: [PATCH v2 1/4] optee: rename rpc_arg_count to rpc_param_count Date: Mon, 21 Mar 2022 14:03:38 +0100 Message-Id: <20220321130341.935535-2-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20220321130341.935535-1-jens.wiklander@linaro.org> References: <20220321130341.935535-1-jens.wiklander@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Renames the field rpc_arg_count in struct optee to rpc_param_count. Function parameter names and local variables are also renamed to match. Signed-off-by: Jens Wiklander Reviewed-by: Sumit Garg --- drivers/tee/optee/call.c | 6 +++--- drivers/tee/optee/ffa_abi.c | 10 +++++----- drivers/tee/optee/optee_private.h | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c index bd49ec934060..a9a237d20c61 100644 --- a/drivers/tee/optee/call.c +++ b/drivers/tee/optee/call.c @@ -113,12 +113,12 @@ struct tee_shm *optee_get_msg_arg(struct tee_context = *ctx, size_t num_params, struct optee_msg_arg *ma; =20 /* - * rpc_arg_count is set to the number of allocated parameters in + * rpc_param_count is set to the number of allocated parameters in * the RPC argument struct if a second MSG arg struct is expected. * The second arg struct will then be used for RPC. */ - if (optee->rpc_arg_count) - sz +=3D OPTEE_MSG_GET_ARG_SIZE(optee->rpc_arg_count); + if (optee->rpc_param_count) + sz +=3D OPTEE_MSG_GET_ARG_SIZE(optee->rpc_param_count); =20 shm =3D tee_shm_alloc_priv_buf(ctx, sz); if (IS_ERR(shm)) diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c index a5eb4ef46971..7686f7020616 100644 --- a/drivers/tee/optee/ffa_abi.c +++ b/drivers/tee/optee/ffa_abi.c @@ -678,7 +678,7 @@ static bool optee_ffa_api_is_compatbile(struct ffa_devi= ce *ffa_dev, =20 static bool optee_ffa_exchange_caps(struct ffa_device *ffa_dev, const struct ffa_dev_ops *ops, - unsigned int *rpc_arg_count) + unsigned int *rpc_param_count) { struct ffa_send_direct_data data =3D { OPTEE_FFA_EXCHANGE_CAPABILITIES }; int rc; @@ -693,7 +693,7 @@ static bool optee_ffa_exchange_caps(struct ffa_device *= ffa_dev, return false; } =20 - *rpc_arg_count =3D (u8)data.data1; + *rpc_param_count =3D (u8)data.data1; =20 return true; } @@ -772,7 +772,7 @@ static void optee_ffa_remove(struct ffa_device *ffa_dev) static int optee_ffa_probe(struct ffa_device *ffa_dev) { const struct ffa_dev_ops *ffa_ops; - unsigned int rpc_arg_count; + unsigned int rpc_param_count; struct tee_shm_pool *pool; struct tee_device *teedev; struct tee_context *ctx; @@ -788,7 +788,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev) if (!optee_ffa_api_is_compatbile(ffa_dev, ffa_ops)) return -EINVAL; =20 - if (!optee_ffa_exchange_caps(ffa_dev, ffa_ops, &rpc_arg_count)) + if (!optee_ffa_exchange_caps(ffa_dev, ffa_ops, &rpc_param_count)) return -EINVAL; =20 optee =3D kzalloc(sizeof(*optee), GFP_KERNEL); @@ -805,7 +805,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev) optee->ops =3D &optee_ffa_ops; optee->ffa.ffa_dev =3D ffa_dev; optee->ffa.ffa_ops =3D ffa_ops; - optee->rpc_arg_count =3D rpc_arg_count; + optee->rpc_param_count =3D rpc_param_count; =20 teedev =3D tee_device_alloc(&optee_ffa_clnt_desc, NULL, optee->pool, optee); diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_pr= ivate.h index e77765c78878..e80c5d9b62ec 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -143,7 +143,7 @@ struct optee_ops { * @notif: notification synchronization struct * @supp: supplicant synchronization struct for RPC to supplicant * @pool: shared memory pool - * @rpc_arg_count: If > 0 number of RPC parameters to make room for + * @rpc_param_count: If > 0 number of RPC parameters to make room for * @scan_bus_done flag if device registation was already done. * @scan_bus_wq workqueue to scan optee bus and register optee drivers * @scan_bus_work workq to scan optee bus and register optee drivers @@ -161,7 +161,7 @@ struct optee { struct optee_notif notif; struct optee_supp supp; struct tee_shm_pool *pool; - unsigned int rpc_arg_count; + unsigned int rpc_param_count; bool scan_bus_done; struct workqueue_struct *scan_bus_wq; struct work_struct scan_bus_work; --=20 2.31.1 From nobody Mon Jun 22 15:43:44 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4AC68C433F5 for ; Mon, 21 Mar 2022 13:04:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347719AbiCUNF3 (ORCPT ); Mon, 21 Mar 2022 09:05:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56274 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347697AbiCUNFV (ORCPT ); Mon, 21 Mar 2022 09:05:21 -0400 Received: from mail-lj1-x22f.google.com (mail-lj1-x22f.google.com [IPv6:2a00:1450:4864:20::22f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7C4311117A for ; Mon, 21 Mar 2022 06:03:55 -0700 (PDT) Received: by mail-lj1-x22f.google.com with SMTP id h11so19740354ljb.2 for ; Mon, 21 Mar 2022 06:03:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=KbYLlp7Upr9pj0+DV8TuCeDNnwboEop+TLursIg/hTQ=; b=tBE+oKdlbcZGLSLtZI7CKHzbPzNSaIfSrUuEPHek5mAzM4cEC1AAOGVfI1Xb6Ll/QY wPg2u9kqORXi7h9/cVO+j8vbku6lNkMorJiYjK1glGmOmXHo3I6rufR+K3yqLm7qeRiY kh68u3VlvtrFvkrcjqA3O/d+282LsPHSv6687M4RqXEzQi1AYJO90R+icBvYxxET96fH NXur7IhNG/mwmh8odvG3ziLOh44zOzazUtnzQ95+aWqUtg4apUu09lwapH/SWWpqnEiB ZZqMoi+1EQYxW0cCXqoXgEmuh5150kpUrsYiW7cm7xU1OssnABSxJ+boQzLVGBJwQQdM 5uJQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=KbYLlp7Upr9pj0+DV8TuCeDNnwboEop+TLursIg/hTQ=; b=4V2qTsND2d5uG6UVfXXJTtEhucq1pfXliNuBZ6SeuMHSmaV7ZmEYU8l+uDEvQzmUba svOUFALZfZhaGLhX4sHia0eUecUyuX4QvgfAUReA4lrSgval2oHX/JZC4eXw0l2AWOP3 LsE3t01tOPPw4nQXLeal6jIyzUh+66uxiEMonYjgo13MXeaW8YudgGDMtgWtyjAJQX0G u3BtfpkBAwbAQ7IeBvcHmjKT7la82kEXeft0+VVMkuuVioyrGnUZm9VbXNodQUKsEohf eIjM+JcdXZIVpHd6b+aabeLIvnrrS+Haiise5mLX3pYSHlCTJr7IppRMqWRhaq7/QVbD Gpvw== X-Gm-Message-State: AOAM531qipVvUjUOVwPLQxUAm+56KLm1XbmPe6ED7g+UWdnEZoZyuq0b leVNDW3v+tCAfh+6em+LEltraaAQvsNgnQ== X-Google-Smtp-Source: ABdhPJyvaLg2GWEnEjxaQ2mDWpxtGZeBtF/kkEqz9/rlVyJwLn9iSiZPz+0JFNnXU8BsiS5jBbu4TA== X-Received: by 2002:a2e:8495:0:b0:247:dca3:f7bc with SMTP id b21-20020a2e8495000000b00247dca3f7bcmr15642995ljh.12.1647867833248; Mon, 21 Mar 2022 06:03:53 -0700 (PDT) Received: from jade.urgonet (h-79-136-84-253.A175.priv.bahnhof.se. [79.136.84.253]) by smtp.gmail.com with ESMTPSA id t27-20020a2e8e7b000000b00247f32b572asm2067738ljk.19.2022.03.21.06.03.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Mar 2022 06:03:52 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, op-tee@lists.trustedfirmware.org Cc: Sumit Garg , Jens Wiklander Subject: [PATCH v2 2/4] optee: add OPTEE_SMC_CALL_WITH_RPC_ARG and OPTEE_SMC_CALL_WITH_REGD_ARG Date: Mon, 21 Mar 2022 14:03:39 +0100 Message-Id: <20220321130341.935535-3-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20220321130341.935535-1-jens.wiklander@linaro.org> References: <20220321130341.935535-1-jens.wiklander@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Adds OPTEE_SMC_CALL_WITH_RPC_ARG and OPTEE_SMC_CALL_WITH_REGD_ARG where the struct optee_msg_arg to be used for RPC is appended in the memory following the normal argument struct optee_msg_arg. This is an optimization to avoid caching the RPC argument struct while still maintaining similar performance as if it was cached. OPTEE_SMC_CALL_WITH_REGD_ARG optimized one step further by using a registered shared memory object instead. It's in other aspects identical to OPTEE_SMC_CALL_WITH_RPC_ARG. The presence of OPTEE_SMC_CALL_WITH_RPC_ARG and OPTEE_SMC_CALL_WITH_REGD_ARG is indicated by the new OPTEE_SMC_SEC_CAP_RPC_ARG bit returned by OPTEE_SMC_EXCHANGE_CAPABILITIES. OPTEE_SMC_EXCHANGE_CAPABILITIES also reports the number of arguments that the RPC argument struct must have room for. OPTEE_SMC_CALL_WITH_RPC_ARG and OPTEE_SMC_CALL_WITH_ARG can be used interleaved with difference that when OPTEE_SMC_CALL_WITH_RPC_ARG is used the RPC argument struct to be used is the one appended to the normal argument struct. The same is true for OPTEE_SMC_CALL_WITH_REGD_ARG. Signed-off-by: Jens Wiklander Reviewed-by: Sumit Garg --- drivers/tee/optee/call.c | 2 +- drivers/tee/optee/optee_smc.h | 47 ++++++++++++++--- drivers/tee/optee/smc_abi.c | 99 ++++++++++++++++++++++++++--------- 3 files changed, 116 insertions(+), 32 deletions(-) diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c index a9a237d20c61..58ac15c02818 100644 --- a/drivers/tee/optee/call.c +++ b/drivers/tee/optee/call.c @@ -130,7 +130,7 @@ struct tee_shm *optee_get_msg_arg(struct tee_context *c= tx, size_t num_params, return (void *)ma; } =20 - memset(ma, 0, OPTEE_MSG_GET_ARG_SIZE(num_params)); + memset(ma, 0, sz); ma->num_params =3D num_params; *msg_arg =3D ma; =20 diff --git a/drivers/tee/optee/optee_smc.h b/drivers/tee/optee/optee_smc.h index d44a6ae994f8..378741a459b6 100644 --- a/drivers/tee/optee/optee_smc.h +++ b/drivers/tee/optee/optee_smc.h @@ -107,14 +107,22 @@ 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: + * When called with OPTEE_SMC_CALL_WITH_RPC_ARG or + * OPTEE_SMC_CALL_WITH_REGD_ARG in a0 there is one RPC struct optee_msg_arg + * following after the first struct optee_msg_arg. The RPC struct + * optee_msg_arg has reserved space for the number of RPC parameters as + * returned by OPTEE_SMC_EXCHANGE_CAPABILITIES. + * + * When calling these functions 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 been negotiated successfully, then - * asynchronous notifications should be unmasked during this call. + * the interrupt for asynchronous notifications should be unmasked + * during this call. * - * Call register usage: - * a0 SMC Function ID, OPTEE_SMC*CALL_WITH_ARG + * Call register usage, OPTEE_SMC_CALL_WITH_ARG and + * OPTEE_SMC_CALL_WITH_RPC_ARG: + * a0 SMC Function ID, OPTEE_SMC_CALL_WITH_ARG or OPTEE_SMC_CALL_WITH_RPC_= ARG * a1 Upper 32 bits of a 64-bit physical pointer to a struct optee_msg_arg * a2 Lower 32 bits of a 64-bit physical pointer to a struct optee_msg_arg * a3 Cache settings, not used if physical pointer is in a predefined shar= ed @@ -122,6 +130,15 @@ struct optee_smc_call_get_os_revision_result { * a4-6 Not used * a7 Hypervisor Client ID register * + * Call register usage, OPTEE_SMC_CALL_WITH_REGD_ARG: + * a0 SMC Function ID, OPTEE_SMC_CALL_WITH_REGD_ARG + * a1 Upper 32 bits of a 64-bit shared memory cookie + * a2 Lower 32 bits of a 64-bit shared memory cookie + * a3 Offset of the struct optee_msg_arg in the shared memory with the + * supplied cookie + * a4-6 Not used + * a7 Hypervisor Client ID register + * * Normal return register usage: * a0 Return value, OPTEE_SMC_RETURN_* * a1-3 Not used @@ -154,6 +171,10 @@ struct optee_smc_call_get_os_revision_result { #define OPTEE_SMC_FUNCID_CALL_WITH_ARG OPTEE_MSG_FUNCID_CALL_WITH_ARG #define OPTEE_SMC_CALL_WITH_ARG \ OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_CALL_WITH_ARG) +#define OPTEE_SMC_CALL_WITH_RPC_ARG \ + OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_CALL_WITH_RPC_ARG) +#define OPTEE_SMC_CALL_WITH_REGD_ARG \ + OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_CALL_WITH_REGD_ARG) =20 /* * Get Shared Memory Config @@ -202,6 +223,10 @@ struct optee_smc_get_shm_config_result { * a0 OPTEE_SMC_RETURN_OK * a1 bitfield of secure world capabilities OPTEE_SMC_SEC_CAP_* * a2 The maximum secure world notification number + * a3 Bit[7:0]: Number of parameters needed for RPC to be supplied + * as the second MSG arg struct for + * OPTEE_SMC_CALL_WITH_ARG + * Bit[31:8]: Reserved (MBZ) * a3-7 Preserved * * Error return register usage: @@ -215,7 +240,6 @@ struct optee_smc_get_shm_config_result { #define OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM BIT(0) /* Secure world can communicate via previously unregistered shared memory = */ #define OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM BIT(1) - /* * Secure world supports commands "register/unregister shared memory", * secure world accepts command buffers located in any parts of non-secure= RAM @@ -227,6 +251,8 @@ struct optee_smc_get_shm_config_result { #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) +/* Secure world supports pre-allocating RPC arg struct */ +#define OPTEE_SMC_SEC_CAP_RPC_ARG BIT(6) =20 #define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES 9 #define OPTEE_SMC_EXCHANGE_CAPABILITIES \ @@ -236,7 +262,7 @@ struct optee_smc_exchange_capabilities_result { unsigned long status; unsigned long capabilities; unsigned long max_notif_value; - unsigned long reserved0; + unsigned long data; }; =20 /* @@ -358,6 +384,9 @@ struct optee_smc_disable_shm_cache_result { * should be called until all pended values have been retrieved. When a * value is retrieved, it's cleared from the record in secure world. * + * It is expected that this function is called from an interrupt handler + * in normal world. + * * Call requests usage: * a0 SMC Function ID, OPTEE_SMC_GET_ASYNC_NOTIF_VALUE * a1-6 Not used @@ -390,6 +419,12 @@ struct optee_smc_disable_shm_cache_result { #define OPTEE_SMC_GET_ASYNC_NOTIF_VALUE \ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_ASYNC_NOTIF_VALUE) =20 +/* See OPTEE_SMC_CALL_WITH_RPC_ARG above */ +#define OPTEE_SMC_FUNCID_CALL_WITH_RPC_ARG 18 + +/* See OPTEE_SMC_CALL_WITH_REGD_ARG above */ +#define OPTEE_SMC_FUNCID_CALL_WITH_REGD_ARG 19 + /* * Resume from RPC (for example after processing a foreign interrupt) * diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c index 67b7f7d2ff27..b258d7306042 100644 --- a/drivers/tee/optee/smc_abi.c +++ b/drivers/tee/optee/smc_abi.c @@ -732,16 +732,9 @@ static void optee_rpc_finalize_call(struct optee_call_= ctx *call_ctx) } =20 static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *opt= ee, - struct tee_shm *shm, + struct optee_msg_arg *arg, struct optee_call_ctx *call_ctx) { - struct optee_msg_arg *arg; - - arg =3D tee_shm_get_va(shm, 0); - if (IS_ERR(arg)) { - pr_err("%s: tee_shm_get_va %p failed\n", __func__, shm); - return; - } =20 switch (arg->cmd) { case OPTEE_RPC_CMD_SHM_ALLOC: @@ -765,11 +758,13 @@ static void handle_rpc_func_cmd(struct tee_context *c= tx, struct optee *optee, * Result of RPC is written back into @param. */ static void optee_handle_rpc(struct tee_context *ctx, + struct optee_msg_arg *rpc_arg, struct optee_rpc_param *param, struct optee_call_ctx *call_ctx) { struct tee_device *teedev =3D ctx->teedev; struct optee *optee =3D tee_get_drvdata(teedev); + struct optee_msg_arg *arg; struct tee_shm *shm; phys_addr_t pa; =20 @@ -801,8 +796,19 @@ static void optee_handle_rpc(struct tee_context *ctx, */ break; case OPTEE_SMC_RPC_FUNC_CMD: - shm =3D reg_pair_to_ptr(param->a1, param->a2); - handle_rpc_func_cmd(ctx, optee, shm, call_ctx); + if (rpc_arg) { + arg =3D rpc_arg; + } else { + shm =3D reg_pair_to_ptr(param->a1, param->a2); + arg =3D tee_shm_get_va(shm, 0); + if (IS_ERR(arg)) { + pr_err("%s: tee_shm_get_va %p failed\n", + __func__, shm); + break; + } + } + + handle_rpc_func_cmd(ctx, optee, arg, call_ctx); break; default: pr_warn("Unknown RPC func 0x%x\n", @@ -816,7 +822,7 @@ static void optee_handle_rpc(struct tee_context *ctx, /** * optee_smc_do_call_with_arg() - Do an SMC to OP-TEE in secure world * @ctx: calling context - * @arg: shared memory holding the message to pass to secure world + * @shm: shared memory holding the message to pass to secure world * * Does and SMC to OP-TEE in secure world and handles eventual resulting * Remote Procedure Calls (RPC) from OP-TEE. @@ -824,21 +830,46 @@ 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 *arg) + struct tee_shm *shm) { struct optee *optee =3D tee_get_drvdata(ctx->teedev); struct optee_call_waiter w; struct optee_rpc_param param =3D { }; struct optee_call_ctx call_ctx =3D { }; - phys_addr_t parg; + struct optee_msg_arg *rpc_arg =3D NULL; int rc; =20 - rc =3D tee_shm_get_pa(arg, 0, &parg); - if (rc) - return rc; + if (optee->rpc_param_count) { + struct optee_msg_arg *arg; + unsigned int rpc_arg_offs; + + arg =3D tee_shm_get_va(shm, 0); + if (IS_ERR(arg)) + return PTR_ERR(arg); =20 - param.a0 =3D OPTEE_SMC_CALL_WITH_ARG; - reg_pair_from_64(¶m.a1, ¶m.a2, parg); + rpc_arg_offs =3D OPTEE_MSG_GET_ARG_SIZE(arg->num_params); + rpc_arg =3D tee_shm_get_va(shm, rpc_arg_offs); + if (IS_ERR(arg)) + return PTR_ERR(arg); + } + + if (rpc_arg && tee_shm_is_dynamic(shm)) { + param.a0 =3D OPTEE_SMC_CALL_WITH_REGD_ARG; + reg_pair_from_64(¶m.a1, ¶m.a2, (u_long)shm); + param.a3 =3D 0; + } else { + phys_addr_t parg; + + rc =3D tee_shm_get_pa(shm, 0, &parg); + if (rc) + return rc; + + if (rpc_arg) + param.a0 =3D OPTEE_SMC_CALL_WITH_RPC_ARG; + else + param.a0 =3D OPTEE_SMC_CALL_WITH_ARG; + reg_pair_from_64(¶m.a1, ¶m.a2, parg); + } /* Initialize waiter */ optee_cq_wait_init(&optee->call_queue, &w); while (true) { @@ -862,7 +893,7 @@ static int optee_smc_do_call_with_arg(struct tee_contex= t *ctx, param.a1 =3D res.a1; param.a2 =3D res.a2; param.a3 =3D res.a3; - optee_handle_rpc(ctx, ¶m, &call_ctx); + optee_handle_rpc(ctx, rpc_arg, ¶m, &call_ctx); } else { rc =3D res.a0; break; @@ -1118,7 +1149,8 @@ static bool optee_msg_api_revision_is_compatible(opte= e_invoke_fn *invoke_fn) } =20 static bool optee_msg_exchange_capabilities(optee_invoke_fn *invoke_fn, - u32 *sec_caps, u32 *max_notif_value) + u32 *sec_caps, u32 *max_notif_value, + unsigned int *rpc_param_count) { union { struct arm_smccc_res smccc; @@ -1145,6 +1177,10 @@ static bool optee_msg_exchange_capabilities(optee_in= voke_fn *invoke_fn, *max_notif_value =3D res.result.max_notif_value; else *max_notif_value =3D OPTEE_DEFAULT_MAX_NOTIF_VALUE; + if (*sec_caps & OPTEE_SMC_SEC_CAP_RPC_ARG) + *rpc_param_count =3D (u8)res.result.data; + else + *rpc_param_count =3D 0; =20 return true; } @@ -1251,7 +1287,8 @@ static int optee_smc_remove(struct platform_device *p= dev) * reference counters and also avoid wild pointers in secure world * into the old shared memory range. */ - optee_disable_shm_cache(optee); + if (!optee->rpc_param_count) + optee_disable_shm_cache(optee); =20 optee_smc_notif_uninit_irq(optee); =20 @@ -1274,7 +1311,10 @@ static int optee_smc_remove(struct platform_device *= pdev) */ static void optee_shutdown(struct platform_device *pdev) { - optee_disable_shm_cache(platform_get_drvdata(pdev)); + struct optee *optee =3D platform_get_drvdata(pdev); + + if (!optee->rpc_param_count) + optee_disable_shm_cache(optee); } =20 static int optee_probe(struct platform_device *pdev) @@ -1283,6 +1323,7 @@ static int optee_probe(struct platform_device *pdev) struct tee_shm_pool *pool =3D ERR_PTR(-EINVAL); struct optee *optee =3D NULL; void *memremaped_shm =3D NULL; + unsigned int rpc_param_count; struct tee_device *teedev; struct tee_context *ctx; u32 max_notif_value; @@ -1306,7 +1347,8 @@ static int optee_probe(struct platform_device *pdev) } =20 if (!optee_msg_exchange_capabilities(invoke_fn, &sec_caps, - &max_notif_value)) { + &max_notif_value, + &rpc_param_count)) { pr_warn("capabilities mismatch\n"); return -EINVAL; } @@ -1335,6 +1377,7 @@ static int optee_probe(struct platform_device *pdev) optee->ops =3D &optee_ops; optee->smc.invoke_fn =3D invoke_fn; optee->smc.sec_caps =3D sec_caps; + optee->rpc_param_count =3D rpc_param_count; =20 teedev =3D tee_device_alloc(&optee_clnt_desc, NULL, pool, optee); if (IS_ERR(teedev)) { @@ -1403,7 +1446,12 @@ static int optee_probe(struct platform_device *pdev) */ optee_disable_unmapped_shm_cache(optee); =20 - optee_enable_shm_cache(optee); + /* + * Only enable the shm cache in case we're not able to pass the RPC + * arg struct right after the normal arg struct. + */ + if (!optee->rpc_param_count) + optee_enable_shm_cache(optee); =20 if (optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM) pr_info("dynamic shared memory is enabled\n"); @@ -1416,7 +1464,8 @@ static int optee_probe(struct platform_device *pdev) return 0; =20 err_disable_shm_cache: - optee_disable_shm_cache(optee); + if (!optee->rpc_param_count) + optee_disable_shm_cache(optee); optee_smc_notif_uninit_irq(optee); optee_unregister_devices(); err_notif_uninit: --=20 2.31.1 From nobody Mon Jun 22 15:43:44 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 00A1DC433F5 for ; Mon, 21 Mar 2022 13:04:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347712AbiCUNF0 (ORCPT ); Mon, 21 Mar 2022 09:05:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56276 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347698AbiCUNFV (ORCPT ); Mon, 21 Mar 2022 09:05:21 -0400 Received: from mail-lf1-x12e.google.com (mail-lf1-x12e.google.com [IPv6:2a00:1450:4864:20::12e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4E04D11A00 for ; Mon, 21 Mar 2022 06:03:56 -0700 (PDT) Received: by mail-lf1-x12e.google.com with SMTP id m3so12496094lfj.11 for ; Mon, 21 Mar 2022 06:03:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=W0z57MDTx8X/SyhgQAkhX31Rs5nhmqitrzVboECbkLA=; b=Lz/FOVX26uayYZYlzmjUwm07Y9oB4oNpOrCjJWBE52iTkKbkClMbVmACvEICTzdbH1 FNfqso+sVxYSbptKLbg4C8K6BTakUnZvgzYLzBWx9Kjkd1hZK9oS9mCBFbgw56xZkjr9 TqUxmyD17y9Jhskz/ttkVGmQdd4OY35QBbxWs5/XM1f9ehDm/KqI4H0LqUCvDClhgY85 NePCqzU2c42u7RWWXg/HnSBaYW6mnpEsmt89aYST9fpE4f3WWanh428wL6NzUi9CkJb6 rH3bVYqs73DQ2PX2mEbiVf9onaLUDerSBMT0h3hKXwpPH/aDNi26tO1FY3Swe0V3km/e DHsg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=W0z57MDTx8X/SyhgQAkhX31Rs5nhmqitrzVboECbkLA=; b=vogp+QkwFnpAoSgCryKkL+fIzfEOB9KWbNOFFXl45DCcG+Qnopt2AfcZboCAr42ebM QJotRkFGqiotDBOu/lJNj9nUvzG/xz4VmyTtMF0nVEeQ0Cq7kqsfTKwVrN8DMjih+1Bx ffbXuxkfWTIMPZOibHgwsJPVPRqOZaCvGeCu6sPiQF/okJEwJf7ptg5cz+t5ng2/Mesi vW59PjWWzQtq+pdbpbPIhrubv0Pqu8iEHP3VEwLP748nBg0yRthcidqN/ExQHvx8pyR6 CDSFA0WcWUrlKHEsXlcFHxhUDZVVlqL7UZ+U1Fu22fJYKWhFvmM5J6i3YFrjY8Yfhb1m XGrA== X-Gm-Message-State: AOAM531tKSONYFgGGWBZtguUt+0Pb1PO3/Wg5S82oB9QeIw8OtayB/ns qBtkac3UXU9TPYfTr14kzb05qfaU+3awYQ== X-Google-Smtp-Source: ABdhPJwOG6jjG3iZ9YMHTq7TqDll1uPUiJNIBWC6llDj8cTK+LUJ+QzrO/qEQqBOlNeA2gh3xmt83w== X-Received: by 2002:a05:6512:3c97:b0:44a:1183:bd48 with SMTP id h23-20020a0565123c9700b0044a1183bd48mr9038739lfv.525.1647867834313; Mon, 21 Mar 2022 06:03:54 -0700 (PDT) Received: from jade.urgonet (h-79-136-84-253.A175.priv.bahnhof.se. [79.136.84.253]) by smtp.gmail.com with ESMTPSA id t27-20020a2e8e7b000000b00247f32b572asm2067738ljk.19.2022.03.21.06.03.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Mar 2022 06:03:53 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, op-tee@lists.trustedfirmware.org Cc: Sumit Garg , Jens Wiklander Subject: [PATCH v2 3/4] optee: add FF-A capability OPTEE_FFA_SEC_CAP_ARG_OFFSET Date: Mon, 21 Mar 2022 14:03:40 +0100 Message-Id: <20220321130341.935535-4-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20220321130341.935535-1-jens.wiklander@linaro.org> References: <20220321130341.935535-1-jens.wiklander@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Adds the secure capability OPTEE_FFA_SEC_CAP_ARG_OFFSET to indicate that OP-TEE with FF-A can support an argument struct at a non-zero offset into a passed shared memory object. Signed-off-by: Jens Wiklander --- drivers/tee/optee/ffa_abi.c | 17 +++++++++++++++-- drivers/tee/optee/optee_ffa.h | 12 +++++++++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c index 7686f7020616..cc863aaefcd9 100644 --- a/drivers/tee/optee/ffa_abi.c +++ b/drivers/tee/optee/ffa_abi.c @@ -615,12 +615,21 @@ static int optee_ffa_do_call_with_arg(struct tee_cont= ext *ctx, .data0 =3D OPTEE_FFA_YIELDING_CALL_WITH_ARG, .data1 =3D (u32)shm->sec_world_id, .data2 =3D (u32)(shm->sec_world_id >> 32), - .data3 =3D shm->offset, + .data3 =3D 0, }; struct optee_msg_arg *arg; unsigned int rpc_arg_offs; struct optee_msg_arg *rpc_arg; =20 + /* + * The shared memory object has to start on a page when passed as + * an argument struct. This is also what the shm pool allocator + * returns, but check this before calling secure world to catch + * eventual errors early in case something changes. + */ + if (shm->offset) + return -EINVAL; + arg =3D tee_shm_get_va(shm, 0); if (IS_ERR(arg)) return PTR_ERR(arg); @@ -678,6 +687,7 @@ static bool optee_ffa_api_is_compatbile(struct ffa_devi= ce *ffa_dev, =20 static bool optee_ffa_exchange_caps(struct ffa_device *ffa_dev, const struct ffa_dev_ops *ops, + u32 *sec_caps, unsigned int *rpc_param_count) { struct ffa_send_direct_data data =3D { OPTEE_FFA_EXCHANGE_CAPABILITIES }; @@ -694,6 +704,7 @@ static bool optee_ffa_exchange_caps(struct ffa_device *= ffa_dev, } =20 *rpc_param_count =3D (u8)data.data1; + *sec_caps =3D data.data2; =20 return true; } @@ -777,6 +788,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev) struct tee_device *teedev; struct tee_context *ctx; struct optee *optee; + u32 sec_caps; int rc; =20 ffa_ops =3D ffa_dev_ops_get(ffa_dev); @@ -788,7 +800,8 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev) if (!optee_ffa_api_is_compatbile(ffa_dev, ffa_ops)) return -EINVAL; =20 - if (!optee_ffa_exchange_caps(ffa_dev, ffa_ops, &rpc_param_count)) + if (!optee_ffa_exchange_caps(ffa_dev, ffa_ops, &sec_caps, + &rpc_param_count)) return -EINVAL; =20 optee =3D kzalloc(sizeof(*optee), GFP_KERNEL); diff --git a/drivers/tee/optee/optee_ffa.h b/drivers/tee/optee/optee_ffa.h index ee3a03fc392c..97266243deaa 100644 --- a/drivers/tee/optee/optee_ffa.h +++ b/drivers/tee/optee/optee_ffa.h @@ -81,8 +81,16 @@ * as the second MSG arg struct for * OPTEE_FFA_YIELDING_CALL_WITH_ARG. * Bit[31:8]: Reserved (MBZ) - * w5-w7: Note used (MBZ) + * w5: Bitfield of secure world capabilities OPTEE_FFA_SEC_CAP_* below, + * unused bits MBZ. + * w6-w7: Not used (MBZ) + */ +/* + * Secure world supports giving an offset into the argument shared memory + * object, see also OPTEE_FFA_YIELDING_CALL_WITH_ARG */ +#define OPTEE_FFA_SEC_CAP_ARG_OFFSET BIT(0) + #define OPTEE_FFA_EXCHANGE_CAPABILITIES OPTEE_FFA_BLOCKING_CALL(2) =20 /* @@ -112,6 +120,8 @@ * OPTEE_MSG_GET_ARG_SIZE(num_params) follows a struct optee_msg_arg * for RPC, this struct has reserved space for the number of RPC * parameters as returned by OPTEE_FFA_EXCHANGE_CAPABILITIES. + * MBZ unless the bit OPTEE_FFA_SEC_CAP_ARG_OFFSET is received with + * OPTEE_FFA_EXCHANGE_CAPABILITIES. * w7: Not used (MBZ) * Resume from RPC. Register usage: * w3: Service ID, OPTEE_FFA_YIELDING_CALL_RESUME --=20 2.31.1 From nobody Mon Jun 22 15:43:44 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8BF05C433EF for ; Mon, 21 Mar 2022 13:04:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347730AbiCUNFc (ORCPT ); Mon, 21 Mar 2022 09:05:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56536 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347707AbiCUNFY (ORCPT ); Mon, 21 Mar 2022 09:05:24 -0400 Received: from mail-lf1-x12a.google.com (mail-lf1-x12a.google.com [IPv6:2a00:1450:4864:20::12a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DAFC4369D6 for ; Mon, 21 Mar 2022 06:03:57 -0700 (PDT) Received: by mail-lf1-x12a.google.com with SMTP id p15so13747443lfk.8 for ; Mon, 21 Mar 2022 06:03:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=7ft3nnxTLFrRTX3OTENxGqi4vuQTbBxIi+yunJ7SLO0=; b=Tq+aKNZNH58QJASyIjywktiZZjFpy/zh5P4Jm0KstLiMt3a9JMV5H0IF1qcZg1ohbR YrK4tObO7n7bgaU81od/CumtNKyWy4JbryydXCN/O2h+cddHQv0MrN7gPanL70prsq2W rtmsDppcwbYGfWBFvV1XVr3cdw54OdhkmKZk/q4OL4ZoBMIaCUpeTK6PUxayYmpP+9P0 QA1p+2MUqlTc0RR8qv/QOWWxCGOhVVF/RSgkfBNJf8m7m1V/Z70/yQiv8JamCTRSVQUR zuwNOjy4Cu078XF0RygxgMv8Gw1yrH4NdGVJi6ZQAm/iMxXd8RIKGjSqcGHnL+F40obV oBhg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=7ft3nnxTLFrRTX3OTENxGqi4vuQTbBxIi+yunJ7SLO0=; b=dscvRoztuirwN9wSNduSRw9OGkTve7sQH6EU7v9XbfpnkhQoG43gp1E65RjbqQ8XE0 L+3Ri6bpsYitRKpLjQKCfFh3pJAjWmkoYqXQvMtTatx8qUNFSoHtmh6my5AafVvztM6Y /cq0aJsbFgp6y7+ums38Emx5Nh1QkoWf9WA+IYKVEERTQvCzSmefdHjHHs4ONNnEAqOa WfvolIV9GQB6bMo/2lTrxpfpqfBsZ4iqc3iLH5gb2tZD0nCwPDVDuM8gz0GYKk7+y1rF mLPUVzsSdCR6DpJKBxhqu995K0VW3s4Zs/WNSu6cPdUkptGasggbH5ttTVN3qkJqleVL OzlA== X-Gm-Message-State: AOAM530dErSyhp51G7aDlhCBoD7UVNLbaAVYiN4z29BaZObzfvaDQDP+ ueXt0GL5RtCXGJ5Ge0rL+r14bdQgAL5MCA== X-Google-Smtp-Source: ABdhPJyEguiEnrgxET5JS76FAIy7r6hbhJohoJWosQSzm/kVoWfuoSlqrtzYNsHXch0+BSWO90m4iA== X-Received: by 2002:a05:6512:10c1:b0:448:3070:7071 with SMTP id k1-20020a05651210c100b0044830707071mr14947486lfg.264.1647867835404; Mon, 21 Mar 2022 06:03:55 -0700 (PDT) Received: from jade.urgonet (h-79-136-84-253.A175.priv.bahnhof.se. [79.136.84.253]) by smtp.gmail.com with ESMTPSA id t27-20020a2e8e7b000000b00247f32b572asm2067738ljk.19.2022.03.21.06.03.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Mar 2022 06:03:54 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, op-tee@lists.trustedfirmware.org Cc: Sumit Garg , Jens Wiklander Subject: [PATCH v2 4/4] optee: cache argument shared memory structs Date: Mon, 21 Mar 2022 14:03:41 +0100 Message-Id: <20220321130341.935535-5-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20220321130341.935535-1-jens.wiklander@linaro.org> References: <20220321130341.935535-1-jens.wiklander@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Implements a cache to handle shared memory used to pass the argument struct needed when doing a normal yielding call into secure world. Signed-off-by: Jens Wiklander --- drivers/tee/optee/call.c | 236 ++++++++++++++++++++++++------ drivers/tee/optee/core.c | 1 + drivers/tee/optee/ffa_abi.c | 13 +- drivers/tee/optee/optee_private.h | 27 +++- drivers/tee/optee/smc_abi.c | 73 +++++++-- 5 files changed, 285 insertions(+), 65 deletions(-) diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c index 58ac15c02818..608d5f4241de 100644 --- a/drivers/tee/optee/call.c +++ b/drivers/tee/optee/call.c @@ -11,6 +11,34 @@ #include #include "optee_private.h" =20 +#define MAX_ARG_PARAM_COUNT 6 + +/* + * How much memory we allocate for each entry. This doesn't have to be a + * single page, but it makes sense to keep at least keep it as multiples of + * the page size. + */ +#define SHM_ENTRY_SIZE PAGE_SIZE + +/* + * We need to have a compile time constant to be able to determine the + * maximum needed size of the bit field. + */ +#define MIN_ARG_SIZE OPTEE_MSG_GET_ARG_SIZE(MAX_ARG_PARAM_COUNT) +#define MAX_ARG_COUNT_PER_ENTRY (SHM_ENTRY_SIZE / MIN_ARG_SIZE) + +/* + * Shared memory for argument structs are cached here. The number of + * arguments structs that can fit is determined at runtime depending on the + * needed RPC parameter count reported by secure world + * (optee->rpc_param_count). + */ +struct optee_shm_arg_entry { + struct list_head list_node; + struct tee_shm *shm; + DECLARE_BITMAP(map, MAX_ARG_COUNT_PER_ENTRY); +}; + void optee_cq_wait_init(struct optee_call_queue *cq, struct optee_call_waiter *w) { @@ -104,37 +132,149 @@ static struct optee_session *find_session(struct opt= ee_context_data *ctxdata, return NULL; } =20 -struct tee_shm *optee_get_msg_arg(struct tee_context *ctx, size_t num_para= ms, - struct optee_msg_arg **msg_arg) +void optee_shm_arg_cache_init(struct optee *optee, u32 flags) +{ + INIT_LIST_HEAD(&optee->shm_arg_cache.shm_args); + mutex_init(&optee->shm_arg_cache.mutex); + optee->shm_arg_cache.flags =3D flags; +} + +void optee_shm_arg_cache_uninit(struct optee *optee) +{ + struct list_head *head =3D &optee->shm_arg_cache.shm_args; + struct optee_shm_arg_entry *entry; + + mutex_destroy(&optee->shm_arg_cache.mutex); + while (!list_empty(head)) { + entry =3D list_first_entry(head, struct optee_shm_arg_entry, + list_node); + list_del(&entry->list_node); + if (find_first_bit(entry->map, MAX_ARG_COUNT_PER_ENTRY) !=3D + MAX_ARG_COUNT_PER_ENTRY) { + pr_err("Freeing non-free entry\n"); + } + tee_shm_free(entry->shm); + kfree(entry); + } +} + +size_t optee_msg_arg_size(size_t rpc_param_count) +{ + size_t sz =3D OPTEE_MSG_GET_ARG_SIZE(MAX_ARG_PARAM_COUNT); + + if (rpc_param_count) + sz +=3D OPTEE_MSG_GET_ARG_SIZE(rpc_param_count); + + return sz; +} + +/** + * optee_get_msg_arg() - Provide shared memory for argument struct + * @ctx: Caller TEE context + * @num_params: Number of parameter to store + * @entry_ret: Entry pointer, needed when freeing the buffer + * @shm_ret: Shared memory buffer + * @offs_ret: Offset of argument strut in shared memory buffer + * + * @returns a pointer to the argument struct in memory, else an ERR_PTR + */ +struct optee_msg_arg *optee_get_msg_arg(struct tee_context *ctx, + size_t num_params, + struct optee_shm_arg_entry **entry_ret, + struct tee_shm **shm_ret, + u_int *offs_ret) { struct optee *optee =3D tee_get_drvdata(ctx->teedev); - size_t sz =3D OPTEE_MSG_GET_ARG_SIZE(num_params); - struct tee_shm *shm; + size_t sz =3D optee_msg_arg_size(optee->rpc_param_count); + struct optee_shm_arg_entry *entry; struct optee_msg_arg *ma; + size_t args_per_entry; + u_long bit; + u_int offs; + void *res; + + if (num_params > MAX_ARG_PARAM_COUNT) + return ERR_PTR(-EINVAL); + + if (optee->shm_arg_cache.flags & OPTEE_SHM_ARG_SHARED) + args_per_entry =3D SHM_ENTRY_SIZE / sz; + else + args_per_entry =3D 1; + + mutex_lock(&optee->shm_arg_cache.mutex); + list_for_each_entry(entry, &optee->shm_arg_cache.shm_args, list_node) { + bit =3D find_first_zero_bit(entry->map, MAX_ARG_COUNT_PER_ENTRY); + if (bit < args_per_entry) + goto have_entry; + } =20 /* - * rpc_param_count is set to the number of allocated parameters in - * the RPC argument struct if a second MSG arg struct is expected. - * The second arg struct will then be used for RPC. + * No entry was found, let's allocate a new. */ - if (optee->rpc_param_count) - sz +=3D OPTEE_MSG_GET_ARG_SIZE(optee->rpc_param_count); + entry =3D kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) { + res =3D ERR_PTR(-ENOMEM); + goto out; + } =20 - shm =3D tee_shm_alloc_priv_buf(ctx, sz); - if (IS_ERR(shm)) - return shm; + if (optee->shm_arg_cache.flags & OPTEE_SHM_ARG_ALLOC_PRIV) + res =3D tee_shm_alloc_priv_buf(ctx, SHM_ENTRY_SIZE); + else + res =3D tee_shm_alloc_kernel_buf(ctx, SHM_ENTRY_SIZE); =20 - ma =3D tee_shm_get_va(shm, 0); - if (IS_ERR(ma)) { - tee_shm_free(shm); - return (void *)ma; + if (IS_ERR(res)) { + kfree(entry); + goto out; } - + entry->shm =3D res; + list_add(&entry->list_node, &optee->shm_arg_cache.shm_args); + bit =3D 0; + +have_entry: + offs =3D bit * sz; + res =3D tee_shm_get_va(entry->shm, offs); + if (IS_ERR(res)) + goto out; + ma =3D res; + set_bit(bit, entry->map); memset(ma, 0, sz); ma->num_params =3D num_params; - *msg_arg =3D ma; + *entry_ret =3D entry; + *shm_ret =3D entry->shm; + *offs_ret =3D offs; +out: + mutex_unlock(&optee->shm_arg_cache.mutex); + return res; +} + +/** + * optee_free_msg_arg() - Free previsouly obtained shared memory + * @ctx: Caller TEE context + * @entry: Pointer returned when the shared memory was obtained + * @offs: Offset of shared memory buffer to free + * + * This function frees the shared memory obtained with optee_get_msg_arg(). + */ +void optee_free_msg_arg(struct tee_context *ctx, + struct optee_shm_arg_entry *entry, u_int offs) +{ + struct optee *optee =3D tee_get_drvdata(ctx->teedev); + size_t sz =3D optee_msg_arg_size(optee->rpc_param_count); + u_long bit; =20 - return shm; + if (offs > SHM_ENTRY_SIZE || offs % sz) { + pr_err("Invalid offs %u\n", offs); + return; + } + bit =3D offs / sz; + + mutex_lock(&optee->shm_arg_cache.mutex); + + if (!test_bit(bit, entry->map)) + pr_err("Bit pos %lu is already free\n", bit); + clear_bit(bit, entry->map); + + mutex_unlock(&optee->shm_arg_cache.mutex); } =20 int optee_open_session(struct tee_context *ctx, @@ -143,16 +283,19 @@ int optee_open_session(struct tee_context *ctx, { struct optee *optee =3D tee_get_drvdata(ctx->teedev); struct optee_context_data *ctxdata =3D ctx->data; - int rc; + struct optee_shm_arg_entry *entry; struct tee_shm *shm; struct optee_msg_arg *msg_arg; struct optee_session *sess =3D NULL; uuid_t client_uuid; + u_int offs; + int rc; =20 /* +2 for the meta parameters added below */ - shm =3D optee_get_msg_arg(ctx, arg->num_params + 2, &msg_arg); - if (IS_ERR(shm)) - return PTR_ERR(shm); + msg_arg =3D optee_get_msg_arg(ctx, arg->num_params + 2, + &entry, &shm, &offs); + if (IS_ERR(msg_arg)) + return PTR_ERR(msg_arg); =20 msg_arg->cmd =3D OPTEE_MSG_CMD_OPEN_SESSION; msg_arg->cancel_id =3D arg->cancel_id; @@ -185,7 +328,7 @@ int optee_open_session(struct tee_context *ctx, goto out; } =20 - if (optee->ops->do_call_with_arg(ctx, shm)) { + if (optee->ops->do_call_with_arg(ctx, shm, offs)) { msg_arg->ret =3D TEEC_ERROR_COMMUNICATION; msg_arg->ret_origin =3D TEEC_ORIGIN_COMMS; } @@ -212,26 +355,28 @@ int optee_open_session(struct tee_context *ctx, arg->ret_origin =3D msg_arg->ret_origin; } out: - tee_shm_free(shm); + optee_free_msg_arg(ctx, entry, offs); =20 return rc; } =20 int optee_close_session_helper(struct tee_context *ctx, u32 session) { - struct tee_shm *shm; struct optee *optee =3D tee_get_drvdata(ctx->teedev); + struct optee_shm_arg_entry *entry; struct optee_msg_arg *msg_arg; + struct tee_shm *shm; + u_int offs; =20 - shm =3D optee_get_msg_arg(ctx, 0, &msg_arg); - if (IS_ERR(shm)) - return PTR_ERR(shm); + msg_arg =3D optee_get_msg_arg(ctx, 0, &entry, &shm, &offs); + if (IS_ERR(msg_arg)) + return PTR_ERR(msg_arg); =20 msg_arg->cmd =3D OPTEE_MSG_CMD_CLOSE_SESSION; msg_arg->session =3D session; - optee->ops->do_call_with_arg(ctx, shm); + optee->ops->do_call_with_arg(ctx, shm, offs); =20 - tee_shm_free(shm); + optee_free_msg_arg(ctx, entry, offs); =20 return 0; } @@ -259,9 +404,11 @@ int optee_invoke_func(struct tee_context *ctx, struct = tee_ioctl_invoke_arg *arg, { struct optee *optee =3D tee_get_drvdata(ctx->teedev); struct optee_context_data *ctxdata =3D ctx->data; - struct tee_shm *shm; + struct optee_shm_arg_entry *entry; struct optee_msg_arg *msg_arg; struct optee_session *sess; + struct tee_shm *shm; + u_int offs; int rc; =20 /* Check that the session is valid */ @@ -271,9 +418,10 @@ int optee_invoke_func(struct tee_context *ctx, struct = tee_ioctl_invoke_arg *arg, if (!sess) return -EINVAL; =20 - shm =3D optee_get_msg_arg(ctx, arg->num_params, &msg_arg); - if (IS_ERR(shm)) - return PTR_ERR(shm); + msg_arg =3D optee_get_msg_arg(ctx, arg->num_params, + &entry, &shm, &offs); + if (IS_ERR(msg_arg)) + return PTR_ERR(msg_arg); msg_arg->cmd =3D OPTEE_MSG_CMD_INVOKE_COMMAND; msg_arg->func =3D arg->func; msg_arg->session =3D arg->session; @@ -284,7 +432,7 @@ int optee_invoke_func(struct tee_context *ctx, struct t= ee_ioctl_invoke_arg *arg, if (rc) goto out; =20 - if (optee->ops->do_call_with_arg(ctx, shm)) { + if (optee->ops->do_call_with_arg(ctx, shm, offs)) { msg_arg->ret =3D TEEC_ERROR_COMMUNICATION; msg_arg->ret_origin =3D TEEC_ORIGIN_COMMS; } @@ -298,7 +446,7 @@ int optee_invoke_func(struct tee_context *ctx, struct t= ee_ioctl_invoke_arg *arg, arg->ret =3D msg_arg->ret; arg->ret_origin =3D msg_arg->ret_origin; out: - tee_shm_free(shm); + optee_free_msg_arg(ctx, entry, offs); return rc; } =20 @@ -306,9 +454,11 @@ int optee_cancel_req(struct tee_context *ctx, u32 canc= el_id, u32 session) { struct optee *optee =3D tee_get_drvdata(ctx->teedev); struct optee_context_data *ctxdata =3D ctx->data; - struct tee_shm *shm; + struct optee_shm_arg_entry *entry; struct optee_msg_arg *msg_arg; struct optee_session *sess; + struct tee_shm *shm; + u_int offs; =20 /* Check that the session is valid */ mutex_lock(&ctxdata->mutex); @@ -317,16 +467,16 @@ int optee_cancel_req(struct tee_context *ctx, u32 can= cel_id, u32 session) if (!sess) return -EINVAL; =20 - shm =3D optee_get_msg_arg(ctx, 0, &msg_arg); - if (IS_ERR(shm)) - return PTR_ERR(shm); + msg_arg =3D optee_get_msg_arg(ctx, 0, &entry, &shm, &offs); + if (IS_ERR(msg_arg)) + return PTR_ERR(msg_arg); =20 msg_arg->cmd =3D OPTEE_MSG_CMD_CANCEL; msg_arg->session =3D session; msg_arg->cancel_id =3D cancel_id; - optee->ops->do_call_with_arg(ctx, shm); + optee->ops->do_call_with_arg(ctx, shm, offs); =20 - tee_shm_free(shm); + optee_free_msg_arg(ctx, entry, offs); return 0; } =20 diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index daf947e98d14..daf07737c4fd 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -171,6 +171,7 @@ void optee_remove_common(struct optee *optee) optee_unregister_devices(); =20 optee_notif_uninit(optee); + optee_shm_arg_cache_uninit(optee); teedev_close_context(optee->ctx); /* * The two devices have to be unregistered before we can free the diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c index cc863aaefcd9..1552cd3f9d4e 100644 --- a/drivers/tee/optee/ffa_abi.c +++ b/drivers/tee/optee/ffa_abi.c @@ -601,6 +601,7 @@ static int optee_ffa_yielding_call(struct tee_context *= ctx, * optee_ffa_do_call_with_arg() - Do a FF-A call to enter OP-TEE in secure= world * @ctx: calling context * @shm: shared memory holding the message to pass to secure world + * @offs: offset of the message in @shm * * Does a FF-A call to OP-TEE in secure world and handles eventual resulti= ng * Remote Procedure Calls (RPC) from OP-TEE. @@ -609,13 +610,13 @@ static int optee_ffa_yielding_call(struct tee_context= *ctx, */ =20 static int optee_ffa_do_call_with_arg(struct tee_context *ctx, - struct tee_shm *shm) + struct tee_shm *shm, u_int offs) { struct ffa_send_direct_data data =3D { .data0 =3D OPTEE_FFA_YIELDING_CALL_WITH_ARG, .data1 =3D (u32)shm->sec_world_id, .data2 =3D (u32)(shm->sec_world_id >> 32), - .data3 =3D 0, + .data3 =3D offs, }; struct optee_msg_arg *arg; unsigned int rpc_arg_offs; @@ -630,12 +631,12 @@ static int optee_ffa_do_call_with_arg(struct tee_cont= ext *ctx, if (shm->offset) return -EINVAL; =20 - arg =3D tee_shm_get_va(shm, 0); + arg =3D tee_shm_get_va(shm, offs); if (IS_ERR(arg)) return PTR_ERR(arg); =20 rpc_arg_offs =3D OPTEE_MSG_GET_ARG_SIZE(arg->num_params); - rpc_arg =3D tee_shm_get_va(shm, rpc_arg_offs); + rpc_arg =3D tee_shm_get_va(shm, offs + rpc_arg_offs); if (IS_ERR(rpc_arg)) return PTR_ERR(rpc_arg); =20 @@ -787,6 +788,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev) struct tee_shm_pool *pool; struct tee_device *teedev; struct tee_context *ctx; + u32 arg_cache_flags =3D 0; struct optee *optee; u32 sec_caps; int rc; @@ -803,6 +805,8 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev) if (!optee_ffa_exchange_caps(ffa_dev, ffa_ops, &sec_caps, &rpc_param_count)) return -EINVAL; + if (sec_caps & OPTEE_FFA_SEC_CAP_ARG_OFFSET) + arg_cache_flags |=3D OPTEE_SHM_ARG_SHARED; =20 optee =3D kzalloc(sizeof(*optee), GFP_KERNEL); if (!optee) @@ -851,6 +855,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev) mutex_init(&optee->call_queue.mutex); INIT_LIST_HEAD(&optee->call_queue.waiters); optee_supp_init(&optee->supp); + optee_shm_arg_cache_init(optee, arg_cache_flags); ffa_dev_set_drvdata(ffa_dev, optee); ctx =3D teedev_open(optee->teedev); if (IS_ERR(ctx)) { diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_pr= ivate.h index e80c5d9b62ec..a33d98d17cfd 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -59,6 +59,16 @@ struct optee_notif { u_long *bitmap; }; =20 +#define OPTEE_SHM_ARG_ALLOC_PRIV BIT(0) +#define OPTEE_SHM_ARG_SHARED BIT(1) +struct optee_shm_arg_entry; +struct optee_shm_arg_cache { + u32 flags; + /* Serializes access to this struct */ + struct mutex mutex; + struct list_head shm_args; +}; + /** * struct optee_supp - supplicant synchronization struct * @ctx the context of current connected supplicant. @@ -121,7 +131,7 @@ struct optee; */ struct optee_ops { int (*do_call_with_arg)(struct tee_context *ctx, - struct tee_shm *shm_arg); + struct tee_shm *shm_arg, u_int offs); int (*to_msg_param)(struct optee *optee, struct optee_msg_param *msg_params, size_t num_params, const struct tee_param *params); @@ -157,6 +167,7 @@ struct optee { struct optee_smc smc; struct optee_ffa ffa; }; + struct optee_shm_arg_cache shm_arg_cache; struct optee_call_queue call_queue; struct optee_notif notif; struct optee_supp supp; @@ -273,8 +284,18 @@ void optee_cq_wait_for_completion(struct optee_call_qu= eue *cq, void optee_cq_wait_final(struct optee_call_queue *cq, struct optee_call_waiter *w); int optee_check_mem_type(unsigned long start, size_t num_pages); -struct tee_shm *optee_get_msg_arg(struct tee_context *ctx, size_t num_para= ms, - struct optee_msg_arg **msg_arg); + +void optee_shm_arg_cache_init(struct optee *optee, u32 flags); +void optee_shm_arg_cache_uninit(struct optee *optee); +struct optee_msg_arg *optee_get_msg_arg(struct tee_context *ctx, + size_t num_params, + struct optee_shm_arg_entry **entry, + struct tee_shm **shm_ret, + u_int *offs); +void optee_free_msg_arg(struct tee_context *ctx, + struct optee_shm_arg_entry *entry, u_int offs); +size_t optee_msg_arg_size(size_t rpc_param_count); + =20 struct tee_shm *optee_rpc_cmd_alloc_suppl(struct tee_context *ctx, size_t = sz); void optee_rpc_cmd_free_suppl(struct tee_context *ctx, struct tee_shm *shm= ); diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c index b258d7306042..fc6fb802b9bf 100644 --- a/drivers/tee/optee/smc_abi.c +++ b/drivers/tee/optee/smc_abi.c @@ -437,6 +437,7 @@ static int optee_shm_register(struct tee_context *ctx, = struct tee_shm *shm, struct optee_msg_arg *msg_arg; struct tee_shm *shm_arg; u64 *pages_list; + size_t sz; int rc; =20 if (!num_pages) @@ -450,15 +451,30 @@ static int optee_shm_register(struct tee_context *ctx= , struct tee_shm *shm, if (!pages_list) return -ENOMEM; =20 - shm_arg =3D optee_get_msg_arg(ctx, 1, &msg_arg); + /* + * We're about to register shared memory we can't register shared + * memory for this request or there's a catch-22. + * + * So in this we'll have to do the good old temporary private + * allocation instead of using optee_get_msg_arg(). + */ + sz =3D optee_msg_arg_size(optee->rpc_param_count); + shm_arg =3D tee_shm_alloc_priv_buf(ctx, sz); if (IS_ERR(shm_arg)) { rc =3D PTR_ERR(shm_arg); goto out; } + msg_arg =3D tee_shm_get_va(shm_arg, 0); + if (IS_ERR(msg_arg)) { + rc =3D PTR_ERR(msg_arg); + goto out; + } =20 optee_fill_pages_list(pages_list, pages, num_pages, tee_shm_get_page_offset(shm)); =20 + memset(msg_arg, 0, OPTEE_MSG_GET_ARG_SIZE(1)); + msg_arg->num_params =3D 1; msg_arg->cmd =3D OPTEE_MSG_CMD_REGISTER_SHM; msg_arg->params->attr =3D OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT | OPTEE_MSG_ATTR_NONCONTIG; @@ -471,7 +487,7 @@ static int optee_shm_register(struct tee_context *ctx, = struct tee_shm *shm, msg_arg->params->u.tmem.buf_ptr =3D virt_to_phys(pages_list) | (tee_shm_get_page_offset(shm) & (OPTEE_MSG_NONCONTIG_PAGE_SIZE - 1)); =20 - if (optee->ops->do_call_with_arg(ctx, shm_arg) || + if (optee->ops->do_call_with_arg(ctx, shm_arg, 0) || msg_arg->ret !=3D TEEC_SUCCESS) rc =3D -EINVAL; =20 @@ -487,19 +503,37 @@ static int optee_shm_unregister(struct tee_context *c= tx, struct tee_shm *shm) struct optee_msg_arg *msg_arg; struct tee_shm *shm_arg; int rc =3D 0; + size_t sz; =20 - shm_arg =3D optee_get_msg_arg(ctx, 1, &msg_arg); + /* + * We're about to unregister shared memory and we may not be able + * register shared memory for this request in case we're called + * from optee_shm_arg_cache_uninit(). + * + * So in order to keep things simple in this function just as in + * optee_shm_register() we'll use temporary private allocation + * instead of using optee_get_msg_arg(). + */ + sz =3D optee_msg_arg_size(optee->rpc_param_count); + shm_arg =3D tee_shm_alloc_priv_buf(ctx, sz); if (IS_ERR(shm_arg)) return PTR_ERR(shm_arg); + msg_arg =3D tee_shm_get_va(shm_arg, 0); + if (IS_ERR(msg_arg)) { + rc =3D PTR_ERR(msg_arg); + goto out; + } =20 + memset(msg_arg, 0, sz); + msg_arg->num_params =3D 1; msg_arg->cmd =3D OPTEE_MSG_CMD_UNREGISTER_SHM; - msg_arg->params[0].attr =3D OPTEE_MSG_ATTR_TYPE_RMEM_INPUT; msg_arg->params[0].u.rmem.shm_ref =3D (unsigned long)shm; =20 - if (optee->ops->do_call_with_arg(ctx, shm_arg) || + if (optee->ops->do_call_with_arg(ctx, shm_arg, 0) || msg_arg->ret !=3D TEEC_SUCCESS) rc =3D -EINVAL; +out: tee_shm_free(shm_arg); return rc; } @@ -823,6 +857,7 @@ static void optee_handle_rpc(struct tee_context *ctx, * optee_smc_do_call_with_arg() - Do an SMC to OP-TEE in secure world * @ctx: calling context * @shm: shared memory holding the message to pass to secure world + * @offs: offset of the message in @shm * * Does and SMC to OP-TEE in secure world and handles eventual resulting * Remote Procedure Calls (RPC) from OP-TEE. @@ -830,7 +865,7 @@ 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) + struct tee_shm *shm, u_int offs) { struct optee *optee =3D tee_get_drvdata(ctx->teedev); struct optee_call_waiter w; @@ -843,12 +878,12 @@ static int optee_smc_do_call_with_arg(struct tee_cont= ext *ctx, struct optee_msg_arg *arg; unsigned int rpc_arg_offs; =20 - arg =3D tee_shm_get_va(shm, 0); + arg =3D tee_shm_get_va(shm, offs); if (IS_ERR(arg)) return PTR_ERR(arg); =20 rpc_arg_offs =3D OPTEE_MSG_GET_ARG_SIZE(arg->num_params); - rpc_arg =3D tee_shm_get_va(shm, rpc_arg_offs); + rpc_arg =3D tee_shm_get_va(shm, offs + rpc_arg_offs); if (IS_ERR(arg)) return PTR_ERR(arg); } @@ -856,11 +891,11 @@ static int optee_smc_do_call_with_arg(struct tee_cont= ext *ctx, if (rpc_arg && tee_shm_is_dynamic(shm)) { param.a0 =3D OPTEE_SMC_CALL_WITH_REGD_ARG; reg_pair_from_64(¶m.a1, ¶m.a2, (u_long)shm); - param.a3 =3D 0; + param.a3 =3D offs; } else { phys_addr_t parg; =20 - rc =3D tee_shm_get_pa(shm, 0, &parg); + rc =3D tee_shm_get_pa(shm, offs, &parg); if (rc) return rc; =20 @@ -912,17 +947,19 @@ static int optee_smc_do_call_with_arg(struct tee_cont= ext *ctx, =20 static int simple_call_with_arg(struct tee_context *ctx, u32 cmd) { + struct optee_shm_arg_entry *entry; struct optee_msg_arg *msg_arg; struct tee_shm *shm; + u_int offs; =20 - shm =3D optee_get_msg_arg(ctx, 0, &msg_arg); - if (IS_ERR(shm)) - return PTR_ERR(shm); + msg_arg =3D optee_get_msg_arg(ctx, 0, &entry, &shm, &offs); + if (IS_ERR(msg_arg)) + return PTR_ERR(msg_arg); =20 msg_arg->cmd =3D cmd; - optee_smc_do_call_with_arg(ctx, shm); + optee_smc_do_call_with_arg(ctx, shm, offs); =20 - tee_shm_free(shm); + optee_free_msg_arg(ctx, entry, offs); return 0; } =20 @@ -1321,6 +1358,7 @@ static int optee_probe(struct platform_device *pdev) { optee_invoke_fn *invoke_fn; struct tee_shm_pool *pool =3D ERR_PTR(-EINVAL); + u32 arg_cache_flags =3D OPTEE_SHM_ARG_SHARED; struct optee *optee =3D NULL; void *memremaped_shm =3D NULL; unsigned int rpc_param_count; @@ -1353,6 +1391,9 @@ static int optee_probe(struct platform_device *pdev) return -EINVAL; } =20 + if (!rpc_param_count) + arg_cache_flags |=3D OPTEE_SHM_ARG_ALLOC_PRIV; + /* * Try to use dynamic shared memory if possible */ @@ -1406,6 +1447,7 @@ static int optee_probe(struct platform_device *pdev) optee_supp_init(&optee->supp); optee->smc.memremaped_shm =3D memremaped_shm; optee->pool =3D pool; + optee_shm_arg_cache_init(optee, arg_cache_flags); =20 platform_set_drvdata(pdev, optee); ctx =3D teedev_open(optee->teedev); @@ -1473,6 +1515,7 @@ static int optee_probe(struct platform_device *pdev) err_close_ctx: teedev_close_context(ctx); err_supp_uninit: + optee_shm_arg_cache_uninit(optee); optee_supp_uninit(&optee->supp); mutex_destroy(&optee->call_queue.mutex); err_unreg_supp_teedev: --=20 2.31.1