From patchwork Thu Mar 25 15:44:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Wiklander X-Patchwork-Id: 12164467 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2224CC433C1 for ; Thu, 25 Mar 2021 15:46:19 +0000 (UTC) Received: from desiato.infradead.org (desiato.infradead.org [90.155.92.199]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id BB015619A3 for ; Thu, 25 Mar 2021 15:46:18 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org BB015619A3 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=desiato.20200630; h=Sender:Content-Transfer-Encoding :Content-Type:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=ZY2+99RVVGCbC9PiLB6tKJ3GDqQb0OIiXfSfTHovqZQ=; b=nsdHh8VbaHS5142rbCQwMlXk1 pXBK0YP3aE6zXXfe7rALbz6PZyNg43zUM058p002YqRjK96v4dAu6DWCNlD5Eq9EsYijjWu4Ge9Dr jCJJq4V4FGPtg87erBgTxvug9OwBOlrpAF1U0UQYhmHqcBlL4vvejNFKwZhSyQg+gDqwYXX9mmzQ1 pp8NCYjLoR7xQqeAE+5Q/wTAhAM5dz+XSopreYJhSHkZKp9M9ismQXmibDL1MVlQB3M9CqgXSv+1B KbBon6SdmtaqtEg0KpWOdywlGB+BZv9636xmVwhppnwqmfqHkkQRKT+CGmGYZEtFsumFmvP4uFYG1 wydwSaWYQ==; Received: from localhost ([::1] helo=desiato.infradead.org) by desiato.infradead.org with esmtp (Exim 4.94 #2 (Red Hat Linux)) id 1lPSAD-001kSz-MI; Thu, 25 Mar 2021 15:44:49 +0000 Received: from mail-lf1-x12f.google.com ([2a00:1450:4864:20::12f]) by desiato.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1lPSA2-001kQb-Cz for linux-arm-kernel@lists.infradead.org; Thu, 25 Mar 2021 15:44:40 +0000 Received: by mail-lf1-x12f.google.com with SMTP id o126so3261436lfa.0 for ; Thu, 25 Mar 2021 08: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=kv02eM8NeYnnByA8FlayEK6mh+4PxaRpmwdYdtGmEa4=; b=Rra31NRtKhL6xfXOQ6S73tmdqvH5K1e1EqVUNVIcwOwViaQOStlau4wLxjKsDMsBX/ QjHYpdH8Tm1C8J2wnjlxXSPkqA9nbDdn/RlNW2wp+E/reQ8Gng+d0Ha2c+A+6Ubo29x2 TiEvrFLMn/+tFiuC7V0nXeTPBEyo5ExYy8kpIe2IUTnRMl4RvfpevTUEbRb6j3c3dP3o xJdqgmJgdPjSuESbLtUgjV+/lY2OVvv9pMhOr2WfLa1UGiuacOEZ5OyrauLyfV/qQuRw JoxJO0JmpVbYQolECFsONwJhV4EsWJpkla/5fR2KcVY/PakdSUhmpzfPpbAOMqt/9Z3R VFZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=kv02eM8NeYnnByA8FlayEK6mh+4PxaRpmwdYdtGmEa4=; b=JF2loQ7QljC2vCgzlYu8TATv/JYg3NOPkV3wZ7Iomolzt/k8jo4XP3dsAHOmddGJ4d p5hrJ/BpKfNu37O3VDW3bp8gzhnoPFNkE/PtKivP3auDH3u1qr6VJNljx6lLjfxytzhe KjKO0v6m35ifdwfDRZ+eK9dE4LeolnkDH8fox3aGcFmUVQlb/fnBV4bLqiQ0b8fgnIqX RFfQB6cgu1cF8/eUG04eu/8V9jOr+RV8NR2EbYPo6Xck57h8huawfxYoDmzf9EYsp3Bp YWvumlbk33JD/pubV/rMz8umE9EZBe6IeO7yE3G/3tXV8L9mviUq2v8CPddkFhIyfV59 A/YQ== X-Gm-Message-State: AOAM532ViF22d7kCLpqBrPzohjtpxi2jh7mMaDOth74lsvWZJ4WF3Oh8 agCRcuoqv6Z45ONTblOm+5CkjA== X-Google-Smtp-Source: ABdhPJwUy0zuNgDLX4J8OZDlAy36S/+zA2k8VHCJcf2rekhc7vYkWdHy/GDxi1sxe4lh4+vaWy596g== X-Received: by 2002:a19:f501:: with SMTP id j1mr5641541lfb.231.1616687076286; Thu, 25 Mar 2021 08:44:36 -0700 (PDT) Received: from jade.urgonet (h-249-223.A175.priv.bahnhof.se. [98.128.249.223]) by smtp.gmail.com with ESMTPSA id m27sm770916ljc.109.2021.03.25.08.44.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Mar 2021 08:44:35 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, op-tee@lists.trustedfirmware.org Cc: Sudeep Holla , Marc Bonnici , Jerome Forissier , Jens Wiklander Subject: [PATCH 1/6] tee: add sec_world_id to struct tee_shm Date: Thu, 25 Mar 2021 16:44:21 +0100 Message-Id: <20210325154426.3520148-2-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210325154426.3520148-1-jens.wiklander@linaro.org> References: <20210325154426.3520148-1-jens.wiklander@linaro.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210325_154438_520241_8069AC13 X-CRM114-Status: GOOD ( 13.62 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Adds sec_world_id to struct tee_shm which describes a shared memory object. sec_world_id can be used by a driver to store an id assigned by secure world. Signed-off-by: Jens Wiklander --- include/linux/tee_drv.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index cdd049a724b1..93d836fded8b 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -196,7 +196,11 @@ int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method, * @num_pages: number of locked pages * @dmabuf: dmabuf used to for exporting to user space * @flags: defined by TEE_SHM_* in tee_drv.h - * @id: unique id of a shared memory object on this device + * @id: unique id of a shared memory object on this device, shared + * with user space + * @sec_world_id: + * secure world assigned id of this shared memory object, not + * used by all drivers * * This pool is only supposed to be accessed directly from the TEE * subsystem and from drivers that implements their own shm pool manager. @@ -212,6 +216,7 @@ struct tee_shm { struct dma_buf *dmabuf; u32 flags; int id; + u64 sec_world_id; }; /** From patchwork Thu Mar 25 15:44:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Wiklander X-Patchwork-Id: 12164471 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DD948C433C1 for ; Thu, 25 Mar 2021 15:46:32 +0000 (UTC) Received: from desiato.infradead.org (desiato.infradead.org [90.155.92.199]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 56A2C619EE for ; Thu, 25 Mar 2021 15:46:32 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 56A2C619EE Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=desiato.20200630; h=Sender:Content-Transfer-Encoding :Content-Type:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=RZoAvJ03CGR91z9vSddIRJX2tmLk89pi9CAqhLdzO5k=; b=Ez9Fu5ExL7BfkbaiihqQeYr6B wS9Mvjc1S0WCwH+o/Q8fPKeNUarWj1yZPVGCH8gGZ3Z9sEArNv0yPcBUkE3ob0+zvqOehALDu1DR1 XjNFPqnKR7nVWuB/Zh6g1YAGPtsG6Pz7dCURbqXuetfRAFeM96cpZXOIz9Gngbl4I4vSYwWm7p3Zq JDeyw3XiP6ZoOCAiclbniPLKY4spV7eA1h1IIb4Fl9u/I7Yjiq/bl8zs30XW103VV000lFkhok2a5 TSwmt3u3z3SKH56LRK/6kjHcK+uostrkan8zBCwvYLE0DM14zXVIClqzoRoLN1pdCAuHdw2ZJ6ix/ IwZ1Z9rRQ==; Received: from localhost ([::1] helo=desiato.infradead.org) by desiato.infradead.org with esmtp (Exim 4.94 #2 (Red Hat Linux)) id 1lPSAR-001kUc-F9; Thu, 25 Mar 2021 15:45:04 +0000 Received: from mail-lf1-x12a.google.com ([2a00:1450:4864:20::12a]) by desiato.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1lPSA5-001kQa-C9 for linux-arm-kernel@lists.infradead.org; Thu, 25 Mar 2021 15:44:43 +0000 Received: by mail-lf1-x12a.google.com with SMTP id b14so3184998lfv.8 for ; Thu, 25 Mar 2021 08: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=xCv397QUGgHoDE+Q2AV20/g8OqLkWLBfz3K3eMlY0VM=; b=XhAfOdZ8NHxWB287FSrtdPh/m9sUMQl7FX2x5uuSaMnzyWV/XNzj6cjZRrdX3yz0E7 26az/uO2fO7fgBdQ90VXdBhM4Zoh1CDvgzO/kEP5lTrhD712tmqPSReMd54G7vMOzDkk ZBtqGk8T2Ru3qPkZ9q/SRtECA8gPjhoNwObVFvYdioJjypdFNKn3clZ5XWwD+rbW0Hon DfU8WvLsfIospBrM/cl4TQA6sKUC/WYym0RIoEV3p1XVolV/L3D9pOah3FXnP/9OOdrO qmMNAVhuaVZoFhZui01fbNvrQjt6FiCgv3RChYOucXcYx20I48HwhSCXhImR/k5baI7s f4QA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=xCv397QUGgHoDE+Q2AV20/g8OqLkWLBfz3K3eMlY0VM=; b=dyLoGYHqYWiDhb/Q9t0vd5E0DmMQCh17ZxmlZbjtTCuFcT6TzTCKYPUlqGq28x9Vs1 esyIcuFcY0I0+MU1zJixeVOPxwTCj2JVFZ8krkP1jZXRXIG3XwPQTcOkHlrD0HVxF/CG arY1RPAdtWCcYN8BIpa/Xudul44pDf1rnYzLD8IRcZTcAb4F9LB0ML4UfNEWSDiDD/6f GBkX6XHtKj0itI6VXQfVZv5uIHSHRwMmj4ISXE2xVlzz/yk2fF+if3Z2mO5lpwN45Gdu f6i0dtM8IFola4NREv7o/V4eiMdLysim3NgHMsdCvpcF5UQZ9W0S1uscB10bhv8y7htY M95w== X-Gm-Message-State: AOAM533weu3elEwrfFyOCQrRmtPYqZCEymwNZ5KgtaFR9lkxEFNaYAjX 2UjPvU/+CIbIfjft+2/Ss7lTGg== X-Google-Smtp-Source: ABdhPJzyMpGMD7Wh2ePkDNY2Et2kYSedwMSEb2MVhczxmjf9lx2FmB8OAxAzKD0bQgbK/IbDPeNH1A== X-Received: by 2002:ac2:5a49:: with SMTP id r9mr5314036lfn.23.1616687077180; Thu, 25 Mar 2021 08:44:37 -0700 (PDT) Received: from jade.urgonet (h-249-223.A175.priv.bahnhof.se. [98.128.249.223]) by smtp.gmail.com with ESMTPSA id m27sm770916ljc.109.2021.03.25.08.44.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Mar 2021 08:44:36 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, op-tee@lists.trustedfirmware.org Cc: Sudeep Holla , Marc Bonnici , Jerome Forissier , Jens Wiklander Subject: [PATCH 2/6] optee: simplify optee_release() Date: Thu, 25 Mar 2021 16:44:22 +0100 Message-Id: <20210325154426.3520148-3-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210325154426.3520148-1-jens.wiklander@linaro.org> References: <20210325154426.3520148-1-jens.wiklander@linaro.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210325_154441_552140_A0115749 X-CRM114-Status: GOOD ( 18.78 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Simplifies optee_release() with a new helper function, optee_close_session_helper() which has been factored out from optee_close_session(). A separate optee_release_supp() is added for the supplicant device. Signed-off-by: Jens Wiklander --- drivers/tee/optee/call.c | 31 ++++++++++------- drivers/tee/optee/core.c | 55 +++++++++++-------------------- drivers/tee/optee/optee_private.h | 1 + 3 files changed, 39 insertions(+), 48 deletions(-) diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c index 780d7c4fd756..c0eca4d7d7f2 100644 --- a/drivers/tee/optee/call.c +++ b/drivers/tee/optee/call.c @@ -283,12 +283,28 @@ int optee_open_session(struct tee_context *ctx, return rc; } -int optee_close_session(struct tee_context *ctx, u32 session) +int optee_close_session_helper(struct tee_context *ctx, u32 session) { - struct optee_context_data *ctxdata = ctx->data; struct tee_shm *shm; struct optee_msg_arg *msg_arg; phys_addr_t msg_parg; + + shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg); + if (IS_ERR(shm)) + return PTR_ERR(shm); + + msg_arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION; + msg_arg->session = session; + optee_do_call_with_arg(ctx, msg_parg); + + tee_shm_free(shm); + + return 0; +} + +int optee_close_session(struct tee_context *ctx, u32 session) +{ + struct optee_context_data *ctxdata = ctx->data; struct optee_session *sess; /* Check that the session is valid and remove it from the list */ @@ -301,16 +317,7 @@ int optee_close_session(struct tee_context *ctx, u32 session) return -EINVAL; kfree(sess); - shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg); - if (IS_ERR(shm)) - return PTR_ERR(shm); - - msg_arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION; - msg_arg->session = session; - optee_do_call_with_arg(ctx, msg_parg); - - tee_shm_free(shm); - return 0; + return optee_close_session_helper(ctx, session); } int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg, diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index cf4718c6d35d..0ffe0c7d68ff 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -273,59 +273,42 @@ static int optee_open(struct tee_context *ctx) return 0; } -static void optee_release(struct tee_context *ctx) +static void optee_release_helper(struct tee_context *ctx, + int (*close_session)(struct tee_context *ctx, + u32 session)) { struct optee_context_data *ctxdata = ctx->data; - struct tee_device *teedev = ctx->teedev; - struct optee *optee = tee_get_drvdata(teedev); - struct tee_shm *shm; - struct optee_msg_arg *arg = NULL; - phys_addr_t parg; struct optee_session *sess; struct optee_session *sess_tmp; if (!ctxdata) return; - shm = tee_shm_alloc(ctx, sizeof(struct optee_msg_arg), TEE_SHM_MAPPED); - if (!IS_ERR(shm)) { - arg = tee_shm_get_va(shm, 0); - /* - * If va2pa fails for some reason, we can't call into - * secure world, only free the memory. Secure OS will leak - * sessions and finally refuse more sessions, but we will - * at least let normal world reclaim its memory. - */ - if (!IS_ERR(arg)) - if (tee_shm_va2pa(shm, arg, &parg)) - arg = NULL; /* prevent usage of parg below */ - } - list_for_each_entry_safe(sess, sess_tmp, &ctxdata->sess_list, list_node) { list_del(&sess->list_node); - if (!IS_ERR_OR_NULL(arg)) { - memset(arg, 0, sizeof(*arg)); - arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION; - arg->session = sess->session_id; - optee_do_call_with_arg(ctx, parg); - } + close_session(ctx, sess->session_id); kfree(sess); } kfree(ctxdata); + ctx->data = NULL; +} - if (!IS_ERR(shm)) - tee_shm_free(shm); +static void optee_release(struct tee_context *ctx) +{ + optee_release_helper(ctx, optee_close_session_helper); +} - ctx->data = NULL; +static void optee_release_supp(struct tee_context *ctx) +{ + struct optee *optee = tee_get_drvdata(ctx->teedev); - if (teedev == optee->supp_teedev) { - if (optee->scan_bus_wq) { - destroy_workqueue(optee->scan_bus_wq); - optee->scan_bus_wq = NULL; - } - optee_supp_release(&optee->supp); + optee_release_helper(ctx, optee_close_session_helper); + if (optee->scan_bus_wq) { + destroy_workqueue(optee->scan_bus_wq); + optee->scan_bus_wq = NULL; } + optee_supp_release(&optee->supp); } static const struct tee_driver_ops optee_ops = { @@ -349,7 +332,7 @@ static const struct tee_desc optee_desc = { static const struct tee_driver_ops optee_supp_ops = { .get_version = optee_get_version, .open = optee_open, - .release = optee_release, + .release = optee_release_supp, .supp_recv = optee_supp_recv, .supp_send = optee_supp_send, .shm_register = optee_shm_register_supp, diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h index e25b216a14ef..2b63b796645e 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -152,6 +152,7 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg); int optee_open_session(struct tee_context *ctx, struct tee_ioctl_open_session_arg *arg, struct tee_param *param); +int optee_close_session_helper(struct tee_context *ctx, u32 session); int optee_close_session(struct tee_context *ctx, u32 session); int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg, struct tee_param *param); From patchwork Thu Mar 25 15:44:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Wiklander X-Patchwork-Id: 12164469 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 05E66C433C1 for ; Thu, 25 Mar 2021 15:46:26 +0000 (UTC) Received: from desiato.infradead.org (desiato.infradead.org [90.155.92.199]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 6691F619A3 for ; Thu, 25 Mar 2021 15:46:25 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6691F619A3 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=desiato.20200630; h=Sender:Content-Transfer-Encoding :Content-Type:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=jY71MAz7ck9QffC89XBvOi4Z7ljmm4GeXenYT08Fshk=; b=LFr8WnuSRN5SuWWh+5n4ozmNW wNXffSEqcAVIbzB/kpL9VSsNC7bl9Jq4MwdCV2ftIBxDNkVpd2DZ3H/mCC3bcbVQwv+TIf+U2xKRB ROeWUAWCtF3X6y980hFOfrlqlNUEynfRxxzlabverkR+mkqHcjITQ8zY4+w6Kv+R7BxJB93egpGi6 1LZcvL/Ibci3inSMlQFDYikwbXdhXvI4384L+UuxiMoBq+RB1k2uv94Nt3pJwoQdcORZHszDeqN7d EChcuEcQt30DiSOQ+NGMGXuNRrbLaA5NMHrkyGuELt3OTnDHcdzyEvuTvuq2S40bdmNAhZIC6tAqQ mHDDWZtYA==; Received: from localhost ([::1] helo=desiato.infradead.org) by desiato.infradead.org with esmtp (Exim 4.94 #2 (Red Hat Linux)) id 1lPSAK-001kTV-DQ; Thu, 25 Mar 2021 15:44:56 +0000 Received: from mail-lf1-x12f.google.com ([2a00:1450:4864:20::12f]) by desiato.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1lPSA2-001kQq-Sg for linux-arm-kernel@lists.infradead.org; Thu, 25 Mar 2021 15:44:41 +0000 Received: by mail-lf1-x12f.google.com with SMTP id 75so3217699lfa.2 for ; Thu, 25 Mar 2021 08: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=HKGQkmjYFlp1QKgdqI/K0D1B4H5SAHhvTMGmrzdGD40=; b=odAnMeVznKNHQWAAoHdEMx4TLwC48WB5rn4nnCuGjpxWkXmCZMZkTrBjgEAUZe0RL1 5pskbyX0GolshiXUAqvS5loh3pLVdj4q4J7BkirF29HmTR2k5myM0tX6w5FrMTDJFsXl 2ABhP1UgKrDjCoRZBswTObg0EoY9c4w5t/W7AYdB3Oq8S++zkUJskdTcd48LH40faGMU OwC87F2oRAhBEq7Jnxs4dIiCkrUucP0yr6+9qMt/BkFflykvjQyMjTDLgHzwz2rjjrJa Izt1rVewukPs+0d15HMxViDUTaREnXhL8MP14dnH9G167G1iGhRhAj3xBfc0khpDxAQA HpoA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=HKGQkmjYFlp1QKgdqI/K0D1B4H5SAHhvTMGmrzdGD40=; b=ascQAkEcZiV4rchNEPsCgL56kBYnKJsrTzWg69PXI3PpCH8ssWOU9HIu/UlniG6nda sworBWlf+WczmER9m0aWHPw4FbEdNp+OhjtWN/EWGNQzF/sJGdiSxi6yPOiJ3lr+a5Jw DemENPDH0kSv7BM6hRwv9At7IySZdqIqRovicWiGI26Hqo/3CxEg6sddYpXr3CYRxRiE 7f/dvETaUKqMmZcMUZOyZhQKcPiTBEJ7UuiP2ke6yh0Le9rogAYczRJxdywYNjXIUSRM mVB85nhI2Efbc0xBbAaNyx8ZDu7cFqWt4kmScKfozF1VSBXeW31JdVYAqWjQrxnGZ94H m7gA== X-Gm-Message-State: AOAM5320Oj3Z4nkeTwEF94m31GhVbwFp+0iUgNlZrHlBp7kWkfYAmo77 w46Xq5Cpp0UyAhWJoZxLHEV2Fg== X-Google-Smtp-Source: ABdhPJxZELUvnYkrpeY8xplfbhpqLmucVpbFdaW5R3w9CH3IgJZfORDODjRSg6Mjh3CQSdQcVuC1zg== X-Received: by 2002:a05:6512:3d1b:: with SMTP id d27mr5262363lfv.248.1616687078154; Thu, 25 Mar 2021 08:44:38 -0700 (PDT) Received: from jade.urgonet (h-249-223.A175.priv.bahnhof.se. [98.128.249.223]) by smtp.gmail.com with ESMTPSA id m27sm770916ljc.109.2021.03.25.08.44.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Mar 2021 08:44:37 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, op-tee@lists.trustedfirmware.org Cc: Sudeep Holla , Marc Bonnici , Jerome Forissier , Jens Wiklander Subject: [PATCH 3/6] optee: sync optee_msg.h and optee_rpc_cmd.h Date: Thu, 25 Mar 2021 16:44:23 +0100 Message-Id: <20210325154426.3520148-4-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210325154426.3520148-1-jens.wiklander@linaro.org> References: <20210325154426.3520148-1-jens.wiklander@linaro.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210325_154439_074514_2CDE18FF X-CRM114-Status: GOOD ( 35.61 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Updates to latest optee_msg.h and optee_rpc_cmd.h. There's no changes in the ABI. Only some clarifications and a complete specification of RPC requests where the latter is now in a separate file, optee_rpc_cmd.h. Most of the RPC requests are not served by the OP-TEE driver instead they are forwarded as opaque requests to tee-supplicant. Signed-off-by: Jens Wiklander --- drivers/tee/optee/optee_msg.h | 143 +------------ drivers/tee/optee/optee_rpc_cmd.h | 333 ++++++++++++++++++++++++++++++ drivers/tee/optee/rpc.c | 32 +-- 3 files changed, 360 insertions(+), 148 deletions(-) create mode 100644 drivers/tee/optee/optee_rpc_cmd.h diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h index 7b2d919da2ac..de96882f7b9b 100644 --- a/drivers/tee/optee/optee_msg.h +++ b/drivers/tee/optee/optee_msg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */ /* - * Copyright (c) 2015-2019, Linaro Limited + * Copyright (c) 2015-2021, Linaro Limited */ #ifndef _OPTEE_MSG_H #define _OPTEE_MSG_H @@ -11,12 +11,6 @@ /* * This file defines the OP-TEE message protocol used to communicate * with an instance of OP-TEE running in secure world. - * - * This file is divided into three sections. - * 1. Formatting of messages. - * 2. Requests from normal world - * 3. Requests from secure world, Remote Procedure Call (RPC), handled by - * tee-supplicant. */ /***************************************************************************** @@ -54,14 +48,14 @@ * Every entry in buffer should point to a 4k page beginning (12 least * significant bits must be equal to zero). * - * 12 least significant bints of optee_msg_param.u.tmem.buf_ptr should hold page - * offset of the user buffer. + * 12 least significant bits of optee_msg_param.u.tmem.buf_ptr should hold + * page offset of user buffer. * * So, entries should be placed like members of this structure: * * struct page_data { - * uint64_t pages_array[OPTEE_MSG_NONCONTIG_PAGE_SIZE/sizeof(uint64_t) - 1]; - * uint64_t next_page_data; + * u64 pages_array[OPTEE_MSG_NONCONTIG_PAGE_SIZE/sizeof(u64) - 1]; + * u64 next_page_data; * }; * * Structure is designed to exactly fit into the page size @@ -150,7 +144,7 @@ struct optee_msg_param_value { * @attr & OPTEE_MSG_ATTR_TYPE_MASK indicates if tmem, rmem or value is used in * the union. OPTEE_MSG_ATTR_TYPE_VALUE_* indicates value, * OPTEE_MSG_ATTR_TYPE_TMEM_* indicates @tmem and - * OPTEE_MSG_ATTR_TYPE_RMEM_* indicates @rmem, + * OPTEE_MSG_ATTR_TYPE_RMEM_* indicates @rmem. * OPTEE_MSG_ATTR_TYPE_NONE indicates that none of the members are used. */ struct optee_msg_param { @@ -176,17 +170,9 @@ struct optee_msg_param { * @params: the parameters supplied to the OS Command * * All normal calls to Trusted OS uses this struct. If cmd requires further - * information than what these field holds it can be passed as a parameter + * information than what these fields hold it can be passed as a parameter * tagged as meta (setting the OPTEE_MSG_ATTR_META bit in corresponding - * attrs field). All parameters tagged as meta has to come first. - * - * Temp memref parameters can be fragmented if supported by the Trusted OS - * (when optee_smc.h is bearer of this protocol this is indicated with - * OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM). If a logical memref parameter is - * fragmented then has all but the last fragment the - * OPTEE_MSG_ATTR_FRAGMENT bit set in attrs. Even if a memref is fragmented - * it will still be presented as a single logical memref to the Trusted - * Application. + * attrs field). All parameters tagged as meta have to come first. */ struct optee_msg_arg { u32 cmd; @@ -199,7 +185,7 @@ struct optee_msg_arg { u32 num_params; /* num_params tells the actual number of element in params */ - struct optee_msg_param params[0]; + struct optee_msg_param params[]; }; /** @@ -290,13 +276,10 @@ struct optee_msg_arg { * OPTEE_MSG_CMD_REGISTER_SHM registers a shared memory reference. The * information is passed as: * [in] param[0].attr OPTEE_MSG_ATTR_TYPE_TMEM_INPUT - * [| OPTEE_MSG_ATTR_FRAGMENT] + * [| OPTEE_MSG_ATTR_NONCONTIG] * [in] param[0].u.tmem.buf_ptr physical address (of first fragment) * [in] param[0].u.tmem.size size (of first fragment) * [in] param[0].u.tmem.shm_ref holds shared memory reference - * ... - * The shared memory can optionally be fragmented, temp memrefs can follow - * each other with all but the last with the OPTEE_MSG_ATTR_FRAGMENT bit set. * * OPTEE_MSG_CMD_UNREGISTER_SHM unregisteres a previously registered shared * memory reference. The information is passed as: @@ -313,112 +296,6 @@ struct optee_msg_arg { #define OPTEE_MSG_CMD_UNREGISTER_SHM 5 #define OPTEE_MSG_FUNCID_CALL_WITH_ARG 0x0004 -/***************************************************************************** - * Part 3 - Requests from secure world, RPC - *****************************************************************************/ - -/* - * All RPC is done with a struct optee_msg_arg as bearer of information, - * struct optee_msg_arg::arg holds values defined by OPTEE_MSG_RPC_CMD_* below - * - * RPC communication with tee-supplicant is reversed compared to normal - * client communication desribed above. The supplicant receives requests - * and sends responses. - */ - -/* - * Load a TA into memory, defined in tee-supplicant - */ -#define OPTEE_MSG_RPC_CMD_LOAD_TA 0 - -/* - * Reserved - */ -#define OPTEE_MSG_RPC_CMD_RPMB 1 - -/* - * File system access, defined in tee-supplicant - */ -#define OPTEE_MSG_RPC_CMD_FS 2 - -/* - * Get time - * - * Returns number of seconds and nano seconds since the Epoch, - * 1970-01-01 00:00:00 +0000 (UTC). - * - * [out] param[0].u.value.a Number of seconds - * [out] param[0].u.value.b Number of nano seconds. - */ -#define OPTEE_MSG_RPC_CMD_GET_TIME 3 - -/* - * Wait queue primitive, helper for secure world to implement a wait queue. - * - * If secure world need to wait for a secure world mutex it issues a sleep - * request instead of spinning in secure world. Conversely is a wakeup - * request issued when a secure world mutex with a thread waiting thread is - * unlocked. - * - * Waiting on a key - * [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP - * [in] param[0].u.value.b wait key - * - * Waking up a key - * [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP - * [in] param[0].u.value.b wakeup key - */ -#define OPTEE_MSG_RPC_CMD_WAIT_QUEUE 4 -#define OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP 0 -#define OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP 1 - -/* - * Suspend execution - * - * [in] param[0].value .a number of milliseconds to suspend - */ -#define OPTEE_MSG_RPC_CMD_SUSPEND 5 - -/* - * Allocate a piece of shared memory - * - * Shared memory can optionally be fragmented, to support that additional - * spare param entries are allocated to make room for eventual fragments. - * The spare param entries has .attr = OPTEE_MSG_ATTR_TYPE_NONE when - * unused. All returned temp memrefs except the last should have the - * OPTEE_MSG_ATTR_FRAGMENT bit set in the attr field. - * - * [in] param[0].u.value.a type of memory one of - * OPTEE_MSG_RPC_SHM_TYPE_* below - * [in] param[0].u.value.b requested size - * [in] param[0].u.value.c required alignment - * - * [out] param[0].u.tmem.buf_ptr physical address (of first fragment) - * [out] param[0].u.tmem.size size (of first fragment) - * [out] param[0].u.tmem.shm_ref shared memory reference - * ... - * [out] param[n].u.tmem.buf_ptr physical address - * [out] param[n].u.tmem.size size - * [out] param[n].u.tmem.shm_ref shared memory reference (same value - * as in param[n-1].u.tmem.shm_ref) - */ -#define OPTEE_MSG_RPC_CMD_SHM_ALLOC 6 -/* Memory that can be shared with a non-secure user space application */ -#define OPTEE_MSG_RPC_SHM_TYPE_APPL 0 -/* Memory only shared with non-secure kernel */ -#define OPTEE_MSG_RPC_SHM_TYPE_KERNEL 1 - -/* - * Free shared memory previously allocated with OPTEE_MSG_RPC_CMD_SHM_ALLOC - * - * [in] param[0].u.value.a type of memory one of - * OPTEE_MSG_RPC_SHM_TYPE_* above - * [in] param[0].u.value.b value of shared memory reference - * returned in param[0].u.tmem.shm_ref - * above - */ -#define OPTEE_MSG_RPC_CMD_SHM_FREE 7 - /* * Access a device on an i2c bus * diff --git a/drivers/tee/optee/optee_rpc_cmd.h b/drivers/tee/optee/optee_rpc_cmd.h new file mode 100644 index 000000000000..712aa32513d7 --- /dev/null +++ b/drivers/tee/optee/optee_rpc_cmd.h @@ -0,0 +1,333 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016-2018, Linaro Limited + */ + +#ifndef __OPTEE_RPC_CMD_H +#define __OPTEE_RPC_CMD_H + +/* + * All RPC is done with a struct optee_msg_arg as bearer of information, + * struct optee_msg_arg::arg holds values defined by OPTEE_RPC_CMD_* below. + * Only the commands handled by the kernel driver are defined here. + * + * RPC communication with tee-supplicant is reversed compared to normal + * client communication described above. The supplicant receives requests + * and sends responses. + */ + +/* + * Load a TA into memory + * + * Since the size of the TA isn't known in advance the size of the TA is + * can be queried with a NULL buffer. + * + * [in] value[0].a-b UUID + * [out] memref[1] Buffer with TA + */ +#define OPTEE_RPC_CMD_LOAD_TA 0 + +/* + * Replay Protected Memory Block access + * + * [in] memref[0] Frames to device + * [out] memref[1] Frames from device + */ +#define OPTEE_RPC_CMD_RPMB 1 + +/* + * File system access, see definition of protocol below + */ +#define OPTEE_RPC_CMD_FS 2 + +/* + * Get time + * + * Returns number of seconds and nano seconds since the Epoch, + * 1970-01-01 00:00:00 +0000 (UTC). + * + * [out] value[0].a Number of seconds + * [out] value[0].b Number of nano seconds. + */ +#define OPTEE_RPC_CMD_GET_TIME 3 + +/* + * Wait queue primitive, helper for secure world to implement a wait queue. + * + * If secure world needs to wait for a secure world mutex it issues a sleep + * request instead of spinning in secure world. Conversely is a wakeup + * request issued when a secure world mutex with a thread waiting thread is + * unlocked. + * + * Waiting on a key + * [in] value[0].a OPTEE_RPC_WAIT_QUEUE_SLEEP + * [in] value[0].b Wait key + * + * Waking up a key + * [in] value[0].a OPTEE_RPC_WAIT_QUEUE_WAKEUP + * [in] value[0].b Wakeup key + */ +#define OPTEE_RPC_CMD_WAIT_QUEUE 4 +#define OPTEE_RPC_WAIT_QUEUE_SLEEP 0 +#define OPTEE_RPC_WAIT_QUEUE_WAKEUP 1 + +/* + * Suspend execution + * + * [in] value[0].a Number of milliseconds to suspend + */ +#define OPTEE_RPC_CMD_SUSPEND 5 + +/* + * Allocate a piece of shared memory + * + * [in] value[0].a Type of memory one of + * OPTEE_RPC_SHM_TYPE_* below + * [in] value[0].b Requested size + * [in] value[0].c Required alignment + * [out] memref[0] Buffer + */ +#define OPTEE_RPC_CMD_SHM_ALLOC 6 +/* Memory that can be shared with a non-secure user space application */ +#define OPTEE_RPC_SHM_TYPE_APPL 0 +/* Memory only shared with non-secure kernel */ +#define OPTEE_RPC_SHM_TYPE_KERNEL 1 +/* + * Memory shared with non-secure kernel and exported to a non-secure user + * space application + */ +#define OPTEE_RPC_SHM_TYPE_GLOBAL 2 + +/* + * Free shared memory previously allocated with OPTEE_RPC_CMD_SHM_ALLOC + * + * [in] value[0].a Type of memory one of + * OPTEE_RPC_SHM_TYPE_* above + * [in] value[0].b Value of shared memory reference or cookie + */ +#define OPTEE_RPC_CMD_SHM_FREE 7 + +/* Was OPTEE_RPC_CMD_SQL_FS, which isn't supported any longer */ +#define OPTEE_RPC_CMD_SQL_FS_RESERVED 8 + +/* + * Send TA profiling information to normal world + * + * [in/out] value[0].a File identifier. Must be set to 0 on + * first call. A value >= 1 will be + * returned on success. Re-use this value + * to append data to the same file. + * [in] memref[1] TA UUID + * [in] memref[2] Profile data + */ +#define OPTEE_RPC_CMD_GPROF 9 + +/* + * Socket command, see definition of protocol below + */ +#define OPTEE_RPC_CMD_SOCKET 10 + +/* + * Send TA function graph data to normal world + * + * [in/out] value[0].a File identifier. Must be set to 0 on + * first call. A value >= 1 will be + * returned on success. Re-use this value + * to append data to the same file. + * [in] memref[1] TA UUID + * [in] memref[2] function graph data + */ +#define OPTEE_RPC_CMD_FTRACE 11 + +/* + * Register timestamp buffer in the linux kernel optee driver + * + * [in] value[0].a Subcommand (register buffer, unregister buffer) + * OPTEE_RPC_CMD_BENCH_REG_* below + * [in] value[0].b Physical address of timestamp buffer + * [in] value[0].c Size of buffer + */ +#define OPTEE_RPC_CMD_BENCH_REG_NEW 0 +#define OPTEE_RPC_CMD_BENCH_REG_DEL 1 +#define OPTEE_RPC_CMD_BENCH_REG 20 + +/* + * Definition of protocol for command OPTEE_RPC_CMD_FS + */ + +/* + * Open a file + * + * [in] value[0].a OPTEE_RPC_FS_OPEN + * [in] memref[1] A string holding the file name + * [out] value[2].a File descriptor of open file + */ +#define OPTEE_RPC_FS_OPEN 0 + +/* + * Create a file + * + * [in] value[0].a OPTEE_RPC_FS_CREATE + * [in] memref[1] A string holding the file name + * [out] value[2].a File descriptor of open file + */ +#define OPTEE_RPC_FS_CREATE 1 + +/* + * Close a file + * + * [in] value[0].a OPTEE_RPC_FS_CLOSE + * [in] value[0].b File descriptor of open file. + */ +#define OPTEE_RPC_FS_CLOSE 2 + +/* + * Read from a file + * + * [in] value[0].a OPTEE_RPC_FS_READ + * [in] value[0].b File descriptor of open file + * [in] value[0].c Offset into file + * [out] memref[1] Buffer to hold returned data + */ +#define OPTEE_RPC_FS_READ 3 + +/* + * Write to a file + * + * [in] value[0].a OPTEE_RPC_FS_WRITE + * [in] value[0].b File descriptor of open file + * [in] value[0].c Offset into file + * [in] memref[1] Buffer holding data to be written + */ +#define OPTEE_RPC_FS_WRITE 4 + +/* + * Truncate a file + * + * [in] value[0].a OPTEE_RPC_FS_TRUNCATE + * [in] value[0].b File descriptor of open file + * [in] value[0].c Length of file. + */ +#define OPTEE_RPC_FS_TRUNCATE 5 + +/* + * Remove a file + * + * [in] value[0].a OPTEE_RPC_FS_REMOVE + * [in] memref[1] A string holding the file name + */ +#define OPTEE_RPC_FS_REMOVE 6 + +/* + * Rename a file + * + * [in] value[0].a OPTEE_RPC_FS_RENAME + * [in] value[0].b True if existing target should be removed + * [in] memref[1] A string holding the old file name + * [in] memref[2] A string holding the new file name + */ +#define OPTEE_RPC_FS_RENAME 7 + +/* + * Opens a directory for file listing + * + * [in] value[0].a OPTEE_RPC_FS_OPENDIR + * [in] memref[1] A string holding the name of the directory + * [out] value[2].a Handle to open directory + */ +#define OPTEE_RPC_FS_OPENDIR 8 + +/* + * Closes a directory handle + * + * [in] value[0].a OPTEE_RPC_FS_CLOSEDIR + * [in] value[0].b Handle to open directory + */ +#define OPTEE_RPC_FS_CLOSEDIR 9 + +/* + * Read next file name of directory + * + * + * [in] value[0].a OPTEE_RPC_FS_READDIR + * [in] value[0].b Handle to open directory + * [out] memref[1] A string holding the file name + */ +#define OPTEE_RPC_FS_READDIR 10 + +/* End of definition of protocol for command OPTEE_RPC_CMD_FS */ + +/* + * Definition of protocol for command OPTEE_RPC_CMD_SOCKET + */ + +#define OPTEE_RPC_SOCKET_TIMEOUT_NONBLOCKING 0 +#define OPTEE_RPC_SOCKET_TIMEOUT_BLOCKING 0xffffffff + +/* + * Open socket + * + * [in] value[0].a OPTEE_RPC_SOCKET_OPEN + * [in] value[0].b TA instance id + * [in] value[1].a Server port number + * [in] value[1].b Protocol, TEE_ISOCKET_PROTOCOLID_* + * [in] value[1].c Ip version TEE_IP_VERSION_* from tee_ipsocket.h + * [in] memref[2] Server address + * [out] value[3].a Socket handle (32-bit) + */ +#define OPTEE_RPC_SOCKET_OPEN 0 + +/* + * Close socket + * + * [in] value[0].a OPTEE_RPC_SOCKET_CLOSE + * [in] value[0].b TA instance id + * [in] value[0].c Socket handle + */ +#define OPTEE_RPC_SOCKET_CLOSE 1 + +/* + * Close all sockets + * + * [in] value[0].a OPTEE_RPC_SOCKET_CLOSE_ALL + * [in] value[0].b TA instance id + */ +#define OPTEE_RPC_SOCKET_CLOSE_ALL 2 + +/* + * Send data on socket + * + * [in] value[0].a OPTEE_RPC_SOCKET_SEND + * [in] value[0].b TA instance id + * [in] value[0].c Socket handle + * [in] memref[1] Buffer to transmit + * [in] value[2].a Timeout ms or OPTEE_RPC_SOCKET_TIMEOUT_* + * [out] value[2].b Number of transmitted bytes + */ +#define OPTEE_RPC_SOCKET_SEND 3 + +/* + * Receive data on socket + * + * [in] value[0].a OPTEE_RPC_SOCKET_RECV + * [in] value[0].b TA instance id + * [in] value[0].c Socket handle + * [out] memref[1] Buffer to receive + * [in] value[2].a Timeout ms or OPTEE_RPC_SOCKET_TIMEOUT_* + */ +#define OPTEE_RPC_SOCKET_RECV 4 + +/* + * Perform IOCTL on socket + * + * [in] value[0].a OPTEE_RPC_SOCKET_IOCTL + * [in] value[0].b TA instance id + * [in] value[0].c Socket handle + * [in/out] memref[1] Buffer + * [in] value[2].a Ioctl command + */ +#define OPTEE_RPC_SOCKET_IOCTL 5 + +/* End of definition of protocol for command OPTEE_RPC_CMD_SOCKET */ + +#endif /*__OPTEE_RPC_CMD_H*/ diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c index 1e3614e4798f..a3a1aa59f639 100644 --- a/drivers/tee/optee/rpc.c +++ b/drivers/tee/optee/rpc.c @@ -10,7 +10,9 @@ #include #include #include +#include "optee_msg.h" #include "optee_private.h" +#include "optee_rpc_cmd.h" #include "optee_smc.h" struct wq_entry { @@ -194,10 +196,10 @@ static void handle_rpc_func_cmd_wq(struct optee *optee, goto bad; switch (arg->params[0].u.value.a) { - case OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP: + case OPTEE_RPC_WAIT_QUEUE_SLEEP: wq_sleep(&optee->wait_queue, arg->params[0].u.value.b); break; - case OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP: + case OPTEE_RPC_WAIT_QUEUE_WAKEUP: wq_wakeup(&optee->wait_queue, arg->params[0].u.value.b); break; default: @@ -267,11 +269,11 @@ static struct tee_shm *cmd_alloc_suppl(struct tee_context *ctx, size_t sz) struct tee_shm *shm; param.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT; - param.u.value.a = OPTEE_MSG_RPC_SHM_TYPE_APPL; + param.u.value.a = OPTEE_RPC_SHM_TYPE_APPL; param.u.value.b = sz; param.u.value.c = 0; - ret = optee_supp_thrd_req(ctx, OPTEE_MSG_RPC_CMD_SHM_ALLOC, 1, ¶m); + ret = optee_supp_thrd_req(ctx, OPTEE_RPC_CMD_SHM_ALLOC, 1, ¶m); if (ret) return ERR_PTR(-ENOMEM); @@ -308,10 +310,10 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx, sz = arg->params[0].u.value.b; switch (arg->params[0].u.value.a) { - case OPTEE_MSG_RPC_SHM_TYPE_APPL: + case OPTEE_RPC_SHM_TYPE_APPL: shm = cmd_alloc_suppl(ctx, sz); break; - case OPTEE_MSG_RPC_SHM_TYPE_KERNEL: + case OPTEE_RPC_SHM_TYPE_KERNEL: shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED); break; default: @@ -383,7 +385,7 @@ static void cmd_free_suppl(struct tee_context *ctx, struct tee_shm *shm) struct tee_param param; param.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT; - param.u.value.a = OPTEE_MSG_RPC_SHM_TYPE_APPL; + param.u.value.a = OPTEE_RPC_SHM_TYPE_APPL; param.u.value.b = tee_shm_get_id(shm); param.u.value.c = 0; @@ -400,7 +402,7 @@ static void cmd_free_suppl(struct tee_context *ctx, struct tee_shm *shm) */ tee_shm_put(shm); - optee_supp_thrd_req(ctx, OPTEE_MSG_RPC_CMD_SHM_FREE, 1, ¶m); + optee_supp_thrd_req(ctx, OPTEE_RPC_CMD_SHM_FREE, 1, ¶m); } static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx, @@ -418,10 +420,10 @@ static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx, shm = (struct tee_shm *)(unsigned long)arg->params[0].u.value.b; switch (arg->params[0].u.value.a) { - case OPTEE_MSG_RPC_SHM_TYPE_APPL: + case OPTEE_RPC_SHM_TYPE_APPL: cmd_free_suppl(ctx, shm); break; - case OPTEE_MSG_RPC_SHM_TYPE_KERNEL: + case OPTEE_RPC_SHM_TYPE_KERNEL: tee_shm_free(shm); break; default: @@ -458,20 +460,20 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee, } switch (arg->cmd) { - case OPTEE_MSG_RPC_CMD_GET_TIME: + case OPTEE_RPC_CMD_GET_TIME: handle_rpc_func_cmd_get_time(arg); break; - case OPTEE_MSG_RPC_CMD_WAIT_QUEUE: + case OPTEE_RPC_CMD_WAIT_QUEUE: handle_rpc_func_cmd_wq(optee, arg); break; - case OPTEE_MSG_RPC_CMD_SUSPEND: + case OPTEE_RPC_CMD_SUSPEND: handle_rpc_func_cmd_wait(arg); break; - case OPTEE_MSG_RPC_CMD_SHM_ALLOC: + case OPTEE_RPC_CMD_SHM_ALLOC: free_pages_list(call_ctx); handle_rpc_func_cmd_shm_alloc(ctx, arg, call_ctx); break; - case OPTEE_MSG_RPC_CMD_SHM_FREE: + case OPTEE_RPC_CMD_SHM_FREE: handle_rpc_func_cmd_shm_free(ctx, arg); break; case OPTEE_MSG_RPC_CMD_I2C_TRANSFER: From patchwork Thu Mar 25 15:44:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Wiklander X-Patchwork-Id: 12164475 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CD776C433DB for ; Thu, 25 Mar 2021 15:46:50 +0000 (UTC) Received: from desiato.infradead.org (desiato.infradead.org [90.155.92.199]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4E8E461A30 for ; Thu, 25 Mar 2021 15:46:50 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4E8E461A30 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=desiato.20200630; h=Sender:Content-Transfer-Encoding :Content-Type:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=w3v9ZwYpzf3N83ZPRQ4sw34Edp+QUJUpXx0JTYIxOdI=; b=mpFri+iOEVdDFgENYLO/xSTA5 JS5v3SmEgbzZkennbX7C6slXXnlifehFBlY6+7N4YZB2REQZzANZTlC/U+f4OhDwCQn1yf/6ErXfz HunwBJudyt/91AMFgGDmP4MDtCKHGKHWodObtya3ozckXAPFhOB9zLtBdSThL616IrKMzeJ/P22eF WGyoSnkosHFtDfNz10RkysT0M9M4zhKpmtvgV8domB3bJDcq3KCvfGCdJ3Lznl2rUblJxgKzK4IPA fJhPg7RIeiKWpimkmJVIlVb6c0nCXDF8nx7YmXorwBrMJW1HEIlzNXUojiWaxYXkdCwn48ILT8hrU YC9aVQ9cQ==; Received: from localhost ([::1] helo=desiato.infradead.org) by desiato.infradead.org with esmtp (Exim 4.94 #2 (Red Hat Linux)) id 1lPSAi-001kXs-Hx; Thu, 25 Mar 2021 15:45:21 +0000 Received: from mail-lj1-x22c.google.com ([2a00:1450:4864:20::22c]) by desiato.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1lPSA6-001kRA-Ax for linux-arm-kernel@lists.infradead.org; Thu, 25 Mar 2021 15:44:45 +0000 Received: by mail-lj1-x22c.google.com with SMTP id u4so3718608ljo.6 for ; Thu, 25 Mar 2021 08:44:41 -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=xb/ekaAw4yE1vZrEjP1Q4IsDdKO/SgIDu5LXCJt+50g=; b=nfD/lM5cVim2BpSB9adQCl5jGJY8tJWqTMqBSimx8Y56gDg8bkN6+Pe/rZQtujdMF6 Q1tBnv2SHIkCUBQ3AFrv/tb9E0cA8x4YzjlCzzi+xSWFlQvZbs234r3Q89TOpZKvod+j lUskc+B6kcbIjd5oQXbaxggPzk8dZVYtww5+xmkX/nVHnhmCqG8e1ttdi8adE6MUW0qZ /tLGeNgl/Zs2l2EYZijf5sDFCLSGoHrGnpOYN9qfNz46TdbjD1NEZeo9d+ikK0mK9c9h 7rYOPGd5jNoHXuWfrNV+/I+e1Fji3FOUvB0wFmLOi4tg3AsD+GK5eDQIR0UecmMvIFc8 2Ejg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=xb/ekaAw4yE1vZrEjP1Q4IsDdKO/SgIDu5LXCJt+50g=; b=PFVE5tgQBcDx0nIlE9WVswwVPPr5TpsEN4D6jG01LNeMr/hDJw4mGFmYORa9YaSZaG B2fjrDcfHVRMXzbPJlUA+45f6CKkbVDhnFt9o8so/mMFW4DVGvIYvhislFfEJQKHT3bV jiGCmSRfVun6rBqtxEcFWe58wsHJu9WlY2cxgJl4VI9lyGhFc3aU+3QQsfADuHMP4cGQ iS7LizfOcl5YosRzzYknVMCxnCj0Z9HNnk17//Featgi/DgBzzqIhBxmG7gKgoZTlpmg gnWvH3fJfcWWYNZZQ30IM1LjPbHapGeOydEIHlxPmiqdsmC1Op6ELK4r/sqQad5924sG NR9g== X-Gm-Message-State: AOAM531IxyV+NKj/ozvQrQVK7QLh4mf97AMOW5N8TE75dHFEFIuipBsT icOYQ8LKCpNeoZDRyivvHf0cJA== X-Google-Smtp-Source: ABdhPJwb7h7awZfni6ksOKSTv5XrH8xx26gCMS4u2WVnhAOsaQCvKRKqgR7YulqSASqWzUS0n7No0A== X-Received: by 2002:a2e:320c:: with SMTP id y12mr6258433ljy.360.1616687079378; Thu, 25 Mar 2021 08:44:39 -0700 (PDT) Received: from jade.urgonet (h-249-223.A175.priv.bahnhof.se. [98.128.249.223]) by smtp.gmail.com with ESMTPSA id m27sm770916ljc.109.2021.03.25.08.44.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Mar 2021 08:44:38 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, op-tee@lists.trustedfirmware.org Cc: Sudeep Holla , Marc Bonnici , Jerome Forissier , Jens Wiklander Subject: [PATCH 4/6] optee: refactor driver with internal callbacks Date: Thu, 25 Mar 2021 16:44:24 +0100 Message-Id: <20210325154426.3520148-5-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210325154426.3520148-1-jens.wiklander@linaro.org> References: <20210325154426.3520148-1-jens.wiklander@linaro.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210325_154442_455506_9BEECADC X-CRM114-Status: GOOD ( 22.97 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The OP-TEE driver is refactored with three internal callbacks replacing direct calls to optee_from_msg_param(), optee_to_msg_param() and optee_do_call_with_arg(). These functions a central to communicating with OP-TEE in secure world by using the SMC Calling Convention directly. This refactoring makes room for using other primitives to communicate with OP-TEE in secure world while being able to reuse as much as possible from the present driver. Signed-off-by: Jens Wiklander --- drivers/tee/optee/call.c | 78 ++++++++------- drivers/tee/optee/core.c | 158 +++++++++++++++++++----------- drivers/tee/optee/optee_private.h | 35 +++++-- drivers/tee/optee/rpc.c | 19 ++-- 4 files changed, 181 insertions(+), 109 deletions(-) diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c index c0eca4d7d7f2..ef049c0dee50 100644 --- a/drivers/tee/optee/call.c +++ b/drivers/tee/optee/call.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2015-2021, Linaro Limited */ #include #include @@ -116,20 +116,25 @@ static struct optee_session *find_session(struct optee_context_data *ctxdata, /** * optee_do_call_with_arg() - Do an SMC to OP-TEE in secure world * @ctx: calling context - * @parg: physical address of message to pass to secure world + * @arg: 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. * * Returns return code from secure world, 0 is OK */ -u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg) +int optee_do_call_with_arg(struct tee_context *ctx, struct tee_shm *arg) { 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; + phys_addr_t parg; + int rc; + + rc = tee_shm_get_pa(arg, 0, &parg); + if (rc) + return rc; param.a0 = OPTEE_SMC_CALL_WITH_ARG; reg_pair_from_64(¶m.a1, ¶m.a2, parg); @@ -157,7 +162,7 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg) param.a3 = res.a3; optee_handle_rpc(ctx, ¶m, &call_ctx); } else { - ret = res.a0; + rc = res.a0; break; } } @@ -169,12 +174,11 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg) */ optee_cq_wait_final(&optee->call_queue, &w); - return ret; + return rc; } static struct tee_shm *get_msg_arg(struct tee_context *ctx, size_t num_params, - struct optee_msg_arg **msg_arg, - phys_addr_t *msg_parg) + struct optee_msg_arg **msg_arg) { int rc; struct tee_shm *shm; @@ -191,10 +195,6 @@ static struct tee_shm *get_msg_arg(struct tee_context *ctx, size_t num_params, goto out; } - rc = tee_shm_get_pa(shm, 0, msg_parg); - if (rc) - goto out; - memset(ma, 0, OPTEE_MSG_GET_ARG_SIZE(num_params)); ma->num_params = num_params; *msg_arg = ma; @@ -211,15 +211,15 @@ int optee_open_session(struct tee_context *ctx, struct tee_ioctl_open_session_arg *arg, struct tee_param *param) { + struct optee *optee = tee_get_drvdata(ctx->teedev); struct optee_context_data *ctxdata = ctx->data; int rc; struct tee_shm *shm; struct optee_msg_arg *msg_arg; - phys_addr_t msg_parg; struct optee_session *sess = NULL; /* +2 for the meta parameters added below */ - shm = get_msg_arg(ctx, arg->num_params + 2, &msg_arg, &msg_parg); + shm = get_msg_arg(ctx, arg->num_params + 2, &msg_arg); if (IS_ERR(shm)) return PTR_ERR(shm); @@ -242,7 +242,8 @@ int optee_open_session(struct tee_context *ctx, if (rc) goto out; - rc = optee_to_msg_param(msg_arg->params + 2, arg->num_params, param); + rc = optee->ops->to_msg_param(optee, msg_arg->params + 2, + arg->num_params, param); if (rc) goto out; @@ -252,7 +253,7 @@ int optee_open_session(struct tee_context *ctx, goto out; } - if (optee_do_call_with_arg(ctx, msg_parg)) { + if (optee->ops->do_call_with_arg(ctx, shm)) { msg_arg->ret = TEEC_ERROR_COMMUNICATION; msg_arg->ret_origin = TEEC_ORIGIN_COMMS; } @@ -267,7 +268,8 @@ int optee_open_session(struct tee_context *ctx, kfree(sess); } - if (optee_from_msg_param(param, arg->num_params, msg_arg->params + 2)) { + if (optee->ops->from_msg_param(optee, param, arg->num_params, + msg_arg->params + 2)) { arg->ret = TEEC_ERROR_COMMUNICATION; arg->ret_origin = TEEC_ORIGIN_COMMS; /* Close session again to avoid leakage */ @@ -286,16 +288,16 @@ int optee_open_session(struct tee_context *ctx, int optee_close_session_helper(struct tee_context *ctx, u32 session) { struct tee_shm *shm; + struct optee *optee = tee_get_drvdata(ctx->teedev); struct optee_msg_arg *msg_arg; - phys_addr_t msg_parg; - shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg); + shm = get_msg_arg(ctx, 0, &msg_arg); if (IS_ERR(shm)) return PTR_ERR(shm); msg_arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION; msg_arg->session = session; - optee_do_call_with_arg(ctx, msg_parg); + optee->ops->do_call_with_arg(ctx, shm); tee_shm_free(shm); @@ -323,10 +325,10 @@ int optee_close_session(struct tee_context *ctx, u32 session) int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg, struct tee_param *param) { + struct optee *optee = tee_get_drvdata(ctx->teedev); struct optee_context_data *ctxdata = ctx->data; struct tee_shm *shm; struct optee_msg_arg *msg_arg; - phys_addr_t msg_parg; struct optee_session *sess; int rc; @@ -337,7 +339,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg, if (!sess) return -EINVAL; - shm = get_msg_arg(ctx, arg->num_params, &msg_arg, &msg_parg); + shm = get_msg_arg(ctx, arg->num_params, &msg_arg); if (IS_ERR(shm)) return PTR_ERR(shm); msg_arg->cmd = OPTEE_MSG_CMD_INVOKE_COMMAND; @@ -345,16 +347,18 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg, msg_arg->session = arg->session; msg_arg->cancel_id = arg->cancel_id; - rc = optee_to_msg_param(msg_arg->params, arg->num_params, param); + rc = optee->ops->to_msg_param(optee, msg_arg->params, arg->num_params, + param); if (rc) goto out; - if (optee_do_call_with_arg(ctx, msg_parg)) { + if (optee->ops->do_call_with_arg(ctx, shm)) { msg_arg->ret = TEEC_ERROR_COMMUNICATION; msg_arg->ret_origin = TEEC_ORIGIN_COMMS; } - if (optee_from_msg_param(param, arg->num_params, msg_arg->params)) { + if (optee->ops->from_msg_param(optee, param, arg->num_params, + msg_arg->params)) { msg_arg->ret = TEEC_ERROR_COMMUNICATION; msg_arg->ret_origin = TEEC_ORIGIN_COMMS; } @@ -368,10 +372,10 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg, int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session) { + struct optee *optee = tee_get_drvdata(ctx->teedev); struct optee_context_data *ctxdata = ctx->data; struct tee_shm *shm; struct optee_msg_arg *msg_arg; - phys_addr_t msg_parg; struct optee_session *sess; /* Check that the session is valid */ @@ -381,14 +385,14 @@ int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session) if (!sess) return -EINVAL; - shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg); + shm = get_msg_arg(ctx, 0, &msg_arg); if (IS_ERR(shm)) return PTR_ERR(shm); msg_arg->cmd = OPTEE_MSG_CMD_CANCEL; msg_arg->session = session; msg_arg->cancel_id = cancel_id; - optee_do_call_with_arg(ctx, msg_parg); + optee->ops->do_call_with_arg(ctx, shm); tee_shm_free(shm); return 0; @@ -587,10 +591,10 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm, struct page **pages, size_t num_pages, unsigned long start) { - struct tee_shm *shm_arg = NULL; + struct optee *optee = tee_get_drvdata(ctx->teedev); struct optee_msg_arg *msg_arg; + struct tee_shm *shm_arg; u64 *pages_list; - phys_addr_t msg_parg; int rc; if (!num_pages) @@ -604,7 +608,7 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm, if (!pages_list) return -ENOMEM; - shm_arg = get_msg_arg(ctx, 1, &msg_arg, &msg_parg); + shm_arg = get_msg_arg(ctx, 1, &msg_arg); if (IS_ERR(shm_arg)) { rc = PTR_ERR(shm_arg); goto out; @@ -625,7 +629,7 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm, msg_arg->params->u.tmem.buf_ptr = virt_to_phys(pages_list) | (tee_shm_get_page_offset(shm) & (OPTEE_MSG_NONCONTIG_PAGE_SIZE - 1)); - if (optee_do_call_with_arg(ctx, msg_parg) || + if (optee->ops->do_call_with_arg(ctx, shm) || msg_arg->ret != TEEC_SUCCESS) rc = -EINVAL; @@ -637,12 +641,12 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm, int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm) { - struct tee_shm *shm_arg; + struct optee *optee = tee_get_drvdata(ctx->teedev); struct optee_msg_arg *msg_arg; - phys_addr_t msg_parg; - int rc = 0; + struct tee_shm *shm_arg; + int rc; - shm_arg = get_msg_arg(ctx, 1, &msg_arg, &msg_parg); + shm_arg = get_msg_arg(ctx, 1, &msg_arg); if (IS_ERR(shm_arg)) return PTR_ERR(shm_arg); @@ -651,7 +655,7 @@ int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm) msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT; msg_arg->params[0].u.rmem.shm_ref = (unsigned long)shm; - if (optee_do_call_with_arg(ctx, msg_parg) || + if (optee->ops->do_call_with_arg(ctx, shm) || msg_arg->ret != TEEC_SUCCESS) rc = -EINVAL; tee_shm_free(shm_arg); diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index 0ffe0c7d68ff..ab602bb8e14a 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2015-2021, Linaro Limited */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -26,21 +26,87 @@ #define OPTEE_SHM_NUM_PRIV_PAGES CONFIG_OPTEE_SHM_NUM_PRIV_PAGES +static void from_msg_param_value(struct tee_param *p, u32 attr, + const struct optee_msg_param *mp) +{ + p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT + + attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; + p->u.value.a = mp->u.value.a; + p->u.value.b = mp->u.value.b; + p->u.value.c = mp->u.value.c; +} + +static int from_msg_param_tmp_mem(struct tee_param *p, u32 attr, + const struct optee_msg_param *mp) +{ + struct tee_shm *shm; + phys_addr_t pa; + int rc; + + p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT + + attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; + p->u.memref.size = mp->u.tmem.size; + shm = (struct tee_shm *)(unsigned long)mp->u.tmem.shm_ref; + if (!shm) { + p->u.memref.shm_offs = 0; + p->u.memref.shm = NULL; + return 0; + } + + rc = tee_shm_get_pa(shm, 0, &pa); + if (rc) + return rc; + + p->u.memref.shm_offs = mp->u.tmem.buf_ptr - pa; + p->u.memref.shm = shm; + + /* Check that the memref is covered by the shm object */ + if (p->u.memref.size) { + size_t o = p->u.memref.shm_offs + + p->u.memref.size - 1; + + rc = tee_shm_get_pa(shm, o, NULL); + if (rc) + return rc; + } + + return 0; +} + +static void from_msg_param_reg_mem(struct tee_param *p, u32 attr, + const struct optee_msg_param *mp) +{ + struct tee_shm *shm; + + p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT + + attr - OPTEE_MSG_ATTR_TYPE_RMEM_INPUT; + p->u.memref.size = mp->u.rmem.size; + shm = (struct tee_shm *)(unsigned long)mp->u.rmem.shm_ref; + + if (shm) { + p->u.memref.shm_offs = mp->u.rmem.offs; + p->u.memref.shm = shm; + } else { + p->u.memref.shm_offs = 0; + p->u.memref.shm = NULL; + } +} + /** * optee_from_msg_param() - convert from OPTEE_MSG parameters to * struct tee_param + * @optee: main service struct * @params: subsystem internal parameter representation * @num_params: number of elements in the parameter arrays * @msg_params: OPTEE_MSG parameters * Returns 0 on success or <0 on failure */ -int optee_from_msg_param(struct tee_param *params, size_t num_params, - const struct optee_msg_param *msg_params) +static int optee_from_msg_param(struct optee *optee, struct tee_param *params, + size_t num_params, + const struct optee_msg_param *msg_params) { int rc; size_t n; - struct tee_shm *shm; - phys_addr_t pa; for (n = 0; n < num_params; n++) { struct tee_param *p = params + n; @@ -55,58 +121,19 @@ int optee_from_msg_param(struct tee_param *params, size_t num_params, case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT: case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT: case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT: - p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT + - attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; - p->u.value.a = mp->u.value.a; - p->u.value.b = mp->u.value.b; - p->u.value.c = mp->u.value.c; + from_msg_param_value(p, attr, mp); break; case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT: case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT: case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT: - p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT + - attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; - p->u.memref.size = mp->u.tmem.size; - shm = (struct tee_shm *)(unsigned long) - mp->u.tmem.shm_ref; - if (!shm) { - p->u.memref.shm_offs = 0; - p->u.memref.shm = NULL; - break; - } - rc = tee_shm_get_pa(shm, 0, &pa); + rc = from_msg_param_tmp_mem(p, attr, mp); if (rc) return rc; - p->u.memref.shm_offs = mp->u.tmem.buf_ptr - pa; - p->u.memref.shm = shm; - - /* Check that the memref is covered by the shm object */ - if (p->u.memref.size) { - size_t o = p->u.memref.shm_offs + - p->u.memref.size - 1; - - rc = tee_shm_get_pa(shm, o, NULL); - if (rc) - return rc; - } break; case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT: case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT: case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT: - p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT + - attr - OPTEE_MSG_ATTR_TYPE_RMEM_INPUT; - p->u.memref.size = mp->u.rmem.size; - shm = (struct tee_shm *)(unsigned long) - mp->u.rmem.shm_ref; - - if (!shm) { - p->u.memref.shm_offs = 0; - p->u.memref.shm = NULL; - break; - } - p->u.memref.shm_offs = mp->u.rmem.offs; - p->u.memref.shm = shm; - + from_msg_param_reg_mem(p, attr, mp); break; default: @@ -116,6 +143,16 @@ int optee_from_msg_param(struct tee_param *params, size_t num_params, return 0; } +static void to_msg_param_value(struct optee_msg_param *mp, + const struct tee_param *p) +{ + mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr - + TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT; + mp->u.value.a = p->u.value.a; + mp->u.value.b = p->u.value.b; + mp->u.value.c = p->u.value.c; +} + static int to_msg_param_tmp_mem(struct optee_msg_param *mp, const struct tee_param *p) { @@ -158,13 +195,15 @@ static int to_msg_param_reg_mem(struct optee_msg_param *mp, /** * optee_to_msg_param() - convert from struct tee_params to OPTEE_MSG parameters + * @optee: main service struct * @msg_params: OPTEE_MSG parameters * @num_params: number of elements in the parameter arrays * @params: subsystem itnernal parameter representation * Returns 0 on success or <0 on failure */ -int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params, - const struct tee_param *params) +static int optee_to_msg_param(struct optee *optee, + struct optee_msg_param *msg_params, + size_t num_params, const struct tee_param *params) { int rc; size_t n; @@ -181,11 +220,7 @@ int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params, case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT: - mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr - - TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT; - mp->u.value.a = p->u.value.a; - mp->u.value.b = p->u.value.b; - mp->u.value.c = p->u.value.c; + to_msg_param_value(mp, p); break; case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: @@ -311,7 +346,7 @@ static void optee_release_supp(struct tee_context *ctx) optee_supp_release(&optee->supp); } -static const struct tee_driver_ops optee_ops = { +static const struct tee_driver_ops optee_clnt_ops = { .get_version = optee_get_version, .open = optee_open, .release = optee_release, @@ -323,9 +358,9 @@ static const struct tee_driver_ops optee_ops = { .shm_unregister = optee_shm_unregister, }; -static const struct tee_desc optee_desc = { +static const struct tee_desc optee_clnt_desc = { .name = DRIVER_NAME "-clnt", - .ops = &optee_ops, + .ops = &optee_clnt_ops, .owner = THIS_MODULE, }; @@ -346,6 +381,12 @@ static const struct tee_desc optee_supp_desc = { .flags = TEE_DESC_PRIVILEGED, }; +static const struct optee_ops optee_ops = { + .do_call_with_arg = optee_do_call_with_arg, + .to_msg_param = optee_to_msg_param, + .from_msg_param = optee_from_msg_param, +}; + static bool optee_msg_api_uid_is_optee_api(optee_invoke_fn *invoke_fn) { struct arm_smccc_res res; @@ -647,10 +688,11 @@ static int optee_probe(struct platform_device *pdev) goto err; } + optee->ops = &optee_ops; optee->invoke_fn = invoke_fn; optee->sec_caps = sec_caps; - teedev = tee_device_alloc(&optee_desc, NULL, pool, optee); + teedev = tee_device_alloc(&optee_clnt_desc, NULL, pool, optee); if (IS_ERR(teedev)) { rc = PTR_ERR(teedev); goto err; diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h index 2b63b796645e..c5741e96e967 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2015-2021, Linaro Limited */ #ifndef OPTEE_PRIVATE_H @@ -66,9 +66,34 @@ struct optee_supp { struct completion reqs_c; }; +struct optee; + +/** + * struct optee_ops - OP-TEE driver internal operations + * @do_call_with_arg: enters OP-TEE in secure world + * @to_msg_param: converts from struct tee_param to OPTEE_MSG parameters + * @from_msg_param: converts from OPTEE_MSG parameters to struct tee_param + * + * These OPs are only supposed to be used internally in the OP-TEE driver + * as a way of abstracting the different methogs of entering OP-TEE in + * secure world. + */ +struct optee_ops { + int (*do_call_with_arg)(struct tee_context *ctx, + struct tee_shm *shm_arg); + int (*to_msg_param)(struct optee *optee, + struct optee_msg_param *msg_params, + size_t num_params, const struct tee_param *params); + int (*from_msg_param)(struct optee *optee, struct tee_param *params, + size_t num_params, + const struct optee_msg_param *msg_params); +}; + /** * struct optee - main service struct * @supp_teedev: supplicant device + * @ops: internal callbacks for different ways to reach secure + * world * @teedev: client device * @invoke_fn: function to issue smc or hvc * @call_queue: queue of threads waiting to call @invoke_fn @@ -86,6 +111,7 @@ struct optee_supp { struct optee { struct tee_device *supp_teedev; struct tee_device *teedev; + const struct optee_ops *ops; optee_invoke_fn *invoke_fn; struct optee_call_queue call_queue; struct optee_wait_queue wait_queue; @@ -148,7 +174,7 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params, int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params, struct tee_param *param); -u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg); +int optee_do_call_with_arg(struct tee_context *ctx, struct tee_shm *arg); int optee_open_session(struct tee_context *ctx, struct tee_ioctl_open_session_arg *arg, struct tee_param *param); @@ -171,11 +197,6 @@ int optee_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm, unsigned long start); 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, - const struct tee_param *params); - u64 *optee_allocate_pages_list(size_t num_entries); void optee_free_pages_list(void *array, size_t num_entries); void optee_fill_pages_list(u64 *dst, struct page **pages, int num_pages, diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c index a3a1aa59f639..f64a0ec472e0 100644 --- a/drivers/tee/optee/rpc.c +++ b/drivers/tee/optee/rpc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2015-2016, Linaro Limited + * Copyright (c) 2015-2021, Linaro Limited */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -56,6 +56,7 @@ static void handle_rpc_func_cmd_get_time(struct optee_msg_arg *arg) static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx, struct optee_msg_arg *arg) { + struct optee *optee = tee_get_drvdata(ctx->teedev); struct i2c_client client = { 0 }; struct tee_param *params; size_t i; @@ -79,7 +80,8 @@ static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx, return; } - if (optee_from_msg_param(params, arg->num_params, arg->params)) + if (optee->ops->from_msg_param(optee, params, arg->num_params, + arg->params)) goto bad; for (i = 0; i < arg->num_params; i++) { @@ -122,7 +124,8 @@ static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx, arg->ret = TEEC_ERROR_COMMUNICATION; } else { params[3].u.value.a = ret; - if (optee_to_msg_param(arg->params, arg->num_params, params)) + if (optee->ops->to_msg_param(optee, arg->params, + arg->num_params, params)) arg->ret = TEEC_ERROR_BAD_PARAMETERS; else arg->ret = TEEC_SUCCESS; @@ -234,7 +237,7 @@ static void handle_rpc_func_cmd_wait(struct optee_msg_arg *arg) arg->ret = TEEC_ERROR_BAD_PARAMETERS; } -static void handle_rpc_supp_cmd(struct tee_context *ctx, +static void handle_rpc_supp_cmd(struct tee_context *ctx, struct optee *optee, struct optee_msg_arg *arg) { struct tee_param *params; @@ -248,14 +251,16 @@ static void handle_rpc_supp_cmd(struct tee_context *ctx, return; } - if (optee_from_msg_param(params, arg->num_params, arg->params)) { + if (optee->ops->from_msg_param(optee, params, arg->num_params, + arg->params)) { arg->ret = TEEC_ERROR_BAD_PARAMETERS; goto out; } arg->ret = optee_supp_thrd_req(ctx, arg->cmd, arg->num_params, params); - if (optee_to_msg_param(arg->params, arg->num_params, params)) + if (optee->ops->to_msg_param(optee, arg->params, arg->num_params, + params)) arg->ret = TEEC_ERROR_BAD_PARAMETERS; out: kfree(params); @@ -480,7 +485,7 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee, handle_rpc_func_cmd_i2c_transfer(ctx, arg); break; default: - handle_rpc_supp_cmd(ctx, arg); + handle_rpc_supp_cmd(ctx, optee, arg); } } From patchwork Thu Mar 25 15:44:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Wiklander X-Patchwork-Id: 12164473 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 08F87C433DB for ; Thu, 25 Mar 2021 15:46:38 +0000 (UTC) Received: from desiato.infradead.org (desiato.infradead.org [90.155.92.199]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 99D6C61A1D for ; Thu, 25 Mar 2021 15:46:37 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 99D6C61A1D Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=desiato.20200630; h=Sender:Content-Transfer-Encoding :Content-Type:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=RSTLG1Rzj81/e6DUiGIgcfhVp7uYwOf/lg9MkVBn+EI=; b=hQApiErR9ITttR05WRyKavnpd akxRzmHkRTpI36Z2iSUqCpOIScSmxXNFhgPc+ijSLYAEhWxsqQOHMW6DjTbDRCKsod4djwHt8vwQm 4zEbqZsNYqqQ5dOc1V59cZL+QhIfpoN+19DKYX1Vg72WXHMUSiU/Dxwor9Z4y//UichmRTMVDWVI+ dv48pkvtALbGVG3/H84/AVuUaTsmIelbg5o1gibBOsoX8GwoxHDeKZ9FgkD8gfCFRGVMZyKJTLiji 8BJV3AeVwSKnzPept/3V7jAmfBLg6q7Rx4AUmXD5dbVu9LPS2LWeb11zGx27TYmbKBuL/i+l14txs rfggvpq+w==; Received: from localhost ([::1] helo=desiato.infradead.org) by desiato.infradead.org with esmtp (Exim 4.94 #2 (Red Hat Linux)) id 1lPSAa-001kVz-Lm; Thu, 25 Mar 2021 15:45:12 +0000 Received: from mail-lf1-x129.google.com ([2a00:1450:4864:20::129]) by desiato.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1lPSA6-001kR8-03 for linux-arm-kernel@lists.infradead.org; Thu, 25 Mar 2021 15:44:44 +0000 Received: by mail-lf1-x129.google.com with SMTP id v15so3200578lfq.5 for ; Thu, 25 Mar 2021 08:44:41 -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=YSMhRaAh0/rjMIx1myzNsTqUJ67O67HuU1P0C4BZ2/I=; b=EFKuh+lJ9rIFnC8y5rU4o8VuR5CXMEyL4syonu1xoPso3+1efItVAIODBBtxJu6HOz 9OdKJHOf7uFynDibDEPArpPqHRN/Vj9KpsRf0Qq+8Z+p2WjVOq0QX2PbV+T+iR92YLHe MxfbOrq+MlOQlFSfeEBQkoG+smcd3ySJOH4AmdlwNNeFqcFlmHIv9RPBrTnPKX/PyBi7 3vfSFkIwwGqd3owY9p85ozgMxUgh9VJo8gEOAQN9DC3R/Dq14jF483sTFXieQtDnXroH KzrggQme1gsorGdxr+MuqnsSrmkuB5S3wzBkeq4xz2UuVUtvIKGXTkY45uVnKohlaRCF ELFg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=YSMhRaAh0/rjMIx1myzNsTqUJ67O67HuU1P0C4BZ2/I=; b=egN5nqn7xGSZVlxieZIvSQD/0wXWwvqrcOsRLLJVhDM2RiCQ99pGeh7BudTt84GBvs ojE6RLHiBRoT6PdgRaEjsIWUMLCAM1PT1VEmMgNsA1xTXlzo1lFAEP0DFImkUH470OeX VJZd484nYG7IB+j6swTlj7ARyA6un7MUO0VLAYnBr1tFyQ8c9Rb4rF0r5SoW+98+cv07 KjXeu1fkgQU1mEfrxWtWmHUN4eMEml9nfF7jULRizfacC2N6/75XriSf1ieo1iwZhygp 3csI+lF5gid5/Eb4yZ0wJpPs4dIj8ecRobffG0yZxm7gbQ1RJ7QcENdmV14Na185PVXL JzMw== X-Gm-Message-State: AOAM5318ZZNhVD5vvJF2c2k6p0SSpPeiW8pwOtMovIf/fpNunLw+o3b6 evjtkDdBipg3Vm3QbFqwVr7sCg== X-Google-Smtp-Source: ABdhPJwb5w57NuuGD741guscv+zO4NeeLTibb/qQCJDVLFcWKCp06a7alF830Xu+/+cw57Os0NaFLw== X-Received: by 2002:a19:b03:: with SMTP id 3mr5493439lfl.236.1616687080578; Thu, 25 Mar 2021 08:44:40 -0700 (PDT) Received: from jade.urgonet (h-249-223.A175.priv.bahnhof.se. [98.128.249.223]) by smtp.gmail.com with ESMTPSA id m27sm770916ljc.109.2021.03.25.08.44.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Mar 2021 08:44:40 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, op-tee@lists.trustedfirmware.org Cc: Sudeep Holla , Marc Bonnici , Jerome Forissier , Jens Wiklander Subject: [PATCH 5/6] optee: add a FF-A memory pool Date: Thu, 25 Mar 2021 16:44:25 +0100 Message-Id: <20210325154426.3520148-6-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210325154426.3520148-1-jens.wiklander@linaro.org> References: <20210325154426.3520148-1-jens.wiklander@linaro.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210325_154442_110229_A35CC92B X-CRM114-Status: GOOD ( 17.75 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Adds a memory pool to be used when the driver uses FF-A [1] as transport layer. [1] https://developer.arm.com/documentation/den0077/latest Signed-off-by: Jens Wiklander --- drivers/tee/optee/shm_pool.c | 65 +++++++++++++++++++++++++++++++++--- drivers/tee/optee/shm_pool.h | 1 + 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/drivers/tee/optee/shm_pool.c b/drivers/tee/optee/shm_pool.c index d767eebf30bd..d2116cb39c8b 100644 --- a/drivers/tee/optee/shm_pool.c +++ b/drivers/tee/optee/shm_pool.c @@ -12,8 +12,14 @@ #include "optee_smc.h" #include "shm_pool.h" -static int pool_op_alloc(struct tee_shm_pool_mgr *poolm, - struct tee_shm *shm, size_t size) +static int +pool_op_alloc_helper(struct tee_shm_pool_mgr *poolm, + struct tee_shm *shm, size_t size, + int (*shm_register)(struct tee_context *ctx, + struct tee_shm *shm, + struct page **pages, + size_t num_pages, + unsigned long start)) { unsigned int order = get_order(size); struct page *page; @@ -27,7 +33,7 @@ static int pool_op_alloc(struct tee_shm_pool_mgr *poolm, shm->paddr = page_to_phys(page); shm->size = PAGE_SIZE << order; - if (shm->flags & TEE_SHM_DMA_BUF) { + if (shm_register) { unsigned int nr_pages = 1 << order, i; struct page **pages; @@ -41,14 +47,23 @@ static int pool_op_alloc(struct tee_shm_pool_mgr *poolm, } shm->flags |= TEE_SHM_REGISTER; - rc = optee_shm_register(shm->ctx, shm, pages, nr_pages, - (unsigned long)shm->kaddr); + rc = shm_register(shm->ctx, shm, pages, nr_pages, + (unsigned long)shm->kaddr); kfree(pages); } return rc; } +static int pool_op_alloc(struct tee_shm_pool_mgr *poolm, + struct tee_shm *shm, size_t size) +{ + if (!(shm->flags & TEE_SHM_DMA_BUF)) + return pool_op_alloc_helper(poolm, shm, size, NULL); + + return pool_op_alloc_helper(poolm, shm, size, optee_shm_register); +} + static void pool_op_free(struct tee_shm_pool_mgr *poolm, struct tee_shm *shm) { @@ -87,3 +102,43 @@ struct tee_shm_pool_mgr *optee_shm_pool_alloc_pages(void) return mgr; } + +#ifdef CONFIG_ARM_FFA_TRANSPORT +static int pool_ffa_op_alloc(struct tee_shm_pool_mgr *poolm, + struct tee_shm *shm, size_t size) +{ + return pool_op_alloc_helper(poolm, shm, size, optee_ffa_shm_register); +} + +static void pool_ffa_op_free(struct tee_shm_pool_mgr *poolm, + struct tee_shm *shm) +{ + optee_ffa_shm_unregister(shm->ctx, shm); + free_pages((unsigned long)shm->kaddr, get_order(shm->size)); + shm->kaddr = NULL; +} + +static const struct tee_shm_pool_mgr_ops pool_ffa_ops = { + .alloc = pool_ffa_op_alloc, + .free = pool_ffa_op_free, + .destroy_poolmgr = pool_op_destroy_poolmgr, +}; + +/** + * optee_ffa_shm_pool_alloc_pages() - create page-based allocator pool + * + * This pool is used with OP-TEE over FF-A. In this case command buffers + * and such are allocated from kernel's own memory. + */ +struct tee_shm_pool_mgr *optee_ffa_shm_pool_alloc_pages(void) +{ + struct tee_shm_pool_mgr *mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); + + if (!mgr) + return ERR_PTR(-ENOMEM); + + mgr->ops = &pool_ffa_ops; + + return mgr; +} +#endif /*CONFIG_ARM_FFA_TRANSPORT*/ diff --git a/drivers/tee/optee/shm_pool.h b/drivers/tee/optee/shm_pool.h index 28109d991c4b..34c5fd74a3ff 100644 --- a/drivers/tee/optee/shm_pool.h +++ b/drivers/tee/optee/shm_pool.h @@ -10,5 +10,6 @@ #include struct tee_shm_pool_mgr *optee_shm_pool_alloc_pages(void); +struct tee_shm_pool_mgr *optee_ffa_shm_pool_alloc_pages(void); #endif From patchwork Thu Mar 25 15:44:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Wiklander X-Patchwork-Id: 12164479 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 00569C433DB for ; Thu, 25 Mar 2021 15:47:09 +0000 (UTC) Received: from desiato.infradead.org (desiato.infradead.org [90.155.92.199]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 50AB2619A3 for ; Thu, 25 Mar 2021 15:47:09 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 50AB2619A3 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=desiato.20200630; h=Sender:Content-Transfer-Encoding :Content-Type:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=euBgkGsdmCTHfkm3eDD9WGxNYtR7WC+p4ZwOdOkqHz4=; b=ew0skK/l1vy0LA0gguJRsvzKD lrR6i+2egK0ki+TxxkrsbhuKCyoGbM6XXA15a8mlFRlrEWSc09JGKCvUyPE4sbzgHfE20lAvninih RD9xx+esyLetr0kiEJqelQ54lKLHtz/REjp/4RDMYw+5R6OGgZ8zrT6eDvwESRAyUPiOQUk0kKfBF 59ZWmZa6Lg3UiurobWgPkrROZN++wir/Mls97MQagVEBU7PqSt3WVZ3jwGllrqwgW25TIPc1S+mSr WEB0jupgfCalqJ1EbN6pWQhvqefcaQcsYyIsEBCjIQP83b0rXwuMtrCUwtyQ4Os7NSyo6ES3MznOW g2prqAh7w==; Received: from localhost ([::1] helo=desiato.infradead.org) by desiato.infradead.org with esmtp (Exim 4.94 #2 (Red Hat Linux)) id 1lPSAx-001kcK-Hw; Thu, 25 Mar 2021 15:45:35 +0000 Received: from mail-lf1-x135.google.com ([2a00:1450:4864:20::135]) by desiato.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1lPSA7-001kRl-Co for linux-arm-kernel@lists.infradead.org; Thu, 25 Mar 2021 15:44:47 +0000 Received: by mail-lf1-x135.google.com with SMTP id w37so3154906lfu.13 for ; Thu, 25 Mar 2021 08:44:42 -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=W/ABsZPfY+hi03qsbfAKmszWHVXCbEsiMHoHqOadIXE=; b=CA8zTXWaDTjMxejLJUvBtNzib8kjMhGVZOAcUItMacer4lO3IyDH9M/DmtzRxwg52R IzuyFq8alG9+zHNTkGiItJraj+hxaXil31nW9iCoFoLsFkpA5Lv9tSiTLxwlgxoppKe/ kLAULrciDUNjXi5SrUxDmdb4wsyel37JdugaN/mpG5zT4WFAS/QaW9WphizCvxXbo5Ui D/OK7kjBhNrNdsZU9AV6t+4X29U+FaZ7e+IwSBeDNCu/6Msl07MPnrSBFLCq36eQrqa3 arndFHpgrUOqyqYUq3VAy6s648WqIg+giAaGrNlxpu2SWzcE0keoHwBs2hy6qmyTB5NE rVhQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=W/ABsZPfY+hi03qsbfAKmszWHVXCbEsiMHoHqOadIXE=; b=ZLOKCA4Fiy273ipizAlb0T+BhBqotvHSx8ntbFNdDu/eONq1P/wscGvlx2GJnhm2xM 9Hbxc/M+U6elk2+V7p2aQg/J9fNyyBsS7wc95of1nn45hyCyd9TRUxaBI6ZL0QzpfveG 187nntooOi0buj/5cMsLSRYQlz+JwgNSHNdNY/Cp5zN/gcAFGb+w6JizlYgbG0ppJ0My gOREIZseSaj4esT9mqQIGpv9XXh7Q9oLTFTxqRWyhOtHSSqIXhtJNeDbTtjVcmAo7q0u X/5+LSKYp1aH6Y6A6FnKlios+PE/kCj01O1/D3tnMtcvD1xGiZe2gChyudmXmHLfV0T6 NxmA== X-Gm-Message-State: AOAM530m+At3pKgPGNfbCb3PpL4dN6ICDNtJnLsth65sQFq87h5J7SoO yuK2w498ubVGGFiaKGC2v9IU9g== X-Google-Smtp-Source: ABdhPJz3VOW6/4oEt7YZrMHBeHSdrQHk89Ci8HIcVr0CBNk3tvdaYNkzkC3+TP9tnFMGfLq36qalcg== X-Received: by 2002:a19:b81:: with SMTP id 123mr5416728lfl.553.1616687081771; Thu, 25 Mar 2021 08:44:41 -0700 (PDT) Received: from jade.urgonet (h-249-223.A175.priv.bahnhof.se. [98.128.249.223]) by smtp.gmail.com with ESMTPSA id m27sm770916ljc.109.2021.03.25.08.44.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Mar 2021 08:44:41 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, op-tee@lists.trustedfirmware.org Cc: Sudeep Holla , Marc Bonnici , Jerome Forissier , Jens Wiklander Subject: [PATCH 6/6] optee: add FF-A support Date: Thu, 25 Mar 2021 16:44:26 +0100 Message-Id: <20210325154426.3520148-7-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210325154426.3520148-1-jens.wiklander@linaro.org> References: <20210325154426.3520148-1-jens.wiklander@linaro.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210325_154443_612014_8060CEDE X-CRM114-Status: GOOD ( 28.99 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Adds support for using FF-A [1] as transport to the OP-TEE driver. Introduces struct optee_msg_param_fmem which carries all information needed when OP-TEE is calling FFA_MEM_RETRIEVE_REQ to get the shared memory reference mapped by the hypervisor in S-EL2. Register usage is also updated to include the information needed. The FF-A part of this driver is enabled if CONFIG_ARM_FFA_TRANSPORT is enabled. [1] https://developer.arm.com/documentation/den0077/latest Signed-off-by: Jens Wiklander --- drivers/tee/optee/call.c | 222 +++++++++++++- drivers/tee/optee/core.c | 485 +++++++++++++++++++++++++++++- drivers/tee/optee/optee_ffa.h | 153 ++++++++++ drivers/tee/optee/optee_msg.h | 27 +- drivers/tee/optee/optee_private.h | 52 ++++ drivers/tee/optee/rpc.c | 118 ++++++++ 6 files changed, 1041 insertions(+), 16 deletions(-) create mode 100644 drivers/tee/optee/optee_ffa.h diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c index ef049c0dee50..c559f82e1343 100644 --- a/drivers/tee/optee/call.c +++ b/drivers/tee/optee/call.c @@ -3,17 +3,20 @@ * Copyright (c) 2015-2021, Linaro Limited */ #include +#include #include #include #include #include #include +#include #include #include #include #include #include "optee_private.h" #include "optee_smc.h" +#include "optee_ffa.h" struct optee_call_waiter { struct list_head list_node; @@ -180,29 +183,33 @@ int optee_do_call_with_arg(struct tee_context *ctx, struct tee_shm *arg) static struct tee_shm *get_msg_arg(struct tee_context *ctx, size_t num_params, struct optee_msg_arg **msg_arg) { - int rc; + struct optee *optee = tee_get_drvdata(ctx->teedev); + size_t sz = OPTEE_MSG_GET_ARG_SIZE(num_params); struct tee_shm *shm; struct optee_msg_arg *ma; - shm = tee_shm_alloc(ctx, OPTEE_MSG_GET_ARG_SIZE(num_params), - TEE_SHM_MAPPED); + /* + * rpc_arg_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. So far only + * enabled when using FF-A as transport layer. + */ + if (optee->rpc_arg_count) + sz += OPTEE_MSG_GET_ARG_SIZE(optee->rpc_arg_count); + + shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED); if (IS_ERR(shm)) return shm; ma = tee_shm_get_va(shm, 0); if (IS_ERR(ma)) { - rc = PTR_ERR(ma); - goto out; + tee_shm_free(shm); + return (void *)ma; } memset(ma, 0, OPTEE_MSG_GET_ARG_SIZE(num_params)); ma->num_params = num_params; *msg_arg = ma; -out: - if (rc) { - tee_shm_free(shm); - return ERR_PTR(rc); - } return shm; } @@ -677,3 +684,198 @@ int optee_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm) { return 0; } + +#ifdef CONFIG_ARM_FFA_TRANSPORT +static int optee_ffa_yielding_call(struct tee_context *ctx, + struct ffa_send_direct_data *data, + struct optee_msg_arg *rpc_arg) +{ + struct optee *optee = tee_get_drvdata(ctx->teedev); + const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_ops; + struct ffa_device *ffa_dev = optee->ffa.ffa_dev; + struct optee_call_waiter w; + u32 cmd = data->data0; + u32 w4 = data->data1; + u32 w5 = data->data2; + u32 w6 = data->data3; + int rc; + + /* Initialize waiter */ + optee_cq_wait_init(&optee->call_queue, &w); + while (true) { + rc = ffa_ops->sync_send_receive(ffa_dev, data); + if (rc) + goto done; + + switch ((int)data->data0) { + case TEEC_SUCCESS: + break; + case TEEC_ERROR_BUSY: + if (cmd == OPTEE_FFA_YIELDING_CALL_RESUME) { + rc = -EIO; + goto done; + } + + /* + * Out of threads in secure world, wait for a thread + * become available. + */ + optee_cq_wait_for_completion(&optee->call_queue, &w); + data->data0 = cmd; + data->data1 = w4; + data->data2 = w5; + data->data3 = w6; + continue; + default: + rc = -EIO; + goto done; + } + + if (data->data1 == OPTEE_FFA_YIELDING_CALL_RETURN_DONE) + goto done; + + /* + * OP-TEE has returned with a RPC request. + * + * Note that data->data4 (passed in register w7) is already + * filled in by ffa_ops->sync_send_receive() returning + * above. + */ + cond_resched(); + optee_handle_ffa_rpc(ctx, data->data1, rpc_arg); + cmd = OPTEE_FFA_YIELDING_CALL_RESUME; + data->data0 = cmd; + data->data1 = 0; + data->data2 = 0; + data->data3 = 0; + } +done: + /* + * We're done with our thread in secure world, if there's any + * thread waiters wake up one. + */ + optee_cq_wait_final(&optee->call_queue, &w); + + return rc; +} + +/** + * 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 + * + * Does a FF-A call to OP-TEE in secure world and handles eventual resulting + * Remote Procedure Calls (RPC) from OP-TEE. + * + * Returns return code from FF-A, 0 is OK + */ + +int optee_ffa_do_call_with_arg(struct tee_context *ctx, struct tee_shm *shm) +{ + struct ffa_send_direct_data data = { + .data0 = OPTEE_FFA_YIELDING_CALL_WITH_ARG, + .data1 = (u32)shm->sec_world_id, + .data2 = (u32)(shm->sec_world_id >> 32), + .data3 = shm->offset, + }; + struct optee_msg_arg *arg = tee_shm_get_va(shm, 0); + unsigned int rpc_arg_offs = OPTEE_MSG_GET_ARG_SIZE(arg->num_params); + struct optee_msg_arg *rpc_arg = tee_shm_get_va(shm, rpc_arg_offs); + + return optee_ffa_yielding_call(ctx, &data, rpc_arg); +} + +int optee_ffa_shm_register(struct tee_context *ctx, struct tee_shm *shm, + struct page **pages, size_t num_pages, + unsigned long start) +{ + struct optee *optee = tee_get_drvdata(ctx->teedev); + const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_ops; + struct ffa_device *ffa_dev = optee->ffa.ffa_dev; + struct ffa_mem_region_attributes mem_attr = { + .receiver = ffa_dev->vm_id, + .attrs = FFA_MEM_RW, + }; + struct ffa_mem_ops_args args = { + .use_txbuf = true, + .attrs = &mem_attr, + .nattrs = 1, + }; + struct sg_table sgt; + int rc; + + rc = check_mem_type(start, num_pages); + if (rc) + return rc; + + rc = sg_alloc_table_from_pages(&sgt, pages, num_pages, 0, + num_pages * PAGE_SIZE, GFP_KERNEL); + if (rc) + return rc; + args.sg = sgt.sgl; + rc = ffa_ops->memory_share(ffa_dev, &args); + sg_free_table(&sgt); + if (rc) + return rc; + + rc = optee_shm_add_ffa_handle(optee, shm, args.g_handle); + if (rc) { + ffa_ops->memory_reclaim(args.g_handle, 0); + return rc; + } + + shm->sec_world_id = args.g_handle; + + return 0; +} + +int optee_ffa_shm_unregister(struct tee_context *ctx, struct tee_shm *shm) +{ + struct optee *optee = tee_get_drvdata(ctx->teedev); + const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_ops; + struct ffa_device *ffa_dev = optee->ffa.ffa_dev; + u64 global_handle = shm->sec_world_id; + struct ffa_send_direct_data data = { + .data0 = OPTEE_FFA_UNREGISTER_SHM, + .data1 = (u32)global_handle, + .data2 = (u32)(global_handle >> 32) + }; + int rc; + + optee_shm_rem_ffa_handle(optee, global_handle); + shm->sec_world_id = 0; + + rc = ffa_ops->sync_send_receive(ffa_dev, &data); + if (rc) + pr_err("Unregister SHM id 0x%llx rc %d\n", global_handle, rc); + + rc = ffa_ops->memory_reclaim(global_handle, 0); + if (rc) + pr_err("mem_reclain: 0x%llx %d", global_handle, rc); + + return rc; +} + +int optee_ffa_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm) +{ + struct optee *optee = tee_get_drvdata(ctx->teedev); + const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_ops; + u64 global_handle = shm->sec_world_id; + int rc; + + /* + * We're skipping the OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM call + * since this is OP-TEE freeing via RPC so it has already retired + * this ID. + */ + + optee_shm_rem_ffa_handle(optee, global_handle); + rc = ffa_ops->memory_reclaim(global_handle, 0); + if (rc) + pr_err("mem_reclain: 0x%llx %d", global_handle, rc); + + shm->sec_world_id = 0; + + return rc; +} +#endif /*CONFIG_ARM_FFA_TRANSPORT*/ diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index ab602bb8e14a..224d402bac98 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -6,6 +6,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include +#include #include #include #include @@ -20,6 +21,7 @@ #include #include "optee_private.h" #include "optee_smc.h" +#include "optee_ffa.h" #include "shm_pool.h" #define DRIVER_NAME "optee" @@ -299,10 +301,9 @@ static int optee_open(struct tee_context *ctx) mutex_init(&ctxdata->mutex); INIT_LIST_HEAD(&ctxdata->sess_list); - if (optee->sec_caps & OPTEE_SMC_SEC_CAP_MEMREF_NULL) - ctx->cap_memref_null = true; - else - ctx->cap_memref_null = false; + ctx->cap_memref_null = optee_is_ffa_based(optee) || + (optee->sec_caps & + OPTEE_SMC_SEC_CAP_MEMREF_NULL); ctx->data = ctxdata; return 0; @@ -567,6 +568,471 @@ optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm) return rc; } +#ifdef CONFIG_ARM_FFA_TRANSPORT +static void optee_ffa_get_version(struct tee_device *teedev, + struct tee_ioctl_version_data *vers) +{ + struct tee_ioctl_version_data v = { + .impl_id = TEE_IMPL_ID_OPTEE, + .impl_caps = TEE_OPTEE_CAP_TZ, + .gen_caps = TEE_GEN_CAP_GP | TEE_GEN_CAP_REG_MEM | + TEE_GEN_CAP_MEMREF_NULL, + }; + + *vers = v; +} + +struct shm_rhash { + struct tee_shm *shm; + u64 global_id; + struct rhash_head linkage; +}; + +static void rh_free_fn(void *ptr, void *arg) +{ + kfree(ptr); +} + +static const struct rhashtable_params shm_rhash_params = { + .head_offset = offsetof(struct shm_rhash, linkage), + .key_len = sizeof(u64), + .key_offset = offsetof(struct shm_rhash, global_id), + .automatic_shrinking = true, +}; + +struct tee_shm *optee_shm_from_ffa_handle(struct optee *optee, u64 global_id) +{ + struct tee_shm *shm = NULL; + struct shm_rhash *r; + + mutex_lock(&optee->ffa.mutex); + r = rhashtable_lookup_fast(&optee->ffa.global_ids, &global_id, + shm_rhash_params); + if (r) + shm = r->shm; + mutex_unlock(&optee->ffa.mutex); + + return shm; +} + +int optee_shm_add_ffa_handle(struct optee *optee, struct tee_shm *shm, + u64 global_id) +{ + struct shm_rhash *r; + int rc; + + r = kmalloc(sizeof(*r), GFP_KERNEL); + if (!r) + return -ENOMEM; + r->shm = shm; + r->global_id = global_id; + + mutex_lock(&optee->ffa.mutex); + rc = rhashtable_lookup_insert_fast(&optee->ffa.global_ids, &r->linkage, + shm_rhash_params); + mutex_unlock(&optee->ffa.mutex); + + if (rc) + kfree(r); + + return rc; +} + +int optee_shm_rem_ffa_handle(struct optee *optee, u64 global_id) +{ + struct shm_rhash *r; + int rc = -ENOENT; + + mutex_lock(&optee->ffa.mutex); + r = rhashtable_lookup_fast(&optee->ffa.global_ids, &global_id, + shm_rhash_params); + if (r) + rc = rhashtable_remove_fast(&optee->ffa.global_ids, + &r->linkage, shm_rhash_params); + mutex_unlock(&optee->ffa.mutex); + + if (!rc) + kfree(r); + + return rc; +} + +static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p, + u32 attr, const struct optee_msg_param *mp) +{ + struct tee_shm *shm = NULL; + u64 offs_high = 0; + u64 offs_low = 0; + + p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT + + attr - OPTEE_MSG_ATTR_TYPE_FMEM_INPUT; + p->u.memref.size = mp->u.fmem.size; + + if (mp->u.fmem.global_id != OPTEE_MSG_FMEM_INVALID_GLOBAL_ID) + shm = optee_shm_from_ffa_handle(optee, mp->u.fmem.global_id); + p->u.memref.shm = shm; + + if (shm) { + offs_low = mp->u.fmem.offs_low; + offs_high = mp->u.fmem.offs_high; + } + p->u.memref.shm_offs = offs_low | offs_high << 32; +} + +/** + * optee_ffa_from_msg_param() - convert from OPTEE_MSG parameters to + * struct tee_param + * @optee: main service struct + * @params: subsystem internal parameter representation + * @num_params: number of elements in the parameter arrays + * @msg_params: OPTEE_MSG parameters + * + * Returns 0 on success or <0 on failure + */ +static int optee_ffa_from_msg_param(struct optee *optee, + struct tee_param *params, size_t num_params, + const struct optee_msg_param *msg_params) +{ + size_t n; + + for (n = 0; n < num_params; n++) { + struct tee_param *p = params + n; + const struct optee_msg_param *mp = msg_params + n; + u32 attr = mp->attr & OPTEE_MSG_ATTR_TYPE_MASK; + + switch (attr) { + case OPTEE_MSG_ATTR_TYPE_NONE: + p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE; + memset(&p->u, 0, sizeof(p->u)); + break; + case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT: + case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT: + case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT: + from_msg_param_value(p, attr, mp); + break; + case OPTEE_MSG_ATTR_TYPE_FMEM_INPUT: + case OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT: + case OPTEE_MSG_ATTR_TYPE_FMEM_INOUT: + from_msg_param_ffa_mem(optee, p, attr, mp); + break; + default: + return -EINVAL; + } + } + + return 0; +} + +static int to_msg_param_ffa_mem(struct optee_msg_param *mp, + const struct tee_param *p) +{ + struct tee_shm *shm = p->u.memref.shm; + + mp->attr = OPTEE_MSG_ATTR_TYPE_FMEM_INPUT + p->attr - + TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT; + + if (shm) { + u64 shm_offs = p->u.memref.shm_offs; + + mp->u.fmem.internal_offs = shm->offset; + + mp->u.fmem.offs_low = shm_offs; + mp->u.fmem.offs_high = shm_offs >> 32; + /* Check that the entire offset could be stored. */ + if (mp->u.fmem.offs_high != shm_offs >> 32) + return -EINVAL; + + mp->u.fmem.global_id = shm->sec_world_id; + } else { + memset(&mp->u, 0, sizeof(mp->u)); + mp->u.fmem.global_id = OPTEE_MSG_FMEM_INVALID_GLOBAL_ID; + } + mp->u.fmem.size = p->u.memref.size; + + return 0; +} + +/** + * optee_to_msg_param() - convert from struct tee_params to OPTEE_MSG parameters + * @optee: main service struct + * @msg_params: OPTEE_MSG parameters + * @num_params: number of elements in the parameter arrays + * @params: subsystem itnernal parameter representation + * Returns 0 on success or <0 on failure + */ +static int optee_ffa_to_msg_param(struct optee *optee, + struct optee_msg_param *msg_params, + size_t num_params, + const struct tee_param *params) +{ + size_t n; + + for (n = 0; n < num_params; n++) { + const struct tee_param *p = params + n; + struct optee_msg_param *mp = msg_params + n; + + switch (p->attr) { + case TEE_IOCTL_PARAM_ATTR_TYPE_NONE: + mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE; + memset(&mp->u, 0, sizeof(mp->u)); + break; + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT: + to_msg_param_value(mp, p); + break; + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: + if (to_msg_param_ffa_mem(mp, p)) + return -EINVAL; + break; + default: + return -EINVAL; + } + } + + return 0; +} + +static bool optee_ffa_api_is_compatbile(struct ffa_device *ffa_dev, + const struct ffa_dev_ops *ops) +{ + struct ffa_send_direct_data data = { OPTEE_FFA_GET_API_VERSION }; + int rc; + + ops->mode_32bit_set(ffa_dev); + + rc = ops->sync_send_receive(ffa_dev, &data); + if (rc) { + pr_err("Unexpected error %d\n", rc); + return false; + } + if (data.data0 != OPTEE_FFA_VERSION_MAJOR || + data.data1 < OPTEE_FFA_VERSION_MINOR) { + pr_err("Incompatible OP-TEE API version %lu.%lu", + data.data0, data.data1); + return false; + } + + data = (struct ffa_send_direct_data){ OPTEE_FFA_GET_OS_VERSION }; + rc = ops->sync_send_receive(ffa_dev, &data); + if (rc) { + pr_err("Unexpected error %d\n", rc); + return false; + } + if (data.data2) + pr_info("revision %lu.%lu (%08lx)", + data.data0, data.data1, data.data2); + else + pr_info("revision %lu.%lu", data.data0, data.data1); + + return true; +} + +static bool optee_ffa_exchange_caps(struct ffa_device *ffa_dev, + const struct ffa_dev_ops *ops, + u32 *sec_caps, unsigned int *rpc_arg_count) +{ + struct ffa_send_direct_data data = { OPTEE_FFA_EXCHANGE_CAPABILITIES }; + int rc; + + rc = ops->sync_send_receive(ffa_dev, &data); + if (rc) { + pr_err("Unexpected error %d", rc); + return false; + } + if (data.data0) { + pr_err("Unexpected exchange error %lu", data.data0); + return false; + } + + *sec_caps = 0; + *rpc_arg_count = (u8)data.data1; + + return true; +} + +static struct tee_shm_pool *optee_ffa_config_dyn_shm(void) +{ + struct tee_shm_pool_mgr *priv_mgr; + struct tee_shm_pool_mgr *dmabuf_mgr; + void *rc; + + rc = optee_ffa_shm_pool_alloc_pages(); + if (IS_ERR(rc)) + return rc; + priv_mgr = rc; + + rc = optee_ffa_shm_pool_alloc_pages(); + if (IS_ERR(rc)) { + tee_shm_pool_mgr_destroy(priv_mgr); + return rc; + } + dmabuf_mgr = rc; + + rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr); + if (IS_ERR(rc)) { + tee_shm_pool_mgr_destroy(priv_mgr); + tee_shm_pool_mgr_destroy(dmabuf_mgr); + } + + return rc; +} + +static const struct tee_driver_ops optee_ffa_clnt_ops = { + .get_version = optee_ffa_get_version, + .open = optee_open, + .release = optee_release, + .open_session = optee_open_session, + .close_session = optee_close_session, + .invoke_func = optee_invoke_func, + .cancel_req = optee_cancel_req, + .shm_register = optee_ffa_shm_register, + .shm_unregister = optee_ffa_shm_unregister, +}; + +static const struct tee_desc optee_ffa_clnt_desc = { + .name = DRIVER_NAME "ffa-clnt", + .ops = &optee_ffa_clnt_ops, + .owner = THIS_MODULE, +}; + +static const struct tee_driver_ops optee_ffa_supp_ops = { + .get_version = optee_ffa_get_version, + .open = optee_open, + .release = optee_release_supp, + .supp_recv = optee_supp_recv, + .supp_send = optee_supp_send, + .shm_register = optee_ffa_shm_register, /* same as for clnt ops */ + .shm_unregister = optee_ffa_shm_unregister_supp, +}; + +static const struct tee_desc optee_ffa_supp_desc = { + .name = DRIVER_NAME "ffa-supp", + .ops = &optee_ffa_supp_ops, + .owner = THIS_MODULE, + .flags = TEE_DESC_PRIVILEGED, +}; + +static const struct optee_ops optee_ffa_ops = { + .do_call_with_arg = optee_ffa_do_call_with_arg, + .to_msg_param = optee_ffa_to_msg_param, + .from_msg_param = optee_ffa_from_msg_param, +}; + +static void optee_ffa_remove(struct ffa_device *ffa_dev) +{ + (void)ffa_dev; +} + +static int optee_ffa_probe(struct ffa_device *ffa_dev) +{ + const struct ffa_dev_ops *ffa_ops; + unsigned int rpc_arg_count; + struct tee_device *teedev; + struct optee *optee; + u32 sec_caps; + int rc; + + ffa_ops = ffa_dev_ops_get(ffa_dev); + if (!ffa_ops) { + pr_warn("failed \"method\" init: ffa\n"); + return -ENOENT; + } + + if (!optee_ffa_api_is_compatbile(ffa_dev, ffa_ops)) + return -EINVAL; + + if (!optee_ffa_exchange_caps(ffa_dev, ffa_ops, &sec_caps, + &rpc_arg_count)) + return -EINVAL; + + optee = kzalloc(sizeof(*optee), GFP_KERNEL); + if (!optee) { + rc = -ENOMEM; + goto err; + } + optee->pool = optee_ffa_config_dyn_shm(); + if (IS_ERR(optee->pool)) { + rc = PTR_ERR(optee->pool); + optee->pool = NULL; + goto err; + } + + optee->ops = &optee_ffa_ops; + optee->ffa.ffa_dev = ffa_dev; + optee->ffa.ffa_ops = ffa_ops; + optee->sec_caps = sec_caps; + optee->rpc_arg_count = rpc_arg_count; + + teedev = tee_device_alloc(&optee_ffa_clnt_desc, NULL, optee->pool, + optee); + if (IS_ERR(teedev)) { + rc = PTR_ERR(teedev); + goto err; + } + optee->teedev = teedev; + + teedev = tee_device_alloc(&optee_ffa_supp_desc, NULL, optee->pool, + optee); + if (IS_ERR(teedev)) { + rc = PTR_ERR(teedev); + goto err; + } + optee->supp_teedev = teedev; + + rc = tee_device_register(optee->teedev); + if (rc) + goto err; + + rc = tee_device_register(optee->supp_teedev); + if (rc) + goto err; + + rc = rhashtable_init(&optee->ffa.global_ids, &shm_rhash_params); + if (rc) + goto err; + mutex_init(&optee->ffa.mutex); + mutex_init(&optee->call_queue.mutex); + INIT_LIST_HEAD(&optee->call_queue.waiters); + optee_wait_queue_init(&optee->wait_queue); + optee_supp_init(&optee->supp); + ffa_dev_set_drvdata(ffa_dev, optee); + + pr_info("initialized driver\n"); + return 0; +err: + /* + * tee_device_unregister() is safe to call even if the + * devices hasn't been registered with + * tee_device_register() yet. + */ + tee_device_unregister(optee->supp_teedev); + tee_device_unregister(optee->teedev); + if (optee->pool) + tee_shm_pool_free(optee->pool); + kfree(optee); + return rc; +} + +static const struct ffa_device_id optee_ffa_device_id[] = { + /* 486178e0-e7f8-11e3-bc5e0002a5d5c51b */ + { UUID_INIT(0x486178e0, 0xe7f8, 0x11e3, + 0xbc, 0x5e, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b) }, + {} +}; + +static struct ffa_driver optee_ffa_driver = { + .name = "optee", + .probe = optee_ffa_probe, + .remove = optee_ffa_remove, + .id_table = optee_ffa_device_id, +}; + +module_ffa_driver(optee_ffa_driver); +#endif /*CONFIG_ARM_FFA_TRANSPORT*/ + /* Simple wrapper functions to be able to use a function pointer */ static void optee_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3, @@ -615,7 +1081,8 @@ static int optee_remove(struct platform_device *pdev) * reference counters and also avoid wild pointers in secure world * into the old shared memory range. */ - optee_disable_shm_cache(optee); + if (!optee_is_ffa_based(optee)) + optee_disable_shm_cache(optee); /* * The two devices have to be unregistered before we can free the @@ -631,6 +1098,14 @@ static int optee_remove(struct platform_device *pdev) optee_supp_uninit(&optee->supp); mutex_destroy(&optee->call_queue.mutex); +#ifdef CONFIG_ARM_FFA_TRANSPORT + if (optee->ffa.ffa_ops) { + mutex_destroy(&optee->ffa.mutex); + rhashtable_free_and_destroy(&optee->ffa.global_ids, + rh_free_fn, NULL); + } +#endif /*CONFIG_ARM_FFA_TRANSPORT*/ + kfree(optee); return 0; diff --git a/drivers/tee/optee/optee_ffa.h b/drivers/tee/optee/optee_ffa.h new file mode 100644 index 000000000000..ee3a03fc392c --- /dev/null +++ b/drivers/tee/optee/optee_ffa.h @@ -0,0 +1,153 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019-2021, Linaro Limited + */ + +/* + * This file is exported by OP-TEE and is kept in sync between secure world + * and normal world drivers. We're using ARM FF-A 1.0 specification. + */ + +#ifndef __OPTEE_FFA_H +#define __OPTEE_FFA_H + +#include + +/* + * Normal world sends requests with FFA_MSG_SEND_DIRECT_REQ and + * responses are returned with FFA_MSG_SEND_DIRECT_RESP for normal + * messages. + * + * All requests with FFA_MSG_SEND_DIRECT_REQ and FFA_MSG_SEND_DIRECT_RESP + * are using the AArch32 SMC calling convention with register usage as + * defined in FF-A specification: + * w0: Function ID (0x8400006F or 0x84000070) + * w1: Source/Destination IDs + * w2: Reserved (MBZ) + * w3-w7: Implementation defined, free to be used below + */ + +#define OPTEE_FFA_VERSION_MAJOR 1 +#define OPTEE_FFA_VERSION_MINOR 0 + +#define OPTEE_FFA_BLOCKING_CALL(id) (id) +#define OPTEE_FFA_YIELDING_CALL_BIT 31 +#define OPTEE_FFA_YIELDING_CALL(id) ((id) | BIT(OPTEE_FFA_YIELDING_CALL_BIT)) + +/* + * Returns the API version implemented, currently follows the FF-A version. + * Call register usage: + * w3: Service ID, OPTEE_FFA_GET_API_VERSION + * w4-w7: Not used (MBZ) + * + * Return register usage: + * w3: OPTEE_FFA_VERSION_MAJOR + * w4: OPTEE_FFA_VERSION_MINOR + * w5-w7: Not used (MBZ) + */ +#define OPTEE_FFA_GET_API_VERSION OPTEE_FFA_BLOCKING_CALL(0) + +/* + * Returns the revision of OP-TEE. + * + * Used by non-secure world to figure out which version of the Trusted OS + * is installed. Note that the returned revision is the revision of the + * Trusted OS, not of the API. + * + * Call register usage: + * w3: Service ID, OPTEE_FFA_GET_OS_VERSION + * w4-w7: Unused (MBZ) + * + * Return register usage: + * w3: CFG_OPTEE_REVISION_MAJOR + * w4: CFG_OPTEE_REVISION_MINOR + * w5: TEE_IMPL_GIT_SHA1 (or zero if not supported) + */ +#define OPTEE_FFA_GET_OS_VERSION OPTEE_FFA_BLOCKING_CALL(1) + +/* + * Exchange capabilities between normal world and secure world. + * + * Currently there are no defined capabilities. When features are added new + * capabilities may be added. + * + * Call register usage: + * w3: Service ID, OPTEE_FFA_EXCHANGE_CAPABILITIES + * w4-w7: Note used (MBZ) + * + * Return register usage: + * w3: Error code, 0 on success + * w4: Bit[7:0]: Number of parameters needed for RPC to be supplied + * as the second MSG arg struct for + * OPTEE_FFA_YIELDING_CALL_WITH_ARG. + * Bit[31:8]: Reserved (MBZ) + * w5-w7: Note used (MBZ) + */ +#define OPTEE_FFA_EXCHANGE_CAPABILITIES OPTEE_FFA_BLOCKING_CALL(2) + +/* + * Unregister shared memory + * + * Call register usage: + * w3: Service ID, OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM + * w4: Shared memory handle, lower bits + * w5: Shared memory handle, higher bits + * w6-w7: Not used (MBZ) + * + * Return register usage: + * w3: Error code, 0 on success + * w4-w7: Note used (MBZ) + */ +#define OPTEE_FFA_UNREGISTER_SHM OPTEE_FFA_BLOCKING_CALL(3) + +/* + * Call with struct optee_msg_arg as argument in the supplied shared memory + * with a zero internal offset and normal cached memory attributes. + * Register usage: + * w3: Service ID, OPTEE_FFA_YIELDING_CALL_WITH_ARG + * w4: Lower 32 bits of a 64-bit Shared memory handle + * w5: Upper 32 bits of a 64-bit Shared memory handle + * w6: Offset into shared memory pointing to a struct optee_msg_arg + * right after the parameters of this struct (at offset + * 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. + * w7: Not used (MBZ) + * Resume from RPC. Register usage: + * w3: Service ID, OPTEE_FFA_YIELDING_CALL_RESUME + * w4-w6: Not used (MBZ) + * w7: Resume info + * + * Normal return (yielding call is completed). Register usage: + * w3: Error code, 0 on success + * w4: OPTEE_FFA_YIELDING_CALL_RETURN_DONE + * w5-w7: Not used (MBZ) + * + * RPC interrupt return (RPC from secure world). Register usage: + * w3: Error code == 0 + * w4: Any defined RPC code but OPTEE_FFA_YIELDING_CALL_RETURN_DONE + * w5-w6: Not used (MBZ) + * w7: Resume info + * + * Possible error codes in register w3: + * 0: Success + * FFA_DENIED: w4 isn't one of OPTEE_FFA_YIELDING_CALL_START + * OPTEE_FFA_YIELDING_CALL_RESUME + * + * Possible error codes for OPTEE_FFA_YIELDING_CALL_START, + * FFA_BUSY: Number of OP-TEE OS threads exceeded, + * try again later + * FFA_DENIED: RPC shared memory object not found + * FFA_INVALID_PARAMETER: Bad shared memory handle or offset into the memory + * + * Possible error codes for OPTEE_FFA_YIELDING_CALL_RESUME + * FFA_INVALID_PARAMETER: Bad resume info + */ +#define OPTEE_FFA_YIELDING_CALL_WITH_ARG OPTEE_FFA_YIELDING_CALL(0) +#define OPTEE_FFA_YIELDING_CALL_RESUME OPTEE_FFA_YIELDING_CALL(1) + +#define OPTEE_FFA_YIELDING_CALL_RETURN_DONE 0 +#define OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD 1 +#define OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT 2 + +#endif /*__OPTEE_FFA_H*/ diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h index de96882f7b9b..fa03daffbfb3 100644 --- a/drivers/tee/optee/optee_msg.h +++ b/drivers/tee/optee/optee_msg.h @@ -24,6 +24,9 @@ #define OPTEE_MSG_ATTR_TYPE_RMEM_INPUT 0x5 #define OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT 0x6 #define OPTEE_MSG_ATTR_TYPE_RMEM_INOUT 0x7 +#define OPTEE_MSG_ATTR_TYPE_FMEM_INPUT OPTEE_MSG_ATTR_TYPE_RMEM_INPUT +#define OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT +#define OPTEE_MSG_ATTR_TYPE_FMEM_INOUT OPTEE_MSG_ATTR_TYPE_RMEM_INOUT #define OPTEE_MSG_ATTR_TYPE_TMEM_INPUT 0x9 #define OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT 0xa #define OPTEE_MSG_ATTR_TYPE_TMEM_INOUT 0xb @@ -92,6 +95,8 @@ */ #define OPTEE_MSG_NONCONTIG_PAGE_SIZE 4096 +#define OPTEE_MSG_FMEM_INVALID_GLOBAL_ID 0xffffffffffffffff + /** * struct optee_msg_param_tmem - temporary memory reference parameter * @buf_ptr: Address of the buffer @@ -123,6 +128,23 @@ struct optee_msg_param_rmem { u64 shm_ref; }; +/** + * struct optee_msg_param_fmem - ffa memory reference parameter + * @offs_lower: Lower bits of offset into shared memory reference + * @offs_upper: Upper bits of offset into shared memory reference + * @internal_offs: Internal offset into the first page of shared memory + * reference + * @size: Size of the buffer + * @global_id: Global identifier of Shared memory + */ +struct optee_msg_param_fmem { + u32 offs_low; + u16 offs_high; + u16 internal_offs; + u64 size; + u64 global_id; +}; + /** * struct optee_msg_param_value - opaque value parameter * @@ -139,12 +161,14 @@ struct optee_msg_param_value { * @attr: attributes * @tmem: parameter by temporary memory reference * @rmem: parameter by registered memory reference + * @fmem: parameter by ffa registered memory reference * @value: parameter by opaque value * * @attr & OPTEE_MSG_ATTR_TYPE_MASK indicates if tmem, rmem or value is used in * the union. OPTEE_MSG_ATTR_TYPE_VALUE_* indicates value, * OPTEE_MSG_ATTR_TYPE_TMEM_* indicates @tmem and - * OPTEE_MSG_ATTR_TYPE_RMEM_* indicates @rmem. + * OPTEE_MSG_ATTR_TYPE_RMEM_* or the alias PTEE_MSG_ATTR_TYPE_SMEM_* indicates + * @rmem or @smem depending on the conduit. * OPTEE_MSG_ATTR_TYPE_NONE indicates that none of the members are used. */ struct optee_msg_param { @@ -152,6 +176,7 @@ struct optee_msg_param { union { struct optee_msg_param_tmem tmem; struct optee_msg_param_rmem rmem; + struct optee_msg_param_fmem fmem; struct optee_msg_param_value value; } u; }; diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h index c5741e96e967..1ffe74e66d15 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -7,6 +7,7 @@ #define OPTEE_PRIVATE_H #include +#include #include #include #include @@ -20,6 +21,7 @@ #define TEEC_ERROR_NOT_SUPPORTED 0xFFFF000A #define TEEC_ERROR_COMMUNICATION 0xFFFF000E #define TEEC_ERROR_OUT_OF_MEMORY 0xFFFF000C +#define TEEC_ERROR_BUSY 0xFFFF000D #define TEEC_ERROR_SHORT_BUFFER 0xFFFF0010 #define TEEC_ORIGIN_COMMS 0x00000002 @@ -66,6 +68,22 @@ struct optee_supp { struct completion reqs_c; }; +/** + * struct optee_ffa_data - FFA communication struct + * @ffa_dev FFA device, contains the destination id, the id of + * OP-TEE in secure world + * @ffa_ops FFA operations + * @mutex Serializes access to @global_ids + * @global_ids FF-A shared memory global handle translation + */ +struct optee_ffa { + struct ffa_device *ffa_dev; + const struct ffa_dev_ops *ffa_ops; + /* Serializes access to @global_ids */ + struct mutex mutex; + struct rhashtable global_ids; +}; + struct optee; /** @@ -113,11 +131,15 @@ struct optee { struct tee_device *teedev; const struct optee_ops *ops; optee_invoke_fn *invoke_fn; +#ifdef CONFIG_ARM_FFA_TRANSPORT + struct optee_ffa ffa; +#endif struct optee_call_queue call_queue; struct optee_wait_queue wait_queue; struct optee_supp supp; struct tee_shm_pool *pool; void *memremaped_shm; + unsigned int rpc_arg_count; u32 sec_caps; bool scan_bus_done; struct workqueue_struct *scan_bus_wq; @@ -206,6 +228,36 @@ void optee_fill_pages_list(u64 *dst, struct page **pages, int num_pages, #define PTA_CMD_GET_DEVICES_SUPP 0x1 int optee_enumerate_devices(u32 func); +int optee_shm_add_ffa_handle(struct optee *optee, struct tee_shm *shm, + u64 global_id); +int optee_shm_rem_ffa_handle(struct optee *optee, u64 global_id); + +struct tee_shm *optee_shm_from_ffa_handle(struct optee *optee, u64 global_id); + +int optee_ffa_shm_register(struct tee_context *ctx, struct tee_shm *shm, + struct page **pages, size_t num_pages, + unsigned long start); +int optee_ffa_shm_unregister(struct tee_context *ctx, struct tee_shm *shm); +int optee_ffa_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm, + struct page **pages, size_t num_pages, + unsigned long start); +int optee_ffa_shm_unregister_supp(struct tee_context *ctx, + struct tee_shm *shm); + +int optee_ffa_do_call_with_arg(struct tee_context *ctx, struct tee_shm *arg); +int optee_ffa_rpc_shm_register(struct tee_context *ctx, struct tee_shm *shm); +void optee_handle_ffa_rpc(struct tee_context *ctx, u32 cmd, + struct optee_msg_arg *arg); + +static inline bool optee_is_ffa_based(struct optee *optee) +{ +#ifdef CONFIG_ARM_FFA_TRANSPORT + return optee->ffa.ffa_ops; +#else + return false; +#endif +} + /* * Small helpers */ diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c index f64a0ec472e0..416b50a23f68 100644 --- a/drivers/tee/optee/rpc.c +++ b/drivers/tee/optee/rpc.c @@ -10,6 +10,7 @@ #include #include #include +#include "optee_ffa.h" #include "optee_msg.h" #include "optee_private.h" #include "optee_rpc_cmd.h" @@ -543,3 +544,120 @@ void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param, param->a0 = OPTEE_SMC_CALL_RETURN_FROM_RPC; } + +#ifdef CONFIG_ARM_FFA_TRANSPORT +static void handle_ffa_rpc_func_cmd_shm_alloc(struct tee_context *ctx, + struct optee_msg_arg *arg) +{ + struct tee_shm *shm; + + if (arg->num_params != 1 || + arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) { + arg->ret = TEEC_ERROR_BAD_PARAMETERS; + return; + } + + switch (arg->params[0].u.value.a) { + case OPTEE_RPC_SHM_TYPE_APPL: + shm = cmd_alloc_suppl(ctx, arg->params[0].u.value.b); + break; + case OPTEE_RPC_SHM_TYPE_KERNEL: + shm = tee_shm_alloc(ctx, arg->params[0].u.value.b, + TEE_SHM_MAPPED); + break; + default: + arg->ret = TEEC_ERROR_BAD_PARAMETERS; + return; + } + + if (IS_ERR(shm)) { + arg->ret = TEEC_ERROR_OUT_OF_MEMORY; + return; + } + + arg->params[0] = (struct optee_msg_param){ + .attr = OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT, + .u.fmem.size = tee_shm_get_size(shm), + .u.fmem.global_id = shm->sec_world_id, + .u.fmem.internal_offs = shm->offset, + }; + + arg->ret = TEEC_SUCCESS; +} + +static void handle_ffa_rpc_func_cmd_shm_free(struct tee_context *ctx, + struct optee *optee, + struct optee_msg_arg *arg) +{ + struct tee_shm *shm; + + if (arg->num_params != 1 || + arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) + goto err_bad_param; + + shm = optee_shm_from_ffa_handle(optee, arg->params[0].u.value.b); + if (!shm) + goto err_bad_param; + switch (arg->params[0].u.value.a) { + case OPTEE_RPC_SHM_TYPE_APPL: + cmd_free_suppl(ctx, shm); + break; + case OPTEE_RPC_SHM_TYPE_KERNEL: + tee_shm_free(shm); + break; + default: + goto err_bad_param; + } + arg->ret = TEEC_SUCCESS; + return; + +err_bad_param: + arg->ret = TEEC_ERROR_BAD_PARAMETERS; +} + +static void handle_ffa_rpc_func_cmd(struct tee_context *ctx, + struct optee_msg_arg *arg) +{ + struct optee *optee = tee_get_drvdata(ctx->teedev); + + arg->ret_origin = TEEC_ORIGIN_COMMS; + switch (arg->cmd) { + case OPTEE_RPC_CMD_GET_TIME: + handle_rpc_func_cmd_get_time(arg); + break; + case OPTEE_RPC_CMD_WAIT_QUEUE: + handle_rpc_func_cmd_wq(optee, arg); + break; + case OPTEE_RPC_CMD_SUSPEND: + handle_rpc_func_cmd_wait(arg); + break; + case OPTEE_RPC_CMD_SHM_ALLOC: + handle_ffa_rpc_func_cmd_shm_alloc(ctx, arg); + break; + case OPTEE_RPC_CMD_SHM_FREE: + handle_ffa_rpc_func_cmd_shm_free(ctx, optee, arg); + break; + case OPTEE_MSG_RPC_CMD_I2C_TRANSFER: + handle_rpc_func_cmd_i2c_transfer(ctx, arg); + break; + default: + handle_rpc_supp_cmd(ctx, optee, arg); + } +} + +void optee_handle_ffa_rpc(struct tee_context *ctx, u32 cmd, + struct optee_msg_arg *arg) +{ + switch (cmd) { + case OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD: + handle_ffa_rpc_func_cmd(ctx, arg); + break; + case OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT: + /* Interrupt delivered by now */ + break; + default: + pr_warn("Unknown RPC func 0x%x\n", cmd); + break; + } +} +#endif /*CONFIG_ARM_FFA_TRANSPORT*/