From patchwork Tue May 20 15:16:45 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Wiklander X-Patchwork-Id: 891429 Received: from mail-ed1-f44.google.com (mail-ed1-f44.google.com [209.85.208.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 21876263F44 for ; Tue, 20 May 2025 15:24:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747754687; cv=none; b=oAaBOa7fxWug9IoZO3CJ9i1H8uAFidaIP6jUjTMrodRJrKl3wPtsuasiFWRSOEg/dU8st39UjozM2lBg42IS+119krbA7icimRauk+ogRy/MYAtS93509lB8lH3ljwzQKCTb6ZDT4WJU/scVP/l1wCLjOpVOeHTJR1jsnEThgyw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747754687; c=relaxed/simple; bh=UxN93SvSHVTP+m+eEEKFbkfsohK3RhjYDOa6gbczcdk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HYJv6JuU3PxEICwBF/KgkfBlIQNcdgMP35VQdamxnI56nwt8dYog4xx9O4D90RgIiWWueTLKtVIzcMz5K6AUpY5JuxtD4rwPrRI0ER6ik9dLpnq66+YrLplGIdkfARgkrcT0YBhgkEY+6koCOOBE7sFtAFaIBo+jyudk/By0oNE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=GLT/u2yA; arc=none smtp.client-ip=209.85.208.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="GLT/u2yA" Received: by mail-ed1-f44.google.com with SMTP id 4fb4d7f45d1cf-6019b564d0bso6595804a12.2 for ; Tue, 20 May 2025 08:24:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1747754684; x=1748359484; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=t+mAUVqOxIXjZijXnkHFZmAFDQtFJ4Kh5PO6PLUJhLU=; b=GLT/u2yAQTo/Ui8guh77KTHRiumuBadbJgCGyBqpWXbduuTGoOGH/QDB8UmRLOFAj2 5L1QQQ1yFxZWNJDwDyoaYkbBEQp8tbFrBTtQVxZcHhunYrUIZ+N7DZ0LwBVr5lbtra1a gfdC9h9sGF3i1BVXn0KaAvGSkHmnMF4yfIwa8VvGPBPvzCHTkScxuBrIFwa9x+Oq3K+P mYbKTmcj++umzLhBtCyLeaBN80m7kf5AmTjft7UXgktOdPwQDqAyJCMjyhuJ9zP395/d bAQzM4R0+RvY1JuXb2B32/3UP9Wh6xou/GiwCd2H6pXmv4kYsOJdwMacY8rII3lhhd6f lZfg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1747754684; x=1748359484; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=t+mAUVqOxIXjZijXnkHFZmAFDQtFJ4Kh5PO6PLUJhLU=; b=kSI+NtJ+7BFdbsLh/wLW3RtjoGQrnuBdyjAwUSOkbflfh273e281Y5zyGtkb8Wzu3V JSeYO1aJUfx1lbtKunbQLcP0tREgmvT6wSS5UHBaBQ/xPPHH0bTMu7BIuMzpB6Gu8Jol T/LKTaBuEOc49G6JguqJh71RPCMXC5zip518ZSGMdMZqwga5eRHVvERIdulCCfwqmBgY 1tEf2SeJYGb5TlryPl80Q2bey50bnCNrguPR+n3dYVIzBXzGa+G1FHL7pfcqnzxz9y/Z PYabZ1golgKD0+vFMMVjbovPbOPP3NqFjySTAs9kEm2OPVWLg6zJSP5hQ9L5GW2GkqSr NGwQ== X-Forwarded-Encrypted: i=1; AJvYcCVhEXnWmfcGOqhuG5kJMeUcdW2nxN+EjLR85K5OEffjdBzN/KEYAoNuLh/tzINgndZXOLKGLuKnhe9Sag==@vger.kernel.org X-Gm-Message-State: AOJu0YxaRbaaCl3kv4gi3rGK6XVD7ibex/sxFyRiNcKa49G7JRiYQy/a 3MH+0Jw6V8tzF1QBlDi6Tfl2tjlYUBltK5rvWlMuU/auq8fTG/LvFkr4xHxIsbFO/2U= X-Gm-Gg: ASbGncvPXNXUMsWqO7AS1SN6089QhNlQoWmZrY0D4WsgQ8+pc/yzwYDqUnOnmsCs6ed oHWN+LYEtjzWrBZGg0yY4EfIV9XpbvGoZp3CXoZO81pjYZJ0eVJ1t/IGdgOt9iS9NGW/H5M4Zeh paD1E0Yg5Wb8qCQ5K7rVvfJEueYKEkZj+n25zbFd93IlZJFyexNkV4DZHQ2G/R2CNR8c9UUPpTN E4OkY00bXYyJlRWBoVn2gJ2JJR0jO87OeEIY1xcIMmlD9YG9hWxpHT0VRup143oPsPwkapFFwBR U/wMvJM/q3izEFccH8HqDueab8Ap5BjfAwM0tPYzhhGU92+eOugCy6DqFbBm3DLpl7d3nSuHSB8 iK+n0gdOqdeHvF/SwEHVQne5pai63 X-Google-Smtp-Source: AGHT+IHJnNS8PsiFV8EVtrc16G9fq8ki6tRPk/s/IIABC/OTj/P3BcTFh9xpStaXrxgzCYdbyyVt2g== X-Received: by 2002:a17:906:22d1:b0:ad5:3055:784d with SMTP id a640c23a62f3a-ad53055f81cmr1041003666b.34.1747754684274; Tue, 20 May 2025 08:24:44 -0700 (PDT) Received: from rayden.urgonet (h-98-128-140-123.A175.priv.bahnhof.se. [98.128.140.123]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ad52d278257sm742608766b.82.2025.05.20.08.24.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 May 2025 08:24:43 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org, op-tee@lists.trustedfirmware.org, linux-arm-kernel@lists.infradead.org Cc: Olivier Masse , Thierry Reding , Yong Wu , Sumit Semwal , Benjamin Gaignard , Brian Starkey , John Stultz , "T . J . Mercier" , =?utf-8?q?Christian_K=C3=B6nig?= , Sumit Garg , Matthias Brugger , AngeloGioacchino Del Regno , azarrabi@qti.qualcomm.com, Simona Vetter , Daniel Stone , Rouven Czerwinski , Jens Wiklander Subject: [PATCH v9 2/9] dma-buf: dma-heap: export declared functions Date: Tue, 20 May 2025 17:16:45 +0200 Message-ID: <20250520152436.474778-3-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250520152436.474778-1-jens.wiklander@linaro.org> References: <20250520152436.474778-1-jens.wiklander@linaro.org> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Export the dma-buf heap functions declared in . Signed-off-by: Jens Wiklander --- drivers/dma-buf/dma-heap.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c index 3cbe87d4a464..cdddf0e24dce 100644 --- a/drivers/dma-buf/dma-heap.c +++ b/drivers/dma-buf/dma-heap.c @@ -202,6 +202,7 @@ void *dma_heap_get_drvdata(struct dma_heap *heap) { return heap->priv; } +EXPORT_SYMBOL(dma_heap_get_drvdata); /** * dma_heap_get_name - get heap name @@ -214,6 +215,7 @@ const char *dma_heap_get_name(struct dma_heap *heap) { return heap->name; } +EXPORT_SYMBOL(dma_heap_get_name); /** * dma_heap_add - adds a heap to dmabuf heaps @@ -303,6 +305,7 @@ struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info) kfree(heap); return err_ret; } +EXPORT_SYMBOL(dma_heap_add); static char *dma_heap_devnode(const struct device *dev, umode_t *mode) { From patchwork Tue May 20 15:16:46 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Wiklander X-Patchwork-Id: 891428 Received: from mail-ej1-f45.google.com (mail-ej1-f45.google.com [209.85.218.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 32CD2266EEA for ; Tue, 20 May 2025 15:24:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747754690; cv=none; b=Q1cl3ImXy+LDuagaVgI7ign4cJLDRuB/iHhe8OvcfoghEZ3iBukL9CGoi3FLehoXyLSw4lysvP7jlNz/UTMMSciwLolkNdDEooV+DlBcLXkhAeiJXiShF6HlkUr5CyEPunzo/sFGZmSCM7pKDYIxPSS+ZrzTYNOrpGVDapURObI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747754690; c=relaxed/simple; bh=lsTPYGnEZvxIiBysY8RyiViCW3nEXJAj+aom6wL/FfI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XJMDOm4NKtSRES78PT1LMooDYfCsxaIBWxSr/4eCzZoSXj9tzcUuOuGQJgOI9VJmMldiQJstS80KtW6dgZkJCQVFWuj5Sl3XuHcvl2ANfvGnDl73NaEL6PAPkFTjaFZUrqBIp95qLfIYzI7k+OdYgpm1bR3RPcMhthDzcqLjoH8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=vYaayUT1; arc=none smtp.client-ip=209.85.218.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="vYaayUT1" Received: by mail-ej1-f45.google.com with SMTP id a640c23a62f3a-ad560321ed9so353076766b.1 for ; Tue, 20 May 2025 08:24:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1747754686; x=1748359486; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=8bl8y9iP5U+Xm+6TVvU2xw4CnUhmFn/1OadGtY/yvq4=; b=vYaayUT14fIRvi7Az11UCiUCT6FoifzFpFTEEzm+svwvyij1JUPKytr5EbSuUEO1Uk AZXH82z73IJAD/FURRgO6ujPW6okZMeRaDFFZYR9uKBTP4mueegusaJcWNO4QC7vtbVX pBX9Re3+xcoVCBrGSPCQ2oBgvHTlsT/GmKeGbtSZjmgk4Eyq5j3b78WSgzSkxyEkRGGk FsH1cN1/raFxjD3ohSkL6QIVe2c7uCPAnCRkxHEN8amVvTHEXHNxwHgxBZZgQZ4fXmD9 mXFGCYog5ej8vzbHW7R01j92mZNMPivMy1gK2CvFC0K76GYnGlH5SVF+2vDpfojn+8MQ E7iQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1747754686; x=1748359486; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=8bl8y9iP5U+Xm+6TVvU2xw4CnUhmFn/1OadGtY/yvq4=; b=XM7Okgax14FEYrEZJQqLzgfwUi6/ylpUWBb3MJNTA+qDbAkMWTwdLlfgOuqWCmBEoy 5lVf3fKKxGrBefaCFpsaC+ll8HvZ6ZxHxNWT62cnEfO+E9eldtza38tCUshzZjkjNbFl GNbea9qSrxMaKh46QbzsUzcQVlHnLF7WguVLB+FQwX4GsGTLqB2fkGPy8UqvVS29s8pk 2DCXEZ8CuT5gJcIwbDlnGzcHr+YGyZ/8ELFd8+mf/WN94NKNz8dPgwHLkUg4B1sokAN4 5VgxbtCJ/xoLKQxwUHeJbqgKJ4FPn7bA0j4b+/pr2RpNBeZ5eRi4vrAwgp6KFWGf0QUI WUvw== X-Forwarded-Encrypted: i=1; AJvYcCXA7qwrdyoaRtGpVFPX7F9zmAGJf3oLyXgQEwE52RlkdBJBpYwcTH/GDGZAouGcthPb2RUTr9ups0m/uQ==@vger.kernel.org X-Gm-Message-State: AOJu0YxBIf3alC2XyBQCpEvSndE3IvYi8lickrHDFP+gKNiOFHjRk26u P6HI1+Ucj90l8+LxSCVCCYnfp3JqGfXCNxpj2CwVSxCta9FJQ+xlfYHUFNo1T3nbHEo= X-Gm-Gg: ASbGncuatVCeBCHfqGMxo51iqZCJGt3ejydFAyBmAZjQ7nEcK8o6l/Vts3/a6K3w+ov jitQwKr/gwx4AvQRzdZShN6IqgKnogoozDj3zUuLrLhWASRtbgcMisxOFm64QLM+G1XzMvBrwXj 9pkMdTHUX81yWhXkAw0Aqsj1k3KihXAqq3pjiiBdBoLLOA7izPstIW4GvtVDOEnvuEOYpOopK8w 45cgeP/G0U7pvS8DVq7g9liRjUOhP+7eH5LQX6YNEyCZUAKDyVNzLbyd2RJlF74LnRjo36PS/Kv 5vA51MgXCp2+JZHcyUwLw72uvQLoBUo4mf+Gf6xAZKMDA7VSKq79bRGI7REKcfeNRBtTA9d+cS7 DpbLFeIRm/9deQsJcXtNeaHbSk6IMLILlGuy5TTE= X-Google-Smtp-Source: AGHT+IGYsUU2+/wZX9KVnCNjKQuqsHQtS7q46txUWoFzPF0Y5yaantzw3YenC93TVWOgKL9pRfUVfQ== X-Received: by 2002:a17:906:3450:b0:ad5:35ab:7a8 with SMTP id a640c23a62f3a-ad535ab08a3mr1172847866b.55.1747754686179; Tue, 20 May 2025 08:24:46 -0700 (PDT) Received: from rayden.urgonet (h-98-128-140-123.A175.priv.bahnhof.se. [98.128.140.123]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ad52d278257sm742608766b.82.2025.05.20.08.24.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 May 2025 08:24:45 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org, op-tee@lists.trustedfirmware.org, linux-arm-kernel@lists.infradead.org Cc: Olivier Masse , Thierry Reding , Yong Wu , Sumit Semwal , Benjamin Gaignard , Brian Starkey , John Stultz , "T . J . Mercier" , =?utf-8?q?Christian_K=C3=B6nig?= , Sumit Garg , Matthias Brugger , AngeloGioacchino Del Regno , azarrabi@qti.qualcomm.com, Simona Vetter , Daniel Stone , Rouven Czerwinski , Jens Wiklander Subject: [PATCH v9 3/9] tee: implement protected DMA-heap Date: Tue, 20 May 2025 17:16:46 +0200 Message-ID: <20250520152436.474778-4-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250520152436.474778-1-jens.wiklander@linaro.org> References: <20250520152436.474778-1-jens.wiklander@linaro.org> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Implement DMA heap for protected DMA-buf allocation in the TEE subsystem. Restricted memory refers to memory buffers behind a hardware enforced firewall. It is not accessible to the kernel during normal circumstances but rather only accessible to certain hardware IPs or CPUs executing in higher or differently privileged mode than the kernel itself. This interface allows to allocate and manage such protected memory buffers via interaction with a TEE implementation. The protected memory is allocated for a specific use-case, like Secure Video Playback, Trusted UI, or Secure Video Recording where certain hardware devices can access the memory. The DMA-heaps are enabled explicitly by the TEE backend driver. The TEE backend drivers needs to implement protected memory pool to manage the protected memory. Signed-off-by: Jens Wiklander --- drivers/tee/Makefile | 1 + drivers/tee/tee_heap.c | 487 ++++++++++++++++++++++++++++++++++++++ drivers/tee/tee_private.h | 6 + include/linux/tee_core.h | 65 +++++ 4 files changed, 559 insertions(+) create mode 100644 drivers/tee/tee_heap.c diff --git a/drivers/tee/Makefile b/drivers/tee/Makefile index 5488cba30bd2..949a6a79fb06 100644 --- a/drivers/tee/Makefile +++ b/drivers/tee/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_TEE) += tee.o tee-objs += tee_core.o +tee-objs += tee_heap.o tee-objs += tee_shm.o tee-objs += tee_shm_pool.o obj-$(CONFIG_OPTEE) += optee/ diff --git a/drivers/tee/tee_heap.c b/drivers/tee/tee_heap.c new file mode 100644 index 000000000000..a332805f9f26 --- /dev/null +++ b/drivers/tee/tee_heap.c @@ -0,0 +1,487 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2025, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tee_private.h" + +struct tee_dma_heap { + struct dma_heap *heap; + enum tee_dma_heap_id id; + struct tee_protmem_pool *pool; + struct tee_device *teedev; + /* Protects pool and teedev above */ + struct mutex mu; +}; + +struct tee_heap_buffer { + struct tee_protmem_pool *pool; + struct tee_device *teedev; + size_t size; + size_t offs; + struct sg_table table; +}; + +struct tee_heap_attachment { + struct sg_table table; + struct device *dev; +}; + +struct tee_protmem_static_pool { + struct tee_protmem_pool pool; + struct gen_pool *gen_pool; + phys_addr_t pa_base; + void *base; +}; + +#if IS_ENABLED(CONFIG_DMABUF_HEAPS) +static DEFINE_XARRAY_ALLOC(tee_dma_heap); + +static int copy_sg_table(struct sg_table *dst, struct sg_table *src) +{ + struct scatterlist *dst_sg; + struct scatterlist *src_sg; + int ret; + int i; + + ret = sg_alloc_table(dst, src->orig_nents, GFP_KERNEL); + if (ret) + return ret; + + dst_sg = dst->sgl; + for_each_sgtable_sg(src, src_sg, i) { + sg_set_page(dst_sg, sg_page(src_sg), src_sg->length, + src_sg->offset); + dst_sg = sg_next(dst_sg); + } + + return 0; +} + +static int tee_heap_attach(struct dma_buf *dmabuf, + struct dma_buf_attachment *attachment) +{ + struct tee_heap_buffer *buf = dmabuf->priv; + struct tee_heap_attachment *a; + int ret; + + a = kzalloc(sizeof(*a), GFP_KERNEL); + if (!a) + return -ENOMEM; + + ret = copy_sg_table(&a->table, &buf->table); + if (ret) { + kfree(a); + return ret; + } + + a->dev = attachment->dev; + attachment->priv = a; + + return 0; +} + +static void tee_heap_detach(struct dma_buf *dmabuf, + struct dma_buf_attachment *attachment) +{ + struct tee_heap_attachment *a = attachment->priv; + + sg_free_table(&a->table); + kfree(a); +} + +static struct sg_table * +tee_heap_map_dma_buf(struct dma_buf_attachment *attachment, + enum dma_data_direction direction) +{ + struct tee_heap_attachment *a = attachment->priv; + int ret; + + ret = dma_map_sgtable(attachment->dev, &a->table, direction, + DMA_ATTR_SKIP_CPU_SYNC); + if (ret) + return ERR_PTR(ret); + + return &a->table; +} + +static void tee_heap_unmap_dma_buf(struct dma_buf_attachment *attachment, + struct sg_table *table, + enum dma_data_direction direction) +{ + struct tee_heap_attachment *a = attachment->priv; + + WARN_ON(&a->table != table); + + dma_unmap_sgtable(attachment->dev, table, direction, + DMA_ATTR_SKIP_CPU_SYNC); +} + +static void tee_heap_buf_free(struct dma_buf *dmabuf) +{ + struct tee_heap_buffer *buf = dmabuf->priv; + struct tee_device *teedev = buf->teedev; + + buf->pool->ops->free(buf->pool, &buf->table); + tee_device_put(teedev); +} + +static const struct dma_buf_ops tee_heap_buf_ops = { + .attach = tee_heap_attach, + .detach = tee_heap_detach, + .map_dma_buf = tee_heap_map_dma_buf, + .unmap_dma_buf = tee_heap_unmap_dma_buf, + .release = tee_heap_buf_free, +}; + +static struct dma_buf *tee_dma_heap_alloc(struct dma_heap *heap, + unsigned long len, u32 fd_flags, + u64 heap_flags) +{ + struct tee_dma_heap *h = dma_heap_get_drvdata(heap); + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); + struct tee_device *teedev = NULL; + struct tee_heap_buffer *buf; + struct tee_protmem_pool *pool; + struct dma_buf *dmabuf; + int rc; + + mutex_lock(&h->mu); + if (tee_device_get(h->teedev)) { + teedev = h->teedev; + pool = h->pool; + } + mutex_unlock(&h->mu); + + if (!teedev) + return ERR_PTR(-EINVAL); + + buf = kzalloc(sizeof(*buf), GFP_KERNEL); + if (!buf) { + dmabuf = ERR_PTR(-ENOMEM); + goto err; + } + buf->size = len; + buf->pool = pool; + buf->teedev = teedev; + + rc = pool->ops->alloc(pool, &buf->table, len, &buf->offs); + if (rc) { + dmabuf = ERR_PTR(rc); + goto err_kfree; + } + + exp_info.ops = &tee_heap_buf_ops; + exp_info.size = len; + exp_info.priv = buf; + exp_info.flags = fd_flags; + dmabuf = dma_buf_export(&exp_info); + if (IS_ERR(dmabuf)) + goto err_protmem_free; + + return dmabuf; + +err_protmem_free: + pool->ops->free(pool, &buf->table); +err_kfree: + kfree(buf); +err: + tee_device_put(h->teedev); + return dmabuf; +} + +static const struct dma_heap_ops tee_dma_heap_ops = { + .allocate = tee_dma_heap_alloc, +}; + +static const char *heap_id_2_name(enum tee_dma_heap_id id) +{ + switch (id) { + case TEE_DMA_HEAP_SECURE_VIDEO_PLAY: + return "protected,secure-video"; + case TEE_DMA_HEAP_TRUSTED_UI: + return "protected,trusted-ui"; + case TEE_DMA_HEAP_SECURE_VIDEO_RECORD: + return "protected,secure-video-record"; + default: + return NULL; + } +} + +static int alloc_dma_heap(struct tee_device *teedev, enum tee_dma_heap_id id, + struct tee_protmem_pool *pool) +{ + struct dma_heap_export_info exp_info = { + .ops = &tee_dma_heap_ops, + .name = heap_id_2_name(id), + }; + struct tee_dma_heap *h; + int rc; + + if (!exp_info.name) + return -EINVAL; + + if (xa_reserve(&tee_dma_heap, id, GFP_KERNEL)) { + if (!xa_load(&tee_dma_heap, id)) + return -EEXIST; + return -ENOMEM; + } + + h = kzalloc(sizeof(*h), GFP_KERNEL); + if (!h) + return -ENOMEM; + h->id = id; + h->teedev = teedev; + h->pool = pool; + mutex_init(&h->mu); + + exp_info.priv = h; + h->heap = dma_heap_add(&exp_info); + if (IS_ERR(h->heap)) { + rc = PTR_ERR(h->heap); + kfree(h); + + return rc; + } + + /* "can't fail" due to the call to xa_reserve() above */ + return WARN(xa_store(&tee_dma_heap, id, h, GFP_KERNEL), + "xa_store() failed"); +} + +int tee_device_register_dma_heap(struct tee_device *teedev, + enum tee_dma_heap_id id, + struct tee_protmem_pool *pool) +{ + struct tee_dma_heap *h; + int rc; + + h = xa_load(&tee_dma_heap, id); + if (h) { + mutex_lock(&h->mu); + if (h->teedev) { + rc = -EBUSY; + } else { + h->teedev = teedev; + h->pool = pool; + rc = 0; + } + mutex_unlock(&h->mu); + } else { + rc = alloc_dma_heap(teedev, id, pool); + } + + if (rc) + dev_err(&teedev->dev, "can't register DMA heap id %d (%s)\n", + id, heap_id_2_name(id)); + + return rc; +} +EXPORT_SYMBOL_GPL(tee_device_register_dma_heap); + +void tee_device_unregister_all_dma_heaps(struct tee_device *teedev) +{ + struct tee_protmem_pool *pool; + struct tee_dma_heap *h; + u_long i; + + xa_for_each(&tee_dma_heap, i, h) { + if (h) { + pool = NULL; + mutex_lock(&h->mu); + if (h->teedev == teedev) { + pool = h->pool; + h->teedev = NULL; + h->pool = NULL; + } + mutex_unlock(&h->mu); + if (pool) + pool->ops->destroy_pool(pool); + } + } +} +EXPORT_SYMBOL_GPL(tee_device_unregister_all_dma_heaps); + +int tee_heap_update_from_dma_buf(struct tee_device *teedev, + struct dma_buf *dmabuf, size_t *offset, + struct tee_shm *shm, + struct tee_shm **parent_shm) +{ + struct tee_heap_buffer *buf; + int rc; + + /* The DMA-buf must be from our heap */ + if (dmabuf->ops != &tee_heap_buf_ops) + return -EINVAL; + + buf = dmabuf->priv; + /* The buffer must be from the same teedev */ + if (buf->teedev != teedev) + return -EINVAL; + + shm->size = buf->size; + + rc = buf->pool->ops->update_shm(buf->pool, &buf->table, buf->offs, shm, + parent_shm); + if (!rc && *parent_shm) + *offset = buf->offs; + + return rc; +} +#else +int tee_device_register_dma_heap(struct tee_device *teedev __always_unused, + enum tee_dma_heap_id id __always_unused, + struct tee_protmem_pool *pool __always_unused) +{ + return -EINVAL; +} +EXPORT_SYMBOL_GPL(tee_device_register_dma_heap); + +void +tee_device_unregister_all_dma_heaps(struct tee_device *teedev __always_unused) +{ +} +EXPORT_SYMBOL_GPL(tee_device_unregister_all_dma_heaps); + +int tee_heap_update_from_dma_buf(struct tee_device *teedev __always_unused, + struct dma_buf *dmabuf __always_unused, + size_t *offset __always_unused, + struct tee_shm *shm __always_unused, + struct tee_shm **parent_shm __always_unused) +{ + return -EINVAL; +} +#endif + +static struct tee_protmem_static_pool * +to_protmem_static_pool(struct tee_protmem_pool *pool) +{ + return container_of(pool, struct tee_protmem_static_pool, pool); +} + +static int protmem_pool_op_static_alloc(struct tee_protmem_pool *pool, + struct sg_table *sgt, size_t size, + size_t *offs) +{ + struct tee_protmem_static_pool *stp = to_protmem_static_pool(pool); + phys_addr_t pa; + int ret; + + pa = gen_pool_alloc(stp->gen_pool, size); + if (!pa) + return -ENOMEM; + + ret = sg_alloc_table(sgt, 1, GFP_KERNEL); + if (ret) { + gen_pool_free(stp->gen_pool, pa, size); + return ret; + } + + sg_set_page(sgt->sgl, phys_to_page(pa), size, 0); + *offs = pa - stp->pa_base; + + return 0; +} + +static void protmem_pool_op_static_free(struct tee_protmem_pool *pool, + struct sg_table *sgt) +{ + struct tee_protmem_static_pool *stp = to_protmem_static_pool(pool); + struct scatterlist *sg; + int i; + + for_each_sgtable_sg(sgt, sg, i) + gen_pool_free(stp->gen_pool, sg_phys(sg), sg->length); + sg_free_table(sgt); +} + +static int protmem_pool_op_static_update_shm(struct tee_protmem_pool *pool, + struct sg_table *sgt, size_t offs, + struct tee_shm *shm, + struct tee_shm **parent_shm) +{ + struct tee_protmem_static_pool *stp = to_protmem_static_pool(pool); + + shm->paddr = stp->pa_base + offs; + *parent_shm = NULL; + + return 0; +} + +static void protmem_pool_op_static_destroy_pool(struct tee_protmem_pool *pool) +{ + struct tee_protmem_static_pool *stp = to_protmem_static_pool(pool); + + gen_pool_destroy(stp->gen_pool); + memunmap(stp->base); + kfree(stp); +} + +static struct tee_protmem_pool_ops protmem_pool_ops_static = { + .alloc = protmem_pool_op_static_alloc, + .free = protmem_pool_op_static_free, + .update_shm = protmem_pool_op_static_update_shm, + .destroy_pool = protmem_pool_op_static_destroy_pool, +}; + +struct tee_protmem_pool *tee_protmem_static_pool_alloc(phys_addr_t paddr, + size_t size) +{ + const size_t page_mask = PAGE_SIZE - 1; + struct tee_protmem_static_pool *stp; + int rc; + + /* Check it's page aligned */ + if ((paddr | size) & page_mask) + return ERR_PTR(-EINVAL); + + stp = kzalloc(sizeof(*stp), GFP_KERNEL); + if (!stp) + return ERR_PTR(-ENOMEM); + + /* + * Map the memory as uncached to make sure the kernel can work with + * __pfn_to_page() and friends since that's needed when passing the + * protected DMA-buf to a device. The memory should otherwise not + * be touched by the kernel since it's likely to cause an external + * abort due to the protection status. + */ + stp->base = memremap(paddr, size, MEMREMAP_WC); + if (!stp->base) { + rc = -EINVAL; + goto err_free; + } + + stp->gen_pool = gen_pool_create(PAGE_SHIFT, -1); + if (!stp->gen_pool) { + rc = -ENOMEM; + goto err_unmap; + } + + rc = gen_pool_add(stp->gen_pool, paddr, size, -1); + if (rc) + goto err_free_pool; + + stp->pool.ops = &protmem_pool_ops_static; + stp->pa_base = paddr; + return &stp->pool; + +err_free_pool: + gen_pool_destroy(stp->gen_pool); +err_unmap: + memunmap(stp->base); +err_free: + kfree(stp); + + return ERR_PTR(rc); +} +EXPORT_SYMBOL_GPL(tee_protmem_static_pool_alloc); diff --git a/drivers/tee/tee_private.h b/drivers/tee/tee_private.h index 9bc50605227c..6c6ff5d5eed2 100644 --- a/drivers/tee/tee_private.h +++ b/drivers/tee/tee_private.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -24,4 +25,9 @@ struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size); struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx, unsigned long addr, size_t length); +int tee_heap_update_from_dma_buf(struct tee_device *teedev, + struct dma_buf *dmabuf, size_t *offset, + struct tee_shm *shm, + struct tee_shm **parent_shm); + #endif /*TEE_PRIVATE_H*/ diff --git a/include/linux/tee_core.h b/include/linux/tee_core.h index a38494d6b5f4..b8b99c97e00c 100644 --- a/include/linux/tee_core.h +++ b/include/linux/tee_core.h @@ -8,9 +8,11 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -30,6 +32,12 @@ #define TEE_DEVICE_FLAG_REGISTERED 0x1 #define TEE_MAX_DEV_NAME_LEN 32 +enum tee_dma_heap_id { + TEE_DMA_HEAP_SECURE_VIDEO_PLAY = 1, + TEE_DMA_HEAP_TRUSTED_UI, + TEE_DMA_HEAP_SECURE_VIDEO_RECORD, +}; + /** * struct tee_device - TEE Device representation * @name: name of device @@ -116,6 +124,36 @@ struct tee_desc { u32 flags; }; +/** + * struct tee_protmem_pool - protected memory pool + * @ops: operations + * + * This is an abstract interface where this struct is expected to be + * embedded in another struct specific to the implementation. + */ +struct tee_protmem_pool { + const struct tee_protmem_pool_ops *ops; +}; + +/** + * struct tee_protmem_pool_ops - protected memory pool operations + * @alloc: called when allocating protected memory + * @free: called when freeing protected memory + * @update_shm: called when registering a dma-buf to update the @shm + * with physical address of the buffer or to return the + * @parent_shm of the memory pool + * @destroy_pool: called when destroying the pool + */ +struct tee_protmem_pool_ops { + int (*alloc)(struct tee_protmem_pool *pool, struct sg_table *sgt, + size_t size, size_t *offs); + void (*free)(struct tee_protmem_pool *pool, struct sg_table *sgt); + int (*update_shm)(struct tee_protmem_pool *pool, struct sg_table *sgt, + size_t offs, struct tee_shm *shm, + struct tee_shm **parent_shm); + void (*destroy_pool)(struct tee_protmem_pool *pool); +}; + /** * tee_device_alloc() - Allocate a new struct tee_device instance * @teedesc: Descriptor for this driver @@ -154,6 +192,11 @@ int tee_device_register(struct tee_device *teedev); */ void tee_device_unregister(struct tee_device *teedev); +int tee_device_register_dma_heap(struct tee_device *teedev, + enum tee_dma_heap_id id, + struct tee_protmem_pool *pool); +void tee_device_unregister_all_dma_heaps(struct tee_device *teedev); + /** * tee_device_set_dev_groups() - Set device attribute groups * @teedev: Device to register @@ -229,6 +272,28 @@ static inline void tee_shm_pool_free(struct tee_shm_pool *pool) pool->ops->destroy_pool(pool); } +/** + * tee_protmem_static_pool_alloc() - Create a protected memory manager + * @paddr: Physical address of start of pool + * @size: Size in bytes of the pool + * + * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure. + */ +struct tee_protmem_pool *tee_protmem_static_pool_alloc(phys_addr_t paddr, + size_t size); + +/** + * tee_protmem_pool_free() - Free a protected memory pool + * @pool: The protected memory pool to free + * + * There must be no remaining protected memory allocated from this pool + * when this function is called. + */ +static inline void tee_protmem_pool_free(struct tee_protmem_pool *pool) +{ + pool->ops->destroy_pool(pool); +} + /** * tee_get_drvdata() - Return driver_data pointer * @returns the driver_data pointer supplied to tee_register(). From patchwork Tue May 20 15:16:48 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Wiklander X-Patchwork-Id: 891427 Received: from mail-ej1-f47.google.com (mail-ej1-f47.google.com [209.85.218.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 29DEF26F45F for ; Tue, 20 May 2025 15:24:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747754694; cv=none; b=k8lNel/BSOnqk14Ja6wocueBbbG/XRhJKzlSXv7W01H0lXQYofla+W9JbcBm1gLc6S/cz5IIU+0jkfx84zWvPPjnIFjIdkvYTIaDGayRYP63SI1Uo0FHPVOASiE5zZvrsRVEg5ILEAXu4H0s03HEm/N0CJvw2zPaMxq5HkxxhSY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747754694; c=relaxed/simple; bh=UnloMxDitulnWnxJxiOEgNM+AW7TcYBrAT7ZpRagJJk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jetQe7nrcRGeWpkau9KHE50mse+szHqwDaDLDgcyW1zbSMQztPk869BqEAwTNd7/1+I+uWs/qZWDseANrozL56qq7AJcNhhZ/Mcbli+gKIiZT4i6xHcoR4RNgP3nGv3Sx1Tz8b9zDWCprGzCCQoHv9+h06su3GqOnX2SmwaAFZA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=r4bkNyCO; arc=none smtp.client-ip=209.85.218.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="r4bkNyCO" Received: by mail-ej1-f47.google.com with SMTP id a640c23a62f3a-ad1b94382b8so1029981466b.0 for ; Tue, 20 May 2025 08:24:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1747754690; x=1748359490; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=TYLMHkDR/tPWcpSeZiIlQos+TrKLGRgGVHxxpAWir3w=; b=r4bkNyCOgBIErLqSrxuMkqsQuTxPL8gDx0RW+gM04zB9bfHQBi1iJeiioRAvsrKcuj R11puNJB/Az8h30DCc1mLmjNPbjOLtfPRYwcebTrOMAX0npoKeBQAL2+KHW7lWFLfuok 3uRkCrnemwfeRL5r7IVBbR0/3MSmij4ixnhazy4+dW9gFj1p2t+WD1aVZYrqmEb6DkJZ bWgyaEEs+qSXmGSM8CZM53N+s7p0a1dJ9GlyzvyeTWozFOjjYf8cPtWXF46KspuOGxw8 U2tgKtNR3PvzpFT0/kup8wwUXMCN81cXQo+GSLqt1DmNzevTUEjx21y6tRQqpGpmLUOo Q2BA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1747754690; x=1748359490; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=TYLMHkDR/tPWcpSeZiIlQos+TrKLGRgGVHxxpAWir3w=; b=tQo8pm4TZbpaHpmVvmbVsEJ9uI1V6sV9wGQWcksAuVHEUYwL3Lx0nXKeaDqqgMhdzJ YgKaYVlmRoOww0brNxOymSfoM6SM4k/cR2SMjy/RhJ1mxv/RdO6i0BQHjlWBprIyTJVz 7BosCzVFepISWf8mV6Ow3uiT642eM7KEmNv5pNFENwXMJBlDzbHW/zHg+Q8FQOD50sGa dce8O16ZxZeGM+a1qgvNoUXhN4hbSuAXYzqq3s1Q3MA1L335NJUG7tCUhwZx0cuY7dH/ YQui5ks/4Bis6a7AP1UZGUnMxDYFb5b+Yfy51GcmRfv9hg0LXvi3DTdJs8n1hqgq+PFQ 7omw== X-Forwarded-Encrypted: i=1; AJvYcCXFYp0YMU/XnQ/5ksQJQbfEDNSZr6tHYm7BVTC86PqgKSd4NCnqfNy/EMEyFrogs5sYuvb/9PtJEAYZHA==@vger.kernel.org X-Gm-Message-State: AOJu0Yw7KehJ/5oQg+4lAO5m0fHqg4FH5Tbi/loxHTvATA+qqr1tVhPM N5H9rIENnFOQ9iijdPZx69w/Zmu9q4X3VGIOOIQGkkYQbe/zlHlCZpGW8DuIce20DgU= X-Gm-Gg: ASbGncuR73YDoeqBkW/yVoyhepQxBYlNub3/ZFJPnUh94ZPLJFHERpZab6+ES8gcxuw XSysV3bL4vIV4DWGjVNTESF8UuG8puifzzCJo8kJojdQtcDo73QZYgLmeU50bWqQjtHVmrdBNZn E/K35pdh17gZ4PyWu+aIoTfpc/Qh2nuNm1mtTJnWOjgbAKSFCFN/iOn2HDM1+GHnDkCBiyv54eR R2bhS0ChfSZNQxuZfuHeUgke2He42ccT8TcoRkVCtxc4voJxQyMP0LoV5sW+V3FMOaCsUpsOeY6 vrHXP1HRJUwFLPIe5xlvxbh/LQSpH6AXYyKXrLQZj+QDrUOXl5GavuwlVoLXoHj8SFdMg58xiTz CVZoOvbupE/IZ6RUBxeU0V2f4Bll9 X-Google-Smtp-Source: AGHT+IH1F3ARaz0eu5TNmhoYwL5GYYxn/a/Uy3LhTz+YKDYcsP+SYPwnNqbxv1AMZgM9n1+zv+umBA== X-Received: by 2002:a17:907:7e85:b0:ad2:25e9:f7a1 with SMTP id a640c23a62f3a-ad52d5b9fb8mr1621475166b.40.1747754690195; Tue, 20 May 2025 08:24:50 -0700 (PDT) Received: from rayden.urgonet (h-98-128-140-123.A175.priv.bahnhof.se. [98.128.140.123]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ad52d278257sm742608766b.82.2025.05.20.08.24.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 May 2025 08:24:49 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org, op-tee@lists.trustedfirmware.org, linux-arm-kernel@lists.infradead.org Cc: Olivier Masse , Thierry Reding , Yong Wu , Sumit Semwal , Benjamin Gaignard , Brian Starkey , John Stultz , "T . J . Mercier" , =?utf-8?q?Christian_K=C3=B6nig?= , Sumit Garg , Matthias Brugger , AngeloGioacchino Del Regno , azarrabi@qti.qualcomm.com, Simona Vetter , Daniel Stone , Rouven Czerwinski , Etienne Carriere , Jens Wiklander Subject: [PATCH v9 5/9] tee: new ioctl to a register tee_shm from a dmabuf file descriptor Date: Tue, 20 May 2025 17:16:48 +0200 Message-ID: <20250520152436.474778-6-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250520152436.474778-1-jens.wiklander@linaro.org> References: <20250520152436.474778-1-jens.wiklander@linaro.org> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Etienne Carriere Add a userspace API to create a tee_shm object that refers to a dmabuf reference. Userspace registers the dmabuf file descriptor as in a tee_shm object. The registration is completed with a tee_shm returned file descriptor. Userspace is free to close the dmabuf file descriptor after it has been registered since all the resources are now held via the new tee_shm object. Closing the tee_shm file descriptor will eventually release all resources used by the tee_shm object when all references are released. The new IOCTL, TEE_IOC_SHM_REGISTER_FD, supports dmabuf references to physically contiguous memory buffers. Dmabuf references acquired from the TEE DMA-heap can be used as protected memory for Secure Video Path and such use cases. It depends on the TEE and the TEE driver if dmabuf references acquired by other means can be used. A new tee_shm flag is added to identify tee_shm objects built from a registered dmabuf, TEE_SHM_DMA_BUF. Signed-off-by: Etienne Carriere Signed-off-by: Olivier Masse Signed-off-by: Jens Wiklander --- drivers/tee/tee_core.c | 63 +++++++++++++++++++++- drivers/tee/tee_private.h | 10 ++++ drivers/tee/tee_shm.c | 111 ++++++++++++++++++++++++++++++++++++-- include/linux/tee_core.h | 1 + include/linux/tee_drv.h | 10 ++++ include/uapi/linux/tee.h | 31 +++++++++++ 6 files changed, 221 insertions(+), 5 deletions(-) diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index 5259b8223c27..0e9d9e5872a4 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -353,11 +353,49 @@ tee_ioctl_shm_register(struct tee_context *ctx, return ret; } +static int +tee_ioctl_shm_register_fd(struct tee_context *ctx, + struct tee_ioctl_shm_register_fd_data __user *udata) +{ + struct tee_ioctl_shm_register_fd_data data; + struct tee_shm *shm; + long ret; + + if (copy_from_user(&data, udata, sizeof(data))) + return -EFAULT; + + /* Currently no input flags are supported */ + if (data.flags) + return -EINVAL; + + shm = tee_shm_register_fd(ctx, data.fd); + if (IS_ERR(shm)) + return -EINVAL; + + data.id = shm->id; + data.flags = shm->flags; + data.size = shm->size; + + if (copy_to_user(udata, &data, sizeof(data))) + ret = -EFAULT; + else + ret = tee_shm_get_fd(shm); + + /* + * When user space closes the file descriptor the shared memory + * should be freed or if tee_shm_get_fd() failed then it will + * be freed immediately. + */ + tee_shm_put(shm); + return ret; +} + static int param_from_user_memref(struct tee_context *ctx, struct tee_param_memref *memref, struct tee_ioctl_param *ip) { struct tee_shm *shm; + size_t offs = 0; /* * If a NULL pointer is passed to a TA in the TEE, @@ -388,6 +426,26 @@ static int param_from_user_memref(struct tee_context *ctx, tee_shm_put(shm); return -EINVAL; } + + if (shm->flags & TEE_SHM_DMA_BUF) { + struct tee_shm_dmabuf_ref *ref; + + ref = container_of(shm, struct tee_shm_dmabuf_ref, shm); + if (ref->parent_shm) { + /* + * The shm already has one reference to + * ref->parent_shm so we are clear of 0. + * We're getting another reference since + * this shm will be used in the parameter + * list instead of the shm we got with + * tee_shm_get_from_id() above. + */ + refcount_inc(&ref->parent_shm->refcount); + tee_shm_put(shm); + shm = ref->parent_shm; + offs = ref->offset; + } + } } else if (ctx->cap_memref_null) { /* Pass NULL pointer to OP-TEE */ shm = NULL; @@ -395,7 +453,7 @@ static int param_from_user_memref(struct tee_context *ctx, return -EINVAL; } - memref->shm_offs = ip->a; + memref->shm_offs = ip->a + offs; memref->size = ip->b; memref->shm = shm; @@ -841,6 +899,8 @@ static long tee_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return tee_ioctl_shm_alloc(ctx, uarg); case TEE_IOC_SHM_REGISTER: return tee_ioctl_shm_register(ctx, uarg); + case TEE_IOC_SHM_REGISTER_FD: + return tee_ioctl_shm_register_fd(ctx, uarg); case TEE_IOC_OPEN_SESSION: return tee_ioctl_open_session(ctx, uarg); case TEE_IOC_INVOKE: @@ -1300,3 +1360,4 @@ MODULE_AUTHOR("Linaro"); MODULE_DESCRIPTION("TEE Driver"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL v2"); +MODULE_IMPORT_NS("DMA_BUF"); diff --git a/drivers/tee/tee_private.h b/drivers/tee/tee_private.h index 6c6ff5d5eed2..308467705da6 100644 --- a/drivers/tee/tee_private.h +++ b/drivers/tee/tee_private.h @@ -13,6 +13,16 @@ #include #include +/* extra references appended to shm object for registered shared memory */ +struct tee_shm_dmabuf_ref { + struct tee_shm shm; + size_t offset; + struct dma_buf *dmabuf; + struct dma_buf_attachment *attach; + struct sg_table *sgt; + struct tee_shm *parent_shm; +}; + int tee_shm_get_fd(struct tee_shm *shm); bool tee_device_get(struct tee_device *teedev); diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c index daf6e5cfd59a..e1ed52ee0a16 100644 --- a/drivers/tee/tee_shm.c +++ b/drivers/tee/tee_shm.c @@ -4,6 +4,7 @@ */ #include #include +#include #include #include #include @@ -45,7 +46,23 @@ static void release_registered_pages(struct tee_shm *shm) static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm) { - if (shm->flags & TEE_SHM_POOL) { + struct tee_shm *parent_shm = NULL; + void *p = shm; + + if (shm->flags & TEE_SHM_DMA_BUF) { + struct tee_shm_dmabuf_ref *ref; + + ref = container_of(shm, struct tee_shm_dmabuf_ref, shm); + parent_shm = ref->parent_shm; + p = ref; + if (ref->attach) { + dma_buf_unmap_attachment(ref->attach, ref->sgt, + DMA_BIDIRECTIONAL); + + dma_buf_detach(ref->dmabuf, ref->attach); + } + dma_buf_put(ref->dmabuf); + } else if (shm->flags & TEE_SHM_POOL) { teedev->pool->ops->free(teedev->pool, shm); } else if (shm->flags & TEE_SHM_DYNAMIC) { int rc = teedev->desc->ops->shm_unregister(shm->ctx, shm); @@ -57,9 +74,10 @@ static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm) release_registered_pages(shm); } - teedev_ctx_put(shm->ctx); + if (shm->ctx) + teedev_ctx_put(shm->ctx); - kfree(shm); + kfree(p); tee_device_put(teedev); } @@ -169,7 +187,7 @@ struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size) * tee_client_invoke_func(). The memory allocated is later freed with a * call to tee_shm_free(). * - * @returns a pointer to 'struct tee_shm' + * @returns a pointer to 'struct tee_shm' on success, and ERR_PTR on failure */ struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size) { @@ -179,6 +197,91 @@ struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size) } EXPORT_SYMBOL_GPL(tee_shm_alloc_kernel_buf); +struct tee_shm *tee_shm_register_fd(struct tee_context *ctx, int fd) +{ + struct tee_shm_dmabuf_ref *ref; + int rc; + + if (!tee_device_get(ctx->teedev)) + return ERR_PTR(-EINVAL); + + teedev_ctx_get(ctx); + + ref = kzalloc(sizeof(*ref), GFP_KERNEL); + if (!ref) { + rc = -ENOMEM; + goto err_put_tee; + } + + refcount_set(&ref->shm.refcount, 1); + ref->shm.ctx = ctx; + ref->shm.id = -1; + ref->shm.flags = TEE_SHM_DMA_BUF; + + ref->dmabuf = dma_buf_get(fd); + if (IS_ERR(ref->dmabuf)) { + rc = PTR_ERR(ref->dmabuf); + goto err_kfree_ref; + } + + rc = tee_heap_update_from_dma_buf(ctx->teedev, ref->dmabuf, + &ref->offset, &ref->shm, + &ref->parent_shm); + if (!rc) + goto out; + if (rc != -EINVAL) + goto err_put_dmabuf; + + ref->attach = dma_buf_attach(ref->dmabuf, &ctx->teedev->dev); + if (IS_ERR(ref->attach)) { + rc = PTR_ERR(ref->attach); + goto err_put_dmabuf; + } + + ref->sgt = dma_buf_map_attachment(ref->attach, DMA_BIDIRECTIONAL); + if (IS_ERR(ref->sgt)) { + rc = PTR_ERR(ref->sgt); + goto err_detach; + } + + if (sg_nents(ref->sgt->sgl) != 1) { + rc = -EINVAL; + goto err_unmap_attachement; + } + + ref->shm.paddr = page_to_phys(sg_page(ref->sgt->sgl)); + ref->shm.size = ref->sgt->sgl->length; + +out: + mutex_lock(&ref->shm.ctx->teedev->mutex); + ref->shm.id = idr_alloc(&ref->shm.ctx->teedev->idr, &ref->shm, + 1, 0, GFP_KERNEL); + mutex_unlock(&ref->shm.ctx->teedev->mutex); + if (ref->shm.id < 0) { + rc = ref->shm.id; + if (ref->attach) + goto err_unmap_attachement; + goto err_put_dmabuf; + } + + return &ref->shm; + +err_unmap_attachement: + dma_buf_unmap_attachment(ref->attach, ref->sgt, DMA_BIDIRECTIONAL); +err_detach: + dma_buf_detach(ref->dmabuf, ref->attach); +err_put_dmabuf: + dma_buf_put(ref->dmabuf); +err_kfree_ref: + kfree(ref); +err_put_tee: + teedev_ctx_put(ctx); + tee_device_put(ctx->teedev); + + return ERR_PTR(rc); +} +EXPORT_SYMBOL_GPL(tee_shm_register_fd); + /** * tee_shm_alloc_priv_buf() - Allocate shared memory for a privately shared * kernel buffer diff --git a/include/linux/tee_core.h b/include/linux/tee_core.h index b8b99c97e00c..02c07f661349 100644 --- a/include/linux/tee_core.h +++ b/include/linux/tee_core.h @@ -28,6 +28,7 @@ #define TEE_SHM_USER_MAPPED BIT(1) /* Memory mapped in user space */ #define TEE_SHM_POOL BIT(2) /* Memory allocated from pool */ #define TEE_SHM_PRIV BIT(3) /* Memory private to TEE driver */ +#define TEE_SHM_DMA_BUF BIT(4) /* Memory with dma-buf handle */ #define TEE_DEVICE_FLAG_REGISTERED 0x1 #define TEE_MAX_DEV_NAME_LEN 32 diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index a54c203000ed..824f1251de60 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -116,6 +116,16 @@ struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size); struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx, void *addr, size_t length); +/** + * tee_shm_register_fd() - Register shared memory from file descriptor + * + * @ctx: Context that allocates the shared memory + * @fd: Shared memory file descriptor reference + * + * @returns a pointer to 'struct tee_shm' on success, and ERR_PTR on failure + */ +struct tee_shm *tee_shm_register_fd(struct tee_context *ctx, int fd); + /** * tee_shm_free() - Free shared memory * @shm: Handle to shared memory to free diff --git a/include/uapi/linux/tee.h b/include/uapi/linux/tee.h index d0430bee8292..8ec5f46fbfbe 100644 --- a/include/uapi/linux/tee.h +++ b/include/uapi/linux/tee.h @@ -118,6 +118,37 @@ struct tee_ioctl_shm_alloc_data { #define TEE_IOC_SHM_ALLOC _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 1, \ struct tee_ioctl_shm_alloc_data) +/** + * struct tee_ioctl_shm_register_fd_data - Shared memory registering argument + * @fd: [in] File descriptor identifying dmabuf reference + * @size: [out] Size of referenced memory + * @flags: [in] Flags to/from allocation. + * @id: [out] Identifier of the shared memory + * + * The flags field should currently be zero as input. Updated by the call + * with actual flags as defined by TEE_IOCTL_SHM_* above. + * This structure is used as argument for TEE_IOC_SHM_REGISTER_FD below. + */ +struct tee_ioctl_shm_register_fd_data { + __s64 fd; + __u64 size; + __u32 flags; + __s32 id; +}; + +/** + * TEE_IOC_SHM_REGISTER_FD - register a shared memory from a file descriptor + * + * Returns a file descriptor on success or < 0 on failure + * + * The returned file descriptor refers to the shared memory object in the + * kernel. The supplied file deccriptor can be closed if it's not needed + * for other purposes. The shared memory is freed when the descriptor is + * closed. + */ +#define TEE_IOC_SHM_REGISTER_FD _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 8, \ + struct tee_ioctl_shm_register_fd_data) + /** * struct tee_ioctl_buf_data - Variable sized buffer * @buf_ptr: [in] A __user pointer to a buffer From patchwork Tue May 20 15:16:50 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Wiklander X-Patchwork-Id: 891426 Received: from mail-ej1-f41.google.com (mail-ej1-f41.google.com [209.85.218.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 98A0A26F45F for ; Tue, 20 May 2025 15:24:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747754697; cv=none; b=bJ4HPA8LLcATHSN6qFh/AUu/1HTzeCUE+4KrGozBGTxSVgrIoR8T1TS1v45IS0Hb7zB6mV4LU1a4CescBijQcG7TcTR7hoT2bA5YtAhITEnjrD2Fb3UJUam5XzVv1QEqFQfBp3/4GlK58Sd3zhirxrK6AshwpoOJcCogucBxY6k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747754697; c=relaxed/simple; bh=QSxT3XOERXLFCoM+NCGjky7MuvldTHq1E3lqJiBK6rM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=oApvTjrQ8yA25y7Tvi8rC5VZ29u6Au+tSeQUyIaRb8MvWbkTKqGboPj2y0VyMoz2X6BBPKbl5NCDmeVuIrZNxwbk4Z16Jze6wbVaQIndpa0u2aULJgCB3LFalXdzP10cIODGmdRTHdC0UiYs1kNymRQ4yfm02eLWxMd5/eUtunQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=I6GI5l4s; arc=none smtp.client-ip=209.85.218.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="I6GI5l4s" Received: by mail-ej1-f41.google.com with SMTP id a640c23a62f3a-ad564b7aea9so492557766b.1 for ; Tue, 20 May 2025 08:24:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1747754694; x=1748359494; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=bld2F8yZ54kGs1+iy6D0HdLuVG17oYynXY/XfJVpzy4=; b=I6GI5l4sU7cE01SA7rvfnPHwShDVotteWSKnOwlUIRPiOeF4AMjox98VKXuX4fEb6T OmPpBA9sRsDhqRg82MuONpbKa91H/NPVmmMxBWjLEcX7C79UPDAAbHsacKPklbCFn7xK naW74iCofyrpMLWvXaa9KW/G8unxV+5T2Z8aSqRE78cwQvdl+3QOdI/IwEr4YW9V/dLv OG8sSDIxNzEYOZVp4cVdamGGZvK0C6QB+bCDqy5QsY72hGKDpOuwNjS8WKV9RY91i1UT aVixDxIyb3yom40zKBRb4Ggl02h9RGV3gxlSNZ+09KPrvP4u7G6i6x/gaaXRMew2JhWz r70w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1747754694; x=1748359494; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=bld2F8yZ54kGs1+iy6D0HdLuVG17oYynXY/XfJVpzy4=; b=IE3jlsj70/Yy2JNrr+zX0EoZii8zpFhwTn877Fyh3gJLIuYwqyZ0GkMcHbPY3OaT1b lLHq5eKuIwNv+PmvjssE2T2W4whcxERkQp4pTf8pXIdAhBCOs9GtT7658vbKZqtFQt4j RVbCWjjKLQmlapjTjvj7RsxjK0ATbbZKtQPNsJ6yOig5VQPwwym7oRmc9PVVux0bOmf8 oAYZURoN3i/aKYcNc8drShT0X3Cxw48o9847YqJMHbVzx2vGOm7VlVs8nEWyTkIdfWwn 48G0YSnhaHLz1kAzhKZnQ1IzlFpt1EO598ndkEfkHU5kn8DdIHLBPMZXYh2SMuMWx1YX UUkA== X-Forwarded-Encrypted: i=1; AJvYcCXRFu5Gczov3EdMjaYa+vTlVupkcmHZyzQXfAR/WhefDOegAifqi9cVOkwRnUVey7RwwU0VLSiBNU/3Xg==@vger.kernel.org X-Gm-Message-State: AOJu0YzBwKq8hRURnQkY58rlwGZsEWjnwF/um7ZHPJ0e4Y/FhG8+37Mh re/MjLiar+wY3X99XdixzDhIFabdZlnLd2QPGb/XAPnKMTJyfyKSpveWUmQW0eRAIVc= X-Gm-Gg: ASbGnctUNnc9h1Q9yA2GpoLel23neIIxYWeSRUZGbjQNXQ0YW6YOwBgwDQrQyKMckI8 4+QrnwwkGrw6TIZus3HDoVXe0ExWtMlVJkeQbLb8X4L+MRMcs4jm0X8fjR2J3g3F3Wb/5Qx7OGm YSNzDKfPvnMZaZM9WDTyUr/tGZj7tHw+lfGCe9rlysvxqSdRIPtKwLuVHqK49+Q+r+hSmPR/3p4 yUOf5zwUWEobtnTmPZPO+9oKPtaP4o+5d9t9Wua7GQA30YmyQMay6fReEdA9u0MuS0ww/eheiPU OBAPgjMqW4/XIwSeYd9btVqzhH+5w1JrNA349yZKZlfNjRgU65Lt2LeJiyv9wtqNfdMKVh0FNDE dtjNxW/2B0ci/yo5e59bU3F/CVtAm X-Google-Smtp-Source: AGHT+IE+oU//7EkaWaSVnBEAmENTiykO6EjOUBrIKYl9jX9zjcRr0m/0LP96+ZckH975FqdkGFgQKA== X-Received: by 2002:a17:907:3e28:b0:ad5:2d5d:206f with SMTP id a640c23a62f3a-ad52fa567ccmr1750869866b.19.1747754693784; Tue, 20 May 2025 08:24:53 -0700 (PDT) Received: from rayden.urgonet (h-98-128-140-123.A175.priv.bahnhof.se. [98.128.140.123]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ad52d278257sm742608766b.82.2025.05.20.08.24.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 May 2025 08:24:53 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org, op-tee@lists.trustedfirmware.org, linux-arm-kernel@lists.infradead.org Cc: Olivier Masse , Thierry Reding , Yong Wu , Sumit Semwal , Benjamin Gaignard , Brian Starkey , John Stultz , "T . J . Mercier" , =?utf-8?q?Christian_K=C3=B6nig?= , Sumit Garg , Matthias Brugger , AngeloGioacchino Del Regno , azarrabi@qti.qualcomm.com, Simona Vetter , Daniel Stone , Rouven Czerwinski , Jens Wiklander Subject: [PATCH v9 7/9] optee: support protected memory allocation Date: Tue, 20 May 2025 17:16:50 +0200 Message-ID: <20250520152436.474778-8-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250520152436.474778-1-jens.wiklander@linaro.org> References: <20250520152436.474778-1-jens.wiklander@linaro.org> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add support in the OP-TEE backend driver for protected memory allocation. The support is limited to only the SMC ABI and for secure video buffers. OP-TEE is probed for the range of protected physical memory and a memory pool allocator is initialized if OP-TEE have support for such memory. Signed-off-by: Jens Wiklander --- drivers/tee/optee/core.c | 10 +++++++ drivers/tee/optee/optee_private.h | 2 ++ drivers/tee/optee/smc_abi.c | 45 +++++++++++++++++++++++++++++-- 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index c75fddc83576..4b14a7ac56f9 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -56,6 +56,15 @@ int optee_rpmb_intf_rdev(struct notifier_block *intf, unsigned long action, return 0; } +int optee_set_dma_mask(struct optee *optee, u_int pa_width) +{ + u64 mask = DMA_BIT_MASK(min(64, pa_width)); + + optee->teedev->dev.dma_mask = &optee->teedev->dev.coherent_dma_mask; + + return dma_set_mask_and_coherent(&optee->teedev->dev, mask); +} + static void optee_bus_scan(struct work_struct *work) { WARN_ON(optee_enumerate_devices(PTA_CMD_GET_DEVICES_SUPP)); @@ -181,6 +190,7 @@ void optee_remove_common(struct optee *optee) tee_device_unregister(optee->supp_teedev); tee_device_unregister(optee->teedev); + tee_device_unregister_all_dma_heaps(optee->teedev); tee_shm_pool_free(optee->pool); optee_supp_uninit(&optee->supp); mutex_destroy(&optee->call_queue.mutex); diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h index dc0f355ef72a..5e3c34802121 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -272,6 +272,8 @@ struct optee_call_ctx { extern struct blocking_notifier_head optee_rpmb_intf_added; +int optee_set_dma_mask(struct optee *optee, u_int pa_width); + int optee_notif_init(struct optee *optee, u_int max_key); void optee_notif_uninit(struct optee *optee); int optee_notif_wait(struct optee *optee, u_int key, u32 timeout); diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c index f0c3ac1103bb..f3cae8243785 100644 --- a/drivers/tee/optee/smc_abi.c +++ b/drivers/tee/optee/smc_abi.c @@ -1584,6 +1584,42 @@ static inline int optee_load_fw(struct platform_device *pdev, } #endif +static int optee_protmem_pool_init(struct optee *optee) +{ + enum tee_dma_heap_id heap_id = TEE_DMA_HEAP_SECURE_VIDEO_PLAY; + struct tee_protmem_pool *pool; + int rc; + + if (optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_PROTMEM) { + union { + struct arm_smccc_res smccc; + struct optee_smc_get_protmem_config_result result; + } res; + + optee->smc.invoke_fn(OPTEE_SMC_GET_PROTMEM_CONFIG, 0, 0, 0, 0, + 0, 0, 0, &res.smccc); + if (res.result.status != OPTEE_SMC_RETURN_OK) { + pr_err("Secure Data Path service not available\n"); + return 0; + } + rc = optee_set_dma_mask(optee, res.result.pa_width); + if (!rc) + pool = tee_protmem_static_pool_alloc(res.result.start, + res.result.size); + if (IS_ERR(pool)) + return PTR_ERR(pool); + + rc = tee_device_register_dma_heap(optee->teedev, heap_id, pool); + if (rc) + goto err; + } + + return 0; +err: + pool->ops->destroy_pool(pool); + return rc; +} + static int optee_probe(struct platform_device *pdev) { optee_invoke_fn *invoke_fn; @@ -1679,7 +1715,7 @@ static int optee_probe(struct platform_device *pdev) optee = kzalloc(sizeof(*optee), GFP_KERNEL); if (!optee) { rc = -ENOMEM; - goto err_free_pool; + goto err_free_shm_pool; } optee->ops = &optee_ops; @@ -1752,6 +1788,10 @@ static int optee_probe(struct platform_device *pdev) pr_info("Asynchronous notifications enabled\n"); } + rc = optee_protmem_pool_init(optee); + if (rc) + goto err_notif_uninit; + /* * Ensure that there are no pre-existing shm objects before enabling * the shm cache so that there's no chance of receiving an invalid @@ -1787,6 +1827,7 @@ static int optee_probe(struct platform_device *pdev) optee_disable_shm_cache(optee); optee_smc_notif_uninit_irq(optee); optee_unregister_devices(); + tee_device_unregister_all_dma_heaps(optee->teedev); err_notif_uninit: optee_notif_uninit(optee); err_close_ctx: @@ -1803,7 +1844,7 @@ static int optee_probe(struct platform_device *pdev) tee_device_unregister(optee->teedev); err_free_optee: kfree(optee); -err_free_pool: +err_free_shm_pool: tee_shm_pool_free(pool); if (memremaped_shm) memunmap(memremaped_shm); From patchwork Tue May 20 15:16:52 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Wiklander X-Patchwork-Id: 891425 Received: from mail-ej1-f41.google.com (mail-ej1-f41.google.com [209.85.218.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 61DAF27F73A for ; Tue, 20 May 2025 15:24:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747754701; cv=none; b=RCLWNOP8S9UklMBMteNuvSUU5o2NZY5embjBuGBpFWWef4cxwPq8GxTVjsAQbSXtGs1z0/qNWnr4DpTkinBZgKG7HGixsJFVjg3pJZVQ9oxGNc1iK0sLziaKgwubXoBFgrXwUqriYHwYiCxAIzDObbP78v1D1NcQrMMzly5/i+Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747754701; c=relaxed/simple; bh=HrWAkjXzo1cwOQkzp5D5PLjihxqiuqVqgMCi74TCylM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=As7E2OrjS0Fr+cq/lah5/1b7gprkfT1SUvxqNp8NsOJFVgN5dx6ZHpUYzq8XvuB+oBv5Tt2AKeDXJ/SQMWFBHNcSJdBmT+whXje6rgUY7NwuEn1xG+ZVirtk1wZBLYiALapSl3sV+ntP1RpXS12uZMCiw6dRTIgJoKrqnEFftUI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=gfXFU4PG; arc=none smtp.client-ip=209.85.218.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="gfXFU4PG" Received: by mail-ej1-f41.google.com with SMTP id a640c23a62f3a-ad216a5a59cso808143566b.3 for ; Tue, 20 May 2025 08:24:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1747754697; x=1748359497; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Sws8LggPb3Nr4WEIwk49/i4GQcd2qsiJjDBUK0g1c0s=; b=gfXFU4PGCj+JV99lZR6A1oIf0EDlGCRXtA28zlGjNR0sRtrTG91gmKlcoGC6+Z2voy PPtx+UOtskL9zX8R2Ldr8ih+VS1ErUFk61EqHorpTAihOc6YUmXgRpVZfZqjcpv9MRQd sAfRvtCjDMYBKV/jpFAKpo7/f4p7nNgJFkWnegmZBfTEH+VIw0nAqtq29AxuoWVGBTN3 Qstpz25KOrjBjX6fSyeARTzQAIXN9yrdgrKUfnCQgnKbCslsxya8H0hrLZXOGUAUwClX 4YO/GhKegTdO6JDUOHgHFMPGY6mAgX0uiz3cExqCIUYrtbDZLF7PzRXsuAh22cs6TUFD mi6w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1747754697; x=1748359497; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Sws8LggPb3Nr4WEIwk49/i4GQcd2qsiJjDBUK0g1c0s=; b=OUJkmhVFdELRrVInxdJ2JfVx11uotE7Yew7AUrIAfK0R73IEEUsag/vgoY3i2OveHu 6X4p1ZkFaIBs0dhc0peR/DqxberU8YMbQlFDY2O4pDZaV0cTJjK+697t44sIz0IgDG4l Wr8e6ZiLdZIxalcY3Gbi7zkwqbZOfoRXeQadLacdADqv4CR4RULKyvioN+c8vaWoO4oH ceo5IYeIQK0PxHH7vK/mMCgvXW+wEBJN8cYG67mFzvD8IcIDR+aXoL7wTI2oZ5PrZyma rOYTPvIm9Mehgq3ddlUavwV5IoV7dTirBQpD3cCDVY44cxFtbilmPg0INadFHu1GNh6j KNnA== X-Forwarded-Encrypted: i=1; AJvYcCWRO8p4+XLJiU9y4x9cWE5dtL2Sk0UQXv/18KxANht6Ms6OfQUnzbbl07McpVrib3bQRukioc+i5YpnaA==@vger.kernel.org X-Gm-Message-State: AOJu0Yz3bti+qYjI8e3eLlqMdHont9Qhn7CCcQrIflSBa+yjZe93pL1l FPkGZTVIDrS9OmXeLw9qakG0YwaKMD7j08tNh6kF175m1gdyGGCIVkV6lDOnd3iB/QA= X-Gm-Gg: ASbGncvKxfXHTVvWhMHPygYYUr9oJZLS98pcB3HHD/BQPQ8Y7A0wvTiEtKx40iFw70h hm60i+/AnVsxbNNquUQCKmKvAzDLJJdFaKWu6DHfDXMSIUiU4cLelSbY7mPna/CgyJlxL3mSnBh KsJAYI9D2/bOboE/aOJoTxGe7CH/3b4UeN+oGXWXaVXK2nWq0oPP2NCZZEZbeJWQCT57/flnhZN +fiS4qVFQYj7BohSug1Kda0Wf6zUSm6h/pXJqN/zK/PQ0v6/uMyDyMXSuJtZg1SxkOScqIJWKUl 5W2oc3mc10TVqNgfap5m2cI0waSnas1WFMIK7PwG2r1CWIff5JmCETEMLctZPhb+cjNny8iDwXx Eolc1N838BpIAzxxmfNKzR/gEZOefUzBSs8xK2lo= X-Google-Smtp-Source: AGHT+IFajjrVIsC7kJISaAObbiybAYfu3AaUSsn1KJ4AT03AxVtsB+czB4nAf85bGG6wnrUQQg0qnQ== X-Received: by 2002:a17:907:7f08:b0:ac7:3817:d8da with SMTP id a640c23a62f3a-ad52d609170mr1346626366b.52.1747754697525; Tue, 20 May 2025 08:24:57 -0700 (PDT) Received: from rayden.urgonet (h-98-128-140-123.A175.priv.bahnhof.se. [98.128.140.123]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ad52d278257sm742608766b.82.2025.05.20.08.24.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 May 2025 08:24:56 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org, op-tee@lists.trustedfirmware.org, linux-arm-kernel@lists.infradead.org Cc: Olivier Masse , Thierry Reding , Yong Wu , Sumit Semwal , Benjamin Gaignard , Brian Starkey , John Stultz , "T . J . Mercier" , =?utf-8?q?Christian_K=C3=B6nig?= , Sumit Garg , Matthias Brugger , AngeloGioacchino Del Regno , azarrabi@qti.qualcomm.com, Simona Vetter , Daniel Stone , Rouven Czerwinski , Jens Wiklander Subject: [PATCH v9 9/9] optee: smc abi: dynamic protected memory allocation Date: Tue, 20 May 2025 17:16:52 +0200 Message-ID: <20250520152436.474778-10-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250520152436.474778-1-jens.wiklander@linaro.org> References: <20250520152436.474778-1-jens.wiklander@linaro.org> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add support in the OP-TEE backend driver for dynamic protected memory allocation using the SMC ABI. Signed-off-by: Jens Wiklander --- drivers/tee/optee/smc_abi.c | 102 ++++++++++++++++++++++++++++++------ 1 file changed, 85 insertions(+), 17 deletions(-) diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c index f3cae8243785..6b3fbe7f0909 100644 --- a/drivers/tee/optee/smc_abi.c +++ b/drivers/tee/optee/smc_abi.c @@ -965,6 +965,70 @@ static int optee_smc_do_call_with_arg(struct tee_context *ctx, return rc; } +static int optee_smc_lend_protmem(struct optee *optee, struct tee_shm *protmem, + u16 *end_points, unsigned int ep_count, + u32 use_case) +{ + struct optee_shm_arg_entry *entry; + struct optee_msg_arg *msg_arg; + struct tee_shm *shm; + u_int offs; + int rc; + + msg_arg = optee_get_msg_arg(optee->ctx, 2, &entry, &shm, &offs); + if (IS_ERR(msg_arg)) + return PTR_ERR(msg_arg); + + msg_arg->cmd = OPTEE_MSG_CMD_LEND_PROTMEM; + msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; + msg_arg->params[0].u.value.a = use_case; + msg_arg->params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; + msg_arg->params[1].u.tmem.buf_ptr = protmem->paddr; + msg_arg->params[1].u.tmem.size = protmem->size; + msg_arg->params[1].u.tmem.shm_ref = (u_long)protmem; + + rc = optee->ops->do_call_with_arg(optee->ctx, shm, offs, false); + if (rc) + goto out; + if (msg_arg->ret != TEEC_SUCCESS) { + rc = -EINVAL; + goto out; + } + protmem->sec_world_id = (u_long)protmem; + +out: + optee_free_msg_arg(optee->ctx, entry, offs); + return rc; +} + +static int optee_smc_reclaim_protmem(struct optee *optee, + struct tee_shm *protmem) +{ + struct optee_shm_arg_entry *entry; + struct optee_msg_arg *msg_arg; + struct tee_shm *shm; + u_int offs; + int rc; + + msg_arg = optee_get_msg_arg(optee->ctx, 1, &entry, &shm, &offs); + if (IS_ERR(msg_arg)) + return PTR_ERR(msg_arg); + + msg_arg->cmd = OPTEE_MSG_CMD_RECLAIM_PROTMEM; + msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT; + msg_arg->params[0].u.rmem.shm_ref = (u_long)protmem; + + rc = optee->ops->do_call_with_arg(optee->ctx, shm, offs, false); + if (rc) + goto out; + if (msg_arg->ret != TEEC_SUCCESS) + rc = -EINVAL; + +out: + optee_free_msg_arg(optee->ctx, entry, offs); + return rc; +} + /* * 5. Asynchronous notification */ @@ -1216,6 +1280,8 @@ static const struct optee_ops optee_ops = { .do_call_with_arg = optee_smc_do_call_with_arg, .to_msg_param = optee_to_msg_param, .from_msg_param = optee_from_msg_param, + .lend_protmem = optee_smc_lend_protmem, + .reclaim_protmem = optee_smc_reclaim_protmem, }; static int enable_async_notif(optee_invoke_fn *invoke_fn) @@ -1586,11 +1652,14 @@ static inline int optee_load_fw(struct platform_device *pdev, static int optee_protmem_pool_init(struct optee *optee) { + bool protm = optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_PROTMEM; + bool dyn_protm = optee->smc.sec_caps & + OPTEE_SMC_SEC_CAP_DYNAMIC_PROTMEM; enum tee_dma_heap_id heap_id = TEE_DMA_HEAP_SECURE_VIDEO_PLAY; - struct tee_protmem_pool *pool; - int rc; + struct tee_protmem_pool *pool = ERR_PTR(-EINVAL); + int rc = -EINVAL; - if (optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_PROTMEM) { + if (protm) { union { struct arm_smccc_res smccc; struct optee_smc_get_protmem_config_result result; @@ -1598,26 +1667,26 @@ static int optee_protmem_pool_init(struct optee *optee) optee->smc.invoke_fn(OPTEE_SMC_GET_PROTMEM_CONFIG, 0, 0, 0, 0, 0, 0, 0, &res.smccc); - if (res.result.status != OPTEE_SMC_RETURN_OK) { - pr_err("Secure Data Path service not available\n"); - return 0; - } - rc = optee_set_dma_mask(optee, res.result.pa_width); + if (res.result.status == OPTEE_SMC_RETURN_OK) + rc = optee_set_dma_mask(optee, res.result.pa_width); if (!rc) pool = tee_protmem_static_pool_alloc(res.result.start, res.result.size); - if (IS_ERR(pool)) - return PTR_ERR(pool); + } + if (dyn_protm && IS_ERR(pool)) + pool = optee_protmem_alloc_dyn_pool(optee, heap_id); + + if (!IS_ERR(pool)) { rc = tee_device_register_dma_heap(optee->teedev, heap_id, pool); if (rc) - goto err; + pool->ops->destroy_pool(pool); } + if (protm || dyn_protm) + return rc; + return 0; -err: - pool->ops->destroy_pool(pool); - return rc; } static int optee_probe(struct platform_device *pdev) @@ -1788,9 +1857,8 @@ static int optee_probe(struct platform_device *pdev) pr_info("Asynchronous notifications enabled\n"); } - rc = optee_protmem_pool_init(optee); - if (rc) - goto err_notif_uninit; + if (optee_protmem_pool_init(optee)) + pr_info("Protected memory service not available\n"); /* * Ensure that there are no pre-existing shm objects before enabling