From nobody Sun Dec 14 02:14:14 2025 Received: from mail-ed1-f47.google.com (mail-ed1-f47.google.com [209.85.208.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 69D682BF3CF for ; Wed, 13 Aug 2025 06:03:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755065035; cv=none; b=uh/VAO69GPZMt+6t1PZki3fqAMCqtQaSyBK55JFNr6RVGO0I8ybHDIOZb+0HML63aMujFgfpRFBZYWo+DXfTSimeNude3Y1a6fbB+5EFQnVFiJLjAy7lQQQvk7eSaqQ50aYte+MUC2OQ7CPvcpnavIQIXcSgyOI+C6mZJjd5PEM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755065035; c=relaxed/simple; bh=C+Sz4SnedftIZ1/NoAGZb6mTKXKJjN7cSwnn0OXrwXw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ng06AceblTd5qZXtLSlPHYG/Mak0z/bqRIFizCKsWop1xO8IG+T6VRGV+xCyLA/tKgynshhgR7CpxNAyYxqQgQ30btvD1R8iehiZ3QgLEIgum8DGRqL3iX8fK8XgTqVXFZ0+L3dUkBzvi9CzGrIPt5oMCdBzmUb65J9ToG2AJck= 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=QS6GHTFb; arc=none smtp.client-ip=209.85.208.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="QS6GHTFb" Received: by mail-ed1-f47.google.com with SMTP id 4fb4d7f45d1cf-615756b1e99so8365978a12.0 for ; Tue, 12 Aug 2025 23:03:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1755065031; x=1755669831; 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=nRMYzGhOSMRi00YSM38TcGWVAJXFsKQy06jgg+FF2rE=; b=QS6GHTFb6Hj0X/2K7VWXWMz2EDZZBPWN2AE6+6HBrYQHcn5lMXQEINlsKBS3/PHSCz e8opE/fHOS4F/usbu/4sDDwgEg5T9pVf+83GbY4fzTguRDyoX6+iR3tM/+5dyQaVgVHv QJ/FpKAi+oF3x27yb0+oYaIbgWxCeSvpn/YhJd3cXa3NvbaYLAj7qtdNNj1yt6LP9ANT if6vdtcYBgskodb/xnrhCi0mBaFhUT9ssmEJAgwXIbiC+atoffpZcu+C5epObaGXNjDa kiMV7TK6zBMDvkVjFV+opg0zqH53GKDGXihTSX3T6nDA6BUbp2K242gCjYGgR6pEiOkz 9VKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755065031; x=1755669831; 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=nRMYzGhOSMRi00YSM38TcGWVAJXFsKQy06jgg+FF2rE=; b=phG8QUcscPcG+KOxLqCxVvyxYP470/Nt7qZ2uEDpvP4n/9f/5TBsa9QGadpk71c9kM pVuuYJi77PpKRzFx5N6Z1Xvkc7LLJOR76urgeCZpTrofceIxnjRxURA1gwOjROf8ZfVW ds+AKMRQwedwuNXHPMnc+9XroFBSpcqRgULFOlI8gkKhNIP5YyjyGDXch+mnSW6+reBM /M5dR1Kxf7/2XWc3BrSdy7uzHv9hYmbzM9aauGaaaRfGfGJalN51BIJEM/4vvDixbe9u /1UtwZ4I8b/ps9xRqGpOrTfyqrCTdpMnB99zjyhi5QL26Xe+MYJ5U6/Q2LFm4skaimAR eFsQ== X-Gm-Message-State: AOJu0YwkvlOWFOTOWK4JlM9xrQY3eYyouDQqOavs1SPchWNXqUZu/ARd Mvamfj5ON+A3FRJTG/fnebh52D2TiJ8GpDmZzjy4ng6nrkMmXrlf2qKP5vCxtZdaXz3unfqohqv y/PQ6OC0= X-Gm-Gg: ASbGncvj6m/AaW8NQTfeKhnsEP2S9tiAFv1R1TS1Dj5ZvNwbOZpf0q6gkyizi0BW25p 0Zm7bI0gfho0eU/vc9k4k/FmDqK8Zzgz1YADgHZxGURv/PBGBJIMNP83K4uH4bl/avXVArlkKed A/2X1uvgMDkLKX0IzsHCGz5QnuXPnkl/AdAfaxAzgGNbD/uYQbtnqf/5HtNyuyPV8aWVoDkAlCV OJe1KbZdO/J6XMNesKhMSN816/ilL63uqiyQsN6YI1HypdJK4EapHjd7fx2hfLy1+Gh4dp8Huaq fRMdC5iRHHol8LOOvJdYO5loOi4m1bu51M5YeXV24M4PyP7ArkgfFP2kdOZLnSukKNh7Y9bIPpN x/LRLXFjHDeci7wNxdK3q6yCUXroSNO/l+dX8nekwqTAYWgDmPGRAKdJPjA4XrN/LyYzB089PPo fn7SSJsdkFjQ== X-Google-Smtp-Source: AGHT+IESz7sY75MZEYJlNFDCMXqqy9HHT+W+mreLkuWcYGas2OheGV4v3f3HmO2S6T6YSl3Fg7PFjw== X-Received: by 2002:a05:6402:27cf:b0:615:cb9c:d5a2 with SMTP id 4fb4d7f45d1cf-6186bfd2d6amr1298331a12.18.1755065030954; Tue, 12 Aug 2025 23:03:50 -0700 (PDT) Received: from rayden.urgonet (h-37-123-177-177.A175.priv.bahnhof.se. [37.123.177.177]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-615a8f2b892sm21498679a12.25.2025.08.12.23.03.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Aug 2025 23:03:50 -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=20K=C3=B6nig?= , Sumit Garg , Matthias Brugger , AngeloGioacchino Del Regno , azarrabi@qti.qualcomm.com, Simona Vetter , Daniel Stone , Rouven Czerwinski , robin.murphy@arm.com, Jens Wiklander , Sumit Garg Subject: [PATCH v11 1/9] optee: sync secure world ABI headers Date: Wed, 13 Aug 2025 08:02:50 +0200 Message-ID: <20250813060339.2977604-2-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250813060339.2977604-1-jens.wiklander@linaro.org> References: <20250813060339.2977604-1-jens.wiklander@linaro.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Update the header files describing the secure world ABI, both with and without FF-A. The ABI is extended to deal with protected memory, but as usual backward compatible. Signed-off-by: Jens Wiklander Reviewed-by: Sumit Garg --- drivers/tee/optee/optee_ffa.h | 27 ++++++++--- drivers/tee/optee/optee_msg.h | 84 ++++++++++++++++++++++++++++++----- drivers/tee/optee/optee_smc.h | 37 ++++++++++++++- 3 files changed, 130 insertions(+), 18 deletions(-) diff --git a/drivers/tee/optee/optee_ffa.h b/drivers/tee/optee/optee_ffa.h index 257735ae5b56..cc257e7956a3 100644 --- a/drivers/tee/optee/optee_ffa.h +++ b/drivers/tee/optee/optee_ffa.h @@ -81,7 +81,7 @@ * as the second MSG arg struct for * OPTEE_FFA_YIELDING_CALL_WITH_ARG. * Bit[31:8]: Reserved (MBZ) - * w5: Bitfield of secure world capabilities OPTEE_FFA_SEC_CAP_* below, + * w5: Bitfield of OP-TEE capabilities OPTEE_FFA_SEC_CAP_* * w6: The maximum secure world notification number * w7: Not used (MBZ) */ @@ -94,6 +94,8 @@ #define OPTEE_FFA_SEC_CAP_ASYNC_NOTIF BIT(1) /* OP-TEE supports probing for RPMB device if needed */ #define OPTEE_FFA_SEC_CAP_RPMB_PROBE BIT(2) +/* OP-TEE supports Protected Memory for secure data path */ +#define OPTEE_FFA_SEC_CAP_PROTMEM BIT(3) =20 #define OPTEE_FFA_EXCHANGE_CAPABILITIES OPTEE_FFA_BLOCKING_CALL(2) =20 @@ -108,7 +110,7 @@ * * Return register usage: * w3: Error code, 0 on success - * w4-w7: Note used (MBZ) + * w4-w7: Not used (MBZ) */ #define OPTEE_FFA_UNREGISTER_SHM OPTEE_FFA_BLOCKING_CALL(3) =20 @@ -119,16 +121,31 @@ * Call register usage: * w3: Service ID, OPTEE_FFA_ENABLE_ASYNC_NOTIF * w4: Notification value to request bottom half processing, should be - * less than OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE. + * less than OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE * w5-w7: Not used (MBZ) * * Return register usage: * w3: Error code, 0 on success - * w4-w7: Note used (MBZ) + * w4-w7: Not used (MBZ) */ #define OPTEE_FFA_ENABLE_ASYNC_NOTIF OPTEE_FFA_BLOCKING_CALL(5) =20 -#define OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE 64 +#define OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE 64 + +/* + * Release Protected memory + * + * Call register usage: + * w3: Service ID, OPTEE_FFA_RECLAIM_PROTMEM + * 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_RELEASE_PROTMEM OPTEE_FFA_BLOCKING_CALL(8) =20 /* * Call with struct optee_msg_arg as argument in the supplied shared memory diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h index e8840a82b983..838e1d4a22f0 100644 --- a/drivers/tee/optee/optee_msg.h +++ b/drivers/tee/optee/optee_msg.h @@ -133,13 +133,13 @@ struct optee_msg_param_rmem { }; =20 /** - * struct optee_msg_param_fmem - ffa memory reference parameter + * struct optee_msg_param_fmem - FF-A 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 + * @global_id: Global identifier of the shared memory */ struct optee_msg_param_fmem { u32 offs_low; @@ -165,7 +165,7 @@ 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 + * @fmem: parameter by FF-A registered memory reference * @value: parameter by opaque value * @octets: parameter by octet string * @@ -296,6 +296,18 @@ struct optee_msg_arg { */ #define OPTEE_MSG_FUNCID_GET_OS_REVISION 0x0001 =20 +/* + * Values used in OPTEE_MSG_CMD_LEND_PROTMEM below + * OPTEE_MSG_PROTMEM_RESERVED Reserved + * OPTEE_MSG_PROTMEM_SECURE_VIDEO_PLAY Secure Video Playback + * OPTEE_MSG_PROTMEM_TRUSTED_UI Trused UI + * OPTEE_MSG_PROTMEM_SECURE_VIDEO_RECORD Secure Video Recording + */ +#define OPTEE_MSG_PROTMEM_RESERVED 0 +#define OPTEE_MSG_PROTMEM_SECURE_VIDEO_PLAY 1 +#define OPTEE_MSG_PROTMEM_TRUSTED_UI 2 +#define OPTEE_MSG_PROTMEM_SECURE_VIDEO_RECORD 3 + /* * Do a secure call with struct optee_msg_arg as argument * The OPTEE_MSG_CMD_* below defines what goes in struct optee_msg_arg::cmd @@ -337,15 +349,63 @@ struct optee_msg_arg { * OPTEE_MSG_CMD_STOP_ASYNC_NOTIF informs secure world that from now is * normal world unable to process asynchronous notifications. Typically * used when the driver is shut down. + * + * OPTEE_MSG_CMD_LEND_PROTMEM lends protected memory. The passed normal + * physical memory is protected from normal world access. The memory + * should be unmapped prior to this call since it becomes inaccessible + * during the request. + * Parameters are passed as: + * [in] param[0].attr OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + * [in] param[0].u.value.a OPTEE_MSG_PROTMEM_* defined above + * [in] param[1].attr OPTEE_MSG_ATTR_TYPE_TMEM_INPUT + * [in] param[1].u.tmem.buf_ptr physical address + * [in] param[1].u.tmem.size size + * [in] param[1].u.tmem.shm_ref holds protected memory reference + * + * OPTEE_MSG_CMD_RECLAIM_PROTMEM reclaims a previously lent protected + * memory reference. The physical memory is accessible by the normal world + * after this function has return and can be mapped again. The information + * is passed as: + * [in] param[0].attr OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + * [in] param[0].u.value.a holds protected memory cookie + * + * OPTEE_MSG_CMD_GET_PROTMEM_CONFIG get configuration for a specific + * protected memory use case. Parameters are passed as: + * [in] param[0].attr OPTEE_MSG_ATTR_TYPE_VALUE_INOUT + * [in] param[0].value.a OPTEE_MSG_PROTMEM_* + * [in] param[1].attr OPTEE_MSG_ATTR_TYPE_{R,F}MEM_OUTPUT + * [in] param[1].u.{r,f}mem Buffer or NULL + * [in] param[1].u.{r,f}mem.size Provided size of buffer or 0 for query + * output for the protected use case: + * [out] param[0].value.a Minimal size of protected memory + * [out] param[0].value.b Required alignment of size and start of + * protected memory + * [out] param[0].value.c PA width, max 64 + * [out] param[1].{r,f}mem.size Size of output data + * [out] param[1].{r,f}mem If non-NULL, contains an array of + * uint32_t memory attributes that must be + * included when lending memory for this + * use case + * + * OPTEE_MSG_CMD_ASSIGN_PROTMEM assigns use-case to protected memory + * previously lent using the FFA_LEND framework ABI. Parameters are passed + * as: + * [in] param[0].attr OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + * [in] param[0].u.value.a holds protected memory cookie + * [in] param[0].u.value.b OPTEE_MSG_PROTMEM_* defined above */ -#define OPTEE_MSG_CMD_OPEN_SESSION 0 -#define OPTEE_MSG_CMD_INVOKE_COMMAND 1 -#define OPTEE_MSG_CMD_CLOSE_SESSION 2 -#define OPTEE_MSG_CMD_CANCEL 3 -#define OPTEE_MSG_CMD_REGISTER_SHM 4 -#define OPTEE_MSG_CMD_UNREGISTER_SHM 5 -#define OPTEE_MSG_CMD_DO_BOTTOM_HALF 6 -#define OPTEE_MSG_CMD_STOP_ASYNC_NOTIF 7 -#define OPTEE_MSG_FUNCID_CALL_WITH_ARG 0x0004 +#define OPTEE_MSG_CMD_OPEN_SESSION 0 +#define OPTEE_MSG_CMD_INVOKE_COMMAND 1 +#define OPTEE_MSG_CMD_CLOSE_SESSION 2 +#define OPTEE_MSG_CMD_CANCEL 3 +#define OPTEE_MSG_CMD_REGISTER_SHM 4 +#define OPTEE_MSG_CMD_UNREGISTER_SHM 5 +#define OPTEE_MSG_CMD_DO_BOTTOM_HALF 6 +#define OPTEE_MSG_CMD_STOP_ASYNC_NOTIF 7 +#define OPTEE_MSG_CMD_LEND_PROTMEM 8 +#define OPTEE_MSG_CMD_RECLAIM_PROTMEM 9 +#define OPTEE_MSG_CMD_GET_PROTMEM_CONFIG 10 +#define OPTEE_MSG_CMD_ASSIGN_PROTMEM 11 +#define OPTEE_MSG_FUNCID_CALL_WITH_ARG 0x0004 =20 #endif /* _OPTEE_MSG_H */ diff --git a/drivers/tee/optee/optee_smc.h b/drivers/tee/optee/optee_smc.h index 879426300821..accf76a99288 100644 --- a/drivers/tee/optee/optee_smc.h +++ b/drivers/tee/optee/optee_smc.h @@ -264,7 +264,6 @@ struct optee_smc_get_shm_config_result { #define OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM BIT(0) /* Secure world can communicate via previously unregistered shared memory = */ #define OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM BIT(1) - /* * Secure world supports commands "register/unregister shared memory", * secure world accepts command buffers located in any parts of non-secure= RAM @@ -280,6 +279,10 @@ struct optee_smc_get_shm_config_result { #define OPTEE_SMC_SEC_CAP_RPC_ARG BIT(6) /* Secure world supports probing for RPMB device if needed */ #define OPTEE_SMC_SEC_CAP_RPMB_PROBE BIT(7) +/* Secure world supports protected memory */ +#define OPTEE_SMC_SEC_CAP_PROTMEM BIT(8) +/* Secure world supports dynamic protected memory */ +#define OPTEE_SMC_SEC_CAP_DYNAMIC_PROTMEM BIT(9) =20 #define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES 9 #define OPTEE_SMC_EXCHANGE_CAPABILITIES \ @@ -451,6 +454,38 @@ struct optee_smc_disable_shm_cache_result { =20 /* See OPTEE_SMC_CALL_WITH_REGD_ARG above */ #define OPTEE_SMC_FUNCID_CALL_WITH_REGD_ARG 19 +/* + * Get protected memory config + * + * Returns the protected memory config. + * + * Call register usage: + * a0 SMC Function ID, OPTEE_SMC_GET_PROTMEM_CONFIG + * a2-6 Not used, must be zero + * a7 Hypervisor Client ID register + * + * Have config return register usage: + * a0 OPTEE_SMC_RETURN_OK + * a1 Physical address of start of protected memory + * a2 Size of protected memory + * a3 PA width, max 64 + * a4-7 Preserved + * + * Not available register usage: + * a0 OPTEE_SMC_RETURN_ENOTAVAIL + * a1-3 Not used + * a4-7 Preserved + */ +#define OPTEE_SMC_FUNCID_GET_PROTMEM_CONFIG 20 +#define OPTEE_SMC_GET_PROTMEM_CONFIG \ + OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_PROTMEM_CONFIG) + +struct optee_smc_get_protmem_config_result { + unsigned long status; + unsigned long start; + unsigned long size; + unsigned long pa_width; +}; =20 /* * Resume from RPC (for example after processing a foreign interrupt) --=20 2.43.0 From nobody Sun Dec 14 02:14:14 2025 Received: from mail-ed1-f43.google.com (mail-ed1-f43.google.com [209.85.208.43]) (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 8076823D7C6 for ; Wed, 13 Aug 2025 06:03:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755065037; cv=none; b=p0MKlOFFD3bMt6oWxE8HVnZLrrG0BV3xEVJCnDXHrPzTHGnvL10v8aIFPdn/ykyANNseoniAgL0uOktyM8wKVzOfZiqRALKNC61fZPmiHkzaEtZO9fhymTs0rQa5pmm4griMJ3rSshqHoXGnHizPtW+5V95EhfXCkusv/ayqBws= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755065037; c=relaxed/simple; bh=UeXlHfCjEZZ+zffjGmSWvLo/6vWoWI8Rd0/rywmOTyk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Xvdyn3GrQQIJnHLRLsmY5GYHzN8KPA7Qg1tJWTrrCRqswNqDXHTTb+XnXWQ/T7EGyCrc+x0zj3k6Pd/8XIBDy/6nw18DaazGQKPzQqy5+jkSt7FWbkDss7ZaffnW50DTjQNK+EOkIHtv0jcyeeuWgkzsRxBiQzdd0zVAmxykLHc= 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=bspXHo5I; arc=none smtp.client-ip=209.85.208.43 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="bspXHo5I" Received: by mail-ed1-f43.google.com with SMTP id 4fb4d7f45d1cf-615460d9897so7062806a12.0 for ; Tue, 12 Aug 2025 23:03:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1755065033; x=1755669833; 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=S9RDpqZGncYw4GV9WsRoAupSSI2K1DVKB1tocQmYgMc=; b=bspXHo5Izbg4C60wgzVQQzZWiBHDbhKv1N7B25bPYfuVwO0t2qQk/WvDVU+zkT43KG 7GP6wy587o3Rf9jCFFpvIX0ZROE3XJnrG4rrY0tgVAXk0q7WtEDBhLUEKU21HtyJ399F 4eHNRGVMQSJekRNqNGNDu2PbB6lkh4dG+e3i686HLuwQHtB0LD6r7zFFG3AavkQCZwco 8DnZUn5yFazLKJW9fE26qz/IjhVsO5gLzYUogLv6T9TMAtG+lSEH8R9/SuruUOdTq4LZ Zl2TpPiHF9HCLqiMElwxV5AqJ9le11dyvVSw2QIn7e7T0k0n1OP8vD2Fvxx32p3zf84v cD0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755065033; x=1755669833; 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=S9RDpqZGncYw4GV9WsRoAupSSI2K1DVKB1tocQmYgMc=; b=tjd9KEjXea8FYj7mtZ/PikRye0praXValpKQ42y1L2I+yTszcml4LG1p30yWIhb57r pXbyNOSGbwyP4jjnSZVgPDwKfnbVbeBCuajZjLaevrlFov3lFHIxzKJ9QyyTDBNJl+MF D6FpF1e2nsKzx/Fg7yoGb3up6rx/fFZxR6DkBCZqY+bF6WoC/Jp98lBPgud6PMX8pr2q sR71B76COd0AczXro8LQJXjc7SYml8xvTNELuJZq9QwEMi9UYx31E/DlrdLnbzvu2l24 VxbgDPecaSHEIy7iK1GktXf933D+wUVgpiZXQ+tiutRT4r1Cn/SlPsytZEnZyZV1LUDB VG/Q== X-Gm-Message-State: AOJu0Yzxm8I+gQ9izs86cYrBxpdGPss7sBUUf/g8AoIRXdhn0mP5Y9wJ 4OROduCHWsAd9XX/3wOPRbfYGWt2juqJEn/VO0cNrdDhUuFAt+NgYXHZfPKiyKc1X0ycYuuWXkp /6nNE86o= X-Gm-Gg: ASbGnct2CFDvZ8xzI8Ss5td0LWtKKbU21W9oiaexhe/ICY9r32g7t2BaBpEEJJFUJhG yoQh54DvkfhrY8vFTzPR7iqeUc1spbLVzE3FBH62SnudtwFEJcyM7JOKDK6O/FGE265z0b0tK39 ZDbTWWklLq567uqlDoTzw2SBWwPZ5Wwt/kAkzDQp61naKYDLc+NIReLnO7ZD8cxnEZu6gv1WaPK uWmqzoF3w10pUbg1yYiHQEwHiGXTdv5UqPNS5W6RRAb05bW+7LGQVrCxrSOUPIK013C2+koi2CB ZmOknPhAB3+/bMYPlAq/6h7tYgqYZvHMw4rtvh+PM2wv6HRzVqcpRc0ywH+FJkYzCirlJi9JU1s L+MvieUIFBm9fsJwh+urUJGP/9hxvwgua34YhVws0Metresq/oP6f2wNooWSA0foe8YD9nKCXt9 w= X-Google-Smtp-Source: AGHT+IHPDW4Qxib/c3fl/QvNCJB64Z5YGN/d1oTyw+2Hx0fudTx9zXp/j1zq+pONC9zrU1nldBcONA== X-Received: by 2002:a05:6402:22cc:b0:618:534:550a with SMTP id 4fb4d7f45d1cf-6186c000f03mr916573a12.24.1755065033114; Tue, 12 Aug 2025 23:03:53 -0700 (PDT) Received: from rayden.urgonet (h-37-123-177-177.A175.priv.bahnhof.se. [37.123.177.177]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-615a8f2b892sm21498679a12.25.2025.08.12.23.03.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Aug 2025 23:03:52 -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=20K=C3=B6nig?= , Sumit Garg , Matthias Brugger , AngeloGioacchino Del Regno , azarrabi@qti.qualcomm.com, Simona Vetter , Daniel Stone , Rouven Czerwinski , robin.murphy@arm.com, Jens Wiklander , Sumit Garg Subject: [PATCH v11 2/9] dma-buf: dma-heap: export declared functions Date: Wed, 13 Aug 2025 08:02:51 +0200 Message-ID: <20250813060339.2977604-3-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250813060339.2977604-1-jens.wiklander@linaro.org> References: <20250813060339.2977604-1-jens.wiklander@linaro.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Export the dma-buf heap functions to allow them to be used by the OP-TEE driver. The OP-TEE driver wants to register and manage specific secure DMA heaps with it. Signed-off-by: Jens Wiklander Reviewed-by: Sumit Garg Acked-by: Sumit Semwal Reviewed-by: T.J. Mercier --- 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); =20 /** * 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); =20 /** * dma_heap_add - adds a heap to dmabuf heaps @@ -303,6 +305,7 @@ struct dma_heap *dma_heap_add(const struct dma_heap_exp= ort_info *exp_info) kfree(heap); return err_ret; } +EXPORT_SYMBOL(dma_heap_add); =20 static char *dma_heap_devnode(const struct device *dev, umode_t *mode) { --=20 2.43.0 From nobody Sun Dec 14 02:14:14 2025 Received: from mail-ed1-f52.google.com (mail-ed1-f52.google.com [209.85.208.52]) (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 8C0282C1585 for ; Wed, 13 Aug 2025 06:03:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755065040; cv=none; b=J5P6r2EEQU4ZvxVNE4U37MFkmvAZ/uE3McfbL1NXFfcX0aObT4hS8BEMDcfHK0odb4Df/nYfhsSodUD466rAGXFaEbFkr6gRl45LZp572oq/FO93Ka/6Wst8OiJZ5Sn4VvCDYZsjIdcMu0Mfz5F/F/1WtdBewI5+azrN7LsrsaE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755065040; c=relaxed/simple; bh=DrYDuhgzi9151bgwqShOy3kkRBO8FxehypC+5p0g8o8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dVj/VJGXq94a51cu5GOqoZf8SV3GnKN4xPR2eN8MAYhIbV65gLWm+L9vTHU0I5Ji40aCrxb+isEuUaiRrxrhIAgbw4PmBvJ9nWAA+/MkcTTNWlme5cH7YfC7l+WGtFmh2oE5EGuc3/VZ437NPXkuqwAedVNeKgH4pBLYCtm/kRM= 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=QyiCROo1; arc=none smtp.client-ip=209.85.208.52 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="QyiCROo1" Received: by mail-ed1-f52.google.com with SMTP id 4fb4d7f45d1cf-615d1865b2dso9203261a12.0 for ; Tue, 12 Aug 2025 23:03:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1755065035; x=1755669835; 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=HslIfr6UrxDAQ4eYDN73R0okgxEMwKel2ECtA9Ty7MM=; b=QyiCROo1aglnGRDHeTIZEljZoHQgrUqcbp6ynY91s0Dp9jE+3T8Mbdt37QW9wJnx9d uDw0yFgHE5afN35kGQ0Pm/Ht+rPJ8Ys1+dLlivcErLnb3f0ZLCCuth3vV4NN3hHA7HpP YkhrF6GvBx1QM+K3gU7Rwr07+e9bshuxk9WAeiCvEWpSgoBeP+oOQAEjdu3N/oD2x8B9 bvoLkkWK2jFdGgMcfAd+6b9VHeGXy3ZHd89h7VFkMl6OyFDSeMcR2KkMEkiZ5wmyjFvR lNG3jRm04rW0llWFUIRYHRvmGIuQ0BMTibYP3Qz9BQUAmU/8DEtqjHaj5t70EbQq0Unk IHzA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755065035; x=1755669835; 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=HslIfr6UrxDAQ4eYDN73R0okgxEMwKel2ECtA9Ty7MM=; b=PBPEyQSX5I6p6qwdY1fVz0nmHTDtXvhGF26PWjrLYtbkbgA4ovqSLvpCOWnbYa0NpH gqD5XJMNYJwsTFfOKSUZ1zLCkN+bPZU0h4S3dMSuK2XXEGML3Mbor8ixw3+ncXmDydjr qpLitg95G+Eb3sTOmppQEWVsaF6ybngs74D2jhp7y4aSKKoMSGIDLa9s2yEptbsqEadb 5jllRY4AKZHNey67psq2JqlmCHIarzGgy2R8NzpiOdAGppJC2fX9jouTQD52xf2gVuje iaaeMCQN9iodhH+GzFopF9Dfbp9uI2yDjGd7G7BBYJdulEQVeS8Wq3v37KXFqQQoDYTe J5+g== X-Gm-Message-State: AOJu0Yx3yirqQrWWxw59j+Fvt1x53ySA2M4T+LjVSxRrvsZhYI/snBPH Wcof04sA1JUZoKIoenGKMAJtq8ucXbt801CYDIxSThQwG33EuKTQOTG6DM7lSIYTFZnRxJwLYBt 3SdOvYFQ= X-Gm-Gg: ASbGncv/vN4Mk+Abyje6Sq4uJMh+3W9ncoPH0/6saUgzjfnwGeynXvcGILoUxT9Put9 v1hBZ7vMNgwSJO7MSyYxKgEjjiZEkvoRxe9Z2UbdoZHuehJxA8e+rXfWReE4jqdGJsg4AQagHa2 /s4X3CprwM2vu/r8PMaxHNxFLexC2n+ZxKM09kZOGAMMZsM0yQxuh7YoEbpLjf94Kxz2Kuj5iof ToXgGLK5gdVy7WQZ57NNO9K/M0RR4d6nCrB8NoAcjcJBwxRbCZ9jzaOxRhiLt10HdYJFrLnoI08 jrQKBZhSPAFOskPqeeCT83aqbmyL/RXMA+yZHIhUMQ02LzH5d5ANGgn/RKFsZkzWT7ZA3Eqgfsd 6w5JUU80jXuQiWmIHZbwjx24X0nQf4VGdrcL2jgcUdN3KNuwtGrvfU/2t6xS4dmMvgOT23aQB17 w= X-Google-Smtp-Source: AGHT+IGZzXrc8tpt9jiXTe6tz9b3sNrqW8znB+h7LlrCLWp5xzmgjzmjXdupn1kUgAZTDMXmyZ/QpQ== X-Received: by 2002:a05:6402:44c9:b0:618:273b:4f51 with SMTP id 4fb4d7f45d1cf-6186bfd5757mr1049458a12.23.1755065035056; Tue, 12 Aug 2025 23:03:55 -0700 (PDT) Received: from rayden.urgonet (h-37-123-177-177.A175.priv.bahnhof.se. [37.123.177.177]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-615a8f2b892sm21498679a12.25.2025.08.12.23.03.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Aug 2025 23:03:54 -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=20K=C3=B6nig?= , Sumit Garg , Matthias Brugger , AngeloGioacchino Del Regno , azarrabi@qti.qualcomm.com, Simona Vetter , Daniel Stone , Rouven Czerwinski , robin.murphy@arm.com, Jens Wiklander , Sumit Garg Subject: [PATCH v11 3/9] tee: implement protected DMA-heap Date: Wed, 13 Aug 2025 08:02:52 +0200 Message-ID: <20250813060339.2977604-4-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250813060339.2977604-1-jens.wiklander@linaro.org> References: <20250813060339.2977604-1-jens.wiklander@linaro.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Implement DMA heap for protected DMA-buf allocation in the TEE subsystem. Protected 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 Reviewed-by: Sumit Garg --- drivers/tee/Kconfig | 5 + drivers/tee/Makefile | 1 + drivers/tee/tee_core.c | 2 + drivers/tee/tee_heap.c | 500 ++++++++++++++++++++++++++++++++++++++ drivers/tee/tee_private.h | 6 + include/linux/tee_core.h | 53 ++++ 6 files changed, 567 insertions(+) create mode 100644 drivers/tee/tee_heap.c diff --git a/drivers/tee/Kconfig b/drivers/tee/Kconfig index 61b507c18780..90600607a9d8 100644 --- a/drivers/tee/Kconfig +++ b/drivers/tee/Kconfig @@ -13,6 +13,11 @@ menuconfig TEE =20 if TEE =20 +config TEE_DMABUF_HEAPS + bool + depends on HAS_DMA && DMABUF_HEAPS + default y + source "drivers/tee/optee/Kconfig" source "drivers/tee/amdtee/Kconfig" source "drivers/tee/tstee/Kconfig" 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) +=3D tee.o tee-objs +=3D tee_core.o +tee-objs +=3D tee_heap.o tee-objs +=3D tee_shm.o tee-objs +=3D tee_shm_pool.o obj-$(CONFIG_OPTEE) +=3D optee/ diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index acc7998758ad..52f5806ed314 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -1064,6 +1064,8 @@ void tee_device_unregister(struct tee_device *teedev) if (!teedev) return; =20 + tee_device_put_all_dma_heaps(teedev); + if (teedev->flags & TEE_DEVICE_FLAG_REGISTERED) cdev_device_del(&teedev->cdev, &teedev->dev); =20 diff --git a/drivers/tee/tee_heap.c b/drivers/tee/tee_heap.c new file mode 100644 index 000000000000..d8d7735cdffb --- /dev/null +++ b/drivers/tee/tee_heap.c @@ -0,0 +1,500 @@ +// 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 kref kref; + struct tee_protmem_pool *pool; + struct tee_device *teedev; + bool shutting_down; + /* Protects pool, teedev, and shutting_down above */ + struct mutex mu; +}; + +struct tee_heap_buffer { + struct tee_dma_heap *heap; + 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; +}; + +#if IS_ENABLED(CONFIG_TEE_DMABUF_HEAPS) +static DEFINE_XARRAY_ALLOC(tee_dma_heap); + +static void tee_heap_release(struct kref *kref) +{ + struct tee_dma_heap *h =3D container_of(kref, struct tee_dma_heap, kref); + + h->pool->ops->destroy_pool(h->pool); + tee_device_put(h->teedev); + h->pool =3D NULL; + h->teedev =3D NULL; +} + +static void put_tee_heap(struct tee_dma_heap *h) +{ + kref_put(&h->kref, tee_heap_release); +} + +static void get_tee_heap(struct tee_dma_heap *h) +{ + kref_get(&h->kref); +} + +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 =3D sg_alloc_table(dst, src->orig_nents, GFP_KERNEL); + if (ret) + return ret; + + dst_sg =3D 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 =3D 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 =3D dmabuf->priv; + struct tee_heap_attachment *a; + int ret; + + a =3D kzalloc(sizeof(*a), GFP_KERNEL); + if (!a) + return -ENOMEM; + + ret =3D copy_sg_table(&a->table, &buf->table); + if (ret) { + kfree(a); + return ret; + } + + a->dev =3D attachment->dev; + attachment->priv =3D a; + + return 0; +} + +static void tee_heap_detach(struct dma_buf *dmabuf, + struct dma_buf_attachment *attachment) +{ + struct tee_heap_attachment *a =3D 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 =3D attachment->priv; + int ret; + + ret =3D 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 =3D attachment->priv; + + WARN_ON(&a->table !=3D 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 =3D dmabuf->priv; + + buf->heap->pool->ops->free(buf->heap->pool, &buf->table); + mutex_lock(&buf->heap->mu); + put_tee_heap(buf->heap); + mutex_unlock(&buf->heap->mu); + kfree(buf); +} + +static const struct dma_buf_ops tee_heap_buf_ops =3D { + .attach =3D tee_heap_attach, + .detach =3D tee_heap_detach, + .map_dma_buf =3D tee_heap_map_dma_buf, + .unmap_dma_buf =3D tee_heap_unmap_dma_buf, + .release =3D 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 =3D dma_heap_get_drvdata(heap); + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); + struct tee_device *teedev =3D NULL; + struct tee_heap_buffer *buf; + struct tee_protmem_pool *pool; + struct dma_buf *dmabuf; + int rc; + + mutex_lock(&h->mu); + if (h->teedev) { + teedev =3D h->teedev; + pool =3D h->pool; + get_tee_heap(h); + } + mutex_unlock(&h->mu); + + if (!teedev) + return ERR_PTR(-EINVAL); + + buf =3D kzalloc(sizeof(*buf), GFP_KERNEL); + if (!buf) { + dmabuf =3D ERR_PTR(-ENOMEM); + goto err; + } + buf->size =3D len; + buf->heap =3D h; + + rc =3D pool->ops->alloc(pool, &buf->table, len, &buf->offs); + if (rc) { + dmabuf =3D ERR_PTR(rc); + goto err_kfree; + } + + exp_info.ops =3D &tee_heap_buf_ops; + exp_info.size =3D len; + exp_info.priv =3D buf; + exp_info.flags =3D fd_flags; + dmabuf =3D 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: + mutex_lock(&h->mu); + put_tee_heap(h); + mutex_unlock(&h->mu); + return dmabuf; +} + +static const struct dma_heap_ops tee_dma_heap_ops =3D { + .allocate =3D 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 =3D { + .ops =3D &tee_dma_heap_ops, + .name =3D 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 =3D kzalloc(sizeof(*h), GFP_KERNEL); + if (!h) + return -ENOMEM; + h->id =3D id; + kref_init(&h->kref); + h->teedev =3D teedev; + h->pool =3D pool; + mutex_init(&h->mu); + + exp_info.priv =3D h; + h->heap =3D dma_heap_add(&exp_info); + if (IS_ERR(h->heap)) { + rc =3D PTR_ERR(h->heap); + kfree(h); + + return rc; + } + + /* "can't fail" due to the call to xa_reserve() above */ + return WARN_ON(xa_is_err(xa_store(&tee_dma_heap, id, h, GFP_KERNEL))); +} + +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; + + if (!tee_device_get(teedev)) + return -EINVAL; + + h =3D xa_load(&tee_dma_heap, id); + if (h) { + mutex_lock(&h->mu); + if (h->teedev) { + rc =3D -EBUSY; + } else { + kref_init(&h->kref); + h->shutting_down =3D false; + h->teedev =3D teedev; + h->pool =3D pool; + rc =3D 0; + } + mutex_unlock(&h->mu); + } else { + rc =3D alloc_dma_heap(teedev, id, pool); + } + + if (rc) { + tee_device_put(teedev); + 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_put_all_dma_heaps(struct tee_device *teedev) +{ + struct tee_dma_heap *h; + u_long i; + + xa_for_each(&tee_dma_heap, i, h) { + if (h) { + mutex_lock(&h->mu); + if (h->teedev =3D=3D teedev && !h->shutting_down) { + h->shutting_down =3D true; + put_tee_heap(h); + } + mutex_unlock(&h->mu); + } + } +} +EXPORT_SYMBOL_GPL(tee_device_put_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 !=3D &tee_heap_buf_ops) + return -EINVAL; + + buf =3D dmabuf->priv; + /* The buffer must be from the same teedev */ + if (buf->heap->teedev !=3D teedev) + return -EINVAL; + + shm->size =3D buf->size; + + rc =3D buf->heap->pool->ops->update_shm(buf->heap->pool, &buf->table, + buf->offs, shm, parent_shm); + if (!rc && *parent_shm) + *offset =3D 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_put_all_dma_heaps(struct tee_device *teedev __always_unused) +{ +} +EXPORT_SYMBOL_GPL(tee_device_put_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 =3D to_protmem_static_pool(pool); + phys_addr_t pa; + int ret; + + pa =3D gen_pool_alloc(stp->gen_pool, size); + if (!pa) + return -ENOMEM; + + ret =3D 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 =3D 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 =3D 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 =3D to_protmem_static_pool(pool); + + shm->paddr =3D stp->pa_base + offs; + *parent_shm =3D NULL; + + return 0; +} + +static void protmem_pool_op_static_destroy_pool(struct tee_protmem_pool *p= ool) +{ + struct tee_protmem_static_pool *stp =3D to_protmem_static_pool(pool); + + gen_pool_destroy(stp->gen_pool); + kfree(stp); +} + +static struct tee_protmem_pool_ops protmem_pool_ops_static =3D { + .alloc =3D protmem_pool_op_static_alloc, + .free =3D protmem_pool_op_static_free, + .update_shm =3D protmem_pool_op_static_update_shm, + .destroy_pool =3D 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 =3D 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); + + if (!pfn_valid(PHYS_PFN(paddr))) + return ERR_PTR(-EINVAL); + + stp =3D kzalloc(sizeof(*stp), GFP_KERNEL); + if (!stp) + return ERR_PTR(-ENOMEM); + + stp->gen_pool =3D gen_pool_create(PAGE_SHIFT, -1); + if (!stp->gen_pool) { + rc =3D -ENOMEM; + goto err_free; + } + + rc =3D gen_pool_add(stp->gen_pool, paddr, size, -1); + if (rc) + goto err_free_pool; + + stp->pool.ops =3D &protmem_pool_ops_static; + stp->pa_base =3D paddr; + return &stp->pool; + +err_free_pool: + gen_pool_destroy(stp->gen_pool); +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); =20 +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..28b65010b9ed 100644 --- a/include/linux/tee_core.h +++ b/include/linux/tee_core.h @@ -8,9 +8,11 @@ =20 #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 =20 +enum tee_dma_heap_id { + TEE_DMA_HEAP_SECURE_VIDEO_PLAY =3D 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; }; =20 +/** + * 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); =20 +int tee_device_register_dma_heap(struct tee_device *teedev, + enum tee_dma_heap_id id, + struct tee_protmem_pool *pool); +void tee_device_put_all_dma_heaps(struct tee_device *teedev); + /** * tee_device_set_dev_groups() - Set device attribute groups * @teedev: Device to register @@ -229,6 +272,16 @@ static inline void tee_shm_pool_free(struct tee_shm_po= ol *pool) pool->ops->destroy_pool(pool); } =20 +/** + * 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_protmem_pool' or an ERR_PTR on failur= e. + */ +struct tee_protmem_pool *tee_protmem_static_pool_alloc(phys_addr_t paddr, + size_t size); + /** * tee_get_drvdata() - Return driver_data pointer * @returns the driver_data pointer supplied to tee_register(). --=20 2.43.0 From nobody Sun Dec 14 02:14:14 2025 Received: from mail-ed1-f51.google.com (mail-ed1-f51.google.com [209.85.208.51]) (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 8A52D2C031E for ; Wed, 13 Aug 2025 06:03:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755065041; cv=none; b=hL+W3IEnOnhws+giQt2kkW6K7c+naUaDwCglKl/W4xcFDi0P2uV4wmUBaZocZrWy5L0ebc6KC96P+Iq/fE/xjiOWzUkThS3K10kFt0rxNd1WqUNeIn6a+7re0ZLSlIRCPWAe3lrkdnt9+mwmYRAwKEyEOSJe9LT/e73hhWQa82c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755065041; c=relaxed/simple; bh=BUl5/6+a2Cb4I+qj31mG7se4S51jFiOFoJudTBIklSY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=sJJETfJw+cq4tCyZXfdLyIIT91QWCE9aD1OECU+BcJOz/k2WqusdZ3n3PD436m14J8mF9lcsavxlr0yjDR5domuA+B/8pmDLs0C/l8v5t6MKYuNcvZClgv2Rd38xMEzOe6R2kUt1biUQPtwGNlroq6C9sqwPH4JvNwPf2PM44+Q= 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=VI25Ov28; arc=none smtp.client-ip=209.85.208.51 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="VI25Ov28" Received: by mail-ed1-f51.google.com with SMTP id 4fb4d7f45d1cf-60c9d8a169bso11390366a12.1 for ; Tue, 12 Aug 2025 23:03:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1755065037; x=1755669837; 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=TSuLcRnSGeJ3xtP5yz3Dg/9JsLri62mj/cqN0HfNB3I=; b=VI25Ov280tNBapW3erRmkXV/k23CwV9u5l1rc8wecUlCPtuMaSQMajhDuzeGQvrJWd CpaT6H0rSChaxDaggK/xpNTBDKVygsIOFL79Ne5RjPakMkKV8H/avjyp+SUYL/gp/bQO GXLeYgZrAfTrMdBchyOWxgrBaPATzND6DwEnJtxzbpZ7nAAlq3UiP0iJgFC+weFU7Tvj 0XaqMBqPp7awBrqB/vuJHdp8qbe47FBHIrDg2420aaOn61T79n/Fwr2RVIiavIngDfQL yxaFRxYI3dp1zeyZH1KfRf9dbzWZGnvu1G9BRr708hu4CVdf59cS8HEwum1gEHGsDZK3 98Ww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755065037; x=1755669837; 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=TSuLcRnSGeJ3xtP5yz3Dg/9JsLri62mj/cqN0HfNB3I=; b=jjnitzQJEgPKgH3JBaMpWLUa1AN6FQYgbfCav3g/pPeczF3Wj+B1Jsb3s+kkp7UZZv Pxp1JIEAx54FJ3MbSoU1ny7xjopPT/0vvJbGRqYf7lPNpbKmHnf+BM2dUklE+1LrYx/t k/P7EDlu2lvGSgvJqwZa+EW2VJZP/WUA7dkm//WyGdVWW3KCbXif0LeTXhpiSRWgHN93 05gImPnG+0mckGcAo/2yTU1QrnhZ6A4gaDo5p+P8+l/3hGCw/ZJehJ4+6gBk+07IQ1SV qAVMuuN9RGhH0ScTl14IJSvh/rzDXEbj1w8yo6yt2C7tWoo+8W5c3AFin8wEnHfaB9F2 n8tw== X-Gm-Message-State: AOJu0YziYIzoIrogeSGghtgeh7pWVyLMfWR9wF5kpj08OdineQiVQcgw Xtwla/aXMBSjKtjQ3ZS106iXK8vfqNM1Nou5KUWNu69xKMbYD1KGoMI+2PbBRxWOIUHKW2fWl49 gz99g3j8= X-Gm-Gg: ASbGncua5kS0r+K2DC/kinMgMbc0qOThaF4IeUShJs7hVgv6Y21BjYrgwNnCuI7YExB /TDNDU6NvVGw7Xftt3UHP/S9/ImD1N3Y4zLQepcD7oZnRhEj/Tvy5mqHinxfLwOvsvILF7Dnaww 3GRH6Q1W3AzYokhBqqv7Sn+HyjwI15Wwz8NkNGB76DTpS15RbLm1XCIAbEyfQraXRu18auOiq6K Ej/c7jD0OEIT7/b05Y2qcswwH39D7ZGj/MTztVJy1aJNLWQZRkT4edl7HxA9L9uCprJeT5ub9RY apUY2XCSc+ZYX3hkZvAxq+HJrYCE6hg6LFHfMKX4b0AkAjdNxkKPmyCiE++E1QoPInKHbExL0Yp dG83x6fe3+x5pcAHqKvD1q1XhtKtUna1p0DoBeoHGUtRN8gKtth1DkPbCnsPb8KNnMoqNAeGfUk k= X-Google-Smtp-Source: AGHT+IGqtQuV3o9beFdm8AV0OFCgrlJsYi4d+51H/4Z6scb5xUCOU4GITJt7DlZEnnM5yYTlW/+1Mg== X-Received: by 2002:a05:6402:3509:b0:615:a60a:38a7 with SMTP id 4fb4d7f45d1cf-6186b758722mr1521502a12.7.1755065037200; Tue, 12 Aug 2025 23:03:57 -0700 (PDT) Received: from rayden.urgonet (h-37-123-177-177.A175.priv.bahnhof.se. [37.123.177.177]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-615a8f2b892sm21498679a12.25.2025.08.12.23.03.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Aug 2025 23:03: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=20K=C3=B6nig?= , Sumit Garg , Matthias Brugger , AngeloGioacchino Del Regno , azarrabi@qti.qualcomm.com, Simona Vetter , Daniel Stone , Rouven Czerwinski , robin.murphy@arm.com, Jens Wiklander , Sumit Garg Subject: [PATCH v11 4/9] tee: refactor params_from_user() Date: Wed, 13 Aug 2025 08:02:53 +0200 Message-ID: <20250813060339.2977604-5-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250813060339.2977604-1-jens.wiklander@linaro.org> References: <20250813060339.2977604-1-jens.wiklander@linaro.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Break out the memref handling into a separate helper function. No change in behavior. Signed-off-by: Jens Wiklander Reviewed-by: Sumit Garg --- drivers/tee/tee_core.c | 94 ++++++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 40 deletions(-) diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index 52f5806ed314..b89f93b1f8f2 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -354,6 +354,55 @@ tee_ioctl_shm_register(struct tee_context *ctx, return ret; } =20 +static int param_from_user_memref(struct tee_context *ctx, + struct tee_param_memref *memref, + struct tee_ioctl_param *ip) +{ + struct tee_shm *shm; + + /* + * If a NULL pointer is passed to a TA in the TEE, + * the ip.c IOCTL parameters is set to TEE_MEMREF_NULL + * indicating a NULL memory reference. + */ + if (ip->c !=3D TEE_MEMREF_NULL) { + /* + * If we fail to get a pointer to a shared + * memory object (and increase the ref count) + * from an identifier we return an error. All + * pointers that has been added in params have + * an increased ref count. It's the callers + * responibility to do tee_shm_put() on all + * resolved pointers. + */ + shm =3D tee_shm_get_from_id(ctx, ip->c); + if (IS_ERR(shm)) + return PTR_ERR(shm); + + /* + * Ensure offset + size does not overflow + * offset and does not overflow the size of + * the referred shared memory object. + */ + if ((ip->a + ip->b) < ip->a || + (ip->a + ip->b) > shm->size) { + tee_shm_put(shm); + return -EINVAL; + } + } else if (ctx->cap_memref_null) { + /* Pass NULL pointer to OP-TEE */ + shm =3D NULL; + } else { + return -EINVAL; + } + + memref->shm_offs =3D ip->a; + memref->size =3D ip->b; + memref->shm =3D shm; + + return 0; +} + static int params_from_user(struct tee_context *ctx, struct tee_param *par= ams, size_t num_params, struct tee_ioctl_param __user *uparams) @@ -361,8 +410,8 @@ static int params_from_user(struct tee_context *ctx, st= ruct tee_param *params, size_t n; =20 for (n =3D 0; n < num_params; n++) { - struct tee_shm *shm; struct tee_ioctl_param ip; + int rc; =20 if (copy_from_user(&ip, uparams + n, sizeof(ip))) return -EFAULT; @@ -385,45 +434,10 @@ static int params_from_user(struct tee_context *ctx, = struct tee_param *params, 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 a NULL pointer is passed to a TA in the TEE, - * the ip.c IOCTL parameters is set to TEE_MEMREF_NULL - * indicating a NULL memory reference. - */ - if (ip.c !=3D TEE_MEMREF_NULL) { - /* - * If we fail to get a pointer to a shared - * memory object (and increase the ref count) - * from an identifier we return an error. All - * pointers that has been added in params have - * an increased ref count. It's the callers - * responibility to do tee_shm_put() on all - * resolved pointers. - */ - shm =3D tee_shm_get_from_id(ctx, ip.c); - if (IS_ERR(shm)) - return PTR_ERR(shm); - - /* - * Ensure offset + size does not overflow - * offset and does not overflow the size of - * the referred shared memory object. - */ - if ((ip.a + ip.b) < ip.a || - (ip.a + ip.b) > shm->size) { - tee_shm_put(shm); - return -EINVAL; - } - } else if (ctx->cap_memref_null) { - /* Pass NULL pointer to OP-TEE */ - shm =3D NULL; - } else { - return -EINVAL; - } - - params[n].u.memref.shm_offs =3D ip.a; - params[n].u.memref.size =3D ip.b; - params[n].u.memref.shm =3D shm; + rc =3D param_from_user_memref(ctx, ¶ms[n].u.memref, + &ip); + if (rc) + return rc; break; default: /* Unknown attribute */ --=20 2.43.0 From nobody Sun Dec 14 02:14:14 2025 Received: from mail-ed1-f42.google.com (mail-ed1-f42.google.com [209.85.208.42]) (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 03D642C3264 for ; Wed, 13 Aug 2025 06:04:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755065044; cv=none; b=o4dRxd7z159A5iG+5IDM0G5qrl1hJdDKUVaYqpq1+8XDg/s5NXi+ghozT1NJnBiU84IlFsCet0y3QAdj1cMlj/Ub7uXIrF/TgqG7sVvJAin7rySB8xDNamUer85ScqL53e8aHB62k24WX2kvFU7KY17qIlCs5+t/zkla+fPTMAY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755065044; c=relaxed/simple; bh=DkO+Bblb9qJE8t/aYwVWANUPOgu4d+yvt/Ia2MS2XKE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TMfvq8hVdJuYG/iwy6JM0N1dKS95g/UFlWvgwKWw3pjHOQrEYLk4XEHQ/5KIpqlXHQrsQGqtB8nt87ItVGowTKhP8mylqd6G7nTrPMnx7EyyC7jKoJjb1qk1hdgES0XJL5NzV8/qkj6bA+PKS0JHjd/qXd6eh4J3ZDyF+6qUzlM= 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=y5Iks8Vp; arc=none smtp.client-ip=209.85.208.42 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="y5Iks8Vp" Received: by mail-ed1-f42.google.com with SMTP id 4fb4d7f45d1cf-605b9488c28so10767805a12.2 for ; Tue, 12 Aug 2025 23:04:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1755065039; x=1755669839; 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=4djoMlBKpvP5y+awagdmFpNKd0vy1SIylF/MMIK4ZMo=; b=y5Iks8Vp1rxBRV0ZoBtiQTvEGwnWFW9d4Ksij0HDhmWeouzYVwhO+33+FMBY116QXr vzYn07p37oMTzhAIRhkZxu4ZvYUca9aipPxgqazxjcBib3Zsbk9K+knbo/ITEBbC7wXE fZ3LX5YTyiy3amuvAYptL8WNgf7hdBEEjdQyWxcu0qXlyaU/KAp55SquXFFSJruU8Vxc kLIcwBzRy9U+nJyLNjYdt4yTUeglI00/9JK6YXrwUdRBrm1CS8SJCQIkHa1joGPimIC2 2IagEX6WrzO9a3ZaqnBX/LFVsFihFQ5RoqVy9ZSb3v4HhKrV0IwggGkjOSvjBhdNlnHj J6JQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755065039; x=1755669839; 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=4djoMlBKpvP5y+awagdmFpNKd0vy1SIylF/MMIK4ZMo=; b=E4D743sNb1epffGpgtbeHTgm205bARUUu/hlB838xPYdr0ydXSIIFXlqml204iZjc2 suTYj1FW5TPdV8kMXFrtD1U3hgb8DQJO/czTC5KMr2fLSbC/b2gvX/diUwHBsFXtL4Uq o4SYkHUnbuUzH461qFBHe1K6QgLdii0N8iKqmSAnv/tAm6dtbV8LfsG/8E14l6qb98Ju /X9Viu/pSwxQKrK+xCu+itB2MgtYGmUHT+mDoADZ55pPazTQfA6irMlXjfLlN9DUGn9/ cb1hE3w067OGgaTJbRSFxiJKmP78hB0ELLSGe3HVkJidbCNHn0HMSUxibquSfKi8qpV5 3giQ== X-Gm-Message-State: AOJu0YzjhopqXKvEkDEAakuAlfloQ896srXMnenl2xGXiDxo77lD0ik1 rasvDqWyhuFtzmTh3g7fhMIxV3YXdI5UkXf90bCO2P3Q40Ch6qQPfqfpr3HXedStNiQuQ3tQQTU WTf/rR9c= X-Gm-Gg: ASbGncvLcjYlCBxXKJ3vWGYMKAgqnRXL3hy0t8MEotxjfygasTM8fe5JPwavR5+lLJX YjJjhEHJaEkmnEou8QRSg0/8DItaVg5Y0zw6DyzTae4n7BKN5pXsbTVjM95o/Tn+FbMoSd79/Xr LGYBXDxvQBPEoWzH8jyIGJFfyIJljVHf5yIFIV2dpu52txGmg8LYa8a1d82zGRCVwNiwQMbumbD X+kG8tzXmhKaujpirKy0AC6oHtRE0u+9148Uny5UUtmKEbhblpU1iMybScmsj9MF2fUFPSjooUW COMRwBlBsqFJTu8NSfN2CNXxEYm3ULv6XeK5KrGP4eCjO+ebUpVMlwZv4zaES42eo2BBjMPtlGQ yoL/ChwJCJa0ZHZY2XC5+n8+sTHaKWxi+ZRFWig7EP1ijX+OblM0/W2YgnJErm8R+5fZa+URErh M= X-Google-Smtp-Source: AGHT+IGr1N+6OZeiUGN2vRdvw56ounKBMi6RzHQ8Frg9hueStqKxU0w7ZfoAyf+vVOL9Y+a5V0ngGw== X-Received: by 2002:a50:a401:0:b0:618:3bc5:88a9 with SMTP id 4fb4d7f45d1cf-6186b78c05emr951599a12.5.1755065039207; Tue, 12 Aug 2025 23:03:59 -0700 (PDT) Received: from rayden.urgonet (h-37-123-177-177.A175.priv.bahnhof.se. [37.123.177.177]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-615a8f2b892sm21498679a12.25.2025.08.12.23.03.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Aug 2025 23:03:58 -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=20K=C3=B6nig?= , Sumit Garg , Matthias Brugger , AngeloGioacchino Del Regno , azarrabi@qti.qualcomm.com, Simona Vetter , Daniel Stone , Rouven Czerwinski , robin.murphy@arm.com, Etienne Carriere , Jens Wiklander Subject: [PATCH v11 5/9] tee: new ioctl to a register tee_shm from a dmabuf file descriptor Date: Wed, 13 Aug 2025 08:02:54 +0200 Message-ID: <20250813060339.2977604-6-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250813060339.2977604-1-jens.wiklander@linaro.org> References: <20250813060339.2977604-1-jens.wiklander@linaro.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 Reviewed-by: Sumit Garg --- drivers/tee/tee_core.c | 63 ++++++++++++++++++++++++++++++++- drivers/tee/tee_private.h | 8 +++++ drivers/tee/tee_shm.c | 74 +++++++++++++++++++++++++++++++++++++-- include/linux/tee_core.h | 1 + include/linux/tee_drv.h | 10 ++++++ include/uapi/linux/tee.h | 31 ++++++++++++++++ 6 files changed, 183 insertions(+), 4 deletions(-) diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index b89f93b1f8f2..fe414595fc2c 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -354,11 +354,49 @@ tee_ioctl_shm_register(struct tee_context *ctx, return ret; } =20 +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 =3D tee_shm_register_fd(ctx, data.fd); + if (IS_ERR(shm)) + return -EINVAL; + + data.id =3D shm->id; + data.flags =3D shm->flags; + data.size =3D shm->size; + + if (copy_to_user(udata, &data, sizeof(data))) + ret =3D -EFAULT; + else + ret =3D 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 =3D 0; =20 /* * If a NULL pointer is passed to a TA in the TEE, @@ -389,6 +427,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 =3D 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 =3D ref->parent_shm; + offs =3D ref->offset; + } + } } else if (ctx->cap_memref_null) { /* Pass NULL pointer to OP-TEE */ shm =3D NULL; @@ -396,7 +454,7 @@ static int param_from_user_memref(struct tee_context *c= tx, return -EINVAL; } =20 - memref->shm_offs =3D ip->a; + memref->shm_offs =3D ip->a + offs; memref->size =3D ip->b; memref->shm =3D shm; =20 @@ -842,6 +900,8 @@ static long tee_ioctl(struct file *filp, unsigned int c= md, 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: @@ -1303,3 +1363,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..a9b5e4a6a8f7 100644 --- a/drivers/tee/tee_private.h +++ b/drivers/tee/tee_private.h @@ -13,6 +13,14 @@ #include #include =20 +/* 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 tee_shm *parent_shm; +}; + int tee_shm_get_fd(struct tee_shm *shm); =20 bool tee_device_get(struct tee_device *teedev); diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c index daf6e5cfd59a..76195a398c89 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,15 @@ static void release_registered_pages(struct tee_shm *shm) =20 static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm) { - if (shm->flags & TEE_SHM_POOL) { + void *p =3D shm; + + if (shm->flags & TEE_SHM_DMA_BUF) { + struct tee_shm_dmabuf_ref *ref; + + ref =3D container_of(shm, struct tee_shm_dmabuf_ref, shm); + p =3D ref; + 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 =3D teedev->desc->ops->shm_unregister(shm->ctx, shm); @@ -59,7 +68,7 @@ static void tee_shm_release(struct tee_device *teedev, st= ruct tee_shm *shm) =20 teedev_ctx_put(shm->ctx); =20 - kfree(shm); + kfree(p); =20 tee_device_put(teedev); } @@ -169,7 +178,7 @@ struct tee_shm *tee_shm_alloc_user_buf(struct tee_conte= xt *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 failu= re */ struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t s= ize) { @@ -179,6 +188,62 @@ struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_co= ntext *ctx, size_t size) } EXPORT_SYMBOL_GPL(tee_shm_alloc_kernel_buf); =20 +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 =3D kzalloc(sizeof(*ref), GFP_KERNEL); + if (!ref) { + rc =3D -ENOMEM; + goto err_put_tee; + } + + refcount_set(&ref->shm.refcount, 1); + ref->shm.ctx =3D ctx; + ref->shm.id =3D -1; + ref->shm.flags =3D TEE_SHM_DMA_BUF; + + ref->dmabuf =3D dma_buf_get(fd); + if (IS_ERR(ref->dmabuf)) { + rc =3D PTR_ERR(ref->dmabuf); + goto err_kfree_ref; + } + + rc =3D tee_heap_update_from_dma_buf(ctx->teedev, ref->dmabuf, + &ref->offset, &ref->shm, + &ref->parent_shm); + if (rc) + goto err_put_dmabuf; + + mutex_lock(&ref->shm.ctx->teedev->mutex); + ref->shm.id =3D 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 =3D ref->shm.id; + goto err_put_dmabuf; + } + + return &ref->shm; + +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 @@ -442,6 +507,9 @@ static int tee_shm_fop_mmap(struct file *filp, struct v= m_area_struct *vma) /* Refuse sharing shared memory provided by application */ if (shm->flags & TEE_SHM_USER_MAPPED) return -EINVAL; + /* Refuse sharing registered DMA_bufs with the application */ + if (shm->flags & TEE_SHM_DMA_BUF) + return -EINVAL; =20 /* check for overflowing the buffer's size */ if (vma->vm_pgoff + vma_pages(vma) > shm->size >> PAGE_SHIFT) diff --git a/include/linux/tee_core.h b/include/linux/tee_core.h index 28b65010b9ed..b6c54b34a8b5 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 */ =20 #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_co= ntext *ctx, size_t size); struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx, void *addr, size_t length); =20 +/** + * 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 failu= re + */ +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..d843cf980d98 100644 --- a/include/uapi/linux/tee.h +++ b/include/uapi/linux/tee.h @@ -378,6 +378,37 @@ struct tee_ioctl_shm_register_data { __s32 id; }; =20 +/** + * struct tee_ioctl_shm_register_fd_data - Shared memory registering argum= ent + * @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 descript= or + * + * 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) + /** * TEE_IOC_SHM_REGISTER - Register shared memory argument * --=20 2.43.0 From nobody Sun Dec 14 02:14:14 2025 Received: from mail-ej1-f54.google.com (mail-ej1-f54.google.com [209.85.218.54]) (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 89D892C327D for ; Wed, 13 Aug 2025 06:04:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755065045; cv=none; b=GaCgcrNbaxT39NvT3KIrC5Xu92XxABYXObk1DkbgeLOVk4KABA9X49f6A0gjkPi1dHSgUox2SoEMR51ZuAtUaOZlzZ8iYFLmFYGx9vmU28P9N5v4WQGZ+QQTtgey32cP7R8fDmt9ImKlrxCjZUdRXVoqyAv+rqBtSwotSKWjEIA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755065045; c=relaxed/simple; bh=wVa/iG6CTwWJo3E4y1mtLKfadh/kv9eGIUdO1h5Hk9Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=L3dx5bap9UmlbE/5RTYHCJYsHLNr/TJRPk7mWnNcwVUqJJZ0w1vlgcBLCCpsH8mHmi3l6j3yZ9+4ZGIpTggbBnqTQ9i07EmuZtsJPcLHdqSwBx7LFczSKssCer4qgoWRAsV69g622ev1ock2fwrH3Jb88wZBwCGNlQrXccuY6qc= 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=TAtWL6Tt; arc=none smtp.client-ip=209.85.218.54 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="TAtWL6Tt" Received: by mail-ej1-f54.google.com with SMTP id a640c23a62f3a-af939afe5efso723859066b.2 for ; Tue, 12 Aug 2025 23:04:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1755065041; x=1755669841; 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=Twd7GfdaaubIhr0igmVjXFbwxXSCknyV61sXbYgmYh4=; b=TAtWL6TttgWP9AEEzvGQcCeT9gQR8jve9mLECcqUzRMDWgsMhZdABiXcuMFO8FQRba OWp3BPvH1Zv5ibbpLMmC4s35P/jAY82kdE3d8vd0muxBcGXshDdQ+nEyp29vZS5eJVh+ mmHUCgOsosALOP11LJCYuvhk8K0ZtzC34UpjfhyqpZOfdTB7ONA/vP6G7EOE6JCu6qD5 F9iCe/JhqacBy9eyYFgB6AtBad2YvtSAespELgLCpXIQ+57wdY4GU5HqWqBe1XllC4bc 2+POnfStYgeYgDuW+1MAXR79wSxufV3J8c55+Zl6CltFJkY9h5ewBRS2HUXEWBdXkvbS MinQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755065041; x=1755669841; 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=Twd7GfdaaubIhr0igmVjXFbwxXSCknyV61sXbYgmYh4=; b=efYe+AGFFYsxqP8zDtfzRNjJN0TV7DUowouvFCSke7j0Q+y1C8lpg3JwQXq43gUSXH lIoHSjnIcb3GsSbMcOhZUSuE1Xg74MpGxKQTn55GV7WZtnQWpjTzUoGztf6xrgbGWMyv 9TZaoFeFDuHgscGxBOMAVFW9AV2/UvDfjnllRCUqcOnYzT91Yxkieo87ksTKGmYOj6dB SDvM4WDYC0Uv8bnM2Eu/oPhka3dZ2Dw32hfGpagBzQhzvUCiRAvATBYbsgHtkwsD5R8V ozyKhnmDUcEwJ8AtaqYmoWV+5Jt2O4UsfbpaLNQVOnPsKDzKIWes8I2fH1030DvVGwmx Jzsg== X-Gm-Message-State: AOJu0Yy8f46AC+WRHsQmyVYMgG7Rs6v/huAM2ATIqSfQVeDc1gd+afsU kH4ApresR+8m9fTB6EppnyY6hP8mb+NQBSrdzsz9x3bIV59TdWRMfq3Fb4WQKKatDh2ePwLwS6f 81IUQDq8= X-Gm-Gg: ASbGncuGbu78Ve6T31DO2n9ApIFjxisiD7LinSUdhgnzuUKp/qGkA4dWmF3I4J+TYNJ UmF7JVeDTh30GsJ5WyFs5ctjWBhDaTyjcitFGY3tnyc56lUpWCM82rNJrSm/s2CL9fQRiix7z8n IRKjTqnifUkU7wsJBANu2g1CgT3o3Pdc2RYXJuZjdn3295jZSYFooVdsmpgzAb+W8rRzCG1uUfP wphkfmRk0mBH0HNPSTi1Ec/0bv4opDaKXGOa1a2/IutbDIXGYPsI8sWeXW0gpiVJ2dpBRZBeKLs X+Hh48Zr5zuNqX/EpMsJ2rR/gCZFVzmDKQdDir0Chzwm/5W8lRi5xQpUHIV+PIXmYhhfag8sedS jz6W4FdU4VWolQx8Jm0wopqlI3M9u9FVl7oPt5b3vWFygVjscwCYNpjWTZXfaGyXMIlz0QPsdAq 0= X-Google-Smtp-Source: AGHT+IEgbRmeLzHygurQ8GrbNyHN6Kt0VXzSY9aLiaH8bdOGe6I40zVx+CJbKLm6X6f5LwY4hBf41g== X-Received: by 2002:a17:907:9629:b0:ae3:c6a3:f855 with SMTP id a640c23a62f3a-afca4dff310mr182406266b.31.1755065041198; Tue, 12 Aug 2025 23:04:01 -0700 (PDT) Received: from rayden.urgonet (h-37-123-177-177.A175.priv.bahnhof.se. [37.123.177.177]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-615a8f2b892sm21498679a12.25.2025.08.12.23.03.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Aug 2025 23:04:00 -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=20K=C3=B6nig?= , Sumit Garg , Matthias Brugger , AngeloGioacchino Del Regno , azarrabi@qti.qualcomm.com, Simona Vetter , Daniel Stone , Rouven Czerwinski , robin.murphy@arm.com, Jens Wiklander Subject: [PATCH v11 6/9] tee: add tee_shm_alloc_dma_mem() Date: Wed, 13 Aug 2025 08:02:55 +0200 Message-ID: <20250813060339.2977604-7-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250813060339.2977604-1-jens.wiklander@linaro.org> References: <20250813060339.2977604-1-jens.wiklander@linaro.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add tee_shm_alloc_dma_mem() to allocate DMA memory. The memory is represented by a tee_shm object using the new flag TEE_SHM_DMA_MEM to identify it as DMA memory. The allocated memory will later be lent to the TEE to be used as protected memory. Signed-off-by: Jens Wiklander Reviewed-by: Sumit Garg --- drivers/tee/tee_shm.c | 85 +++++++++++++++++++++++++++++++++++++++- include/linux/tee_core.h | 5 +++ 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c index 76195a398c89..e195c892431d 100644 --- a/drivers/tee/tee_shm.c +++ b/drivers/tee/tee_shm.c @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include #include #include @@ -13,9 +15,14 @@ #include #include #include -#include #include "tee_private.h" =20 +struct tee_shm_dma_mem { + struct tee_shm shm; + dma_addr_t dma_addr; + struct page *page; +}; + static void shm_put_kernel_pages(struct page **pages, size_t page_count) { size_t n; @@ -48,7 +55,16 @@ static void tee_shm_release(struct tee_device *teedev, s= truct tee_shm *shm) { void *p =3D shm; =20 - if (shm->flags & TEE_SHM_DMA_BUF) { + if (shm->flags & TEE_SHM_DMA_MEM) { +#if IS_ENABLED(CONFIG_TEE_DMABUF_HEAPS) + struct tee_shm_dma_mem *dma_mem; + + dma_mem =3D container_of(shm, struct tee_shm_dma_mem, shm); + p =3D dma_mem; + dma_free_pages(&teedev->dev, shm->size, dma_mem->page, + dma_mem->dma_addr, DMA_BIDIRECTIONAL); +#endif + } else if (shm->flags & TEE_SHM_DMA_BUF) { struct tee_shm_dmabuf_ref *ref; =20 ref =3D container_of(shm, struct tee_shm_dmabuf_ref, shm); @@ -268,6 +284,71 @@ struct tee_shm *tee_shm_alloc_priv_buf(struct tee_cont= ext *ctx, size_t size) } EXPORT_SYMBOL_GPL(tee_shm_alloc_priv_buf); =20 +#if IS_ENABLED(CONFIG_TEE_DMABUF_HEAPS) +/** + * tee_shm_alloc_dma_mem() - Allocate DMA memory as shared memory object + * @ctx: Context that allocates the shared memory + * @page_count: Number of pages + * + * The allocated memory is expected to be lent (made inaccessible to the + * kernel) to the TEE while it's used and returned (accessible to the + * kernel again) before it's freed. + * + * This function should normally only be used internally in the TEE + * drivers. + * + * @returns a pointer to 'struct tee_shm' + */ +struct tee_shm *tee_shm_alloc_dma_mem(struct tee_context *ctx, + size_t page_count) +{ + struct tee_device *teedev =3D ctx->teedev; + struct tee_shm_dma_mem *dma_mem; + dma_addr_t dma_addr; + struct page *page; + + if (!tee_device_get(teedev)) + return ERR_PTR(-EINVAL); + + page =3D dma_alloc_pages(&teedev->dev, page_count * PAGE_SIZE, + &dma_addr, DMA_BIDIRECTIONAL, GFP_KERNEL); + if (!page) + goto err_put_teedev; + + dma_mem =3D kzalloc(sizeof(*dma_mem), GFP_KERNEL); + if (!dma_mem) + goto err_free_pages; + + refcount_set(&dma_mem->shm.refcount, 1); + dma_mem->shm.ctx =3D ctx; + dma_mem->shm.paddr =3D page_to_phys(page); + dma_mem->dma_addr =3D dma_addr; + dma_mem->page =3D page; + dma_mem->shm.size =3D page_count * PAGE_SIZE; + dma_mem->shm.flags =3D TEE_SHM_DMA_MEM; + + teedev_ctx_get(ctx); + + return &dma_mem->shm; + +err_free_pages: + dma_free_pages(&teedev->dev, page_count * PAGE_SIZE, page, dma_addr, + DMA_BIDIRECTIONAL); +err_put_teedev: + tee_device_put(teedev); + + return ERR_PTR(-ENOMEM); +} +EXPORT_SYMBOL_GPL(tee_shm_alloc_dma_mem); +#else +struct tee_shm *tee_shm_alloc_dma_mem(struct tee_context *ctx, + size_t page_count) +{ + return ERR_PTR(-EINVAL); +} +EXPORT_SYMBOL_GPL(tee_shm_alloc_dma_mem); +#endif + int tee_dyn_shm_alloc_helper(struct tee_shm *shm, size_t size, size_t alig= n, int (*shm_register)(struct tee_context *ctx, struct tee_shm *shm, diff --git a/include/linux/tee_core.h b/include/linux/tee_core.h index b6c54b34a8b5..7b0c1da2ca6c 100644 --- a/include/linux/tee_core.h +++ b/include/linux/tee_core.h @@ -29,6 +29,8 @@ #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_SHM_DMA_MEM BIT(5) /* Memory allocated with */ + /* dma_alloc_pages() */ =20 #define TEE_DEVICE_FLAG_REGISTERED 0x1 #define TEE_MAX_DEV_NAME_LEN 32 @@ -298,6 +300,9 @@ void *tee_get_drvdata(struct tee_device *teedev); */ struct tee_shm *tee_shm_alloc_priv_buf(struct tee_context *ctx, size_t siz= e); =20 +struct tee_shm *tee_shm_alloc_dma_mem(struct tee_context *ctx, + size_t page_count); + int tee_dyn_shm_alloc_helper(struct tee_shm *shm, size_t size, size_t alig= n, int (*shm_register)(struct tee_context *ctx, struct tee_shm *shm, --=20 2.43.0 From nobody Sun Dec 14 02:14:14 2025 Received: from mail-ed1-f45.google.com (mail-ed1-f45.google.com [209.85.208.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 8B8E12D0C72 for ; Wed, 13 Aug 2025 06:04:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755065048; cv=none; b=TGd2YVByZWwY+ChFI0fH4Cv6ktTJjJg7h840sZi5TaZrWemM+hfrGdlLOEPSY9O2HhUKO9xYGCIQWmGd0LjTbRDRaRfcL/E1shoTc8YfDNpDRXeYs+6PFAkbjpLdBOQ4CmP3o9F5PI1SEZwM9B7/xeT+cIh93Zk7cg1+TDM8vZU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755065048; c=relaxed/simple; bh=AIJlgFk7fUjfn21LDq4M47dl0OPLcCvx0c6kQCRqWw4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=k6szV2USV9pkHzQ2Jdl/rp8kBWxXHR4V4ZANaPaJDZM0StZZ+QKJBW1CzkYQjxNbtlGp6urfxWxcwq7ESCjTDaaKhvlTX0EAHWrBWrep3L88iv31qCSa6qI9Oig1B9d8OmRuPL9jzWdJg7C9F+snCcDlPX3IPB8QLqerpZM3MtE= 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=WRcDyVjh; arc=none smtp.client-ip=209.85.208.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="WRcDyVjh" Received: by mail-ed1-f45.google.com with SMTP id 4fb4d7f45d1cf-6180ce2197cso7755620a12.2 for ; Tue, 12 Aug 2025 23:04:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1755065044; x=1755669844; 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=Mlsk/bAk7ySrKDp6zbKeV5kpDxvVSbwlV8t4Q8Bml4k=; b=WRcDyVjh9hn+O2un6eYqge0WRHZepwsW9Q6T4HD/PNp2r8d8fgAp19ehYj72zEkxu0 jUOgMxaxAj4rOrtiVZKj+vgcQyds1famOY26vTfJDWlssxyKUJIkbAk7VZqcfiTTP61v 5W4GmowyXCN68a5C+RDYU7DasbkmWngzqQdiPQqeAq1vs/usjj/hVRyFUyi69TJ12yKv Bq+T+Hp/Fg7kxwVqej86rAghzSRkRi80ZRHvASpMFdt7t8XOI7msR13C6XdaCMwMvl7v 32LJ2Te/cy5LSShhypUFQ6wThL3kBaC0CKfO9d71qqAwjO0bqgnjRmewOiLZJC3nxjgM 09bQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755065044; x=1755669844; 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=Mlsk/bAk7ySrKDp6zbKeV5kpDxvVSbwlV8t4Q8Bml4k=; b=Yw6Wlfs1b5TnYq3WND5YmZpDobSO4chYd2R+NbLUBeMhwjRA0/igaTEKmMZXlXuNoQ aCXaXQn36nGLDx9ahyShFafMvpEUOWq3vHVdomiNO+maL5b/EdPKyFaqbs5219NYGkL7 cDpppCStoj0PjSxrb3zVRh0G48Z2CgWW2YAcSrsKha+GA5PCTVYI+yZ3i8dr1KCHGl46 WFvCuhF1YWWFCseazxEeBCwAqmz/GKGxyw74EjQcqNb/lXtIgm3I9d/YMLC3i+e5Y1pq mms6lql6mS56K7Gdm+IKLgRmG/askWT9R7qXNYQvBQgovWejZDcJOS5RAc8r1NIiZerj ThdA== X-Gm-Message-State: AOJu0YzzjgKWlre0Fkj7yj05+8jObHVnhZQL5d2hARZWceGZGReQNYtt gAvacC0SpWYsvodTaEvNflQf8qYICD8uwZGmhiVsQvuIpv3aTKvmsCh2KWvMX1/Ifyl+6CCL1hF heGF1Sjo= X-Gm-Gg: ASbGncssgCtYQzqYMnywHMi/aQy+toCNaWgu9k5vjB8eHHf/JZRtt5myAnHB+drZtQs /HUQfdwGE7Mi3cKtzE/jBdsZc/poKg/sudEa20CI5V1My3IEctNUhRdPj5eHm8lMX0N5a8wW9nr CYUf7OotUdUc7aczl+RDHZRkirNdohF8dYeiepr/gRnkg4us++EKS43g2RzgINkX57KzfiaFYTj 2/lh2f9QLwztU188FGV5Y/aW9K4LsRYzuTK+2qQ4FEpqQJOuGt2ErBzJwV4umD+xOPu/GqHFf3p LrC+tE/UzipehLiRLd8XxijnMTkYVmDlfw+ABmKSowgRRTfJhwBMVRO2XbQC9mgBWjBkW9xKIJU eXGrx4Jd0i3EeOznabx2NDiyKqMmuzVEfvWCwPxaY1GL6PsZ/ZoqiWFi0VNznjsocZumG6OSep0 s= X-Google-Smtp-Source: AGHT+IGPP3R6N4Dt8iwgkksibZ5tUqdsMY5R2I3knc3e7zzNRFbaVSRs5R96bdCj/pA/8Zc73+XZ0w== X-Received: by 2002:a50:8710:0:b0:608:50ab:7e38 with SMTP id 4fb4d7f45d1cf-6186bf92a89mr984962a12.14.1755065043966; Tue, 12 Aug 2025 23:04:03 -0700 (PDT) Received: from rayden.urgonet (h-37-123-177-177.A175.priv.bahnhof.se. [37.123.177.177]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-615a8f2b892sm21498679a12.25.2025.08.12.23.04.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Aug 2025 23:04:03 -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=20K=C3=B6nig?= , Sumit Garg , Matthias Brugger , AngeloGioacchino Del Regno , azarrabi@qti.qualcomm.com, Simona Vetter , Daniel Stone , Rouven Czerwinski , robin.murphy@arm.com, Jens Wiklander , Sumit Garg Subject: [PATCH v11 7/9] optee: support protected memory allocation Date: Wed, 13 Aug 2025 08:02:56 +0200 Message-ID: <20250813060339.2977604-8-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250813060339.2977604-1-jens.wiklander@linaro.org> References: <20250813060339.2977604-1-jens.wiklander@linaro.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 Reviewed-by: Sumit Garg --- drivers/tee/optee/Kconfig | 5 +++ drivers/tee/optee/core.c | 7 ++++ drivers/tee/optee/optee_private.h | 2 + drivers/tee/optee/smc_abi.c | 69 ++++++++++++++++++++++++++++++- 4 files changed, 81 insertions(+), 2 deletions(-) diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig index 7bb7990d0b07..50d2051f7f20 100644 --- a/drivers/tee/optee/Kconfig +++ b/drivers/tee/optee/Kconfig @@ -25,3 +25,8 @@ config OPTEE_INSECURE_LOAD_IMAGE =20 Additional documentation on kernel security risks are at Documentation/tee/op-tee.rst. + +config OPTEE_STATIC_PROTMEM_POOL + bool + depends on HAS_IOMEM && TEE_DMABUF_HEAPS + default y diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index c75fddc83576..49ccfe6f6583 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -56,6 +56,13 @@ int optee_rpmb_intf_rdev(struct notifier_block *intf, un= signed long action, return 0; } =20 +int optee_set_dma_mask(struct optee *optee, u_int pa_width) +{ + u64 mask =3D DMA_BIT_MASK(min(64, pa_width)); + + return dma_coerce_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)); diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_pr= ivate.h index 9526087f0e68..4969b83a9851 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -274,6 +274,8 @@ struct optee_call_ctx { =20 extern struct blocking_notifier_head optee_rpmb_intf_added; =20 +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 26f8f7bbbe56..b4c007ed3b94 100644 --- a/drivers/tee/optee/smc_abi.c +++ b/drivers/tee/optee/smc_abi.c @@ -1583,6 +1583,68 @@ static inline int optee_load_fw(struct platform_devi= ce *pdev, } #endif =20 +static struct tee_protmem_pool *static_protmem_pool_init(struct optee *opt= ee) +{ +#if IS_ENABLED(CONFIG_OPTEE_STATIC_PROTMEM_POOL) + union { + struct arm_smccc_res smccc; + struct optee_smc_get_protmem_config_result result; + } res; + struct tee_protmem_pool *pool; + void *p; + int rc; + + optee->smc.invoke_fn(OPTEE_SMC_GET_PROTMEM_CONFIG, 0, 0, 0, 0, + 0, 0, 0, &res.smccc); + if (res.result.status !=3D OPTEE_SMC_RETURN_OK) + return ERR_PTR(-EINVAL); + + rc =3D optee_set_dma_mask(optee, res.result.pa_width); + if (rc) + return ERR_PTR(rc); + + /* + * 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. + */ + p =3D devm_memremap(&optee->teedev->dev, res.result.start, + res.result.size, MEMREMAP_WC); + if (IS_ERR(p)) + return p; + + pool =3D tee_protmem_static_pool_alloc(res.result.start, res.result.size); + if (IS_ERR(pool)) + devm_memunmap(&optee->teedev->dev, p); + + return pool; +#else + return ERR_PTR(-EINVAL); +#endif +} + +static int optee_protmem_pool_init(struct optee *optee) +{ + enum tee_dma_heap_id heap_id =3D TEE_DMA_HEAP_SECURE_VIDEO_PLAY; + struct tee_protmem_pool *pool =3D ERR_PTR(-EINVAL); + int rc; + + if (!(optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_PROTMEM)) + return 0; + + pool =3D static_protmem_pool_init(optee); + if (IS_ERR(pool)) + return PTR_ERR(pool); + + rc =3D tee_device_register_dma_heap(optee->teedev, heap_id, pool); + if (rc) + pool->ops->destroy_pool(pool); + + return rc; +} + static int optee_probe(struct platform_device *pdev) { optee_invoke_fn *invoke_fn; @@ -1678,7 +1740,7 @@ static int optee_probe(struct platform_device *pdev) optee =3D kzalloc(sizeof(*optee), GFP_KERNEL); if (!optee) { rc =3D -ENOMEM; - goto err_free_pool; + goto err_free_shm_pool; } =20 optee->ops =3D &optee_ops; @@ -1751,6 +1813,9 @@ static int optee_probe(struct platform_device *pdev) pr_info("Asynchronous notifications enabled\n"); } =20 + 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 * the shm cache so that there's no chance of receiving an invalid @@ -1802,7 +1867,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); --=20 2.43.0 From nobody Sun Dec 14 02:14:14 2025 Received: from mail-ed1-f42.google.com (mail-ed1-f42.google.com [209.85.208.42]) (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 47B2A2D0C84 for ; Wed, 13 Aug 2025 06:04:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755065050; cv=none; b=WTmNCOjDGyCn8fhceR4qpAf1uEXemGCripKYOm7vTqgm2rnRUOWRTPJ47Wy5ZcgJpR8Tl4AsURegIPXj7z1zS8zctPQHbQ3+xV/SHo09ehdu+dypEGVfX4Qx3R4Fwtgq/zGAaXVce4mmg9XHDUacaUdetNuTg/r6fjWD2db6LD8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755065050; c=relaxed/simple; bh=72qRpvLDAQVQ4ZZVrcYQV46VhyUyJLs6grjzr6r3i2Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ck4LOpE83v1IRUu4bPxF5QWXhv755iSE2z/WtGj3F1dj6M2L70Wgf9MQPyFn5QZFBGCBezSHJ+zhMKraiux3PLBkZF+xuHpakAnyQ3ANr3WEBbELJrE8HuQAUMCQNicN0+lfWZ8XOkiMmky6nMaR3SuTKi7Br/CtduOPCITMi84= 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=JB+Cl/7w; arc=none smtp.client-ip=209.85.208.42 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="JB+Cl/7w" Received: by mail-ed1-f42.google.com with SMTP id 4fb4d7f45d1cf-61571192c3aso7365386a12.2 for ; Tue, 12 Aug 2025 23:04:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1755065046; x=1755669846; 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=OtHmu57rTTaTDV1QBcMfjB04WNzBM5+uJeova27sa60=; b=JB+Cl/7wuLhDbfqxpv0z5/PKaYy4bRfhdy0yZwL+ZdJpYVBeyZgabLbgiYI2jssM97 5IfGngA3VEn+DzKk6fPyvTZxjRdQI3ETdUv2xzz18QbkTn3pgY48Ro+FPhQpDoxiQN3W VgZWckkCd/fJKHAUFxdqSHuNLeqQGOshTzgsY7KnGz1dWjt9r8wUkIoYqlX5CUERORYY 2yr4osfLDgqMOxvRnleVxCRxdHMMbVjHZLA3qkTuX9fKAQ+j/6n8dkOSpk1TuJXwTcg9 oz9bba117UOFjhPhofbkyBqqkeEntCL8tp+h9cDdwMd4pN5cpSBnNqMZaSucyq9ADUuD DKIQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755065046; x=1755669846; 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=OtHmu57rTTaTDV1QBcMfjB04WNzBM5+uJeova27sa60=; b=uW0q+SmsXbbWXmJTeLBnymmm8vw7vJjKcOorLVQmLyGIBS08uRcLaEuHUcJV8N5Vty tpjrs3pWxsXLqqXGznm3A4N44yfiSs6096PTFTc3br/SsfTRcpH2YNOoHHGuKOv9TuFS Ia7+iLHD0PxuE/uA7kMpZipKH0mj0NPjCest2hpFBHC24gIsQb+68TmlQOLiBfmxM1pU xKGjFCyise4V1TgPvu6cCq672+yibC+GfSNyh/miJzS6ffAhMGjAlX6ak35GsudIz7wl Y1KYRgFWKTgNrCIRg4PG88IB0MKmuvOE6W9dY5Hhhhj1lynCGDbrPvVyCMwWQEs8HliV StIA== X-Gm-Message-State: AOJu0YxyxmtN60yh81+EfqgNNbd/sffaabnob6eJ0II+IzOuwWqZ21e1 91jJhUvqcSC7FT6giOBNZTq3MCP5OTvpug0LOYIpbiisuOxz9ZE+VjAyVOtyUxXaIywwd8n2tdx QVyBsD8g= X-Gm-Gg: ASbGncuArvhL08JpUgtaxtqcMFZTFcpxArfYzpud9QQE17wRuGNJH/ZaXuiVR03R66p nj8zM3LR4ggpn8T2eKEVGW+vzjmWRCsHLTwpsgj33M6xcZOsif/9a4QACKHWEEaiIP0RjLAfLrp 3NbmvWtht4fHc0pNiF5s9kuG2n2dm/0zOeMdepyoXBVHTgHf48/gF5zK3sR/MsXeTvgIYRi4OK/ 4ij85g5RYnmTrBkrQryAsX2DrF5yhKuPKYaLlIUUtGAtnp3FXxeeGdifxLRU/5tcSY0HzQuHFI6 SZNcOhb7T2LeYptourHdq7LxbmntHdcuIh8eLZYnJY/8pP2g/5R2Yru7pxebkYc/srhpghjmjL5 iArjZCMe4WdqnM5UI7Pm+khOo5IknNVPk1MSjWluOYtCmoSuATdHVfUcl/K/5pfswhTpPukKexf E= X-Google-Smtp-Source: AGHT+IFqidhskDlaHJgNRIX22KVWXY2sCg3jNSI9Rc9uFKDKbLGm8gsWSa6DmckslUcaXx9VGF3TWQ== X-Received: by 2002:a05:6402:1ed5:b0:615:9d94:2934 with SMTP id 4fb4d7f45d1cf-6186b77438bmr1469054a12.10.1755065045951; Tue, 12 Aug 2025 23:04:05 -0700 (PDT) Received: from rayden.urgonet (h-37-123-177-177.A175.priv.bahnhof.se. [37.123.177.177]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-615a8f2b892sm21498679a12.25.2025.08.12.23.04.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Aug 2025 23:04:05 -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=20K=C3=B6nig?= , Sumit Garg , Matthias Brugger , AngeloGioacchino Del Regno , azarrabi@qti.qualcomm.com, Simona Vetter , Daniel Stone , Rouven Czerwinski , robin.murphy@arm.com, Jens Wiklander , Sumit Garg Subject: [PATCH v11 8/9] optee: FF-A: dynamic protected memory allocation Date: Wed, 13 Aug 2025 08:02:57 +0200 Message-ID: <20250813060339.2977604-9-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250813060339.2977604-1-jens.wiklander@linaro.org> References: <20250813060339.2977604-1-jens.wiklander@linaro.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add support in the OP-TEE backend driver dynamic protected memory allocation with FF-A. The protected memory pools for dynamically allocated protected memory are instantiated when requested by user-space. This instantiation can fail if OP-TEE doesn't support the requested use-case of protected memory. Restricted memory pools based on a static carveout or dynamic allocation can coexist for different use-cases. We use only dynamic allocation with FF-A. Signed-off-by: Jens Wiklander Reviewed-by: Sumit Garg --- drivers/tee/optee/Makefile | 1 + drivers/tee/optee/ffa_abi.c | 146 ++++++++++++- drivers/tee/optee/optee_private.h | 13 +- drivers/tee/optee/protmem.c | 335 ++++++++++++++++++++++++++++++ 4 files changed, 492 insertions(+), 3 deletions(-) create mode 100644 drivers/tee/optee/protmem.c diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile index a6eff388d300..ad7049c1c107 100644 --- a/drivers/tee/optee/Makefile +++ b/drivers/tee/optee/Makefile @@ -4,6 +4,7 @@ optee-objs +=3D core.o optee-objs +=3D call.o optee-objs +=3D notif.o optee-objs +=3D rpc.o +optee-objs +=3D protmem.o optee-objs +=3D supp.o optee-objs +=3D device.o optee-objs +=3D smc_abi.o diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c index f9ef7d94cebd..11c543ac65c6 100644 --- a/drivers/tee/optee/ffa_abi.c +++ b/drivers/tee/optee/ffa_abi.c @@ -649,6 +649,124 @@ static int optee_ffa_do_call_with_arg(struct tee_cont= ext *ctx, return optee_ffa_yielding_call(ctx, &data, rpc_arg, system_thread); } =20 +static int do_call_lend_protmem(struct optee *optee, u64 cookie, u32 use_c= ase) +{ + struct optee_shm_arg_entry *entry; + struct optee_msg_arg *msg_arg; + struct tee_shm *shm; + u_int offs; + int rc; + + msg_arg =3D optee_get_msg_arg(optee->ctx, 1, &entry, &shm, &offs); + if (IS_ERR(msg_arg)) + return PTR_ERR(msg_arg); + + msg_arg->cmd =3D OPTEE_MSG_CMD_ASSIGN_PROTMEM; + msg_arg->params[0].attr =3D OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; + msg_arg->params[0].u.value.a =3D cookie; + msg_arg->params[0].u.value.b =3D use_case; + + rc =3D optee->ops->do_call_with_arg(optee->ctx, shm, offs, false); + if (rc) + goto out; + if (msg_arg->ret !=3D TEEC_SUCCESS) { + rc =3D -EINVAL; + goto out; + } + +out: + optee_free_msg_arg(optee->ctx, entry, offs); + return rc; +} + +static int optee_ffa_lend_protmem(struct optee *optee, struct tee_shm *pro= tmem, + u32 *mem_attrs, unsigned int ma_count, + u32 use_case) +{ + struct ffa_device *ffa_dev =3D optee->ffa.ffa_dev; + const struct ffa_mem_ops *mem_ops =3D ffa_dev->ops->mem_ops; + const struct ffa_msg_ops *msg_ops =3D ffa_dev->ops->msg_ops; + struct ffa_send_direct_data data; + struct ffa_mem_region_attributes *mem_attr; + struct ffa_mem_ops_args args =3D { + .use_txbuf =3D true, + .tag =3D use_case, + }; + struct page *page; + struct scatterlist sgl; + unsigned int n; + int rc; + + mem_attr =3D kcalloc(ma_count, sizeof(*mem_attr), GFP_KERNEL); + for (n =3D 0; n < ma_count; n++) { + mem_attr[n].receiver =3D mem_attrs[n] & U16_MAX; + mem_attr[n].attrs =3D mem_attrs[n] >> 16; + } + args.attrs =3D mem_attr; + args.nattrs =3D ma_count; + + page =3D phys_to_page(protmem->paddr); + sg_init_table(&sgl, 1); + sg_set_page(&sgl, page, protmem->size, 0); + + args.sg =3D &sgl; + rc =3D mem_ops->memory_lend(&args); + kfree(mem_attr); + if (rc) + return rc; + + rc =3D do_call_lend_protmem(optee, args.g_handle, use_case); + if (rc) + goto err_reclaim; + + rc =3D optee_shm_add_ffa_handle(optee, protmem, args.g_handle); + if (rc) + goto err_unreg; + + protmem->sec_world_id =3D args.g_handle; + + return 0; + +err_unreg: + data =3D (struct ffa_send_direct_data){ + .data0 =3D OPTEE_FFA_RELEASE_PROTMEM, + .data1 =3D (u32)args.g_handle, + .data2 =3D (u32)(args.g_handle >> 32), + }; + msg_ops->sync_send_receive(ffa_dev, &data); +err_reclaim: + mem_ops->memory_reclaim(args.g_handle, 0); + return rc; +} + +static int optee_ffa_reclaim_protmem(struct optee *optee, + struct tee_shm *protmem) +{ + struct ffa_device *ffa_dev =3D optee->ffa.ffa_dev; + const struct ffa_msg_ops *msg_ops =3D ffa_dev->ops->msg_ops; + const struct ffa_mem_ops *mem_ops =3D ffa_dev->ops->mem_ops; + u64 global_handle =3D protmem->sec_world_id; + struct ffa_send_direct_data data =3D { + .data0 =3D OPTEE_FFA_RELEASE_PROTMEM, + .data1 =3D (u32)global_handle, + .data2 =3D (u32)(global_handle >> 32) + }; + int rc; + + optee_shm_rem_ffa_handle(optee, global_handle); + protmem->sec_world_id =3D 0; + + rc =3D msg_ops->sync_send_receive(ffa_dev, &data); + if (rc) + pr_err("Release SHM id 0x%llx rc %d\n", global_handle, rc); + + rc =3D mem_ops->memory_reclaim(global_handle, 0); + if (rc) + pr_err("mem_reclaim: 0x%llx %d", global_handle, rc); + + return rc; +} + /* * 6. Driver initialization * @@ -819,6 +937,8 @@ static const struct optee_ops optee_ffa_ops =3D { .do_call_with_arg =3D optee_ffa_do_call_with_arg, .to_msg_param =3D optee_ffa_to_msg_param, .from_msg_param =3D optee_ffa_from_msg_param, + .lend_protmem =3D optee_ffa_lend_protmem, + .reclaim_protmem =3D optee_ffa_reclaim_protmem, }; =20 static void optee_ffa_remove(struct ffa_device *ffa_dev) @@ -891,6 +1011,25 @@ static int optee_ffa_async_notif_init(struct ffa_devi= ce *ffa_dev, return rc; } =20 +static int optee_ffa_protmem_pool_init(struct optee *optee, u32 sec_caps) +{ + enum tee_dma_heap_id id =3D TEE_DMA_HEAP_SECURE_VIDEO_PLAY; + struct tee_protmem_pool *pool; + int rc =3D 0; + + if (sec_caps & OPTEE_FFA_SEC_CAP_PROTMEM) { + pool =3D optee_protmem_alloc_dyn_pool(optee, id); + if (IS_ERR(pool)) + return PTR_ERR(pool); + + rc =3D tee_device_register_dma_heap(optee->teedev, id, pool); + if (rc) + pool->ops->destroy_pool(pool); + } + + return rc; +} + static int optee_ffa_probe(struct ffa_device *ffa_dev) { const struct ffa_notifier_ops *notif_ops; @@ -941,7 +1080,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev) optee); if (IS_ERR(teedev)) { rc =3D PTR_ERR(teedev); - goto err_free_pool; + goto err_free_shm_pool; } optee->teedev =3D teedev; =20 @@ -988,6 +1127,9 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev) rc); } =20 + if (optee_ffa_protmem_pool_init(optee, sec_caps)) + pr_info("Protected memory service not available\n"); + rc =3D optee_enumerate_devices(PTA_CMD_GET_DEVICES); if (rc) goto err_unregister_devices; @@ -1018,7 +1160,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev) tee_device_unregister(optee->supp_teedev); err_unreg_teedev: tee_device_unregister(optee->teedev); -err_free_pool: +err_free_shm_pool: tee_shm_pool_free(pool); err_free_optee: kfree(optee); diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_pr= ivate.h index 4969b83a9851..db9ea673fbca 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -176,9 +176,14 @@ struct optee; * @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 + * @lend_protmem: lends physically contiguous memory as restricted + * memory, inaccessible by the kernel + * @reclaim_protmem: reclaims restricted memory previously lent with + * @lend_protmem() and makes it accessible by the + * kernel again * * 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 + * as a way of abstracting the different methods of entering OP-TEE in * secure world. */ struct optee_ops { @@ -191,6 +196,10 @@ struct optee_ops { int (*from_msg_param)(struct optee *optee, struct tee_param *params, size_t num_params, const struct optee_msg_param *msg_params); + int (*lend_protmem)(struct optee *optee, struct tee_shm *protmem, + u32 *mem_attr, unsigned int ma_count, + u32 use_case); + int (*reclaim_protmem)(struct optee *optee, struct tee_shm *protmem); }; =20 /** @@ -287,6 +296,8 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 fu= nc, size_t num_params, void optee_supp_init(struct optee_supp *supp); void optee_supp_uninit(struct optee_supp *supp); void optee_supp_release(struct optee_supp *supp); +struct tee_protmem_pool *optee_protmem_alloc_dyn_pool(struct optee *optee, + enum tee_dma_heap_id id); =20 int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params, struct tee_param *param); diff --git a/drivers/tee/optee/protmem.c b/drivers/tee/optee/protmem.c new file mode 100644 index 000000000000..2eba48d5ac73 --- /dev/null +++ b/drivers/tee/optee/protmem.c @@ -0,0 +1,335 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2025, Linaro Limited + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include "optee_private.h" + +struct optee_protmem_dyn_pool { + struct tee_protmem_pool pool; + struct gen_pool *gen_pool; + struct optee *optee; + size_t page_count; + u32 *mem_attrs; + u_int mem_attr_count; + refcount_t refcount; + u32 use_case; + struct tee_shm *protmem; + /* Protects when initializing and tearing down this struct */ + struct mutex mutex; +}; + +static struct optee_protmem_dyn_pool * +to_protmem_dyn_pool(struct tee_protmem_pool *pool) +{ + return container_of(pool, struct optee_protmem_dyn_pool, pool); +} + +static int init_dyn_protmem(struct optee_protmem_dyn_pool *rp) +{ + int rc; + + rp->protmem =3D tee_shm_alloc_dma_mem(rp->optee->ctx, rp->page_count); + if (IS_ERR(rp->protmem)) { + rc =3D PTR_ERR(rp->protmem); + goto err_null_protmem; + } + + /* + * TODO unmap the memory range since the physical memory will + * become inaccesible after the lend_protmem() call. + * + * If the platform supports a hypervisor at EL2, it will unmap the + * intermediate physical memory for us and stop cache pre-fetch of + * the memory. + */ + rc =3D rp->optee->ops->lend_protmem(rp->optee, rp->protmem, + rp->mem_attrs, + rp->mem_attr_count, rp->use_case); + if (rc) + goto err_put_shm; + rp->protmem->flags |=3D TEE_SHM_DYNAMIC; + + rp->gen_pool =3D gen_pool_create(PAGE_SHIFT, -1); + if (!rp->gen_pool) { + rc =3D -ENOMEM; + goto err_reclaim; + } + + rc =3D gen_pool_add(rp->gen_pool, rp->protmem->paddr, + rp->protmem->size, -1); + if (rc) + goto err_free_pool; + + refcount_set(&rp->refcount, 1); + return 0; + +err_free_pool: + gen_pool_destroy(rp->gen_pool); + rp->gen_pool =3D NULL; +err_reclaim: + rp->optee->ops->reclaim_protmem(rp->optee, rp->protmem); +err_put_shm: + tee_shm_put(rp->protmem); +err_null_protmem: + rp->protmem =3D NULL; + return rc; +} + +static int get_dyn_protmem(struct optee_protmem_dyn_pool *rp) +{ + int rc =3D 0; + + if (!refcount_inc_not_zero(&rp->refcount)) { + mutex_lock(&rp->mutex); + if (rp->gen_pool) { + /* + * Another thread has already initialized the pool + * before us, or the pool was just about to be torn + * down. Either way we only need to increase the + * refcount and we're done. + */ + refcount_inc(&rp->refcount); + } else { + rc =3D init_dyn_protmem(rp); + } + mutex_unlock(&rp->mutex); + } + + return rc; +} + +static void release_dyn_protmem(struct optee_protmem_dyn_pool *rp) +{ + gen_pool_destroy(rp->gen_pool); + rp->gen_pool =3D NULL; + + rp->optee->ops->reclaim_protmem(rp->optee, rp->protmem); + rp->protmem->flags &=3D ~TEE_SHM_DYNAMIC; + + WARN(refcount_read(&rp->protmem->refcount) !=3D 1, "Unexpected refcount"); + tee_shm_put(rp->protmem); + rp->protmem =3D NULL; +} + +static void put_dyn_protmem(struct optee_protmem_dyn_pool *rp) +{ + if (refcount_dec_and_test(&rp->refcount)) { + mutex_lock(&rp->mutex); + if (rp->gen_pool) + release_dyn_protmem(rp); + mutex_unlock(&rp->mutex); + } +} + +static int protmem_pool_op_dyn_alloc(struct tee_protmem_pool *pool, + struct sg_table *sgt, size_t size, + size_t *offs) +{ + struct optee_protmem_dyn_pool *rp =3D to_protmem_dyn_pool(pool); + size_t sz =3D ALIGN(size, PAGE_SIZE); + phys_addr_t pa; + int rc; + + rc =3D get_dyn_protmem(rp); + if (rc) + return rc; + + pa =3D gen_pool_alloc(rp->gen_pool, sz); + if (!pa) { + rc =3D -ENOMEM; + goto err_put; + } + + rc =3D sg_alloc_table(sgt, 1, GFP_KERNEL); + if (rc) + goto err_free; + + sg_set_page(sgt->sgl, phys_to_page(pa), size, 0); + *offs =3D pa - rp->protmem->paddr; + + return 0; +err_free: + gen_pool_free(rp->gen_pool, pa, size); +err_put: + put_dyn_protmem(rp); + + return rc; +} + +static void protmem_pool_op_dyn_free(struct tee_protmem_pool *pool, + struct sg_table *sgt) +{ + struct optee_protmem_dyn_pool *rp =3D to_protmem_dyn_pool(pool); + struct scatterlist *sg; + int i; + + for_each_sgtable_sg(sgt, sg, i) + gen_pool_free(rp->gen_pool, sg_phys(sg), sg->length); + sg_free_table(sgt); + put_dyn_protmem(rp); +} + +static int protmem_pool_op_dyn_update_shm(struct tee_protmem_pool *pool, + struct sg_table *sgt, size_t offs, + struct tee_shm *shm, + struct tee_shm **parent_shm) +{ + struct optee_protmem_dyn_pool *rp =3D to_protmem_dyn_pool(pool); + + *parent_shm =3D rp->protmem; + + return 0; +} + +static void pool_op_dyn_destroy_pool(struct tee_protmem_pool *pool) +{ + struct optee_protmem_dyn_pool *rp =3D to_protmem_dyn_pool(pool); + + mutex_destroy(&rp->mutex); + kfree(rp); +} + +static struct tee_protmem_pool_ops protmem_pool_ops_dyn =3D { + .alloc =3D protmem_pool_op_dyn_alloc, + .free =3D protmem_pool_op_dyn_free, + .update_shm =3D protmem_pool_op_dyn_update_shm, + .destroy_pool =3D pool_op_dyn_destroy_pool, +}; + +static int get_protmem_config(struct optee *optee, u32 use_case, + size_t *min_size, u_int *pa_width, + u32 *mem_attrs, u_int *ma_count) +{ + struct tee_param params[2] =3D { + [0] =3D { + .attr =3D TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT, + .u.value.a =3D use_case, + }, + [1] =3D { + .attr =3D TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT, + }, + }; + struct optee_shm_arg_entry *entry; + struct tee_shm *shm_param =3D NULL; + struct optee_msg_arg *msg_arg; + struct tee_shm *shm; + u_int offs; + int rc; + + if (mem_attrs && *ma_count) { + params[1].u.memref.size =3D *ma_count * sizeof(*mem_attrs); + shm_param =3D tee_shm_alloc_priv_buf(optee->ctx, + params[1].u.memref.size); + if (IS_ERR(shm_param)) + return PTR_ERR(shm_param); + params[1].u.memref.shm =3D shm_param; + } + + msg_arg =3D optee_get_msg_arg(optee->ctx, ARRAY_SIZE(params), &entry, + &shm, &offs); + if (IS_ERR(msg_arg)) { + rc =3D PTR_ERR(msg_arg); + goto out_free_shm; + } + msg_arg->cmd =3D OPTEE_MSG_CMD_GET_PROTMEM_CONFIG; + + rc =3D optee->ops->to_msg_param(optee, msg_arg->params, + ARRAY_SIZE(params), params); + if (rc) + goto out_free_msg; + + rc =3D optee->ops->do_call_with_arg(optee->ctx, shm, offs, false); + if (rc) + goto out_free_msg; + if (msg_arg->ret && msg_arg->ret !=3D TEEC_ERROR_SHORT_BUFFER) { + rc =3D -EINVAL; + goto out_free_msg; + } + + rc =3D optee->ops->from_msg_param(optee, params, ARRAY_SIZE(params), + msg_arg->params); + if (rc) + goto out_free_msg; + + if (!msg_arg->ret && mem_attrs && + *ma_count < params[1].u.memref.size / sizeof(*mem_attrs)) { + rc =3D -EINVAL; + goto out_free_msg; + } + + *min_size =3D params[0].u.value.a; + *pa_width =3D params[0].u.value.c; + *ma_count =3D params[1].u.memref.size / sizeof(*mem_attrs); + + if (msg_arg->ret =3D=3D TEEC_ERROR_SHORT_BUFFER) { + rc =3D -ENOSPC; + goto out_free_msg; + } + + if (mem_attrs) + memcpy(mem_attrs, tee_shm_get_va(shm_param, 0), + params[1].u.memref.size); + +out_free_msg: + optee_free_msg_arg(optee->ctx, entry, offs); +out_free_shm: + if (shm_param) + tee_shm_free(shm_param); + return rc; +} + +struct tee_protmem_pool *optee_protmem_alloc_dyn_pool(struct optee *optee, + enum tee_dma_heap_id id) +{ + struct optee_protmem_dyn_pool *rp; + size_t min_size; + u_int pa_width; + int rc; + + rp =3D kzalloc(sizeof(*rp), GFP_KERNEL); + if (!rp) + return ERR_PTR(-ENOMEM); + rp->use_case =3D id; + + rc =3D get_protmem_config(optee, id, &min_size, &pa_width, NULL, + &rp->mem_attr_count); + if (rc) { + if (rc !=3D -ENOSPC) + goto err; + rp->mem_attrs =3D kcalloc(rp->mem_attr_count, + sizeof(*rp->mem_attrs), GFP_KERNEL); + if (!rp->mem_attrs) { + rc =3D -ENOMEM; + goto err; + } + rc =3D get_protmem_config(optee, id, &min_size, &pa_width, + rp->mem_attrs, &rp->mem_attr_count); + if (rc) + goto err_kfree_eps; + } + + rc =3D optee_set_dma_mask(optee, pa_width); + if (rc) + goto err_kfree_eps; + + rp->pool.ops =3D &protmem_pool_ops_dyn; + rp->optee =3D optee; + rp->page_count =3D min_size / PAGE_SIZE; + mutex_init(&rp->mutex); + + return &rp->pool; + +err_kfree_eps: + kfree(rp->mem_attrs); +err: + kfree(rp); + return ERR_PTR(rc); +} --=20 2.43.0 From nobody Sun Dec 14 02:14:14 2025 Received: from mail-ed1-f41.google.com (mail-ed1-f41.google.com [209.85.208.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 139BC2D191C for ; Wed, 13 Aug 2025 06:04:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755065053; cv=none; b=CtnJlUX7kF17vjHaZ4M9+LJpTBdJfOt7wSvfzYz/Pvv2Vn2ENamCRNtdWfBwzH/wh5BeljIm2IpvkgtRDactEmtTB7pTGaiV+yYaCRS4+ErvZaotKnopVBcqkRgCqy233cKS+JJc7iHSXMFr0kgKTXjvK5FG62AnAWtBTmlvIS4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755065053; c=relaxed/simple; bh=RREeFH4FApT8BsWG6hYwTdwXNy+z8q66uH2RuunAKOI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lUL7r1qGL9lHfLL8EgOa0fg+NjfkxcjP9HlL7poRb6jv/S47Z4BrQiiNCuLafAvJnzPQhvNcqMiQou8/7DmthUbFo8rqGtktWL3YzwvZc5ovd381WSpkV5465UAo6b749htpk+XqlkvRkKs0C5YWnN/3ncm+DKxDUZifqQ4U3oo= 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=JCmHefOK; arc=none smtp.client-ip=209.85.208.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="JCmHefOK" Received: by mail-ed1-f41.google.com with SMTP id 4fb4d7f45d1cf-615622ed70fso9999693a12.3 for ; Tue, 12 Aug 2025 23:04:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1755065050; x=1755669850; 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=YMyd1M5LZgFUuwfgUjsWaWr5cxJRx+F31yZrIJB0d8c=; b=JCmHefOKy0QDEGm8BANws+TFSWJsmAbigmpu6j8rVbxANrwWKZuC1tRvKsFTvI//wg uViYZwZ51QTkpYnfqcTvkt4iC6sY9q9txBNcpo0GsQ4h7jcQly48/NhiVSsUqK9wiwlf WF5u3Z5qv9X3OBv6xFIH/4tVXI+o9FCHDTjJ65KvNnaWX6rn0sI3k2jCcxPGZIUnNL41 wLEf+1dfVFUpQd/DG93itBAx+c+WvwlEdtXVjTOPDkXrTRKj+s1S6cqbO/n0Gvg5RQlN ADrUkSayyFznfA/6xiY9N4+CT2D1bWj51gOezPk8BqMTkQ5TJwvkz2SrbdCOAMZaYVNs 8LPQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755065050; x=1755669850; 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=YMyd1M5LZgFUuwfgUjsWaWr5cxJRx+F31yZrIJB0d8c=; b=TsgI4iOoPQLzRYoZ5CdVGDqsaY51SjopN+Qztlo3XHCp+fqlFEvMhsLHi166UOaumR Xg18AoAQulYfsy6GGfl4jJqktQScsnN9qIOmasEDOXsXIVZqd0Sjb7ZinDpBZxcCWHcx sRL0UpoiI5zpufHs69gERkskk7AqhsVDP9AYWUudvZYXqsofpKbdvbq3e8YQpIxNk0+m 8p1Xt8LZbDeXixbNplJVeEupfmQ3ZHQM1pCV2erf6gPoEiTPU0a26Pr//8lsfoIxUpn2 Tole99YlJgYseUKcbyNBGJOfxiwvS5fFPTErleOtgK6fGNsEjPjpK8HrRm2h//g71OJf JKoA== X-Gm-Message-State: AOJu0Yw6y5r8LvvDOGHMTNgqBOwtcId8TL0lAmuTM0/jyMIlZrZDPje3 d9BTe2YGrQu+/QoV4SOtEcgUlcZptmZnoNR4/VJYOhjvIbXAqBs+eoVp/2jZPwbGKpwq1cxFvvd 0Oy+J8UI= X-Gm-Gg: ASbGncsAB7Vi2TFiMoTng8oPM4C4reboLdAbREg1RGpC4OlXS14tm+U4ZeTGQtTNgEl qxhnzmvCSbJGFPIbYYpsAMmd0mg2xUZH1GvziHomfEnoFSoTmkmZnPflZycVhccne7cOp2hIwkc 4iRLTdjpTdtWCs/KifpeZONRw/y5ftXnhjc5j27aVi4HPTzDP5AsWKncn1LTfVZlp0WwLWS52GR DE3CJSrX29gIIQZvn5Om3JeufiffJCA6dM2sTJcV9dR8fQ1Dfu4gc9AMKRR0P45dME3zSlvJKLF nZe6J9B+I6qGEVr5uXVjtL9aCjq0a10WfbqNqD+9Uk8mXz6npAljFHaGOSE5P6y1mMdxrBwPU0l pqoYUn9TJUAGoEIyOOy9VGaTg0waWITJGJz/rPlUavTZhYXftE1dDaX91uANiqDMkCzl3GGp85Y w= X-Google-Smtp-Source: AGHT+IGl+zk2kZ7dGtXoXvUAogPksLb/KD4WUBLmDCFuz3Yjsb2gUsdZ4PxNJjaVjkahgiQaR0qEBw== X-Received: by 2002:a05:6402:2753:b0:615:38e6:b739 with SMTP id 4fb4d7f45d1cf-6186bb8e5damr1297264a12.10.1755065049472; Tue, 12 Aug 2025 23:04:09 -0700 (PDT) Received: from rayden.urgonet (h-37-123-177-177.A175.priv.bahnhof.se. [37.123.177.177]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-615a8f2b892sm21498679a12.25.2025.08.12.23.04.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Aug 2025 23:04:08 -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=20K=C3=B6nig?= , Sumit Garg , Matthias Brugger , AngeloGioacchino Del Regno , azarrabi@qti.qualcomm.com, Simona Vetter , Daniel Stone , Rouven Czerwinski , robin.murphy@arm.com, Jens Wiklander , Sumit Garg Subject: [PATCH v11 9/9] optee: smc abi: dynamic protected memory allocation Date: Wed, 13 Aug 2025 08:02:58 +0200 Message-ID: <20250813060339.2977604-10-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250813060339.2977604-1-jens.wiklander@linaro.org> References: <20250813060339.2977604-1-jens.wiklander@linaro.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add support in the OP-TEE backend driver for dynamic protected memory allocation using the SMC ABI. Signed-off-by: Jens Wiklander Reviewed-by: Sumit Garg --- drivers/tee/optee/smc_abi.c | 78 +++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c index b4c007ed3b94..0be663fcd52b 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_conte= xt *ctx, return rc; } =20 +static int optee_smc_lend_protmem(struct optee *optee, struct tee_shm *pro= tmem, + u32 *mem_attrs, unsigned int ma_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 =3D optee_get_msg_arg(optee->ctx, 2, &entry, &shm, &offs); + if (IS_ERR(msg_arg)) + return PTR_ERR(msg_arg); + + msg_arg->cmd =3D OPTEE_MSG_CMD_LEND_PROTMEM; + msg_arg->params[0].attr =3D OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; + msg_arg->params[0].u.value.a =3D use_case; + msg_arg->params[1].attr =3D OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; + msg_arg->params[1].u.tmem.buf_ptr =3D protmem->paddr; + msg_arg->params[1].u.tmem.size =3D protmem->size; + msg_arg->params[1].u.tmem.shm_ref =3D (u_long)protmem; + + rc =3D optee->ops->do_call_with_arg(optee->ctx, shm, offs, false); + if (rc) + goto out; + if (msg_arg->ret !=3D TEEC_SUCCESS) { + rc =3D -EINVAL; + goto out; + } + protmem->sec_world_id =3D (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 =3D optee_get_msg_arg(optee->ctx, 1, &entry, &shm, &offs); + if (IS_ERR(msg_arg)) + return PTR_ERR(msg_arg); + + msg_arg->cmd =3D OPTEE_MSG_CMD_RECLAIM_PROTMEM; + msg_arg->params[0].attr =3D OPTEE_MSG_ATTR_TYPE_RMEM_INPUT; + msg_arg->params[0].u.rmem.shm_ref =3D (u_long)protmem; + + rc =3D optee->ops->do_call_with_arg(optee->ctx, shm, offs, false); + if (rc) + goto out; + if (msg_arg->ret !=3D TEEC_SUCCESS) + rc =3D -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 =3D { .do_call_with_arg =3D optee_smc_do_call_with_arg, .to_msg_param =3D optee_to_msg_param, .from_msg_param =3D optee_from_msg_param, + .lend_protmem =3D optee_smc_lend_protmem, + .reclaim_protmem =3D optee_smc_reclaim_protmem, }; =20 static int enable_async_notif(optee_invoke_fn *invoke_fn) @@ -1627,14 +1693,20 @@ static struct tee_protmem_pool *static_protmem_pool= _init(struct optee *optee) =20 static int optee_protmem_pool_init(struct optee *optee) { + bool protm =3D optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_PROTMEM; + bool dyn_protm =3D optee->smc.sec_caps & + OPTEE_SMC_SEC_CAP_DYNAMIC_PROTMEM; enum tee_dma_heap_id heap_id =3D TEE_DMA_HEAP_SECURE_VIDEO_PLAY; struct tee_protmem_pool *pool =3D ERR_PTR(-EINVAL); - int rc; + int rc =3D -EINVAL; =20 - if (!(optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_PROTMEM)) + if (!protm && !dyn_protm) return 0; =20 - pool =3D static_protmem_pool_init(optee); + if (protm) + pool =3D static_protmem_pool_init(optee); + if (dyn_protm && IS_ERR(pool)) + pool =3D optee_protmem_alloc_dyn_pool(optee, heap_id); if (IS_ERR(pool)) return PTR_ERR(pool); =20 --=20 2.43.0