From nobody Tue Jun 9 21:20:02 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 9086BC433EF for ; Wed, 13 Apr 2022 05:44:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232557AbiDMFrF (ORCPT ); Wed, 13 Apr 2022 01:47:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48974 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232517AbiDMFqz (ORCPT ); Wed, 13 Apr 2022 01:46:55 -0400 Received: from mail-lf1-x131.google.com (mail-lf1-x131.google.com [IPv6:2a00:1450:4864:20::131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B006A237C3 for ; Tue, 12 Apr 2022 22:44:34 -0700 (PDT) Received: by mail-lf1-x131.google.com with SMTP id u7so1572119lfs.8 for ; Tue, 12 Apr 2022 22:44:34 -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=+iLRC4aU4qXf7p4vZnxdbVNl0iSUfIahtx7crMn/woE=; b=yW+2fWO74/EtvYbWgcoWEP43l9iixVreA4b0UHBWAuN/fA4KJTwDhKNxx3BZTeJ+Ce I2nuuey9qo2IW2Hu3k0peAb48xv34jRWvNpX7VdcV8mf1JSRqxX3v+t1rZ+KXCNsWqJc jOQCiEl6u5FNcbQA5i08f4fkmpCvYt9DR/im1S4I4ES8eOnHzkHitkwP9hC6C9NTRLHI 0asM1U+zf6U2ngKn7NrDo61sUbkbFwdfGjwO9xaCN2p1UR1EGLEkupfnYwti2v4wX0BJ 8PVmrlNUUKrZ/I9mzG96I3DF3gw5Wx9fhwl0A0+4E7DFUsrgp4SAtDumzTV3DT0qthyb VzxA== 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=+iLRC4aU4qXf7p4vZnxdbVNl0iSUfIahtx7crMn/woE=; b=KMMyhgRYi+oyEo4BWG86DrqPq6KJ9HMuc3OiBvKqd3NNUuDg+87glHE30eX2XpF62P jLX6Onq3EoyDVyna2LU4AO27YLIecgmTl2hpxbJBVhbxp1w8GJRwW4AGY/q5/NexFO+P lY9YP5gmOxthY8PYu3FqN2P1TFRaOWdy10O4v0jPk1pVejLdQkcK9WSHJyfUsr4wGxxh f74z/oEMFjUvuIXM2Pi43iGlGLzHHfqymGAkCSFaJiBhSQFBvrJqpeKh0MN5J+HI5gZp bSo8PYaMgnsDFwBeb4oCkhdO14qhraVR5ujkzowo9/WW9rWpbcccdNntxZOmSVCmq1He mlDg== X-Gm-Message-State: AOAM5332gxsM4Ejb1sG+Z5c4kixG6OXjpHxWbwTTlYNjRSH3Q+S4e5ah GXP3MkJTExAsS5S96CBIigW2paxgVLaYdg== X-Google-Smtp-Source: ABdhPJxfBzFOPRzYxYcJ9o0Hy5UFK2ERnW/X3RJa4RFL/NsqibuseH6x3B1oisBDavLfRmj0kIi9Vg== X-Received: by 2002:a05:6512:31d5:b0:44a:7a30:d83 with SMTP id j21-20020a05651231d500b0044a7a300d83mr26484525lfe.330.1649828672618; Tue, 12 Apr 2022 22:44:32 -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 o23-20020ac24357000000b0044adb34b68csm3919835lfl.32.2022.04.12.22.44.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Apr 2022 22:44:31 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, op-tee@lists.trustedfirmware.org Cc: Sumit Garg , Jens Wiklander Subject: [PATCH v3 1/4] optee: rename rpc_arg_count to rpc_param_count Date: Wed, 13 Apr 2022 07:44:15 +0200 Message-Id: <20220413054418.71996-2-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20220413054418.71996-1-jens.wiklander@linaro.org> References: <20220413054418.71996-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. Reviewed-by: Sumit Garg Signed-off-by: Jens Wiklander --- 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 Tue Jun 9 21:20:02 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 5110AC433F5 for ; Wed, 13 Apr 2022 05:44:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232568AbiDMFrK (ORCPT ); Wed, 13 Apr 2022 01:47:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49056 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232538AbiDMFq5 (ORCPT ); Wed, 13 Apr 2022 01:46:57 -0400 Received: from mail-lf1-x134.google.com (mail-lf1-x134.google.com [IPv6:2a00:1450:4864:20::134]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2EDD6237CD for ; Tue, 12 Apr 2022 22:44:36 -0700 (PDT) Received: by mail-lf1-x134.google.com with SMTP id u19so1608607lff.4 for ; Tue, 12 Apr 2022 22:44:36 -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=+fCZQDuoSrbrLFYuyEb7lQepn72Qtjbl9h9EqBbJS6Y=; b=ALnc9f+aXR/tcGzBgxoFX+Dw23hHYG1qmm/q4ih6WQjMdn6nFrdbq27ut1y++LXs4O xAGyKqsU2IHYFIIhyKs4n65FjR+Pdmwh1GfnHbjPE4FI4XPKvkpDWJIbeeDg1ip2T3Pi sCGfjULlOvRr0eJCxgPU6yN1vioy+WcmpgVIcQHHTu/P8wTWhEgmBBq55oGvy0ynIo5h Atc10WERl20apVqRxuq53kSg/IHs+YN/TEBToIB9CR7+2HGLXg804x+DulvZJGnynBB6 0zWdtb3yMcDsnGLDAfrrjg3/WVNhqDze8jp0BSPvOrwLUAUaZRgPlTQUjsHLg5dmfala r8vQ== 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=+fCZQDuoSrbrLFYuyEb7lQepn72Qtjbl9h9EqBbJS6Y=; b=yQ0rQJCdnAsSS1fkr+Uge9czYbElwhbmJTI6wUwn9uAgLNJdhZLfrMHb75ysQUp1vT 3FNvQy7c6dGLHRf/P/GKNxJ1k1KKaeSvt5RjB/jQDpIKrXwJ9LBvGx5cCuQ7FYsL6rKX gtoI0lOERoG99OYbfMk3HDyZpFyUMyh5yZG6Xh6XVI5AGp9DVX98BNI8s3Ywjie9CiZU 4Jg/5/mUumKGLcSkEk+MlOIeklDXDo+XzB5qMXR/O9DZKeMWpqxlkiRfrqPbz746liEC H2ysGideDlsIw9LoDBK1I1Zwmgp/KNfNC4rNbNK3uxbPR7MsIOK4439flrrRbRvdNKLA X74A== X-Gm-Message-State: AOAM533BK+PJdN3O5oYNtMCYp7+RwmIRGJFOPyvrcbEsRLHVwsrXx3Mq yJCnRtg0hgrELJwVF1pFNnE+v5k0PkcJxQ== X-Google-Smtp-Source: ABdhPJxwWOmAeaEBpDZx+Yn3+Xje6IFsoM4AevYah3uMql8gljv9kXTqyghdx3gVA793qJ+1w6AEPg== X-Received: by 2002:a05:6512:1094:b0:46d:302:bc93 with SMTP id j20-20020a056512109400b0046d0302bc93mr446752lfg.311.1649828674004; Tue, 12 Apr 2022 22:44:34 -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 o23-20020ac24357000000b0044adb34b68csm3919835lfl.32.2022.04.12.22.44.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Apr 2022 22:44:33 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, op-tee@lists.trustedfirmware.org Cc: Sumit Garg , Jens Wiklander Subject: [PATCH v3 2/4] optee: add OPTEE_SMC_CALL_WITH_RPC_ARG and OPTEE_SMC_CALL_WITH_REGD_ARG Date: Wed, 13 Apr 2022 07:44:16 +0200 Message-Id: <20220413054418.71996-3-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20220413054418.71996-1-jens.wiklander@linaro.org> References: <20220413054418.71996-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. Reviewed-by: Sumit Garg Signed-off-by: Jens Wiklander --- drivers/tee/optee/call.c | 2 +- drivers/tee/optee/optee_smc.h | 48 ++++++++++++++--- drivers/tee/optee/smc_abi.c | 99 ++++++++++++++++++++++++++--------- 3 files changed, 117 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..c60896cf71cb 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,7 +223,11 @@ 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-7 Preserved + * 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) + * a4-7 Preserved * * Error return register usage: * a0 OPTEE_SMC_RETURN_ENOTAVAIL, can't use the capabilities from normal w= orld @@ -227,6 +252,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 +263,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 +385,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 +420,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 Tue Jun 9 21:20:02 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 A1E12C433EF for ; Wed, 13 Apr 2022 05:44:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232575AbiDMFrP (ORCPT ); Wed, 13 Apr 2022 01:47:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49058 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232537AbiDMFq5 (ORCPT ); Wed, 13 Apr 2022 01:46:57 -0400 Received: from mail-lj1-x22a.google.com (mail-lj1-x22a.google.com [IPv6:2a00:1450:4864:20::22a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 428202708 for ; Tue, 12 Apr 2022 22:44:37 -0700 (PDT) Received: by mail-lj1-x22a.google.com with SMTP id o16so882523ljp.3 for ; Tue, 12 Apr 2022 22:44:37 -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=rU2AzZuJAp1JfGXOemwV55qQxLH91Hle7zcjeugWvEydD6koOJpUdTS9mbg+7HJott DmWB/17z9XvJjvBTm9t33zQVNS1dc/APsukVytXI87b6JGGPrBPZpF7e4HfndvX4hh3V V7AdCang6aSJ/6v/qfeu1BIY2nKvD+PyiGKic0Q1/uFc39IZ0Yyey8uIXMVbrjoAooBx rrKMWzzNmCEnKNOA+QDqrDNbT6gasa8zPu1UFTII5H5cF8d0tnb/v9uUWwHunXJJQ3Js P6xyLlI6kf8x37/mTNPYJS6lRprnidnJfejxeXbv8VL9WMFpjDA1fdUHXJEdOzdqR0e4 mt3w== 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=u94ZKUoPTAHYa0r5fJE1Yj+X9I/48D+Qu5yvNBCOTgMnYXizeJyA2bTkaXu0g9o0b3 M/RaCKKFfltj0TBYcrM1nQb2DaQHJ0vdyV9Y2MMMJrBSQViIct9j3ypVU4uF113fGnxJ ZkBY8JtQc2pK8gg23VKaa8cHLA5qn0C2/EivtrHtmYcSThZZv93U64Sb413001uHTMdT JGzI0WiVX2wAOvIcul2z5R2byJDxr/NWg3I3hA8pvTFqM3A9b1rZfd1aZQkaPXs4d70s bfNcieCr7inM1KSQ3DZkTWr7SxL1fJ+0YylbT0Kr/DsZlGl+4YPIsPinzzl+JoYH1ffl JxLg== X-Gm-Message-State: AOAM531Fq3px+MDCXUpt7JzQttvbuYEeFZDHOfiM9o+IpQvlXjs29iDp ug+Hm5EGOCGYZoYioYrUaLITGWchDTwh7Q== X-Google-Smtp-Source: ABdhPJyVD6VDw+a4kTmHcoyJaG4kEavKbFleUM867bPMK4dNmQIY8XXEA0SZ9vZXdnx4jdbvi36Feg== X-Received: by 2002:a2e:9089:0:b0:24b:5d12:18cc with SMTP id l9-20020a2e9089000000b0024b5d1218ccmr11304160ljg.105.1649828674970; Tue, 12 Apr 2022 22:44:34 -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 o23-20020ac24357000000b0044adb34b68csm3919835lfl.32.2022.04.12.22.44.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Apr 2022 22:44:34 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, op-tee@lists.trustedfirmware.org Cc: Sumit Garg , Jens Wiklander Subject: [PATCH v3 3/4] optee: add FF-A capability OPTEE_FFA_SEC_CAP_ARG_OFFSET Date: Wed, 13 Apr 2022 07:44:17 +0200 Message-Id: <20220413054418.71996-4-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20220413054418.71996-1-jens.wiklander@linaro.org> References: <20220413054418.71996-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 Tue Jun 9 21:20:02 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 CC2DCC433F5 for ; Wed, 13 Apr 2022 05:45:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232589AbiDMFrT (ORCPT ); Wed, 13 Apr 2022 01:47:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49094 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232544AbiDMFrA (ORCPT ); Wed, 13 Apr 2022 01:47:00 -0400 Received: from mail-lf1-x12d.google.com (mail-lf1-x12d.google.com [IPv6:2a00:1450:4864:20::12d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BC462237C3 for ; Tue, 12 Apr 2022 22:44:38 -0700 (PDT) Received: by mail-lf1-x12d.google.com with SMTP id y32so1585148lfa.6 for ; Tue, 12 Apr 2022 22:44:38 -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=VhOASjmMPkAiR6KXKTf8AU4e0L/d5X6FwSKwN0RRgOoOhu0VMZTRf2xdlenGS34yZ7 TDTjb19+5zMyYQVUoN9g4TyLKdo7rYi3vkP/4Z5IMD2SJ3TxFUmNxlOC/7HkjrQLWpe6 lQ/Ji0NzniMbDmYlEJbngD1GMtxhZSgbteRpsZygY8BWjpKEHBLi2zeONxpdZHRYuUMi bXk9Ef/9lwWDkIib9vI0fHhcX/fv2Fe0aPRiSHkMHmhW/84PpV+S6obqit5zBwWzD1uw /cKrGHWee6UtOow6ecEuRheQwUeQ1p2h9AhQuVKovP6oayA3PLYA77cBeRmZffnmoB3w k0mw== 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=En7+A88qTHk2qogMFudyPZQDaBiE3bAC1Udf51FT9E9N5zyt6Y9K+V0gPs5XSn81l/ Mry9CSpyWLWAVFc3Gakj72uSO4SIF/vbqvWPeWHOKjX+gyQNEJWzPMY6z5gUHkbGQDA5 hi0AhkZfROBhL93D4BfX1AROpTs0qW/pMFN0HeUkZumfrdACkNvZrTxBcFinebJq4vhQ zTokK7d5vOW/e9fzn1D+tRvBH0elWV8VXKYirmJudMINdi1JkpGojUW2Kjb8vk8FKoR9 64fT7LTFfIyTcO5me6N0PlB80PzUJRL/C+3IYGxhjfk69iKbjgZLcVClbKsbiCMQMOzJ ajFA== X-Gm-Message-State: AOAM530VpZvGOkX3tKB63ABEYDAEmscPaJ+VQGtJ5lij/XwwkqkAE7dJ wqsmmHZr7C5gRCc7oDWPTTCds7aOurpMcA== X-Google-Smtp-Source: ABdhPJx51To59G11sblolK+2OL5WDYWW6YA/trJymb1pNBWSAGefGthbmy2eet6sDyI2o3lYhP2gvQ== X-Received: by 2002:ac2:5231:0:b0:46b:93c5:e0a7 with SMTP id i17-20020ac25231000000b0046b93c5e0a7mr13313749lfl.441.1649828676510; Tue, 12 Apr 2022 22:44:36 -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 o23-20020ac24357000000b0044adb34b68csm3919835lfl.32.2022.04.12.22.44.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Apr 2022 22:44:35 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, op-tee@lists.trustedfirmware.org Cc: Sumit Garg , Jens Wiklander Subject: [PATCH v3 4/4] optee: cache argument shared memory structs Date: Wed, 13 Apr 2022 07:44:18 +0200 Message-Id: <20220413054418.71996-5-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20220413054418.71996-1-jens.wiklander@linaro.org> References: <20220413054418.71996-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