From nobody Sun May 10 19:14:25 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 4E51FC433EF for ; Tue, 26 Apr 2022 07:33:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344037AbiDZHgz (ORCPT ); Tue, 26 Apr 2022 03:36:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38490 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238229AbiDZHgv (ORCPT ); Tue, 26 Apr 2022 03:36:51 -0400 Received: from mail-lf1-x129.google.com (mail-lf1-x129.google.com [IPv6:2a00:1450:4864:20::129]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D43311331AF for ; Tue, 26 Apr 2022 00:33:44 -0700 (PDT) Received: by mail-lf1-x129.google.com with SMTP id j4so5857812lfh.8 for ; Tue, 26 Apr 2022 00:33:44 -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=wWqeoszwG81V7Cfq+HpRlPMkW7tnD6rpM3BEEetOC2ei+RyCz+ccC+yCWN+wD2AWRX pjaNFtvWPL8ZCQSBvTtr7mmsyV8mk4wSvyomfmtbE5PUYElZ+jfVVyJlTQADMMB6LNmd xe5iR0FpRsWHsiaG8Jnb7QhJC2nddq5AzB3ARL1HolFH8JtH4m+HFKllFsKCeCjk1e0e 7Oz6qIkKDJAzo8S/9uC/kvZwd2tkcx4Zucujp9CBvxmtEFfXm6Rxqg1FbqzJHRUQuF6Z KFdhlK4YeanpLUTWI1mm+qWgxN0SdkRBZmGObil/l5Tv+vYl+wBXCx0cRKOpR61S2RAB 625w== 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=H6FbB6hugASlKNF7mryGyg+CDXxwh4caVrBsFBW5LME+HBb3C93bNnCGwjAUI7SG/p B47jvVu96eL5ZuRFlEwBzonJPxrLz0MF570jZ9zw9kt5niEuh1A/qjT5KBJtIAGh4X8i adi4yI+r6B4AIiR6a/STJEfBtWNV5fD8CUto9zxWmcmlLZZuq/CMGiTYi2sim227AiP0 MMwF3xVsPsz44cmInARgZYzZ0Qs1Kb8/E+Kl0IreBYDVNEjD472QWYHKM6jFWD23Yq0p CI8wRZLHtWNjUfPF5Wks7CRXf/c8OEB3J2N4NlpULgylEpqCEBPyaALkki2AhnwRdpIu yigg== X-Gm-Message-State: AOAM531grrDBlxIAmQY4uY4JW/KzQwQWE324ePcD887KeK04+JBffwWY 3U9E3/ps9QTTyGBXoOBkz++7xbvzBmA2aA== X-Google-Smtp-Source: ABdhPJxo4B68tJERJrz5wzn553yH8TsOsLDYhLlCMLE+e7ixlID2L9QNinhzU18z0GfqT+VMM3z03A== X-Received: by 2002:a05:6512:3b81:b0:471:8f4f:51e6 with SMTP id g1-20020a0565123b8100b004718f4f51e6mr16612657lfv.374.1650958422827; Tue, 26 Apr 2022 00:33:42 -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 s11-20020a2e9c0b000000b0024ace83744asm1430491lji.116.2022.04.26.00.33.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Apr 2022 00:33:42 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, op-tee@lists.trustedfirmware.org Cc: Sumit Garg , Jens Wiklander Subject: [PATCH v4 1/4] optee: rename rpc_arg_count to rpc_param_count Date: Tue, 26 Apr 2022 09:33:35 +0200 Message-Id: <20220426073338.3048192-2-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20220426073338.3048192-1-jens.wiklander@linaro.org> References: <20220426073338.3048192-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 Sun May 10 19:14:25 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 5CB8DC433F5 for ; Tue, 26 Apr 2022 07:33:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344043AbiDZHg6 (ORCPT ); Tue, 26 Apr 2022 03:36:58 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38690 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241886AbiDZHgy (ORCPT ); Tue, 26 Apr 2022 03:36:54 -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 85D171331AE for ; Tue, 26 Apr 2022 00:33:46 -0700 (PDT) Received: by mail-lf1-x12e.google.com with SMTP id p12so24829170lfs.5 for ; Tue, 26 Apr 2022 00:33:46 -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=jEKNHR7vmiFBmVYSwNBsirQuJDGj7/RNVVXjEtRPHRkL0OJJZdNrDnyh6vYKO3II7/ ru2WdFscL/dR/zFUVzPrRMRM2ZdYKLYECBbr9fGDNnQ3NtklHsXcpfpeKwIQJy0BJQ3I G2U4NUGi1vQKUPnT+W+sw9tL0KfHX03HAGSNqUw0Lrpjxx/q9nsxS88Hmem3wYirJNSD gbY3YzlxHgn5+FLyS/ox1fGNbA2KbCFk1JgG2+6Nqp/FJ9yopH2Suq1ISV9m0BNZaJd8 uhAxFjKf0EpNyALCcSzzg4VA69M5m7OlPTPIlacNt6ehFeODvMA78h3UgjKt+91M5m5T Uwwg== 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=NkGqgdGqxELUku+9bOmdIdtZE+P8M6S5Bcmd1Inm6HD8+WWQojxzqBz/61/yWHQ+/2 jCOMThMLSxP9QbMMBlZ3RL88IqU03FBIfYrFQL/JKWN9quOQ/fjJBNMho5bM4OS/P+du YJBIDHaFVOXaUtSnEzR3Y24Deow1X2spzCXrvoVz9Gz45aWS25KU3E+/zdc/f1U6Yzem lXh+zT0UlmVXyC2L16i50GI4m9S1E25Un4He8IrBn/HfgWCrO86rNUixvJ8ZnXFd/7zO L59nxmh3r7oVxbrb0uwNwkpR4S4mVDEfCtdRfBPvUJvusOFbcvkjgkOz2SG+CXTNPdE3 L1mw== X-Gm-Message-State: AOAM5302Eql31hReE4nekewLMdCRa1GZuahqWRjvlGLb6/twhwuyUPdn M+l7aMBSlisnWz98Y9pm5ExyVOyiTrckVQ== X-Google-Smtp-Source: ABdhPJxKHYUhFVS4pT6TZXWousRtuRBSuvWzOv87TGIRMJdL9tYWakpiRulfCjILQjVzZ78saSsb7A== X-Received: by 2002:a05:6512:2009:b0:471:ffee:6ee1 with SMTP id a9-20020a056512200900b00471ffee6ee1mr8371713lfb.268.1650958424182; Tue, 26 Apr 2022 00:33:44 -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 s11-20020a2e9c0b000000b0024ace83744asm1430491lji.116.2022.04.26.00.33.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Apr 2022 00:33:43 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, op-tee@lists.trustedfirmware.org Cc: Sumit Garg , Jens Wiklander Subject: [PATCH v4 2/4] optee: add OPTEE_SMC_CALL_WITH_RPC_ARG and OPTEE_SMC_CALL_WITH_REGD_ARG Date: Tue, 26 Apr 2022 09:33:36 +0200 Message-Id: <20220426073338.3048192-3-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20220426073338.3048192-1-jens.wiklander@linaro.org> References: <20220426073338.3048192-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 Sun May 10 19:14:25 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 B81D5C433EF for ; Tue, 26 Apr 2022 07:33:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243734AbiDZHhA (ORCPT ); Tue, 26 Apr 2022 03:37:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38714 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243801AbiDZHgy (ORCPT ); Tue, 26 Apr 2022 03:36:54 -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 BE8A81331AD for ; Tue, 26 Apr 2022 00:33:47 -0700 (PDT) Received: by mail-lf1-x12e.google.com with SMTP id n14so9653946lfu.13 for ; Tue, 26 Apr 2022 00:33:47 -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=WP7sqDZ48rEv4cSxiRTawe+56Tc6xRmz/UeackTd98EFc1XhED+zkuowlnNnhyF4Yt e8346QfOghWfxKAsRZ88R+ruPw71rUOVqpEUe0iq44nTtX2CwgfpAPuEMvGp2cQqDCkT jx6W290Lrph+qu3d43vIPujkfVCeccWyI7do7aHK2l3XWWQNDVpQKjyYn7DKCdqG1Yth +PKC0AcwA9RzaZaB2gt1XeLaYwTOlpXvqTShi6ydjuAs1NoXQ+tY/WCWoPBK4pf+9K+M iNKVmnJhZ/C1DS0kYdNJj+11WvXAlX1eZETZ4cJIh4VUScczAYnST3BkGxkPP/v2IxYd /aMg== 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=iwmKWKIAJyXCnB9bZk0+0Nvh12oic4b3SLzpMjuBAaNoidiPacJ8o5qwla1HzDjUsR 4DtoS/8ij20dpSbJbnF0iT4rYcjYKSOuU39YgrN3Xb4UUUruDycklkOEvcuOSxW0CMSt WXdjhv/PTJadC1Dnmfdyv0dwW7qhJZsyUYL0+BH2CPkVHjYl8rwQzJcoeAlsKJ72HUEi szBNCLfku3kU4J09ebFd3QdOMOVG4ZO59AcE8Fvru+LbGDrKjbV1lpK6Zh+6PjP3M9z2 rhchLrehCemud52A2UBJqp89CRR7V0X2+puwJv191kKUzUhShxLFz+v6DGXHgxh7F8Xl VvcA== X-Gm-Message-State: AOAM533jbWSKZg0iotaWu0QemDJ1u9A9ifLb2TEbOdSeOMtkEoLExzBa Ki+8WkBDt/850LSbUPqqt9xLd9z95tkmPg== X-Google-Smtp-Source: ABdhPJxUi1qWTQu0+2nmb1rDZMm0oMG+mPhs1iILA/YVf9MpPFQfHjTiSkp33Cpo2lt00ZofPq8djA== X-Received: by 2002:a05:6512:260e:b0:44a:fa3e:f77b with SMTP id bt14-20020a056512260e00b0044afa3ef77bmr15334948lfb.175.1650958425635; Tue, 26 Apr 2022 00:33:45 -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 s11-20020a2e9c0b000000b0024ace83744asm1430491lji.116.2022.04.26.00.33.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Apr 2022 00:33:44 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, op-tee@lists.trustedfirmware.org Cc: Sumit Garg , Jens Wiklander Subject: [PATCH v4 3/4] optee: add FF-A capability OPTEE_FFA_SEC_CAP_ARG_OFFSET Date: Tue, 26 Apr 2022 09:33:37 +0200 Message-Id: <20220426073338.3048192-4-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20220426073338.3048192-1-jens.wiklander@linaro.org> References: <20220426073338.3048192-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 Sun May 10 19:14:25 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 468D1C433F5 for ; Tue, 26 Apr 2022 07:34:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344045AbiDZHhI (ORCPT ); Tue, 26 Apr 2022 03:37:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38744 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344041AbiDZHg5 (ORCPT ); Tue, 26 Apr 2022 03:36:57 -0400 Received: from mail-lf1-x136.google.com (mail-lf1-x136.google.com [IPv6:2a00:1450:4864:20::136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6BD7E1331AD for ; Tue, 26 Apr 2022 00:33:49 -0700 (PDT) Received: by mail-lf1-x136.google.com with SMTP id p10so30374519lfa.12 for ; Tue, 26 Apr 2022 00:33:49 -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=edAsroqs7TfihNqomWEkYK/z12d/TpdEcg83xIC3aK0=; b=cdxdpbp/ZC5mzISb/c69bA2k/c9O4ehCYca3RrgPB9VvJC3p3reH02VT/oqlPUE+zI 5n6P7uUdJqHzsDPB58eWWQ8lu4vZutT/HA+0C1bNsu4/f+9aQY1sj8DWRFfgZubqHUiA IoSpo0YdKOCjHaJzSfKT2LVPAST4SfUCch6Sin44Btli6ALc2Z0I7YMfLwlzI0F/3hLd cAl0+TyBz/Iaa+kb2nhJSULyw3zQpstdgmdo+fqpAJq8/4CjwIjlwp2DXfaFeDojKtPU vxVFN2uHkZ4XxdDT7TWzmQn3VgsadDm0gyQ1Rvhde2TabAVB/6t6krbhjITARTMlrDod Pglw== 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=edAsroqs7TfihNqomWEkYK/z12d/TpdEcg83xIC3aK0=; b=kL2yesDYCE7frLsJKF9RjEHdB0aTpFAoDtWKiBh7behShmPM10LGMzpxwDYeD8a9lJ xii/EJOzba2HDvIeA8DDQ3Eq+7YjZwDLWwlMQ9HuFlHjfhyl95mg8A7EPVSCCRYV4Tnx wINnl5EjBR1LgNXsOp6jnS+WQOpexMF+kFDfWl5wJP83T6Rw+g3SxiL11qB20Yzf26gS Z7fYZC/E+PRn61Ah5M/0pGpwreQI9/mLGg0XsitAxbXqWlZG04Sq+Iw46Rj8m6GUsjKA xA49AzON37fgcAc9rz4ZKacGuE+onnnV2nNNn1qFCC680g8ZJiQF2hAZbReRiOjZNPLB t/FQ== X-Gm-Message-State: AOAM5311R1n1UsE47atWsLmKJ1vXVh5Ptaj273Y30U+kIakRF2lSVvbP AFh5s4zqh63A9H1u5I+f0/Ecs0F/UWp4tQ== X-Google-Smtp-Source: ABdhPJxqzGIftcl/UZzKMiQQltr/x3zgi0VKrp13as7LhJs6dF89rcNXFvNsNdlmEUgzhjkTM9YsSA== X-Received: by 2002:a05:6512:33b9:b0:472:10b0:4c14 with SMTP id i25-20020a05651233b900b0047210b04c14mr3335027lfg.77.1650958427073; Tue, 26 Apr 2022 00:33:47 -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 s11-20020a2e9c0b000000b0024ace83744asm1430491lji.116.2022.04.26.00.33.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Apr 2022 00:33:46 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, op-tee@lists.trustedfirmware.org Cc: Sumit Garg , Jens Wiklander Subject: [PATCH v4 4/4] optee: cache argument shared memory structs Date: Tue, 26 Apr 2022 09:33:38 +0200 Message-Id: <20220426073338.3048192-5-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20220426073338.3048192-1-jens.wiklander@linaro.org> References: <20220426073338.3048192-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 | 108 +++++++++++--- 5 files changed, 318 insertions(+), 67 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..385cb0aee610 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 @@ -1327,6 +1364,7 @@ static int optee_probe(struct platform_device *pdev) struct tee_device *teedev; struct tee_context *ctx; u32 max_notif_value; + u32 arg_cache_flags; u32 sec_caps; int rc; =20 @@ -1356,14 +1394,48 @@ static int optee_probe(struct platform_device *pdev) /* * Try to use dynamic shared memory if possible */ - if (sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM) + if (sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM) { + /* + * If we have OPTEE_SMC_SEC_CAP_RPC_ARG we can ask + * optee_get_msg_arg() to pre-register (by having + * OPTEE_SHM_ARG_ALLOC_PRIV cleared) the page used to pass + * an argument struct. + * + * With the page is pre-registered we can use a non-zero + * offset for argument struct, this is indicated with + * OPTEE_SHM_ARG_SHARED. + * + * This means that optee_smc_do_call_with_arg() will use + * OPTEE_SMC_CALL_WITH_REGD_ARG for pre-registered pages. + */ + if (sec_caps & OPTEE_SMC_SEC_CAP_RPC_ARG) + arg_cache_flags =3D OPTEE_SHM_ARG_SHARED; + else + arg_cache_flags =3D OPTEE_SHM_ARG_ALLOC_PRIV; + pool =3D optee_shm_pool_alloc_pages(); + } =20 /* * If dynamic shared memory is not available or failed - try static one */ - if (IS_ERR(pool) && (sec_caps & OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM)) + if (IS_ERR(pool) && (sec_caps & OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM)) { + /* + * The static memory pool can use non-zero page offsets so + * let optee_get_msg_arg() know that with OPTEE_SHM_ARG_SHARED. + * + * optee_get_msg_arg() should not pre-register the + * allocated page used to pass an argument struct, this is + * indicated with OPTEE_SHM_ARG_ALLOC_PRIV. + * + * This means that optee_smc_do_call_with_arg() will use + * OPTEE_SMC_CALL_WITH_ARG if rpc_param_count is 0, else + * OPTEE_SMC_CALL_WITH_RPC_ARG. + */ + arg_cache_flags =3D OPTEE_SHM_ARG_SHARED | + OPTEE_SHM_ARG_ALLOC_PRIV; pool =3D optee_config_shm_memremap(invoke_fn, &memremaped_shm); + } =20 if (IS_ERR(pool)) return PTR_ERR(pool); @@ -1406,6 +1478,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 +1546,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