From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752347AbdI1SFj (ORCPT ); Thu, 28 Sep 2017 14:05:39 -0400 Received: from mail-he1eur01on0047.outbound.protection.outlook.com ([104.47.0.47]:63787 "EHLO EUR01-HE1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1750902AbdI1SFf (ORCPT ); Thu, 28 Sep 2017 14:05:35 -0400 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Volodymyr_Babchuk@epam.com; From: Volodymyr Babchuk To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, tee-dev@lists.linaro.org, Jens Wiklander Cc: Volodymyr Babchuk Subject: [PATCH v1 09/14] tee: optee: add registered buffers handling into RPC calls Date: Thu, 28 Sep 2017 21:04:06 +0300 Message-Id: <1506621851-6929-10-git-send-email-volodymyr_babchuk@epam.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1506621851-6929-1-git-send-email-volodymyr_babchuk@epam.com> References: <1506621851-6929-1-git-send-email-volodymyr_babchuk@epam.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [85.223.209.59] X-ClientProxiedBy: VI1P18901CA0016.EURP189.PROD.OUTLOOK.COM (2603:10a6:801::26) To AM4PR0301MB2129.eurprd03.prod.outlook.com (2603:10a6:200:4d::14) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 45c16986-9267-4f48-1f73-08d5069b826a X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(22001)(2017030254152)(2017052603199)(201703131423075)(201703031133081)(201702281549075);SRVR:AM4PR0301MB2129; X-Microsoft-Exchange-Diagnostics: 1;AM4PR0301MB2129;3:H0qCGTdBcxvP1DoPwdkRkAedj5ZXu3JN0wEtXdkhg8MaebreN37apMNr1NM3LPDMmypjFV6zJ6v6FcJ59savJTEhoCJ5ZB2Os0xP3B2jm+mTN4Dts6daxorGQGyEC4LbsXZrpba4NHKHEx0easLAN95KOJ8RUMbTWmG1Dk015IntS3ZkULZjinJ0yyLmDM5yPFI/eBMhhEUGG9gaGBuDFqtDNEx5QRZff8d421WLV/aE4sXLR58kdH8wapsmlY1+;25:HVIMyYx1h/iGXtGdHrGz3s8KGsXSFQhA87sllfGgPX7MFqgEgaBl30Z7Vc8QsPSLRv8Td0X1k2hDDc7smCapmXgShJxAZBbaqoOOvjopnzHOxQCzdnijIPDGipqbKGy3Y0T6RaU8cw5m07oMqtvjoTjH3b8pPG5K/dIR8m5TQnh5TTEQauAw7/DgtKEiRdd3/8BNyxCG5r9FUh5zS81VTWN7Pm0JiksnYmIfiwTjnuAJFT9Ah3NAc/zgiHwzGrAFgAL61/ZujnDchobrxPDSo5phhVAAFXgv+t5/tuWL4KLEJwYlOfqrV9twrztO+M7tT/IFkyIsSChM2aRUOfuWiQ==;31:w4Iou0MkxUC30gx2mfmcUDdWzdz3iA2/LgHjGZTT+P1cHhP10SPUxyY08G6gqxWUW2LM/+3GVX3ZVrdzY2bkVF0mgvOw/IHHJucy7D5FRIBcVrWRylHmbXRPvKX6BsCHkK0p69sWOZBBtxKFXRhc5xw3chfsm8NgsUuljfAEK3t6a2hCSOq6qS08eZs4Cy1HTVb4miab3r2mrAPkZw7iUjljQ3FoGotHg1cvds/fOjk= X-MS-TrafficTypeDiagnostic: AM4PR0301MB2129: X-Microsoft-Exchange-Diagnostics: 1;AM4PR0301MB2129;20:3JtTAM9EEd20NhS/+e3dPRuBRoCZdb4eeKWB1RIxsdk4Hrkc2k4Hbi8ICkdQYr6cFh2/jbdagw33fHt/k+UhL9Up8s8pPLDK0XeQ48IaMQUWyT1TckCOoo4CKR3E9swyNhlzHQIcG6PWq+RuNWNj7ocMFiBHojFazALKxX/nnAVjs779gK2s4KUpCmS2YApz2Gyr72laiWi0M/JpwRCnKNnd8xweLSN+Qy5VC+oQxps0G1oPR/ffqxCHQTj7pkGo+E0vUOsI/eFLmsYk+iVomAKd7tYxmORx1n2GsxFLFLh1Zalf1ruTDWA1Pxk/T2Pac0NFK/Q3me+VBmLvrHyS8dytn7jK8xeLrSuDeZjSv4Mgl5R5as+W83K+TmObYr0p1MIfS6Nir6BsddZS1QhzJ/TokSkpfVCGbtAB5FTmDHNav78YIKzBp6Za9eTxWF0C4MeDPgJ2EMQvDDk6Tr+r0IMqI0p7X0K2K0h34mdQCBwPul5XQ6N9j9UKhiz0e+cx;4:D22B09e1xtf73og+e2AgnOLS/sRC9KHexTs3fWuNCeNabn5zMBzlOBdh7EgsC3P9rNp2hAeViiSOnkoxpkQku3RMqzhuoxdjt1YLpfA2qie70S8xmz7HYOXa3WtOIXmLS5n1B1b11QMdWKnX2H97V9R/MQPdk/pwT32xQgnx+E6q51TAE1cJI2XfwWzjLUgx2lhgcF9JjcDWGqrtQEV9UDBJoz/lpJqgq69+ZixkOJikFliSVkBeve/5tSadLuLi X-Exchange-Antispam-Report-Test: UriScan:; X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6040450)(2401047)(5005006)(8121501046)(100000703101)(100105400095)(93006095)(93001095)(3002001)(10201501046)(6041248)(20161123564025)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123562025)(20161123560025)(20161123558100)(20161123555025)(6072148)(201708071742011)(100000704101)(100105200095)(100000705101)(100105500095);SRVR:AM4PR0301MB2129;BCL:0;PCL:0;RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095);SRVR:AM4PR0301MB2129; X-Forefront-PRVS: 0444EB1997 X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10009020)(6009001)(376002)(346002)(189002)(199003)(81156014)(53936002)(5660300001)(81166006)(97736004)(8676002)(8936002)(7736002)(4326008)(305945005)(72206003)(316002)(50986999)(76176999)(42186006)(80792005)(86362001)(16586007)(50466002)(101416001)(48376002)(2906002)(66066001)(478600001)(50226002)(2950100002)(6666003)(6916009)(36756003)(68736007)(6116002)(122856001)(47776003)(189998001)(106356001)(3846002)(105586002)(33646002)(39060400002)(5003940100001);DIR:OUT;SFP:1101;SCL:1;SRVR:AM4PR0301MB2129;H:EPUAKYIW2556.kyiv.epam.com;FPR:;SPF:None;PTR:InfoNoRecords;MX:1;A:1;LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;AM4PR0301MB2129;23:97sJCVJSfFZzI6OcP6KsXMHYSEPZ2Re6ryn84hH?= =?us-ascii?Q?jX1caMVqqKUZiZPRvJhbNLcO69vHgafhAam5MjrzWqorl502F35HnIfyBYSd?= =?us-ascii?Q?hjkn51JOt13LXIXNGGK5BxiUBdzfwosfMydm6a0JapGISkrxHtiLElGfIoJp?= =?us-ascii?Q?GGfVLqrktMIkwGu30KZr2NZYNWJwgKvN+nADGzzAocWptnhn14MtPjo9Y8za?= =?us-ascii?Q?hvJnPa3sINuqT9hh/n+JMRcoqZ6X/nN/FcvI5h+Nku0GuQofeni/AM2QcSrx?= =?us-ascii?Q?dpjIGOVkt6uB6lr+vKEbUoJtsd1NE2fOpcbIPJEaz6DAEgGtp3laE5bMk8Lt?= =?us-ascii?Q?xjQXAdTKg3/SFOeXjC8a+baoToH1eHurrpiQKJno4Tz63yujJ8F2I+043Vse?= =?us-ascii?Q?bu/3SmsXaZHwIVgBVlKBUHJ79RNn+dxrWDiymzvdkBOXxgwDdu1Ulli1KWko?= =?us-ascii?Q?S5iH1aHte7OFbZAJYnerCETLVQSf3j8DqAaKKqm0z4YKloVDT530MxLHcFCv?= =?us-ascii?Q?LQZcF/S+wjGldueKC3k3DVVphPsjZMl1rUW888pt9hAekkSA+3islP3QUTxx?= =?us-ascii?Q?TTo9Y5KAeQRqu7IYvZ4MtLKPPwquUcJz506IuEET7DOoWsC16Vr4CTj3XcI6?= =?us-ascii?Q?pGLD63NIzcJb1uAv9JOz2HxYHmCUoLjIy4j86Hc85WtwTfw6uF8hO4D926Tv?= =?us-ascii?Q?SPD6rz4DIyMhXToLtmRoWQUSXxyFhTfNKOrrzb6lkPmMYXnNUm3gCTVNhnfd?= =?us-ascii?Q?+mD+LdlzzIWQX4p7Geor5RsM//BeZl2hk9XNH5DWKUY4AeQNlcO71vgiuq+c?= =?us-ascii?Q?BZCENil5jMF5rXCkYDlaccUs5MRRyM6V3C4INIXxkX+ZUvSaGFBdz7McEwu4?= =?us-ascii?Q?4/njyKv6Se04SruAlzUTElmth+gEwv5VCQ8a+ZqSNAy6WQ4rR9UbSokrU25n?= =?us-ascii?Q?s896pUfG/C5dMeaCAg9r/M4gYhdVCQbfWwDZP8GYqqulAihonWS8rhyTjlQT?= =?us-ascii?Q?xsWSSRzyYuv0kVcOLDxEEYq3VeD1ZsKle3iEUtll28s3LojSriCK2OZOi1ng?= =?us-ascii?Q?9rNuYydNzvqIyVq+Zfppf0DVM85jA?= X-Microsoft-Exchange-Diagnostics: 1;AM4PR0301MB2129;6:J98UIUiAk65AuC1PnQrKzQ7TA3y74x/ShAJ3a97eT7voy9E42KChKfdhxT1UC9tNgV9ye7qn3jI6rEXMz/FwQqnqtdpBwIE9sI4yw8rUPSOEt5Pe7SR8fzbTHbvqxbV/bhSb4a2vz5JfiEYrgGj4mhv3KSZlTltizYkFwAMpAW9L7I9j4H+Qh8m35/FsMhxT1/8+2pd8IYAqMHqQ8NLVipb0at+rsKGFGe/20pp4AuJDjr/SGKgwFMIo6CtdS49oPSwNPe9ut/CBomX0cZhVpxzPgJaiMzpMd4lcOOMkzbd7ceoDzKGRjTjRjokx7RwEZuHCRwWcxxsPkkE5s3cJfw==;5:4kIT41Mv2aOcipnc/SyV87S2lJBszlO1xEJP5rR16UxxqVL01n4IAhk2ZRC14MACRtAQ0wIAYd3d8tebrKsLYWeTSXjOsG/9j/1ifG4rWRJxNmcscLhq3mvFlnpy/o95yLKmNaBrSooPwawnaoe3Iw==;24:VhcqM4zaRO9V6CRFzguYWDShrU5nMumJXHbolgN2EuPTKV05fp5hPUglDg6Wr38LPfXY3aLSBjvsryVbAZtY2OdsBS2x9uCPEwB9jGggF0U=;7:6Qn3Gp5g11ATXBSgqVFDNSuf6uUMYwwA7FzwueheRROgUvQ93LoopXP0BPbGstVbZB+SgQPE35iTmzLELIuYJwswDTZ/yfGLQN6fFK1XJr+pWXGXp9oGG4FdnJdlrD6rcyeYZQyZF6frmlPIfT4kRptT4nnAR4WWkjBIEbYTuBJmrRgYfmWgdYllgE0KkhdZGupoFbbDU+4Y/j/MB88V1U+fI55kEVFvt0CKGAMxb/c= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: epam.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 28 Sep 2017 18:05:31.6108 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: b41b72d0-4e9f-4c26-8a69-f949f367c91d X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM4PR0301MB2129 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Volodymyr Babchuk With latest changes to OP-TEE we can use any buffers as a shared memory. Thus, it is possible for supplicant to provide part of own memory when OP-TEE asks to allocate a shared buffer. This patch adds support for such feature into RPC handling code. Now when OP-TEE asks supplicant to allocate shared buffer, supplicant can use TEE_IOC_SHM_REGISTER to provide such buffer. RPC handler is aware of this, so it will pass list of allocated pages to OP-TEE. Signed-off-by: Volodymyr Babchuk --- drivers/tee/optee/call.c | 19 ++++++++++- drivers/tee/optee/core.c | 2 ++ drivers/tee/optee/optee_private.h | 15 +++++++- drivers/tee/optee/rpc.c | 72 ++++++++++++++++++++++++++++++++++----- 4 files changed, 97 insertions(+), 11 deletions(-) diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c index ec53dca..7702991 100644 --- a/drivers/tee/optee/call.c +++ b/drivers/tee/optee/call.c @@ -136,6 +136,7 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg) struct optee *optee = tee_get_drvdata(ctx->teedev); struct optee_call_waiter w; struct optee_rpc_param param = { }; + struct optee_call_ctx call_ctx = { }; u32 ret; param.a0 = OPTEE_SMC_CALL_WITH_ARG; @@ -160,13 +161,14 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg) param.a1 = res.a1; param.a2 = res.a2; param.a3 = res.a3; - optee_handle_rpc(ctx, ¶m); + optee_handle_rpc(ctx, ¶m, &call_ctx); } else { ret = res.a0; break; } } + optee_rpc_finalize_call(&call_ctx); /* * We're done with our thread in secure world, if there's any * thread waiters wake up one. @@ -554,3 +556,18 @@ int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm) tee_shm_free(shm_arg); return rc; } + +int optee_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm, + struct page **pages, size_t num_pages) +{ + /* + * We don't want to register supplicant memory in OP-TEE. + * Instead information about it will be passed in RPC code. + */ + return 0; +} + +int optee_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm) +{ + return 0; +} diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index a962f60..9883592 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -339,6 +339,8 @@ static const struct tee_driver_ops optee_supp_ops = { .release = optee_release, .supp_recv = optee_supp_recv, .supp_send = optee_supp_send, + .shm_register = optee_shm_register_supp, + .shm_unregister = optee_shm_unregister_supp, }; static const struct tee_desc optee_supp_desc = { diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h index 3ea7f7a..dfe1158 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -130,7 +130,16 @@ struct optee_rpc_param { u32 a7; }; -void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param); +/* Holds context that is preserved during one STD call */ +struct optee_call_ctx { + /* information about page array used in last allocation */ + void *pages_array; + size_t num_entries; +}; + +void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param, + struct optee_call_ctx *call_ctx); +void optee_rpc_finalize_call(struct optee_call_ctx *call_ctx); void optee_wait_queue_init(struct optee_wait_queue *wq); void optee_wait_queue_exit(struct optee_wait_queue *wq); @@ -164,6 +173,10 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm, struct page **pages, size_t num_pages); int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm); +int optee_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm, + struct page **pages, size_t num_pages); +int optee_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm); + int optee_from_msg_param(struct tee_param *params, size_t num_params, const struct optee_msg_param *msg_params); int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params, diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c index cef417f..1ff86bd 100644 --- a/drivers/tee/optee/rpc.c +++ b/drivers/tee/optee/rpc.c @@ -200,7 +200,8 @@ static struct tee_shm *cmd_alloc_suppl(struct tee_context *ctx, size_t sz) } static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx, - struct optee_msg_arg *arg) + struct optee_msg_arg *arg, + struct optee_call_ctx *call_ctx) { phys_addr_t pa; struct tee_shm *shm; @@ -245,10 +246,44 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx, goto bad; } - arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT; - arg->params[0].u.tmem.buf_ptr = pa; - arg->params[0].u.tmem.size = sz; - arg->params[0].u.tmem.shm_ref = (unsigned long)shm; + sz = tee_shm_get_size(shm); + + if (tee_shm_is_registered(shm)) { + struct page **pages; + u64 *pages_array; + size_t page_num; + + pages = tee_shm_get_pages(shm, &page_num); + if (!pages || !page_num) { + arg->ret = TEEC_ERROR_OUT_OF_MEMORY; + goto bad; + } + + pages_array = optee_allocate_pages_array(page_num); + if (!pages_array) { + arg->ret = TEEC_ERROR_OUT_OF_MEMORY; + goto bad; + } + + call_ctx->pages_array = pages_array; + call_ctx->num_entries = page_num; + + arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT | + OPTEE_MSG_ATTR_NONCONTIG; + arg->params[0].u.tmem.buf_ptr = virt_to_phys(pages_array) + + tee_shm_get_page_offset(shm); + + arg->params[0].u.tmem.size = tee_shm_get_size(shm); + arg->params[0].u.tmem.shm_ref = (unsigned long)shm; + + optee_fill_pages_list(pages_array, pages, page_num); + } else { + arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT; + arg->params[0].u.tmem.buf_ptr = pa; + arg->params[0].u.tmem.size = sz; + arg->params[0].u.tmem.shm_ref = (unsigned long)shm; + } + arg->ret = TEEC_SUCCESS; return; bad: @@ -307,8 +342,24 @@ static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx, arg->ret = TEEC_SUCCESS; } +static void free_page_array(struct optee_call_ctx *call_ctx) +{ + if (call_ctx->pages_array) { + optee_free_pages_array(call_ctx->pages_array, + call_ctx->num_entries); + call_ctx->pages_array = NULL; + call_ctx->num_entries = 0; + } +} + +void optee_rpc_finalize_call(struct optee_call_ctx *call_ctx) +{ + free_page_array(call_ctx); +} + static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee, - struct tee_shm *shm) + struct tee_shm *shm, + struct optee_call_ctx *call_ctx) { struct optee_msg_arg *arg; @@ -329,7 +380,8 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee, handle_rpc_func_cmd_wait(arg); break; case OPTEE_MSG_RPC_CMD_SHM_ALLOC: - handle_rpc_func_cmd_shm_alloc(ctx, arg); + free_page_array(call_ctx); + handle_rpc_func_cmd_shm_alloc(ctx, arg, call_ctx); break; case OPTEE_MSG_RPC_CMD_SHM_FREE: handle_rpc_func_cmd_shm_free(ctx, arg); @@ -343,10 +395,12 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee, * optee_handle_rpc() - handle RPC from secure world * @ctx: context doing the RPC * @param: value of registers for the RPC + * @call_ctx: call context. Preserved during one OP-TEE invocation * * Result of RPC is written back into @param. */ -void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param) +void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param, + struct optee_call_ctx *call_ctx) { struct tee_device *teedev = ctx->teedev; struct optee *optee = tee_get_drvdata(teedev); @@ -381,7 +435,7 @@ void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param) break; case OPTEE_SMC_RPC_FUNC_CMD: shm = reg_pair_to_ptr(param->a1, param->a2); - handle_rpc_func_cmd(ctx, optee, shm); + handle_rpc_func_cmd(ctx, optee, shm, call_ctx); break; default: pr_warn("Unknown RPC func 0x%x\n", -- 2.7.4 From mboxrd@z Thu Jan 1 00:00:00 1970 From: volodymyr_babchuk@epam.com (Volodymyr Babchuk) Date: Thu, 28 Sep 2017 21:04:06 +0300 Subject: [PATCH v1 09/14] tee: optee: add registered buffers handling into RPC calls In-Reply-To: <1506621851-6929-1-git-send-email-volodymyr_babchuk@epam.com> References: <1506621851-6929-1-git-send-email-volodymyr_babchuk@epam.com> Message-ID: <1506621851-6929-10-git-send-email-volodymyr_babchuk@epam.com> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org From: Volodymyr Babchuk With latest changes to OP-TEE we can use any buffers as a shared memory. Thus, it is possible for supplicant to provide part of own memory when OP-TEE asks to allocate a shared buffer. This patch adds support for such feature into RPC handling code. Now when OP-TEE asks supplicant to allocate shared buffer, supplicant can use TEE_IOC_SHM_REGISTER to provide such buffer. RPC handler is aware of this, so it will pass list of allocated pages to OP-TEE. Signed-off-by: Volodymyr Babchuk --- drivers/tee/optee/call.c | 19 ++++++++++- drivers/tee/optee/core.c | 2 ++ drivers/tee/optee/optee_private.h | 15 +++++++- drivers/tee/optee/rpc.c | 72 ++++++++++++++++++++++++++++++++++----- 4 files changed, 97 insertions(+), 11 deletions(-) diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c index ec53dca..7702991 100644 --- a/drivers/tee/optee/call.c +++ b/drivers/tee/optee/call.c @@ -136,6 +136,7 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg) struct optee *optee = tee_get_drvdata(ctx->teedev); struct optee_call_waiter w; struct optee_rpc_param param = { }; + struct optee_call_ctx call_ctx = { }; u32 ret; param.a0 = OPTEE_SMC_CALL_WITH_ARG; @@ -160,13 +161,14 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg) param.a1 = res.a1; param.a2 = res.a2; param.a3 = res.a3; - optee_handle_rpc(ctx, ¶m); + optee_handle_rpc(ctx, ¶m, &call_ctx); } else { ret = res.a0; break; } } + optee_rpc_finalize_call(&call_ctx); /* * We're done with our thread in secure world, if there's any * thread waiters wake up one. @@ -554,3 +556,18 @@ int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm) tee_shm_free(shm_arg); return rc; } + +int optee_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm, + struct page **pages, size_t num_pages) +{ + /* + * We don't want to register supplicant memory in OP-TEE. + * Instead information about it will be passed in RPC code. + */ + return 0; +} + +int optee_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm) +{ + return 0; +} diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index a962f60..9883592 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -339,6 +339,8 @@ static const struct tee_driver_ops optee_supp_ops = { .release = optee_release, .supp_recv = optee_supp_recv, .supp_send = optee_supp_send, + .shm_register = optee_shm_register_supp, + .shm_unregister = optee_shm_unregister_supp, }; static const struct tee_desc optee_supp_desc = { diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h index 3ea7f7a..dfe1158 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -130,7 +130,16 @@ struct optee_rpc_param { u32 a7; }; -void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param); +/* Holds context that is preserved during one STD call */ +struct optee_call_ctx { + /* information about page array used in last allocation */ + void *pages_array; + size_t num_entries; +}; + +void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param, + struct optee_call_ctx *call_ctx); +void optee_rpc_finalize_call(struct optee_call_ctx *call_ctx); void optee_wait_queue_init(struct optee_wait_queue *wq); void optee_wait_queue_exit(struct optee_wait_queue *wq); @@ -164,6 +173,10 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm, struct page **pages, size_t num_pages); int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm); +int optee_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm, + struct page **pages, size_t num_pages); +int optee_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm); + int optee_from_msg_param(struct tee_param *params, size_t num_params, const struct optee_msg_param *msg_params); int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params, diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c index cef417f..1ff86bd 100644 --- a/drivers/tee/optee/rpc.c +++ b/drivers/tee/optee/rpc.c @@ -200,7 +200,8 @@ static struct tee_shm *cmd_alloc_suppl(struct tee_context *ctx, size_t sz) } static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx, - struct optee_msg_arg *arg) + struct optee_msg_arg *arg, + struct optee_call_ctx *call_ctx) { phys_addr_t pa; struct tee_shm *shm; @@ -245,10 +246,44 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx, goto bad; } - arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT; - arg->params[0].u.tmem.buf_ptr = pa; - arg->params[0].u.tmem.size = sz; - arg->params[0].u.tmem.shm_ref = (unsigned long)shm; + sz = tee_shm_get_size(shm); + + if (tee_shm_is_registered(shm)) { + struct page **pages; + u64 *pages_array; + size_t page_num; + + pages = tee_shm_get_pages(shm, &page_num); + if (!pages || !page_num) { + arg->ret = TEEC_ERROR_OUT_OF_MEMORY; + goto bad; + } + + pages_array = optee_allocate_pages_array(page_num); + if (!pages_array) { + arg->ret = TEEC_ERROR_OUT_OF_MEMORY; + goto bad; + } + + call_ctx->pages_array = pages_array; + call_ctx->num_entries = page_num; + + arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT | + OPTEE_MSG_ATTR_NONCONTIG; + arg->params[0].u.tmem.buf_ptr = virt_to_phys(pages_array) + + tee_shm_get_page_offset(shm); + + arg->params[0].u.tmem.size = tee_shm_get_size(shm); + arg->params[0].u.tmem.shm_ref = (unsigned long)shm; + + optee_fill_pages_list(pages_array, pages, page_num); + } else { + arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT; + arg->params[0].u.tmem.buf_ptr = pa; + arg->params[0].u.tmem.size = sz; + arg->params[0].u.tmem.shm_ref = (unsigned long)shm; + } + arg->ret = TEEC_SUCCESS; return; bad: @@ -307,8 +342,24 @@ static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx, arg->ret = TEEC_SUCCESS; } +static void free_page_array(struct optee_call_ctx *call_ctx) +{ + if (call_ctx->pages_array) { + optee_free_pages_array(call_ctx->pages_array, + call_ctx->num_entries); + call_ctx->pages_array = NULL; + call_ctx->num_entries = 0; + } +} + +void optee_rpc_finalize_call(struct optee_call_ctx *call_ctx) +{ + free_page_array(call_ctx); +} + static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee, - struct tee_shm *shm) + struct tee_shm *shm, + struct optee_call_ctx *call_ctx) { struct optee_msg_arg *arg; @@ -329,7 +380,8 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee, handle_rpc_func_cmd_wait(arg); break; case OPTEE_MSG_RPC_CMD_SHM_ALLOC: - handle_rpc_func_cmd_shm_alloc(ctx, arg); + free_page_array(call_ctx); + handle_rpc_func_cmd_shm_alloc(ctx, arg, call_ctx); break; case OPTEE_MSG_RPC_CMD_SHM_FREE: handle_rpc_func_cmd_shm_free(ctx, arg); @@ -343,10 +395,12 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee, * optee_handle_rpc() - handle RPC from secure world * @ctx: context doing the RPC * @param: value of registers for the RPC + * @call_ctx: call context. Preserved during one OP-TEE invocation * * Result of RPC is written back into @param. */ -void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param) +void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param, + struct optee_call_ctx *call_ctx) { struct tee_device *teedev = ctx->teedev; struct optee *optee = tee_get_drvdata(teedev); @@ -381,7 +435,7 @@ void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param) break; case OPTEE_SMC_RPC_FUNC_CMD: shm = reg_pair_to_ptr(param->a1, param->a2); - handle_rpc_func_cmd(ctx, optee, shm); + handle_rpc_func_cmd(ctx, optee, shm, call_ctx); break; default: pr_warn("Unknown RPC func 0x%x\n", -- 2.7.4