From nobody Fri Sep 25 12:38:50 2026 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DAD87426D0A for ; Sat, 12 Sep 2026 10:15:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789208133; cv=none; b=bdrI0RBwSrqVkuXDl4akLWfLoLWgBnvcOOUVGd+DcM/hN9X37BOI4UUzTYfgSE7rWHXMMxoAV9MFDKlS8or5G2kvppNwrEuHQO/Zpxek2zaKJyQ/3V2hFelxLSdk2zJUsdWXkg8ZmmMlkbA1JwTrIEQZX63hbp8GYtWAKLvjC3o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789208133; c=relaxed/simple; bh=Qb7t3LD0tQpSkGNku35odIorRGrTh4kf86HfWCxatzs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=XsoOonvihGzMmEMpkqf8ckchGdiGa/LeokilaU3lTipVelfbqn75mUdW/eLQtSq90bq7kybEzM00Rgah+k/muGdaut7gdtfIRjL6yUgOwys29oSVH0G+UHpjAcXkOCfXqvDcly7zs36OJqlxrIyAIEUuYV0reN+96g5K94X6BhU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=WC9Foc0a; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=U63MrLXG; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="WC9Foc0a"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="U63MrLXG" Received: from pps.filterd (m0279868.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 68C85AHB2342823 for ; Sat, 12 Sep 2026 10:15:30 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= 7+Ef6q3Hgytc9hPBKFwx3x7VTNrMji0EsP21MgBetjs=; b=WC9Foc0aCPnEQfZk vsXYrgiqZT9V3ANGgqzv4P8VdkGTr/fwAEAqnKAcJ0CXQUroEhN24VZJSX1XqtH2 duQUSmLUurY+9gCPGkIPcGjti0I8NoXq70V427Qi1MdOASbpQMU15vgki7bd22yO Dpkgh1xDMA6et+J7mqcaKPYpAFFGp+8LpAgxiqIlA1P/T1XegTHn3o1/EpMaV3Gy MmU9uRh+FfHO0ee7yJTVxYytQwX2Qf7irAT8Ncvo8b0/pAfdRwPgEx3Fy+vkghu2 o2xOnh+5/GQt/QBPnpUcouU5gnux8mmFyR+iatkQdKm3UUWcLMI32hY/BdJjMm2V Ad6dkA== Received: from mail-pj1-f71.google.com (mail-pj1-f71.google.com [209.85.216.71]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4gmy9d8p65-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Sat, 12 Sep 2026 10:15:30 +0000 (GMT) Received: by mail-pj1-f71.google.com with SMTP id 98e67ed59e1d1-38dbf293831so3644483a91.3 for ; Sat, 12 Sep 2026 03:15:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1789208129; x=1789812929; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=7+Ef6q3Hgytc9hPBKFwx3x7VTNrMji0EsP21MgBetjs=; b=U63MrLXGQ/CC/Dj9LHIzHXLuUREPMWuBOPqI+3ZhSNjG1npoKkiku2iFHFGvo4wxKg PdQ+hZPR2VslSmXe9brkQOr70RhL0cl3ajWDayIgC5Qb/3XMl6DyKPOroSJtaoO5eDbZ 0ML9gKbsGAMFPaDOGbB/zlCjKSpjLVrqe4uGiGg2MVbnyhbqwyfyw8noxGbLPkiNDkru /Q29CwHQdWev0VY53GHfENmpFJb0Eki04twYb6d3CvS+WA+avoz17lJr0C4dtq0jRTMa gajxUgoqdj7WuQzhkRH5xM1JvbNTwL6A45I5pE/MSCISphBxDPWh7Lme8rhQ+PwP1JYO zf2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789208129; x=1789812929; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=7+Ef6q3Hgytc9hPBKFwx3x7VTNrMji0EsP21MgBetjs=; b=AeUpwlrDM2YVTfptihI5U1SE8n9DDMuUDLYq15WcqOKA8tyoLjGPGn9mFI/aGW+rA7 9/5CA26E1UkRJ3oH1OWBsf1e7LjyxIO5wQQGfgS98ntHTWjkm37ALkSsbHkqaFKnzyE4 jyU/QHMNBLCXt0jwEdl7WpHbTB+7N3zGXpduyQxGqThbx6kCOOlyTMYupk6oBa/LGShD JJWjXtxhVphb8An7FAuwmv6Utf6ts0QH6uryPl4oRnRZVnPy0VmW+Qe31AabAcA0SglS zmHyXK2Zu78kX8hS9SVhnURo2yyf9AiZ37ehnXYzqKeq3pl0TMxk8yUTASnw3AcoSWcI Q3Bw== X-Forwarded-Encrypted: i=1; AKwUvBw1wrzlvLmNSU5H6Z0iiHh+YssHkxndLG7DdFHlhdQSVFHDUvsAlwBd2lt7HsBONg0V895C3xTm9Eof3+o=@vger.kernel.org X-Gm-Message-State: AFuF++mj9AA9agsmSRfj7qc0DSrjQajF2FO7HH5lpCGxA49MYhZOZNOk Zth+Qma4785eC1ppPOY7Us128w5G/Ud+P32u/fg+bwvALlIFlEwd+gBk3VSNxr62K7xnoLPfs0N 0M7J0z/XT1wewUF3LcikLTdShgwhgIB3Oi3bKwwwNZP/zTvvpKzxqX/xKRrDkeWjhmw== X-Gm-Gg: AYBFou0644d7INpWDFLUCZ44B9PiswzbwDghMYW8c3DK4zkYBv+w4U1RjPxjGjQVWOY zarf1ijBLbpg2WRcKo4/iDDh4XOnMJihbMmEWP2RNkxIAj9ldoP39l6WZvbL8fzZXFiQ/F6uI1p u4tf2KEpzaeaz3aax2ZLNfkw3YE5SMMuBU3ExbA3bVp6fmyKqWBsRwkGjqwXHQkfKKEhFm8yfwW IWJS+akrTZd+0JXvZllm5HEjWIvCWygyl7Py+iQTDITBJuCcgQiPdVBu7MwycYwYgUenU87LyLa MrUuQeLDoSAD+AP3KU93VpS+rAS+oP5n09NPf4E6jPALrUFePzbLKGdvy8CbWiz5ZzGW9he+A9Y o3wxYzqxu+m24mDsQNHEW4OMfMVlE+GFqVNcsj3ScHW29MGeK1oZ+/euAOuQ= X-Received: by 2002:a17:90b:586f:b0:39b:66ee:a14 with SMTP id 98e67ed59e1d1-39d9c374d49mr12976389a91.25.1789208129233; Sat, 12 Sep 2026 03:15:29 -0700 (PDT) X-Received: by 2002:a17:90b:586f:b0:39b:66ee:a14 with SMTP id 98e67ed59e1d1-39d9c374d49mr12976328a91.25.1789208128638; Sat, 12 Sep 2026 03:15:28 -0700 (PDT) Received: from hu-azarrabi-lv.qualcomm.com (Global_NAT1.qualcomm.com. [129.46.96.20]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-33baf0ea9a1sm10340085eec.8.2026.09.12.03.15.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Sep 2026 03:15:28 -0700 (PDT) From: Amirreza Zarrabi Date: Sat, 12 Sep 2026 03:15:12 -0700 Subject: [PATCH RFC 1/5] optee: riscv: add RPMI TEE service group transport Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260912-rpmi-tee-service-grp-dev-v1-1-1d1d35c2a859@oss.qualcomm.com> References: <20260912-rpmi-tee-service-grp-dev-v1-0-1d1d35c2a859@oss.qualcomm.com> In-Reply-To: <20260912-rpmi-tee-service-grp-dev-v1-0-1d1d35c2a859@oss.qualcomm.com> To: Jens Wiklander , Sumit Garg , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Rahul Pathak , Anup Patel , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, op-tee@lists.trustedfirmware.org, linux-riscv@lists.infradead.org, devicetree@vger.kernel.org, Amirreza Zarrabi X-Mailer: b4 0.13.0 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTEyMDE0NiBTYWx0ZWRfX0oegBLbdpah/ 1P3e25bM+emUgg2Ure6e5zV/B4Cc5MaXmrNSwp878i37vD4k/bTHpIXRcszz1pp2u6onhCxDlQH Zqr/WAxTYtHCDBAsSshRNiiepcpDq/tqu0a9VFuamiZl2Eqf3qMak73r+zTyPi18yI89NmkyBHz pT3ztHQaUaRTVtPO7GzfabYidCpE61qRHQU5vewYm2BZXR6vcXl9gicAZTqlNOQm07FQMyAZ5cd FQiTMRw+NZqitq600DINbdllw4bP+MnIb3EBmWHksf3FIU6hBfhNcq3hZqX2x6N/mvbRTf7m5fP iIMvLv9CU9s0EVncFHE21dDXGeeJhSFFpiqBvdZjDutploebLytZSN9JBXWnB71+g9d5lCYL2kP 71iChveAS3etrPHaRmi+C5ms2amDbg9ujNpwHpkmPVfIZrlkejHzAo5mSkgjIb1dpa9VRn3Bhyv RM+oS3zElUDg1KouL7w== X-Proofpoint-Spam-Info: AW1haW4tMjYwOTEyMDE0NiBTYWx0ZWRfX5hxSkMQsRsz5 8tOrKlGiF8ynigtUE5Zedg1RsOzsz4/g7UDmgoJgHjmfzunlr07jITJW7HI9qjp9mnYeBDnEyrw cUzWh28v9WrPyaju0r3sd4ntFXe4/cs= X-Proofpoint-GUID: Mhi2IyyAFUoiL1fyIf2Nc9B9daVpEVTW X-Authority-Analysis: v=2.4 cv=OeUNnRTY c=1 sm=1 tr=0 ts=6aa52642 cx=c_pps a=UNFcQwm+pnOIJct1K4W+Mw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17 a=IkcTkHD0fZMA:10 a=VdqzKS8jKosA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=ZpdpYltYx_vBUK5n70dp:22 a=EUspDBNiAAAA:8 a=CzNDq5WWsTbfHUazBTgA:9 a=QEXdDO2ut3YA:10 a=uKXjsCUrEbL0IQVhDsJ9:22 X-Proofpoint-ORIG-GUID: Mhi2IyyAFUoiL1fyIf2Nc9B9daVpEVTW X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-09-12_03,2026-09-11_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 malwarescore=0 phishscore=0 bulkscore=0 spamscore=0 priorityscore=1501 suspectscore=0 impostorscore=0 adultscore=0 clxscore=1011 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2609040000 definitions=main-2609120146 Add an OP-TEE transport for RISC-V using the RPMI TEE service group over the SBI MPXY mailbox framework. Request one mailbox channel per hart and use the channel corresponding to the current CPU when issuing a TEE request. Probe the RPMI TEE service group and required memory-sharing capabilities before registering the transport. This provides the basic transport and discovery support needed by the following patches. Signed-off-by: Amirreza Zarrabi --- drivers/tee/optee/Makefile | 1 + drivers/tee/optee/core.c | 8 +- drivers/tee/optee/optee_private.h | 34 ++++ drivers/tee/optee/optee_riscv.c | 312 +++++++++++++++++++++++++= ++++ drivers/tee/optee/optee_riscv.h | 141 +++++++++++++ include/linux/mailbox/riscv-rpmi-message.h | 1 + 6 files changed, 495 insertions(+), 2 deletions(-) diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile index ad7049c1c107..925b8ec7ef68 100644 --- a/drivers/tee/optee/Makefile +++ b/drivers/tee/optee/Makefile @@ -9,6 +9,7 @@ optee-objs +=3D supp.o optee-objs +=3D device.o optee-objs +=3D smc_abi.o optee-objs +=3D ffa_abi.o +optee-$(CONFIG_RISCV_SBI_MPXY_MBOX) +=3D optee_riscv.o =20 # for tracing framework to find optee_trace.h CFLAGS_smc_abi.o :=3D -I$(src) diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index a52c1f498b99..63f1725e646e 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -220,6 +220,7 @@ void optee_remove_common(struct optee *optee) =20 static int smc_abi_rc; static int ffa_abi_rc; +static int riscv_abi_rc; static bool intf_is_regged; =20 static int __init optee_core_init(void) @@ -245,9 +246,10 @@ static int __init optee_core_init(void) =20 smc_abi_rc =3D optee_smc_abi_register(); ffa_abi_rc =3D optee_ffa_abi_register(); + riscv_abi_rc =3D optee_riscv_abi_register(); =20 - /* If both failed there's no point with this module */ - if (smc_abi_rc && ffa_abi_rc) { + /* If all failed there's no point with this module */ + if (smc_abi_rc && ffa_abi_rc && riscv_abi_rc) { if (IS_REACHABLE(CONFIG_RPMB)) { rpmb_interface_unregister(&rpmb_class_intf); intf_is_regged =3D false; @@ -270,6 +272,8 @@ static void __exit optee_core_exit(void) optee_smc_abi_unregister(); if (!ffa_abi_rc) optee_ffa_abi_unregister(); + if (!riscv_abi_rc) + optee_riscv_abi_unregister(); } module_exit(optee_core_exit); =20 diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_pr= ivate.h index aefe1e6f5689..8d22d65e087b 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -171,6 +171,31 @@ struct optee_ffa { struct work_struct notif_work; }; =20 +/** + * struct optee_riscv - RPMI TEE communication struct + * @chan: per-hart RPMI TEE service group mailbox channels + * @client: RPMI mailbox client used to request @chan + * @dev: device backing the RPMI TEE mailbox client + * @nr_chan: number of entries in @chan + * @max_msg_data_size: maximum RPMI message data size of the TEE channel + * @mutex: serializes access to @global_ids + * @global_ids: memory parcel id to tee_shm translation table + * + * This is the RISC-V analog of struct optee_ffa: communication with secure + * world OP-TEE OS rides the RPMI TEE service group (RPMI spec section 4.1= 6) + * over the SBI MPXY mailbox instead of Arm FF-A. + */ +struct optee_riscv { + struct mbox_chan **chan; + struct mbox_client *client; + struct device *dev; + unsigned int nr_chan; + u32 max_msg_data_size; + /* Serializes access to @global_ids */ + struct mutex mutex; + struct rhashtable global_ids; +}; + struct optee; =20 /** @@ -231,6 +256,7 @@ struct optee_ops { * @ctx: driver internal TEE context * @smc: specific to SMC ABI * @ffa: specific to FF-A ABI + * @riscv: specific to RPMI TEE ABI * @shm_arg_cache: shared memory cache argument * @call_queue: queue of threads waiting to call @invoke_fn * @notif: notification synchronization struct @@ -259,6 +285,7 @@ struct optee { union { struct optee_smc smc; struct optee_ffa ffa; + struct optee_riscv riscv; }; struct optee_shm_arg_cache shm_arg_cache; struct optee_call_queue call_queue; @@ -426,5 +453,12 @@ int optee_smc_abi_register(void); void optee_smc_abi_unregister(void); int optee_ffa_abi_register(void); void optee_ffa_abi_unregister(void); +#ifdef CONFIG_RISCV_SBI_MPXY_MBOX +int optee_riscv_abi_register(void); +void optee_riscv_abi_unregister(void); +#else +static inline int optee_riscv_abi_register(void) { return -EOPNOTSUPP; } +static inline void optee_riscv_abi_unregister(void) { } +#endif =20 #endif /*OPTEE_PRIVATE_H*/ diff --git a/drivers/tee/optee/optee_riscv.c b/drivers/tee/optee/optee_risc= v.c new file mode 100644 index 000000000000..0fe4edf92fc9 --- /dev/null +++ b/drivers/tee/optee/optee_riscv.c @@ -0,0 +1,312 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * This file implements the ABI used when communicating with secure world + * OP-TEE OS over the RPMI TEE service group (RPMI spec section 4.16). It = is + * the RISC-V analog of ffa_abi.c: OP-TEE and Linux are peer endpoints of = the + * RPMI framework (OpenSBI), and shared memory follows the FF-A memory-don= ation + * model through the RPMI memory parcel services. + * + * This file is divided into the following sections: + * 1. Low level RPMI TEE service group transport over the SBI MPXY mailbox + * 2. Feature discovery and notification handshake + * 3. Driver initialization + * + * The remaining FF-A-equivalent sections (parcel id hash table, tee_param + * marshalling, dynamic shared memory pool and the scheduled call into sec= ure + * world) are added on top of this transport layer. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "optee_private.h" +#include "optee_riscv.h" + +/* + * 1. Low level RPMI TEE service group transport over the SBI MPXY mailbox + * + * The RPMI TEE service group is reached through the SBI MPXY mailbox. Each + * hart owns a dedicated MPXY channel so that a call issued on a given har= t is + * serviced by the OP-TEE context bound to it; optee_riscv_send() therefore + * selects the channel of the running hart. All RPMI messages are exchanged + * synchronously with rpmi_mbox_send_message(). + */ + +static int optee_riscv_send(struct optee *optee, struct rpmi_mbox_message = *msg) +{ + int cpu, ret; + + cpu =3D get_cpu(); + if (cpu >=3D optee->riscv.nr_chan || !optee->riscv.chan[cpu]) { + put_cpu(); + return -ENODEV; + } + ret =3D rpmi_mbox_send_message(optee->riscv.chan[cpu], msg); + put_cpu(); + + return ret; +} + +/* + * 2. Feature discovery and notification handshake + * + * TEE_PROBE_FEATURES (0x02) reports which framework features are availabl= e; + * TEE_ENABLE_NOTIFICATION (0x01) subscribes to TEE service group events. = Both + * are mandatory services (RPMI spec section 4.16), so probing them also + * confirms that the framework speaks the TEE service group on this channe= l. + */ + +static int optee_riscv_probe_feature(struct optee *optee, u32 feature_id, + u32 *value) +{ + struct rpmi_tee_probe_features_req tx =3D { + .feature_id =3D cpu_to_le32(feature_id), + }; + struct rpmi_tee_probe_features_resp rx =3D { }; + struct rpmi_mbox_message msg; + int ret; + + rpmi_mbox_init_send_with_response(&msg, RPMI_TEE_SRV_PROBE_FEATURES, + &tx, sizeof(tx), &rx, sizeof(rx)); + ret =3D optee_riscv_send(optee, &msg); + if (ret) + return ret; + if (rx.status) + return rpmi_to_linux_error(le32_to_cpu(rx.status)); + + if (value) + *value =3D le32_to_cpu(rx.value); + + return 0; +} + +static int optee_riscv_features(struct optee *optee) +{ + u32 share =3D RPMI_TEE_MEMORY_SHARE_NONE; + int ret; + + /* + * Memory parcels carry normal-world shared memory to OP-TEE, so the + * framework must support sharing memory between the REE and a TEE. + */ + ret =3D optee_riscv_probe_feature(optee, RPMI_TEE_FEAT_MEMORY_SHARE, + &share); + if (ret) { + pr_err("Failed to probe MEMORY_SHARE feature: %d\n", ret); + return ret; + } + if (share !=3D RPMI_TEE_MEMORY_SHARE_FULL) { + pr_err("Framework cannot share memory between REE and TEE (%u)\n", + share); + return -EOPNOTSUPP; + } + + return 0; +} + +static int optee_riscv_enable_notif(struct optee *optee) +{ + struct rpmi_tee_probe_features_resp rx =3D { }; + struct rpmi_mbox_message msg; + int ret; + + rpmi_mbox_init_send_with_response(&msg, RPMI_TEE_SRV_ENABLE_NOTIFICATION, + NULL, 0, &rx, sizeof(rx)); + ret =3D optee_riscv_send(optee, &msg); + if (ret) + return ret; + + /* + * The TEE service group defines no notification events on this + * platform, so RPMI_ERR_NOTSUPP is expected and not fatal. + */ + if (rx.status && le32_to_cpu(rx.status) !=3D (u32)RPMI_ERR_NOTSUPP) + return rpmi_to_linux_error(le32_to_cpu(rx.status)); + + return 0; +} + +/* + * 3. Driver initialization + * + * The RPMI TEE service group is described in the device tree by a single + * node whose "mboxes" property lists one SBI MPXY channel per hart, in ha= rt + * order. The driver requests each list entry by index and validates the + * transport before building the OP-TEE device. + */ + +static int optee_riscv_request_channels(struct optee *optee) +{ + struct device *dev =3D optee->riscv.dev; + int nr_mboxes; + unsigned int cpuid; + + nr_mboxes =3D of_count_phandle_with_args(dev->of_node, "mboxes", + "#mbox-cells"); + if (nr_mboxes !=3D optee->riscv.nr_chan) + return dev_err_probe(dev, -EINVAL, + "Expected %u mailbox channels, got %d\n", + optee->riscv.nr_chan, nr_mboxes); + + for (cpuid =3D 0; cpuid < optee->riscv.nr_chan; cpuid++) { + optee->riscv.chan[cpuid] =3D + mbox_request_channel(optee->riscv.client, cpuid); + if (IS_ERR(optee->riscv.chan[cpuid])) { + int ret =3D PTR_ERR(optee->riscv.chan[cpuid]); + + optee->riscv.chan[cpuid] =3D NULL; + return dev_err_probe(dev, ret, + "Failed to request channel %u\n", + cpuid); + } + } + + return 0; +} + +static void optee_riscv_free_channels(struct optee *optee) +{ + unsigned int i; + + for (i =3D 0; i < optee->riscv.nr_chan; i++) { + if (optee->riscv.chan[i]) + mbox_free_channel(optee->riscv.chan[i]); + } +} + +static int optee_riscv_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct rpmi_mbox_message msg; + struct mbox_client *client; + struct optee *optee; + u32 servicegroup_id; + unsigned int nr_cpus; + int ret; + + nr_cpus =3D num_possible_cpus(); + if (!nr_cpus) + return dev_err_probe(dev, -ENODEV, "No harts found\n"); + + optee =3D kzalloc_obj(*optee); + if (!optee) + return -ENOMEM; + + client =3D devm_kzalloc(dev, sizeof(*client), GFP_KERNEL); + if (!client) { + ret =3D -ENOMEM; + goto err_free_optee; + } + client->dev =3D dev; + client->rx_callback =3D NULL; + client->tx_block =3D false; + client->knows_txdone =3D true; + client->tx_tout =3D 0; + + optee->riscv.dev =3D dev; + optee->riscv.client =3D client; + optee->riscv.nr_chan =3D nr_cpus; + optee->riscv.chan =3D kcalloc(nr_cpus, sizeof(*optee->riscv.chan), + GFP_KERNEL); + if (!optee->riscv.chan) { + ret =3D -ENOMEM; + goto err_free_optee; + } + + ret =3D optee_riscv_request_channels(optee); + if (ret) + goto err_free_channels; + + /* Confirm the channel really speaks the TEE service group. */ + rpmi_mbox_init_get_attribute(&msg, RPMI_MBOX_ATTR_SERVICEGROUP_ID); + ret =3D optee_riscv_send(optee, &msg); + if (ret) { + dev_err_probe(dev, ret, "Failed to get service group id\n"); + goto err_free_channels; + } + servicegroup_id =3D msg.attr.value; + if (servicegroup_id !=3D RPMI_SRVGRP_TEE) { + ret =3D -ENODEV; + dev_err_probe(dev, ret, "Not a TEE service group channel (0x%x)\n", + servicegroup_id); + goto err_free_channels; + } + + rpmi_mbox_init_get_attribute(&msg, RPMI_MBOX_ATTR_MAX_MSG_DATA_SIZE); + ret =3D optee_riscv_send(optee, &msg); + if (ret) { + dev_err_probe(dev, ret, "Failed to get max msg data size\n"); + goto err_free_channels; + } + optee->riscv.max_msg_data_size =3D msg.attr.value; + + ret =3D optee_riscv_features(optee); + if (ret) { + dev_err_probe(dev, ret, "Missing required TEE features\n"); + goto err_free_channels; + } + + ret =3D optee_riscv_enable_notif(optee); + if (ret) { + dev_err_probe(dev, ret, "Failed to enable notifications\n"); + goto err_free_channels; + } + + platform_set_drvdata(pdev, optee); + dev_info(dev, "initialized driver\n"); + + return 0; + +err_free_channels: + optee_riscv_free_channels(optee); + kfree(optee->riscv.chan); +err_free_optee: + kfree(optee); + return ret; +} + +static void optee_riscv_remove(struct platform_device *pdev) +{ + struct optee *optee =3D platform_get_drvdata(pdev); + + optee_riscv_free_channels(optee); + kfree(optee->riscv.chan); + kfree(optee); +} + +static const struct of_device_id optee_riscv_match[] =3D { + { .compatible =3D "riscv,rpmi-mpxy-tee" }, + { } +}; +MODULE_DEVICE_TABLE(of, optee_riscv_match); + +static struct platform_driver optee_riscv_driver =3D { + .driver =3D { + .name =3D DRIVER_NAME "-riscv", + .of_match_table =3D optee_riscv_match, + }, + .probe =3D optee_riscv_probe, + .remove =3D optee_riscv_remove, +}; + +int optee_riscv_abi_register(void) +{ + return platform_driver_register(&optee_riscv_driver); +} + +void optee_riscv_abi_unregister(void) +{ + platform_driver_unregister(&optee_riscv_driver); +} diff --git a/drivers/tee/optee/optee_riscv.h b/drivers/tee/optee/optee_risc= v.h new file mode 100644 index 000000000000..d87298faa6a2 --- /dev/null +++ b/drivers/tee/optee/optee_riscv.h @@ -0,0 +1,141 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/* + * This file is exported by OP-TEE and is kept in sync between secure world + * and normal world drivers. It describes the wire contract used when + * communicating with secure world OP-TEE OS over the RPMI TEE service gro= up + * (RPMI specification section 4.16, SERVICEGROUP_ID 0x0010). + * + * The RPMI TEE service group is the RISC-V analog of Arm FF-A: OP-TEE and= the + * rich execution environment (REE, i.e. Linux) are peer endpoints, and the + * RPMI framework (OpenSBI in M-mode) mediates every message. Memory shari= ng + * follows the FF-A memory-donation model through the memory parcel servic= es: + * the REE creates a parcel describing its pages, OP-TEE accepts it lazily= by + * parcel id, and teardown is two phased (OP-TEE releases, the REE reclaim= s). + * + * All request and response payloads are little-endian uint32 words as def= ined + * by the RPMI specification. These definitions MUST byte-match the OpenSBI + * framework definitions in . + */ + +#ifndef __OPTEE_RISCV_H +#define __OPTEE_RISCV_H + +#include +#include + +/* + * RPMI TEE service ids (RPMI spec section 4.16, Table 181). + * + * Only TEE_ENABLE_NOTIFICATION, TEE_PROBE_FEATURES and TEE_CALL are manda= ted; + * the remaining services are optional and may return RPMI_ERR_NOTSUPP. + */ +enum rpmi_tee_service_id { + RPMI_TEE_SRV_ENABLE_NOTIFICATION =3D 0x01, + RPMI_TEE_SRV_PROBE_FEATURES =3D 0x02, + RPMI_TEE_SRV_PROBE_SYSTEM =3D 0x03, + RPMI_TEE_SRV_EXIT =3D 0x04, + RPMI_TEE_SRV_SIGNAL_BUS_SETUP =3D 0x05, + RPMI_TEE_SRV_SIGNAL_BUS_TEARDOWN =3D 0x06, + RPMI_TEE_SRV_SIGNAL_RAISE =3D 0x07, + RPMI_TEE_SRV_SIGNAL_RETRIEVE =3D 0x08, + RPMI_TEE_SRV_MEM_PARCEL_CREATE =3D 0x09, + RPMI_TEE_SRV_MEM_PARCEL_ACCEPT =3D 0x0a, + RPMI_TEE_SRV_MEM_PARCEL_RELEASE =3D 0x0b, + RPMI_TEE_SRV_MEM_PARCEL_RECLAIM =3D 0x0c, + RPMI_TEE_SRV_MEM_PARCEL_SEGMENT_SEND =3D 0x0d, + RPMI_TEE_SRV_MEM_PARCEL_SEGMENT_RECEIVE =3D 0x0e, + RPMI_TEE_SRV_CALL =3D 0x13, + RPMI_TEE_SRV_MAX_COUNT, +}; + +/* + * RPMI TEE endpoint identities. + * + * The RPMI specification does not fix numeric endpoint ids; they are assi= gned + * by the framework at runtime. These values match the OpenSBI framework + * assignment used on this platform: the REE is endpoint 0 and OP-TEE is + * endpoint 1. + */ +#define RPMI_TEE_ENDPOINT_REE 0 +#define RPMI_TEE_ENDPOINT_OPTEE 1 + +/* + * RPMI TEE feature ids for TEE_PROBE_FEATURES (RPMI spec section 4.16.4, + * Table 182). + */ +enum rpmi_tee_feature_id { + RPMI_TEE_FEAT_MEMORY_DONATE =3D 1, + RPMI_TEE_FEAT_MEMORY_LEND =3D 2, + RPMI_TEE_FEAT_MEMORY_SHARE =3D 3, + RPMI_TEE_FEAT_SIGNAL_BUS =3D 4, + RPMI_TEE_FEAT_MULTISEGMENT_OPS =3D 5, + RPMI_TEE_FEAT_SYSINFO_FORMAT =3D 6, +}; + +/* MEMORY_SHARE feature values (RPMI spec Table 182). */ +#define RPMI_TEE_MEMORY_SHARE_NONE 0 +#define RPMI_TEE_MEMORY_SHARE_TEE_ONLY 1 +#define RPMI_TEE_MEMORY_SHARE_FULL 2 + +/* TEE_PROBE_FEATURES request (Table 183) / response (Table 184). */ +struct rpmi_tee_probe_features_req { + __le32 feature_id; +}; + +struct rpmi_tee_probe_features_resp { + __le32 status; + __le32 value; +}; + +/* + * TEE_CALL wire encoding (RPMI spec section 4.16.21, Tables 218 and 219). + * + * TEE_CALL is the mandatory doorbell service used to enter OP-TEE. The + * request carries a fixed REE->OP-TEE identity, the well-known OP-TEE ser= vice + * UUID and a SERVICE_DATA payload; the response carries a STATUS word, a + * SERVICE_RSP_LEN word and the SERVICE_RSP payload. + * + * The SERVICE_DATA/SERVICE_RSP registers are XLEN-sized little-endian val= ues. + * The structures are __packed so the 16-byte UUID does not force padding + * before the length word. + */ +#define RPMI_TEE_UUID_LEN 16 + +/* OP-TEE communicate service UUID: 5be1b1a0-7e11-4e7a-9b10-0010c0ffee00 */ +#define RPMI_TEE_OPTEE_UUID \ + { 0x5b, 0xe1, 0xb1, 0xa0, 0x7e, 0x11, 0x4e, 0x7a, \ + 0x9b, 0x10, 0x00, 0x10, 0xc0, 0xff, 0xee, 0x00 } + +/* OP-TEE SMC-style call convention carried inside SERVICE_DATA. */ +#define RPMI_TEE_OPTEE_CALL_REGS 8 /* a0-a7 */ +#define RPMI_TEE_OPTEE_RESP_REGS 4 /* a0-a3 */ + +#if __riscv_xlen =3D=3D 64 +typedef __le64 rpmi_xlen_t; +#define cpu_to_rpmi_xlen(x) cpu_to_le64(x) +#define rpmi_xlen_to_cpu(x) le64_to_cpu(x) +#else +typedef __le32 rpmi_xlen_t; +#define cpu_to_rpmi_xlen(x) cpu_to_le32(x) +#define rpmi_xlen_to_cpu(x) le32_to_cpu(x) +#endif + +struct rpmi_tee_call_req { + __le32 sender_id; + __le32 target_id; + u8 service[RPMI_TEE_UUID_LEN]; + __le32 service_data_len; + rpmi_xlen_t reg[RPMI_TEE_OPTEE_CALL_REGS]; +} __packed; + +struct rpmi_tee_call_resp { + __le32 status; + __le32 service_rsp_len; + rpmi_xlen_t reg[RPMI_TEE_OPTEE_RESP_REGS]; +} __packed; + +#endif /* __OPTEE_RISCV_H */ diff --git a/include/linux/mailbox/riscv-rpmi-message.h b/include/linux/mai= lbox/riscv-rpmi-message.h index e135c6564d0c..47a540bd81c9 100644 --- a/include/linux/mailbox/riscv-rpmi-message.h +++ b/include/linux/mailbox/riscv-rpmi-message.h @@ -93,6 +93,7 @@ static inline int rpmi_to_linux_error(int rpmi_error) /* RPMI service group IDs */ #define RPMI_SRVGRP_SYSTEM_MSI 0x00002 #define RPMI_SRVGRP_CLOCK 0x00008 +#define RPMI_SRVGRP_TEE 0x00010 =20 /* RPMI clock service IDs */ enum rpmi_clock_service_id { --=20 2.34.1 From nobody Fri Sep 25 12:38:50 2026 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 17510427F89 for ; Sat, 12 Sep 2026 10:15:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789208138; cv=none; b=fySEE79FlglW592q8MCqmg2124Lcw/SnYI09f+mUlAJUWSYu6a8+KZkaaM/hgQzOIgd2+9bRL776meOc5YVIhvSKcAxofm10S6Y98rrgy1F4vAD/HNZmcDXAAONr4OqYpM4Uju5w8qPXzCTWHJNj9w4QGzR29w7okjJDSTfWIAs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789208138; c=relaxed/simple; bh=sARL4dPYRxMvYgVNSvQfNt3Ga3Sr9irnvb13sM7/k0g=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mPdTxkMNUz/k09orcaz8U0w6Xz1xZ0PiGrBUftv/5Y589JodsaL26+XehqJwH6vLvwrAgtSvOjp2fl7aVJ+Fn9AmGCazbXNLnkQWUkMMJwAhB2AgCYgXpK3a+1hHusZR1ArSvJsQtHV5hogOBsXptb8tpETesx+X5dpXrOcqHcs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=KfP1Qt8y; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=NSAv61xP; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="KfP1Qt8y"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="NSAv61xP" Received: from pps.filterd (m0279871.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 68C85I8S3019892 for ; Sat, 12 Sep 2026 10:15:33 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= d6UoxbSLyrBSPbqba+6zSoUWkcciKGuJ9cbgG2XM+Ss=; b=KfP1Qt8yIKzZyFz+ d1Gx7hXLTWBKY2E4o8uOqYzhoqMlAxWBgNzY12p3HrEoyJ8rhUYj1nZH823cwkV9 pYgMQZECdOt5Vxp4rb0+IUaQA2gYMQKo5WiNIkjx670hQcl6W2tMXFl0upTHeKML OOMMNRGbrnoFrYdLKh5AcS7QjbgFybXgOpO40JsP0o16HrBwcSzEwIbT3WhZlhIy oy3OXBFwSaRlPCwidNUnH4KGyiyLpD+Qf1kDM3yTgTUh0mqIafqhK7IfKwICfZGP lM57Gxz7dUMODdXa3BuqHai2roUCW+YDuTGuYJgfjOPRDZIbB0WJ+R1ejO0Und2Y QKdhuQ== Received: from mail-pj1-f71.google.com (mail-pj1-f71.google.com [209.85.216.71]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4gmy9dgp8e-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Sat, 12 Sep 2026 10:15:32 +0000 (GMT) Received: by mail-pj1-f71.google.com with SMTP id 98e67ed59e1d1-39dc5d85a9cso100628a91.2 for ; Sat, 12 Sep 2026 03:15:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1789208131; x=1789812931; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=d6UoxbSLyrBSPbqba+6zSoUWkcciKGuJ9cbgG2XM+Ss=; b=NSAv61xPvZT5Td2HTb8Y9y+t0TCHLP7d8+uj6gHlxvY5tzxMhYInlyT8xLHLC/67ca GZ2tdySOoHRiIhOifiZ1Qw3B/ut4zhEhh4Iuf+bnn/q3wXT+HnM0tMjTK5QdSelxWnSw nixhkdnfgJ40k8C5xfvkVKRHJXrxFwNlzuP15I74yYVy6od8KkorRs9tnmfzLPiTcIOM FWAJxfslafebmwqQF/OB3nLDcLJz6HCWHAkk9eziT07AP1IWj90ulT+SARssaDoKWw39 RVLDFiNzmFW0wulgPJpaamBLeSi00sJNjCUBP66HB4geAe3RBy+T7gOwS1TK6dEgNd8t vwtQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789208131; x=1789812931; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=d6UoxbSLyrBSPbqba+6zSoUWkcciKGuJ9cbgG2XM+Ss=; b=DdggzoCkrYV2M6rkJSIiE/G4hdAA9NXSdjhwF8lLds2VRa3aY8C7ZrO0JYVjJuQwTW NuiiEmP2eBlfGFuWJF1lIEvGoLftnpaGa++RU5rGAG82c1khSpZMMc5/WXtZppA3Jecs Q8posAJ4Cqbl3L6QioyeyKbbRwLF5GeCxgFZf4niQy9RBBejuRo8NqNZIHf6jqWLV3AJ DWLnTlh/e8NNTvcjMauPB/LNl32Z4s8i13gXfzXD7Csz7aNe2Ksz4V9tn8NMrA9LDONP YZepmp0tSWcFA3prjgGO5KJUBBUnSqtfur0sYWHzNGRAKF7izjPVcY+Ehqn6jCcvHw6f wtYA== X-Forwarded-Encrypted: i=1; AKwUvBwXqcmYvVxd2u8HXp/uCtEuEIbDcWR0abDnZoZ744TVEsCcslSsqSbLag6f4kB6N+x4b+fdaGxZsEd2pDk=@vger.kernel.org X-Gm-Message-State: AFuF++lS3k8atQlBuwgrP3XRHDENqwOyyZqiET23H/sjf0EoDOKcirJU +wNuxSHKC10057j63/YzQfLZ7+l5+VscNvJM0+D2yMQcTUVmYupY2IVKTtMe7lBk1EhjYaLGALD RQGXEwJ0g7OVzDLFI9BuYgpFZIXLz3gVjOFrtMPP2gOeVTLiYfaW72oASqu7hh2trLw== X-Gm-Gg: AYBFou2Y9sASmIvg8BxuciAdSCO094bQhG32QhYUtuhZFgXI6mhUU1mEkk4dm+1CT06 OwxziMhuq7JG/+5GPrOOxeCDbfWIM5qUSz7z52ON6HKJzXO5IAj0b6XeSfTKKNlIJSzC/yO5OuC PmzkjCDqwam/GMhVPUXz7Y6eY0Lr/gYs9VyyuQDDvxMxizBEj2/1YEC2IkuGvFsYhgw2+b1Wa6u A/YHKfWyiFLn5/A26Gu9ZFCgopzgHNcUZ07ih2wNh6IYt+We3WbwsfOIaVCq7cFr1stYO14ifvH f3xOnN1AL5VExKHkfDb9rFJsRs9Zr3NL6dsbwDJZ6z5RqRxgmQTCTu8YZVPauVyc0Qrmts6W1qz /4Bk7VIoIjNtixhSA49PAo0RUK3R5Brm5bux4AwEzfSt8Vl9DpZYYKP7UKF4= X-Received: by 2002:a17:90b:5745:b0:398:c292:ac80 with SMTP id 98e67ed59e1d1-39d9bd685e6mr14334874a91.10.1789208130948; Sat, 12 Sep 2026 03:15:30 -0700 (PDT) X-Received: by 2002:a17:90b:5745:b0:398:c292:ac80 with SMTP id 98e67ed59e1d1-39d9bd685e6mr14334765a91.10.1789208130120; Sat, 12 Sep 2026 03:15:30 -0700 (PDT) Received: from hu-azarrabi-lv.qualcomm.com (Global_NAT1.qualcomm.com. [129.46.96.20]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-33baf0ea9a1sm10340085eec.8.2026.09.12.03.15.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Sep 2026 03:15:29 -0700 (PDT) From: Amirreza Zarrabi Date: Sat, 12 Sep 2026 03:15:13 -0700 Subject: [PATCH RFC 2/5] optee: riscv: add shared memory and scheduled calls Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260912-rpmi-tee-service-grp-dev-v1-2-1d1d35c2a859@oss.qualcomm.com> References: <20260912-rpmi-tee-service-grp-dev-v1-0-1d1d35c2a859@oss.qualcomm.com> In-Reply-To: <20260912-rpmi-tee-service-grp-dev-v1-0-1d1d35c2a859@oss.qualcomm.com> To: Jens Wiklander , Sumit Garg , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Rahul Pathak , Anup Patel , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, op-tee@lists.trustedfirmware.org, linux-riscv@lists.infradead.org, devicetree@vger.kernel.org, Amirreza Zarrabi X-Mailer: b4 0.13.0 X-Proofpoint-GUID: 8QkB9hKqPLJ0Nn3LfcUUHQVAFjKjPpBw X-Proofpoint-ORIG-GUID: 8QkB9hKqPLJ0Nn3LfcUUHQVAFjKjPpBw X-Authority-Analysis: v=2.4 cv=NelzRGD4 c=1 sm=1 tr=0 ts=6aa52644 cx=c_pps a=UNFcQwm+pnOIJct1K4W+Mw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17 a=IkcTkHD0fZMA:10 a=VdqzKS8jKosA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=3WHJM1ZQz_JShphwDgj5:22 a=EUspDBNiAAAA:8 a=xB-oHHMGf5EPZTKqN7QA:9 a=QEXdDO2ut3YA:10 a=uKXjsCUrEbL0IQVhDsJ9:22 X-Proofpoint-Spam-Info: AW1haW4tMjYwOTEyMDE0NiBTYWx0ZWRfX5vUAmx31yCGa +0madbpUlpEshCauZSTym6Zu7gdV8wsmFS8oLRmJHthRRksxOMdFBhzpUSYw1kkjWIW4yKjKabH 9y2u2mBTgFZIUbL5/VUpQTolxlv1eeg= X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTEyMDE0NiBTYWx0ZWRfX7Kaecj+5WuwM dMhkRV/fcv4ZiSj5bNo8ZfY3J62olHXWjJh8EHlLQ5pO8CVhTStdnTbXFZkZbvpa+PT3eAdmHli 1L/jsrjUmQi4sEn6E/6hSTehd7HTWs9h6e8SvOu5kXOSshxyXjbBlahu7FqhCWEDQHpRIl4zMeW pa2V+u37KaUxOUbSWEfcyHfn9wsTW7PAlMoMBs7LIFwOHWyfsmHXSBayEAZcFK6AwUqlEhV0hBK IzfTbJONG7l3UVOPkn4xmW/IY2VtwVRjPGvgdlUE1ff1Xi9smCFLAy1FXVa2CF06+/8Eke/QfpT 9SrSpOV4NaiAwpZ5SpstEuMxqgrzJNBOY/zvZqzcdTYDUaOErgbRSrpazqQ1uzH3p+Vg7YWSt5B qnlqITW1hOBAFrpAs1oUrlIjWHXPndNiPZ3mcyjTNihEyKOBWMKrL4X3kh6y+Gb3eJoG3UFnZms jJiECWMuh3nG6108Z7w== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-09-12_03,2026-09-11_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 adultscore=0 impostorscore=0 priorityscore=1501 clxscore=1011 spamscore=0 malwarescore=0 suspectscore=0 lowpriorityscore=0 phishscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2609040000 definitions=main-2609120146 Add the shared-memory and call support required by the RISC-V RPMI transport. Use RPMI memory parcels to share memory between Linux and OP-TEE and keep a mapping between parcel identifiers and struct tee_shm. Pass the parcel identifier and offset when referencing shared memory from OP-TEE message parameters. Implement scheduled calls using RPMI TEE_CALL, including yielding calls, RPC handling and shared-memory allocation. Also add OP-TEE version and capability negotiation and complete registration of the OP-TEE device. Signed-off-by: Amirreza Zarrabi --- drivers/tee/optee/optee_private.h | 2 + drivers/tee/optee/optee_riscv.c | 1198 +++++++++++++++++++++++++++++++++= +--- drivers/tee/optee/optee_riscv.h | 135 ++++- 3 files changed, 1257 insertions(+), 78 deletions(-) diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_pr= ivate.h index 8d22d65e087b..cf878b8178f9 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -178,6 +178,7 @@ struct optee_ffa { * @dev: device backing the RPMI TEE mailbox client * @nr_chan: number of entries in @chan * @max_msg_data_size: maximum RPMI message data size of the TEE channel + * @next_nonce: monotonic nonce source for memory parcel creation * @mutex: serializes access to @global_ids * @global_ids: memory parcel id to tee_shm translation table * @@ -191,6 +192,7 @@ struct optee_riscv { struct device *dev; unsigned int nr_chan; u32 max_msg_data_size; + atomic_t next_nonce; /* Serializes access to @global_ids */ struct mutex mutex; struct rhashtable global_ids; diff --git a/drivers/tee/optee/optee_riscv.c b/drivers/tee/optee/optee_risc= v.c index 0fe4edf92fc9..36115326486d 100644 --- a/drivers/tee/optee/optee_riscv.c +++ b/drivers/tee/optee/optee_riscv.c @@ -8,34 +8,46 @@ * RPMI framework (OpenSBI), and shared memory follows the FF-A memory-don= ation * model through the RPMI memory parcel services. * - * This file is divided into the following sections: - * 1. Low level RPMI TEE service group transport over the SBI MPXY mailbox - * 2. Feature discovery and notification handshake - * 3. Driver initialization + * This file is structured exactly like ffa_abi.c: + * 1. Maintain a hash table for lookup of a memory parcel id + * 2. Convert between struct tee_param and struct optee_msg_param + * 3. Low level support functions to register shared memory in secure world + * 4. Dynamic shared memory pool based on alloc_pages() + * 5. Do a normal scheduled call into secure world + * 6. Driver initialization * - * The remaining FF-A-equivalent sections (parcel id hash table, tee_param - * marshalling, dynamic shared memory pool and the scheduled call into sec= ure - * world) are added on top of this transport layer. + * Every FF-A memory operation has a direct RPMI TEE service group analog: + * FFA_MEM_SHARE -> MEM_PARCEL_CREATE (0x09), issued by the REE + * FFA_MEM_RECLAIM -> MEM_PARCEL_RECLAIM (0x0c), issued by the REE + * direct message -> TEE_CALL (0x13), the call doorbell + * and the FF-A g_handle is replaced by a memory parcel id folded together + * with a caller-supplied nonce. */ =20 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt =20 +#include #include #include #include +#include #include #include #include +#include +#include #include #include +#include #include #include =20 #include "optee_private.h" #include "optee_riscv.h" +#include "optee_rpc_cmd.h" =20 /* - * 1. Low level RPMI TEE service group transport over the SBI MPXY mailbox + * Low level RPMI TEE service group transport over the SBI MPXY mailbox. * * The RPMI TEE service group is reached through the SBI MPXY mailbox. Each * hart owns a dedicated MPXY channel so that a call issued on a given har= t is @@ -60,25 +72,43 @@ static int optee_riscv_send(struct optee *optee, struct= rpmi_mbox_message *msg) } =20 /* - * 2. Feature discovery and notification handshake + * optee_riscv_tee_call() - issue a TEE_CALL (RPMI service 0x13) + * @optee: main service struct + * @in: the command words carried in SERVICE_DATA, the RISC-V analog + * of struct ffa_send_direct_data's data0-data4 (w3-w7) + * @out: the response words returned in SERVICE_RSP, the RISC-V analog + * of the same data0-data4 set on the return path * - * TEE_PROBE_FEATURES (0x02) reports which framework features are availabl= e; - * TEE_ENABLE_NOTIFICATION (0x01) subscribes to TEE service group events. = Both - * are mandatory services (RPMI spec section 4.16), so probing them also - * confirms that the framework speaks the TEE service group on this channe= l. + * TEE_CALL is the RISC-V analog of the FF-A direct message: it is the sin= gle + * doorbell used both for the blocking (fast) calls of section 6 and for t= he + * yielding call of section 5. The struct optee_msg_arg itself is never + * carried here, only its parcel handle and offset, exactly as FF-A carries + * only w4-w6. + * + * Returns 0 on success or <0 on failure. */ - -static int optee_riscv_probe_feature(struct optee *optee, u32 feature_id, - u32 *value) +static int optee_riscv_tee_call(struct optee *optee, + const u64 in[RPMI_TEE_OPTEE_CALL_REGS], + u64 out[RPMI_TEE_OPTEE_RESP_REGS]) { - struct rpmi_tee_probe_features_req tx =3D { - .feature_id =3D cpu_to_le32(feature_id), + static const u8 optee_uuid[RPMI_TEE_UUID_LEN] =3D RPMI_TEE_OPTEE_UUID; + struct rpmi_tee_call_req tx =3D { + .sender_id =3D cpu_to_le32(RPMI_TEE_ENDPOINT_REE), + .target_id =3D cpu_to_le32(RPMI_TEE_ENDPOINT_OPTEE), + .service_data_len =3D + cpu_to_le32(RPMI_TEE_OPTEE_CALL_REGS * + sizeof(rpmi_xlen_t)), }; - struct rpmi_tee_probe_features_resp rx =3D { }; + struct rpmi_tee_call_resp rx =3D { }; struct rpmi_mbox_message msg; + unsigned int i; int ret; =20 - rpmi_mbox_init_send_with_response(&msg, RPMI_TEE_SRV_PROBE_FEATURES, + memcpy(tx.service, optee_uuid, sizeof(tx.service)); + for (i =3D 0; i < RPMI_TEE_OPTEE_CALL_REGS; i++) + tx.reg[i] =3D cpu_to_rpmi_xlen(in[i]); + + rpmi_mbox_init_send_with_response(&msg, RPMI_TEE_SRV_CALL, &tx, sizeof(tx), &rx, sizeof(rx)); ret =3D optee_riscv_send(optee, &msg); if (ret) @@ -86,61 +116,887 @@ static int optee_riscv_probe_feature(struct optee *op= tee, u32 feature_id, if (rx.status) return rpmi_to_linux_error(le32_to_cpu(rx.status)); =20 - if (value) - *value =3D le32_to_cpu(rx.value); + for (i =3D 0; i < RPMI_TEE_OPTEE_RESP_REGS; i++) + out[i] =3D rpmi_xlen_to_cpu(rx.reg[i]); =20 return 0; } =20 -static int optee_riscv_features(struct optee *optee) +/* + * 1. Maintain a hash table for lookup of a memory parcel id + * + * The RPMI framework assigns a memory parcel id for each piece of shared + * memory. Together with a caller-supplied nonce it forms the wire identity + * used when communicating with secure world, playing the exact role of the + * FF-A global memory handle. + * + * Main functions are optee_shm_add_riscv_handle() and + * optee_shm_rem_riscv_handle(). + */ +struct shm_rhash { + struct tee_shm *shm; + u64 global_id; + struct rhash_head linkage; +}; + +static void rh_free_fn(void *ptr, void *arg) { - u32 share =3D RPMI_TEE_MEMORY_SHARE_NONE; + kfree(ptr); +} + +static const struct rhashtable_params shm_rhash_params =3D { + .head_offset =3D offsetof(struct shm_rhash, linkage), + .key_len =3D sizeof(u64), + .key_offset =3D offsetof(struct shm_rhash, global_id), + .automatic_shrinking =3D true, +}; + +static struct tee_shm *optee_shm_from_riscv_handle(struct optee *optee, + u64 global_id) +{ + struct tee_shm *shm =3D NULL; + struct shm_rhash *r; + + mutex_lock(&optee->riscv.mutex); + r =3D rhashtable_lookup_fast(&optee->riscv.global_ids, &global_id, + shm_rhash_params); + if (r) + shm =3D r->shm; + mutex_unlock(&optee->riscv.mutex); + + return shm; +} + +static int optee_shm_add_riscv_handle(struct optee *optee, struct tee_shm = *shm, + u64 global_id) +{ + struct shm_rhash *r; + int rc; + + r =3D kmalloc_obj(*r); + if (!r) + return -ENOMEM; + r->shm =3D shm; + r->global_id =3D global_id; + + mutex_lock(&optee->riscv.mutex); + rc =3D rhashtable_lookup_insert_fast(&optee->riscv.global_ids, + &r->linkage, shm_rhash_params); + mutex_unlock(&optee->riscv.mutex); + + if (rc) + kfree(r); + + return rc; +} + +static int optee_shm_rem_riscv_handle(struct optee *optee, u64 global_id) +{ + struct shm_rhash *r; + int rc =3D -ENOENT; + + mutex_lock(&optee->riscv.mutex); + r =3D rhashtable_lookup_fast(&optee->riscv.global_ids, &global_id, + shm_rhash_params); + if (r) + rc =3D rhashtable_remove_fast(&optee->riscv.global_ids, + &r->linkage, shm_rhash_params); + mutex_unlock(&optee->riscv.mutex); + + if (!rc) + kfree(r); + + return rc; +} + +/* + * 2. Convert between struct tee_param and struct optee_msg_param + * + * optee_riscv_from_msg_param() and optee_riscv_to_msg_param() are the main + * functions. They are identical to their FF-A counterparts: the memref + * carries only the parcel handle (stored in fmem.global_id, the same slot + * FF-A uses for its g_handle), an offset and a size, never a page list. + */ + +static void from_msg_param_riscv_mem(struct optee *optee, struct tee_param= *p, + u32 attr, const struct optee_msg_param *mp) +{ + struct tee_shm *shm =3D NULL; + u64 offs_high =3D 0; + u64 offs_low =3D 0; + + p->attr =3D TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT + + attr - OPTEE_MSG_ATTR_TYPE_FMEM_INPUT; + p->u.memref.size =3D mp->u.fmem.size; + + if (mp->u.fmem.global_id !=3D OPTEE_MSG_FMEM_INVALID_GLOBAL_ID) + shm =3D optee_shm_from_riscv_handle(optee, mp->u.fmem.global_id); + p->u.memref.shm =3D shm; + + if (shm) { + offs_low =3D mp->u.fmem.offs_low; + offs_high =3D mp->u.fmem.offs_high; + } + p->u.memref.shm_offs =3D offs_low | offs_high << 32; +} + +/** + * optee_riscv_from_msg_param() - convert from OPTEE_MSG parameters to + * struct tee_param + * @optee: main service struct + * @params: subsystem internal parameter representation + * @num_params: number of elements in the parameter arrays + * @msg_params: OPTEE_MSG parameters + * + * Returns 0 on success or <0 on failure + */ +static int optee_riscv_from_msg_param(struct optee *optee, + struct tee_param *params, + size_t num_params, + const struct optee_msg_param *msg_params) +{ + size_t n; + + for (n =3D 0; n < num_params; n++) { + struct tee_param *p =3D params + n; + const struct optee_msg_param *mp =3D msg_params + n; + u32 attr =3D mp->attr & OPTEE_MSG_ATTR_TYPE_MASK; + + switch (attr) { + case OPTEE_MSG_ATTR_TYPE_NONE: + p->attr =3D TEE_IOCTL_PARAM_ATTR_TYPE_NONE; + memset(&p->u, 0, sizeof(p->u)); + break; + case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT: + case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT: + case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT: + optee_from_msg_param_value(p, attr, mp); + break; + case OPTEE_MSG_ATTR_TYPE_FMEM_INPUT: + case OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT: + case OPTEE_MSG_ATTR_TYPE_FMEM_INOUT: + from_msg_param_riscv_mem(optee, p, attr, mp); + break; + default: + return -EINVAL; + } + } + + return 0; +} + +static int to_msg_param_riscv_mem(struct optee_msg_param *mp, + const struct tee_param *p) +{ + struct tee_shm *shm =3D p->u.memref.shm; + + mp->attr =3D OPTEE_MSG_ATTR_TYPE_FMEM_INPUT + p->attr - + TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT; + + if (shm) { + u64 shm_offs =3D p->u.memref.shm_offs; + + mp->u.fmem.internal_offs =3D shm->offset; + + mp->u.fmem.offs_low =3D shm_offs; + mp->u.fmem.offs_high =3D shm_offs >> 32; + /* Check that the entire offset could be stored. */ + if (mp->u.fmem.offs_high !=3D shm_offs >> 32) + return -EINVAL; + + mp->u.fmem.global_id =3D shm->sec_world_id; + } else { + memset(&mp->u, 0, sizeof(mp->u)); + mp->u.fmem.global_id =3D OPTEE_MSG_FMEM_INVALID_GLOBAL_ID; + } + mp->u.fmem.size =3D p->u.memref.size; + + return 0; +} + +/** + * optee_riscv_to_msg_param() - convert from struct tee_params to OPTEE_MSG + * parameters + * @optee: main service struct + * @msg_params: OPTEE_MSG parameters + * @num_params: number of elements in the parameter arrays + * @params: subsystem internal parameter representation + * + * Returns 0 on success or <0 on failure + */ +static int optee_riscv_to_msg_param(struct optee *optee, + struct optee_msg_param *msg_params, + size_t num_params, + const struct tee_param *params) +{ + size_t n; + + for (n =3D 0; n < num_params; n++) { + const struct tee_param *p =3D params + n; + struct optee_msg_param *mp =3D msg_params + n; + + switch (p->attr) { + case TEE_IOCTL_PARAM_ATTR_TYPE_NONE: + mp->attr =3D TEE_IOCTL_PARAM_ATTR_TYPE_NONE; + memset(&mp->u, 0, sizeof(mp->u)); + break; + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT: + optee_to_msg_param_value(mp, p); + break; + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: + if (to_msg_param_riscv_mem(mp, p)) + return -EINVAL; + break; + default: + return -EINVAL; + } + } + + return 0; +} + +/* + * 3. Low level support functions to register shared memory in secure world + * + * Functions to register and unregister shared memory both for normal + * clients and for tee-supplicant. Registration creates an RPMI memory + * parcel (MEM_PARCEL_CREATE), which is the analog of FFA_MEM_SHARE; + * unregistration reclaims it (MEM_PARCEL_RECLAIM), the analog of + * FFA_MEM_RECLAIM, after a synchronous handshake with OP-TEE. + */ + +/* + * Coalesce a page array into RPMI block-list entries (Table 198). Each en= try + * spans a run of physically contiguous pages, up to RPMI_TEE_PARCEL_BLOCK= _MAX_ + * PAGES. When @block_high / @block_low are NULL only the entry count is + * computed, so the caller can size the request buffer first. + */ +static u32 optee_riscv_build_blocks(struct page **pages, size_t num_pages, + __le32 *block_high, __le32 *block_low) +{ + u32 nblocks =3D 0; + size_t i =3D 0; + + while (i < num_pages) { + u64 pfn =3D page_to_pfn(pages[i]); + u32 run =3D 1; + + while (i + run < num_pages && + run < RPMI_TEE_PARCEL_BLOCK_MAX_PAGES && + page_to_pfn(pages[i + run]) =3D=3D pfn + run) + run++; + + if (block_high && block_low) { + block_high[nblocks] =3D rpmi_tee_block_high(pfn); + block_low[nblocks] =3D rpmi_tee_block_low(pfn, run); + } + nblocks++; + i +=3D run; + } + + return nblocks; +} + +/* + * Issue MEM_PARCEL_CREATE (RPMI service 0x09) for @pages with the REE as = the + * creator and OP-TEE as the sole read/write receiver. Returns the framewo= rk + * assigned parcel id (>=3D 0) or a negative errno. + */ +static int optee_riscv_parcel_create(struct optee *optee, struct page **pa= ges, + size_t num_pages, u32 nonce) +{ + struct rpmi_tee_mem_parcel_create_req *req; + struct rpmi_tee_mem_parcel_create_resp rx =3D { }; + struct rpmi_mbox_message msg; + __le32 *block_high, *block_low; + size_t req_len; + u32 block_cnt; + __le32 *data; int ret; =20 + block_cnt =3D optee_riscv_build_blocks(pages, num_pages, NULL, NULL); + /* - * Memory parcels carry normal-world shared memory to OP-TEE, so the - * framework must support sharing memory between the REE and a TEE. + * Layout of the trailing data[] array (Table 200): one receiver_id and + * one access word (receiver_cnt =3D=3D 1), then block_high[block_cnt] and + * block_low[block_cnt]. */ - ret =3D optee_riscv_probe_feature(optee, RPMI_TEE_FEAT_MEMORY_SHARE, - &share); - if (ret) { - pr_err("Failed to probe MEMORY_SHARE feature: %d\n", ret); + req_len =3D struct_size(req, data, 2 + 2 * block_cnt); + if (optee->riscv.max_msg_data_size && + req_len > optee->riscv.max_msg_data_size) + return -E2BIG; + + req =3D kzalloc(req_len, GFP_KERNEL); + if (!req) + return -ENOMEM; + + req->creator_id =3D cpu_to_le32(RPMI_TEE_ENDPOINT_REE); + req->creator_access =3D cpu_to_le32(RPMI_TEE_PARCEL_ACCESS_R | + RPMI_TEE_PARCEL_ACCESS_W); + req->receiver_cnt =3D cpu_to_le32(1); + req->flags =3D 0; + req->nonce =3D cpu_to_le32(nonce); + req->block_cnt =3D cpu_to_le32(block_cnt); + + data =3D req->data; + data[0] =3D cpu_to_le32(RPMI_TEE_ENDPOINT_OPTEE); + data[1] =3D cpu_to_le32(RPMI_TEE_PARCEL_ACCESS_R | + RPMI_TEE_PARCEL_ACCESS_W); + block_high =3D &data[2]; + block_low =3D &data[2 + block_cnt]; + optee_riscv_build_blocks(pages, num_pages, block_high, block_low); + + rpmi_mbox_init_send_with_response(&msg, RPMI_TEE_SRV_MEM_PARCEL_CREATE, + req, req_len, &rx, sizeof(rx)); + ret =3D optee_riscv_send(optee, &msg); + kfree(req); + if (ret) return ret; - } - if (share !=3D RPMI_TEE_MEMORY_SHARE_FULL) { - pr_err("Framework cannot share memory between REE and TEE (%u)\n", - share); - return -EOPNOTSUPP; - } + if (rx.status) + return rpmi_to_linux_error(le32_to_cpu(rx.status)); =20 - return 0; + return le32_to_cpu(rx.mem_parcel_id); } =20 -static int optee_riscv_enable_notif(struct optee *optee) +/* + * Issue MEM_PARCEL_RECLAIM (RPMI service 0x0c). OpenSBI fails the reclaim + * while any receiver still holds the parcel, so this is only called after= the + * OPTEE_ABI_UNREGISTER_SHM handshake below has confirmed OP-TEE released = it. + */ +static int optee_riscv_parcel_reclaim(struct optee *optee, u32 parcel_id) { - struct rpmi_tee_probe_features_resp rx =3D { }; + struct rpmi_tee_mem_parcel_reclaim_req tx =3D { + .mem_parcel_id =3D cpu_to_le32(parcel_id), + }; + struct rpmi_tee_mem_parcel_reclaim_resp rx =3D { }; struct rpmi_mbox_message msg; int ret; =20 - rpmi_mbox_init_send_with_response(&msg, RPMI_TEE_SRV_ENABLE_NOTIFICATION, - NULL, 0, &rx, sizeof(rx)); + rpmi_mbox_init_send_with_response(&msg, RPMI_TEE_SRV_MEM_PARCEL_RECLAIM, + &tx, sizeof(tx), &rx, sizeof(rx)); ret =3D optee_riscv_send(optee, &msg); if (ret) return ret; + if (rx.status) + return rpmi_to_linux_error(le32_to_cpu(rx.status)); + + return 0; +} + +static int optee_riscv_shm_register(struct tee_context *ctx, + struct tee_shm *shm, struct page **pages, + size_t num_pages, unsigned long start) +{ + struct optee *optee =3D tee_get_drvdata(ctx->teedev); + u64 global_id; + u32 nonce; + int rc; + + rc =3D optee_check_mem_type(start, num_pages); + if (rc) + return rc; =20 /* - * The TEE service group defines no notification events on this - * platform, so RPMI_ERR_NOTSUPP is expected and not fatal. + * MEM_PARCEL_CREATE returns only a parcel id; the nonce is + * caller-supplied. Fold them into the FF-A style 64-bit handle: + * parcel id in the low word, nonce in the high word. */ - if (rx.status && le32_to_cpu(rx.status) !=3D (u32)RPMI_ERR_NOTSUPP) - return rpmi_to_linux_error(le32_to_cpu(rx.status)); + nonce =3D (u32)atomic_inc_return(&optee->riscv.next_nonce); + rc =3D optee_riscv_parcel_create(optee, pages, num_pages, nonce); + if (rc < 0) + return rc; + global_id =3D (u32)rc | ((u64)nonce << 32); + + rc =3D optee_shm_add_riscv_handle(optee, shm, global_id); + if (rc) { + optee_riscv_parcel_reclaim(optee, (u32)global_id); + return rc; + } + + shm->sec_world_id =3D global_id; =20 return 0; } =20 +static int optee_riscv_shm_unregister(struct tee_context *ctx, + struct tee_shm *shm) +{ + struct optee *optee =3D tee_get_drvdata(ctx->teedev); + u64 global_id =3D shm->sec_world_id; + u64 in[RPMI_TEE_OPTEE_CALL_REGS] =3D { + OPTEE_ABI_UNREGISTER_SHM, + (u32)global_id, + global_id >> 32, + 0, + }; + u64 out[RPMI_TEE_OPTEE_RESP_REGS] =3D { }; + int rc; + + optee_shm_rem_riscv_handle(optee, global_id); + shm->sec_world_id =3D 0; + + /* + * Synchronous teardown handshake, the analog of the FF-A + * OPTEE_FFA_UNREGISTER_SHM blocking call: OP-TEE releases the parcel on + * its own TEE channel before we reclaim it. Only reclaim once OP-TEE + * has acknowledged, so we never race the release. + */ + rc =3D optee_riscv_tee_call(optee, in, out); + if (rc) + pr_err("Unregister SHM id 0x%llx rc %d\n", global_id, rc); + + rc =3D optee_riscv_parcel_reclaim(optee, (u32)global_id); + if (rc) + pr_err("parcel_reclaim: 0x%llx %d\n", global_id, rc); + + return rc; +} + +static int optee_riscv_shm_unregister_supp(struct tee_context *ctx, + struct tee_shm *shm) +{ + struct optee *optee =3D tee_get_drvdata(ctx->teedev); + u64 global_id =3D shm->sec_world_id; + int rc; + + /* + * We're skipping the OPTEE_ABI_UNREGISTER_SHM handshake since this is + * OP-TEE freeing via RPC, so it has already retired this parcel. + */ + optee_shm_rem_riscv_handle(optee, global_id); + shm->sec_world_id =3D 0; + + rc =3D optee_riscv_parcel_reclaim(optee, (u32)global_id); + if (rc) + pr_err("parcel_reclaim: 0x%llx %d\n", global_id, rc); + + return rc; +} + +/* + * 4. Dynamic shared memory pool based on alloc_pages() + * + * Implements an OP-TEE specific shared memory pool. + * The main function is optee_riscv_shm_pool_alloc_pages(). + */ + +static int pool_riscv_op_alloc(struct tee_shm_pool *pool, + struct tee_shm *shm, size_t size, size_t align) +{ + return tee_dyn_shm_alloc_helper(shm, size, align, + optee_riscv_shm_register); +} + +static void pool_riscv_op_free(struct tee_shm_pool *pool, struct tee_shm *= shm) +{ + tee_dyn_shm_free_helper(shm, optee_riscv_shm_unregister); +} + +static void pool_riscv_op_destroy_pool(struct tee_shm_pool *pool) +{ + kfree(pool); +} + +static const struct tee_shm_pool_ops pool_riscv_ops =3D { + .alloc =3D pool_riscv_op_alloc, + .free =3D pool_riscv_op_free, + .destroy_pool =3D pool_riscv_op_destroy_pool, +}; + +/** + * optee_riscv_shm_pool_alloc_pages() - create page-based allocator pool + * + * This pool is used with OP-TEE over the RPMI TEE service group. In this = case + * command buffers and such are allocated from kernel's own memory. + */ +static struct tee_shm_pool *optee_riscv_shm_pool_alloc_pages(void) +{ + struct tee_shm_pool *pool =3D kzalloc_obj(*pool); + + if (!pool) + return ERR_PTR(-ENOMEM); + + pool->ops =3D &pool_riscv_ops; + + return pool; +} + /* - * 3. Driver initialization + * 5. Do a normal scheduled call into secure world * + * The function optee_riscv_do_call_with_arg() performs a normal scheduled + * call into secure world. During this call secure world may request help + * from normal world using RPCs, Remote Procedure Calls. This includes + * delivery of non-secure interrupts to for instance allow rescheduling of + * the current task. + */ + +static void handle_riscv_rpc_func_cmd_shm_alloc(struct tee_context *ctx, + struct optee *optee, + struct optee_msg_arg *arg) +{ + struct tee_shm *shm; + + if (arg->num_params !=3D 1 || + arg->params[0].attr !=3D OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) { + arg->ret =3D TEEC_ERROR_BAD_PARAMETERS; + return; + } + + switch (arg->params[0].u.value.a) { + case OPTEE_RPC_SHM_TYPE_APPL: + shm =3D optee_rpc_cmd_alloc_suppl(ctx, arg->params[0].u.value.b); + break; + case OPTEE_RPC_SHM_TYPE_KERNEL: + shm =3D tee_shm_alloc_priv_buf(optee->ctx, + arg->params[0].u.value.b); + break; + default: + arg->ret =3D TEEC_ERROR_BAD_PARAMETERS; + return; + } + + if (IS_ERR(shm)) { + arg->ret =3D TEEC_ERROR_OUT_OF_MEMORY; + return; + } + + arg->params[0] =3D (struct optee_msg_param){ + .attr =3D OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT, + .u.fmem.size =3D tee_shm_get_size(shm), + .u.fmem.global_id =3D shm->sec_world_id, + .u.fmem.internal_offs =3D shm->offset, + }; + + arg->ret =3D TEEC_SUCCESS; +} + +static void handle_riscv_rpc_func_cmd_shm_free(struct tee_context *ctx, + struct optee *optee, + struct optee_msg_arg *arg) +{ + struct tee_shm *shm; + + if (arg->num_params !=3D 1 || + arg->params[0].attr !=3D OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) + goto err_bad_param; + + shm =3D optee_shm_from_riscv_handle(optee, arg->params[0].u.value.b); + if (!shm) + goto err_bad_param; + switch (arg->params[0].u.value.a) { + case OPTEE_RPC_SHM_TYPE_APPL: + optee_rpc_cmd_free_suppl(ctx, shm); + break; + case OPTEE_RPC_SHM_TYPE_KERNEL: + tee_shm_free(shm); + break; + default: + goto err_bad_param; + } + arg->ret =3D TEEC_SUCCESS; + return; + +err_bad_param: + arg->ret =3D TEEC_ERROR_BAD_PARAMETERS; +} + +static void handle_riscv_rpc_func_cmd(struct tee_context *ctx, + struct optee *optee, + struct optee_msg_arg *arg) +{ + arg->ret_origin =3D TEEC_ORIGIN_COMMS; + switch (arg->cmd) { + case OPTEE_RPC_CMD_SHM_ALLOC: + handle_riscv_rpc_func_cmd_shm_alloc(ctx, optee, arg); + break; + case OPTEE_RPC_CMD_SHM_FREE: + handle_riscv_rpc_func_cmd_shm_free(ctx, optee, arg); + break; + default: + optee_rpc_cmd(ctx, optee, arg); + } +} + +static void optee_handle_riscv_rpc(struct tee_context *ctx, + struct optee *optee, u32 cmd, + struct optee_msg_arg *arg) +{ + switch (cmd) { + case OPTEE_ABI_YIELDING_CALL_RETURN_RPC_CMD: + handle_riscv_rpc_func_cmd(ctx, optee, arg); + break; + case OPTEE_ABI_YIELDING_CALL_RETURN_INTERRUPT: + /* Interrupt delivered by now */ + break; + default: + pr_warn("Unknown RPC func 0x%x\n", cmd); + break; + } +} + +static int optee_riscv_yielding_call(struct tee_context *ctx, + u64 in[RPMI_TEE_OPTEE_CALL_REGS], + struct optee_msg_arg *rpc_arg, + bool system_thread) +{ + struct optee *optee =3D tee_get_drvdata(ctx->teedev); + struct optee_call_waiter w; + u64 out[RPMI_TEE_OPTEE_RESP_REGS] =3D { }; + int rc; + + /* Initialize waiter */ + optee_cq_wait_init(&optee->call_queue, &w, system_thread); + while (true) { + rc =3D optee_riscv_tee_call(optee, in, out); + if (rc) + goto done; + + switch ((int)out[0]) { + case TEEC_SUCCESS: + break; + case TEEC_ERROR_BUSY: + if (in[0] =3D=3D OPTEE_ABI_YIELDING_CALL_RESUME) { + rc =3D -EIO; + goto done; + } + + /* + * Out of threads in secure world, wait for a thread + * to become available. + */ + optee_cq_wait_for_completion(&optee->call_queue, &w); + continue; + default: + rc =3D -EIO; + goto done; + } + + if (out[1] =3D=3D OPTEE_ABI_YIELDING_CALL_RETURN_DONE) + goto done; + + /* + * OP-TEE has returned with an RPC request. + * + * Note that out[4] (returned in reg[4]) is already filled in + * by optee_riscv_tee_call() returning above. + */ + cond_resched(); + optee_handle_riscv_rpc(ctx, optee, out[1], rpc_arg); + in[0] =3D OPTEE_ABI_YIELDING_CALL_RESUME; + in[1] =3D 0; + in[2] =3D 0; + in[3] =3D 0; + in[4] =3D out[4]; /* resume info */ + } +done: + /* + * We're done with our thread in secure world, if there are any + * thread waiters wake up one. + */ + optee_cq_wait_final(&optee->call_queue, &w); + + return rc; +} + +/** + * optee_riscv_do_call_with_arg() - enter OP-TEE in secure world + * @ctx: calling context + * @shm: shared memory holding the message to pass to secure world + * @offs: offset of the message in @shm + * @system_thread: true if caller requests TEE system thread support + * + * Does a TEE_CALL to OP-TEE in secure world and handles the resulting + * Remote Procedure Calls (RPC) from OP-TEE. The struct optee_msg_arg is + * passed by its parcel handle plus @offs, exactly as FF-A passes it by + * shared memory handle. + * + * Returns return code from OP-TEE, 0 is OK + */ +static int optee_riscv_do_call_with_arg(struct tee_context *ctx, + struct tee_shm *shm, u_int offs, + bool system_thread) +{ + u64 in[RPMI_TEE_OPTEE_CALL_REGS] =3D { + OPTEE_ABI_YIELDING_CALL_WITH_ARG, + (u32)shm->sec_world_id, + shm->sec_world_id >> 32, + offs, + }; + struct optee_msg_arg *arg; + unsigned int rpc_arg_offs; + struct optee_msg_arg *rpc_arg; + + /* + * The shared memory object has to start on a page when passed as + * an argument struct. This is also what the shm pool allocator + * returns, but check this before calling secure world to catch + * eventual errors early in case something changes. + */ + if (shm->offset) + return -EINVAL; + + arg =3D tee_shm_get_va(shm, offs); + if (IS_ERR(arg)) + return PTR_ERR(arg); + + rpc_arg_offs =3D OPTEE_MSG_GET_ARG_SIZE(arg->num_params); + rpc_arg =3D tee_shm_get_va(shm, offs + rpc_arg_offs); + if (IS_ERR(rpc_arg)) + return PTR_ERR(rpc_arg); + + return optee_riscv_yielding_call(ctx, in, rpc_arg, system_thread); +} + +/* + * 6. Driver initialization + * + * During driver initialization the OP-TEE Trusted OS is probed over TEE_C= ALL + * to find out which features it supports so the driver can be initialized + * with a matching configuration. These blocking calls mirror the FF-A + * OPTEE_FFA_GET_API_VERSION / GET_OS_VERSION / EXCHANGE_CAPABILITIES prob= es. + */ + +static bool optee_riscv_api_is_compatible(struct optee *optee) +{ + u64 in[RPMI_TEE_OPTEE_CALL_REGS] =3D { OPTEE_ABI_GET_API_VERSION }; + u64 out[RPMI_TEE_OPTEE_RESP_REGS] =3D { }; + int rc; + + rc =3D optee_riscv_tee_call(optee, in, out); + if (rc) { + pr_err("Unexpected error %d\n", rc); + return false; + } + if (out[0] !=3D OPTEE_ABI_VERSION_MAJOR || + out[1] < OPTEE_ABI_VERSION_MINOR) { + pr_err("Incompatible OP-TEE API version %llu.%llu\n", + out[0], out[1]); + return false; + } + + return true; +} + +static bool optee_riscv_get_os_revision(struct optee *optee) +{ + u64 in[RPMI_TEE_OPTEE_CALL_REGS] =3D { OPTEE_ABI_GET_OS_VERSION }; + u64 out[RPMI_TEE_OPTEE_RESP_REGS] =3D { }; + int rc; + + rc =3D optee_riscv_tee_call(optee, in, out); + if (rc) { + pr_err("Unexpected error %d\n", rc); + return false; + } + + optee->revision.os_major =3D out[0]; + optee->revision.os_minor =3D out[1]; + optee->revision.os_build_id =3D out[2]; + + if (out[2]) + pr_info("revision %llu.%llu (%08llx)\n", out[0], out[1], + out[2]); + else + pr_info("revision %llu.%llu\n", out[0], out[1]); + + return true; +} + +static bool optee_riscv_exchange_caps(struct optee *optee, u32 *sec_caps, + unsigned int *rpc_param_count, + unsigned int *max_notif_value) +{ + u64 in[RPMI_TEE_OPTEE_CALL_REGS] =3D { OPTEE_ABI_EXCHANGE_CAPABILITIES }; + u64 out[RPMI_TEE_OPTEE_RESP_REGS] =3D { }; + int rc; + + rc =3D optee_riscv_tee_call(optee, in, out); + if (rc) { + pr_err("Unexpected error %d\n", rc); + return false; + } + if (out[0]) { + pr_err("Unexpected exchange error %llu\n", out[0]); + return false; + } + + *rpc_param_count =3D (u8)out[1]; + *sec_caps =3D out[2]; + if (out[3]) + *max_notif_value =3D out[3]; + else + *max_notif_value =3D OPTEE_DEFAULT_MAX_NOTIF_VALUE; + + return true; +} + +static void optee_riscv_get_version(struct tee_device *teedev, + struct tee_ioctl_version_data *vers) +{ + struct tee_ioctl_version_data v =3D { + .impl_id =3D TEE_IMPL_ID_OPTEE, + .impl_caps =3D TEE_OPTEE_CAP_TZ, + .gen_caps =3D TEE_GEN_CAP_GP | TEE_GEN_CAP_REG_MEM | + TEE_GEN_CAP_MEMREF_NULL, + }; + + *vers =3D v; +} + +static int optee_riscv_open(struct tee_context *ctx) +{ + return optee_open(ctx, true); +} + +static const struct tee_driver_ops optee_riscv_clnt_ops =3D { + .get_version =3D optee_riscv_get_version, + .get_tee_revision =3D optee_get_revision, + .open =3D optee_riscv_open, + .release =3D optee_release, + .open_session =3D optee_open_session, + .close_session =3D optee_close_session, + .invoke_func =3D optee_invoke_func, + .cancel_req =3D optee_cancel_req, + .shm_register =3D optee_riscv_shm_register, + .shm_unregister =3D optee_riscv_shm_unregister, +}; + +static const struct tee_desc optee_riscv_clnt_desc =3D { + .name =3D DRIVER_NAME "-riscv-clnt", + .ops =3D &optee_riscv_clnt_ops, + .owner =3D THIS_MODULE, +}; + +static const struct tee_driver_ops optee_riscv_supp_ops =3D { + .get_version =3D optee_riscv_get_version, + .get_tee_revision =3D optee_get_revision, + .open =3D optee_riscv_open, + .release =3D optee_release_supp, + .supp_recv =3D optee_supp_recv, + .supp_send =3D optee_supp_send, + .shm_register =3D optee_riscv_shm_register, /* same as for clnt ops */ + .shm_unregister =3D optee_riscv_shm_unregister_supp, +}; + +static const struct tee_desc optee_riscv_supp_desc =3D { + .name =3D DRIVER_NAME "-riscv-supp", + .ops =3D &optee_riscv_supp_ops, + .owner =3D THIS_MODULE, + .flags =3D TEE_DESC_PRIVILEGED, +}; + +static const struct optee_ops optee_riscv_ops =3D { + .do_call_with_arg =3D optee_riscv_do_call_with_arg, + .to_msg_param =3D optee_riscv_to_msg_param, + .from_msg_param =3D optee_riscv_from_msg_param, +}; + +/* * The RPMI TEE service group is described in the device tree by a single * node whose "mboxes" property lists one SBI MPXY channel per hart, in ha= rt * order. The driver requests each list entry by index and validates the @@ -186,15 +1042,117 @@ static void optee_riscv_free_channels(struct optee = *optee) } } =20 +/* Confirm the TEE service group and read its transport attributes. */ +static int optee_riscv_check_transport(struct optee *optee) +{ + struct device *dev =3D optee->riscv.dev; + struct rpmi_mbox_message msg; + int ret; + + rpmi_mbox_init_get_attribute(&msg, RPMI_MBOX_ATTR_SERVICEGROUP_ID); + ret =3D optee_riscv_send(optee, &msg); + if (ret) + return dev_err_probe(dev, ret, + "Failed to get service group id\n"); + if (msg.attr.value !=3D RPMI_SRVGRP_TEE) + return dev_err_probe(dev, -ENODEV, + "Not a TEE service group channel (0x%x)\n", + msg.attr.value); + + rpmi_mbox_init_get_attribute(&msg, RPMI_MBOX_ATTR_MAX_MSG_DATA_SIZE); + ret =3D optee_riscv_send(optee, &msg); + if (ret) + return dev_err_probe(dev, ret, + "Failed to get max msg data size\n"); + optee->riscv.max_msg_data_size =3D msg.attr.value; + + return 0; +} + +/* + * TEE_PROBE_FEATURES (0x02) reports which framework features are availabl= e; + * memory parcels carry normal-world shared memory to OP-TEE, so the frame= work + * must support sharing memory between the REE and a TEE. + */ +static int optee_riscv_probe_feature(struct optee *optee, u32 feature_id, + u32 *value) +{ + struct rpmi_tee_probe_features_req tx =3D { + .feature_id =3D cpu_to_le32(feature_id), + }; + struct rpmi_tee_probe_features_resp rx =3D { }; + struct rpmi_mbox_message msg; + int ret; + + rpmi_mbox_init_send_with_response(&msg, RPMI_TEE_SRV_PROBE_FEATURES, + &tx, sizeof(tx), &rx, sizeof(rx)); + ret =3D optee_riscv_send(optee, &msg); + if (ret) + return ret; + if (rx.status) + return rpmi_to_linux_error(le32_to_cpu(rx.status)); + + if (value) + *value =3D le32_to_cpu(rx.value); + + return 0; +} + +static int optee_riscv_features(struct optee *optee) +{ + u32 share =3D RPMI_TEE_MEMORY_SHARE_NONE; + int ret; + + ret =3D optee_riscv_probe_feature(optee, RPMI_TEE_FEAT_MEMORY_SHARE, + &share); + if (ret) { + pr_err("Failed to probe MEMORY_SHARE feature: %d\n", ret); + return ret; + } + if (share !=3D RPMI_TEE_MEMORY_SHARE_FULL) { + pr_err("Framework cannot share memory between REE and TEE (%u)\n", + share); + return -EOPNOTSUPP; + } + + return 0; +} + +static int optee_riscv_enable_notif(struct optee *optee) +{ + struct rpmi_tee_probe_features_resp rx =3D { }; + struct rpmi_mbox_message msg; + int ret; + + rpmi_mbox_init_send_with_response(&msg, RPMI_TEE_SRV_ENABLE_NOTIFICATION, + NULL, 0, &rx, sizeof(rx)); + ret =3D optee_riscv_send(optee, &msg); + if (ret) + return ret; + + /* + * The TEE service group defines no notification events on this + * platform, so RPMI_ERR_NOTSUPP is expected and not fatal. + */ + if (rx.status && le32_to_cpu(rx.status) !=3D (u32)RPMI_ERR_NOTSUPP) + return rpmi_to_linux_error(le32_to_cpu(rx.status)); + + return 0; +} + static int optee_riscv_probe(struct platform_device *pdev) { struct device *dev =3D &pdev->dev; - struct rpmi_mbox_message msg; + unsigned int rpc_param_count; + unsigned int max_notif_value; + struct tee_shm_pool *pool; + struct tee_device *teedev; + struct tee_context *ctx; struct mbox_client *client; struct optee *optee; - u32 servicegroup_id; + u32 sec_caps; unsigned int nr_cpus; - int ret; + int rc; =20 nr_cpus =3D num_possible_cpus(); if (!nr_cpus) @@ -206,7 +1164,7 @@ static int optee_riscv_probe(struct platform_device *p= dev) =20 client =3D devm_kzalloc(dev, sizeof(*client), GFP_KERNEL); if (!client) { - ret =3D -ENOMEM; + rc =3D -ENOMEM; goto err_free_optee; } client->dev =3D dev; @@ -221,66 +1179,156 @@ static int optee_riscv_probe(struct platform_device= *pdev) optee->riscv.chan =3D kcalloc(nr_cpus, sizeof(*optee->riscv.chan), GFP_KERNEL); if (!optee->riscv.chan) { - ret =3D -ENOMEM; + rc =3D -ENOMEM; goto err_free_optee; } =20 - ret =3D optee_riscv_request_channels(optee); - if (ret) + rc =3D optee_riscv_request_channels(optee); + if (rc) goto err_free_channels; =20 - /* Confirm the channel really speaks the TEE service group. */ - rpmi_mbox_init_get_attribute(&msg, RPMI_MBOX_ATTR_SERVICEGROUP_ID); - ret =3D optee_riscv_send(optee, &msg); - if (ret) { - dev_err_probe(dev, ret, "Failed to get service group id\n"); + rc =3D optee_riscv_check_transport(optee); + if (rc) + goto err_free_channels; + + rc =3D optee_riscv_features(optee); + if (rc) { + dev_err_probe(dev, rc, "Missing required TEE features\n"); goto err_free_channels; } - servicegroup_id =3D msg.attr.value; - if (servicegroup_id !=3D RPMI_SRVGRP_TEE) { - ret =3D -ENODEV; - dev_err_probe(dev, ret, "Not a TEE service group channel (0x%x)\n", - servicegroup_id); + + rc =3D optee_riscv_enable_notif(optee); + if (rc) { + dev_err_probe(dev, rc, "Failed to enable notifications\n"); goto err_free_channels; } =20 - rpmi_mbox_init_get_attribute(&msg, RPMI_MBOX_ATTR_MAX_MSG_DATA_SIZE); - ret =3D optee_riscv_send(optee, &msg); - if (ret) { - dev_err_probe(dev, ret, "Failed to get max msg data size\n"); + if (!optee_riscv_api_is_compatible(optee)) { + rc =3D -EINVAL; goto err_free_channels; } - optee->riscv.max_msg_data_size =3D msg.attr.value; =20 - ret =3D optee_riscv_features(optee); - if (ret) { - dev_err_probe(dev, ret, "Missing required TEE features\n"); + if (!optee_riscv_get_os_revision(optee)) { + rc =3D -EINVAL; goto err_free_channels; } =20 - ret =3D optee_riscv_enable_notif(optee); - if (ret) { - dev_err_probe(dev, ret, "Failed to enable notifications\n"); + if (!optee_riscv_exchange_caps(optee, &sec_caps, &rpc_param_count, + &max_notif_value)) { + rc =3D -EINVAL; + goto err_free_channels; + } + + pool =3D optee_riscv_shm_pool_alloc_pages(); + if (IS_ERR(pool)) { + rc =3D PTR_ERR(pool); goto err_free_channels; } + optee->pool =3D pool; + + optee->ops =3D &optee_riscv_ops; + optee->rpc_param_count =3D rpc_param_count; + + if (IS_REACHABLE(CONFIG_RPMB) && + (sec_caps & OPTEE_ABI_SEC_CAP_RPMB_PROBE)) + optee->in_kernel_rpmb_routing =3D true; + + teedev =3D tee_device_alloc(&optee_riscv_clnt_desc, NULL, optee->pool, + optee); + if (IS_ERR(teedev)) { + rc =3D PTR_ERR(teedev); + goto err_free_shm_pool; + } + optee->teedev =3D teedev; + + teedev =3D tee_device_alloc(&optee_riscv_supp_desc, NULL, optee->pool, + optee); + if (IS_ERR(teedev)) { + rc =3D PTR_ERR(teedev); + goto err_unreg_teedev; + } + optee->supp_teedev =3D teedev; =20 + optee_set_dev_group(optee); + + rc =3D tee_device_register(optee->teedev); + if (rc) + goto err_unreg_supp_teedev; + + rc =3D tee_device_register(optee->supp_teedev); + if (rc) + goto err_unreg_supp_teedev; + + rc =3D rhashtable_init(&optee->riscv.global_ids, &shm_rhash_params); + if (rc) + goto err_unreg_supp_teedev; + mutex_init(&optee->riscv.mutex); + atomic_set(&optee->riscv.next_nonce, 0); + optee_cq_init(&optee->call_queue, 0); + optee_supp_init(&optee->supp); + optee_shm_arg_cache_init(optee, 0); + mutex_init(&optee->rpmb_dev_mutex); platform_set_drvdata(pdev, optee); + + ctx =3D teedev_open(optee->teedev); + if (IS_ERR(ctx)) { + rc =3D PTR_ERR(ctx); + goto err_rhashtable_free; + } + optee->ctx =3D ctx; + + rc =3D optee_notif_init(optee, max_notif_value); + if (rc) + goto err_close_ctx; + + rc =3D optee_enumerate_devices(PTA_CMD_GET_DEVICES); + if (rc) + goto err_unregister_devices; + + INIT_WORK(&optee->rpmb_scan_bus_work, optee_bus_scan_rpmb); + optee->rpmb_intf.notifier_call =3D optee_rpmb_intf_rdev; + blocking_notifier_chain_register(&optee_rpmb_intf_added, + &optee->rpmb_intf); + dev_info(dev, "initialized driver\n"); =20 return 0; =20 +err_unregister_devices: + optee_unregister_devices(); + optee_notif_uninit(optee); +err_close_ctx: + teedev_close_context(ctx); +err_rhashtable_free: + rhashtable_free_and_destroy(&optee->riscv.global_ids, rh_free_fn, NULL); + rpmb_dev_put(optee->rpmb_dev); + mutex_destroy(&optee->rpmb_dev_mutex); + optee_supp_uninit(&optee->supp); + mutex_destroy(&optee->call_queue.mutex); + mutex_destroy(&optee->riscv.mutex); +err_unreg_supp_teedev: + tee_device_unregister(optee->supp_teedev); +err_unreg_teedev: + tee_device_unregister(optee->teedev); +err_free_shm_pool: + tee_shm_pool_free(pool); err_free_channels: optee_riscv_free_channels(optee); kfree(optee->riscv.chan); err_free_optee: kfree(optee); - return ret; + return rc; } =20 static void optee_riscv_remove(struct platform_device *pdev) { struct optee *optee =3D platform_get_drvdata(pdev); =20 + optee_remove_common(optee); + + mutex_destroy(&optee->riscv.mutex); + rhashtable_free_and_destroy(&optee->riscv.global_ids, rh_free_fn, NULL); + optee_riscv_free_channels(optee); kfree(optee->riscv.chan); kfree(optee); diff --git a/drivers/tee/optee/optee_riscv.h b/drivers/tee/optee/optee_risc= v.h index d87298faa6a2..2cdbb1fb4eab 100644 --- a/drivers/tee/optee/optee_riscv.h +++ b/drivers/tee/optee/optee_riscv.h @@ -24,6 +24,7 @@ #ifndef __OPTEE_RISCV_H #define __OPTEE_RISCV_H =20 +#include #include #include =20 @@ -110,9 +111,13 @@ struct rpmi_tee_probe_features_resp { { 0x5b, 0xe1, 0xb1, 0xa0, 0x7e, 0x11, 0x4e, 0x7a, \ 0x9b, 0x10, 0x00, 0x10, 0xc0, 0xff, 0xee, 0x00 } =20 -/* OP-TEE SMC-style call convention carried inside SERVICE_DATA. */ -#define RPMI_TEE_OPTEE_CALL_REGS 8 /* a0-a7 */ -#define RPMI_TEE_OPTEE_RESP_REGS 4 /* a0-a3 */ +/* + * OP-TEE FF-A direct message convention carried inside SERVICE_DATA: + * five command words each way, the RISC-V analog of the FF-A data0-data4 + * (w3-w7) set of struct ffa_send_direct_data. + */ +#define RPMI_TEE_OPTEE_CALL_REGS 5 +#define RPMI_TEE_OPTEE_RESP_REGS 5 =20 #if __riscv_xlen =3D=3D 64 typedef __le64 rpmi_xlen_t; @@ -138,4 +143,128 @@ struct rpmi_tee_call_resp { rpmi_xlen_t reg[RPMI_TEE_OPTEE_RESP_REGS]; } __packed; =20 +/* + * OP-TEE message ABI carried inside the TEE_CALL SERVICE_DATA words. + * + * This mirrors the FF-A message ABI in : OP-TEE and the REE = are + * peer endpoints and the argument struct optee_msg_arg is passed by shared + * memory handle (a parcel id) plus an offset, never by a register block. = The + * SERVICE_DATA registers carry a small command word set that is the RISC-V + * analog of the FF-A w3-w7 register usage: + * + * reg[0]: command / service id (OPTEE_ABI_YIELDING_CALL_* below) + * reg[1]: shared memory handle, lower 32 bits (parcel id) + * reg[2]: shared memory handle, upper 32 bits (parcel nonce) + * reg[3]: offset into the shared memory to the struct optee_msg_arg + * reg[4]: not used on this call, resume info on OPTEE_ABI_YIELDING_CALL= _RESUME + * + * On return the SERVICE_RSP registers carry: + * reg[0]: error code, 0 on success + * reg[1]: return code (OPTEE_ABI_YIELDING_CALL_RETURN_* below) + * reg[2..3]: not used + * reg[4]: RPC resume info + * + * These MUST byte-match the secure world OP-TEE header. + */ +#define OPTEE_ABI_BLOCKING_CALL(id) (id) +#define OPTEE_ABI_YIELDING_CALL_BIT 31 +#define OPTEE_ABI_YIELDING_CALL(id) ((id) | BIT(OPTEE_ABI_YIELDING_CALL_BI= T)) + +/* Blocking (fast) calls, mirror of OPTEE_FFA_BLOCKING_CALL ids. */ +#define OPTEE_ABI_GET_API_VERSION OPTEE_ABI_BLOCKING_CALL(0) +#define OPTEE_ABI_GET_OS_VERSION OPTEE_ABI_BLOCKING_CALL(1) +#define OPTEE_ABI_EXCHANGE_CAPABILITIES OPTEE_ABI_BLOCKING_CALL(2) +#define OPTEE_ABI_UNREGISTER_SHM OPTEE_ABI_BLOCKING_CALL(3) +#define OPTEE_ABI_ENABLE_ASYNC_NOTIF OPTEE_ABI_BLOCKING_CALL(5) + +/* OP-TEE ABI version, mirror of OPTEE_FFA_VERSION_*. */ +#define OPTEE_ABI_VERSION_MAJOR 1 +#define OPTEE_ABI_VERSION_MINOR 0 + +/* Capabilities returned by EXCHANGE_CAPABILITIES (OPTEE_FFA_SEC_CAP_* ana= log). */ +#define OPTEE_ABI_SEC_CAP_ARG_OFFSET BIT(0) +#define OPTEE_ABI_SEC_CAP_ASYNC_NOTIF BIT(1) +#define OPTEE_ABI_SEC_CAP_RPMB_PROBE BIT(2) + +#define OPTEE_ABI_MAX_ASYNC_NOTIF_VALUE 64 + +/* Yielding calls, mirror of OPTEE_FFA_YIELDING_CALL_*. */ +#define OPTEE_ABI_YIELDING_CALL_WITH_ARG OPTEE_ABI_YIELDING_CALL(0) +#define OPTEE_ABI_YIELDING_CALL_RESUME OPTEE_ABI_YIELDING_CALL(1) + +#define OPTEE_ABI_YIELDING_CALL_RETURN_DONE 0 +#define OPTEE_ABI_YIELDING_CALL_RETURN_RPC_CMD 1 +#define OPTEE_ABI_YIELDING_CALL_RETURN_INTERRUPT 2 + +/* + * Memory parcel wire encodings (RPMI spec section 4.16, Tables 198-207). + * + * A memory parcel is the RISC-V analog of an FF-A memory-share handle: th= e REE + * creates a parcel describing its pages and OP-TEE accepts it lazily by p= arcel + * id. All fields are little-endian uint32 words; block-list addresses are + * expressed in units of 4kB pages. + */ + +/* Memory access encoding (Table 199). */ +#define RPMI_TEE_PARCEL_ACCESS_R BIT(29) +#define RPMI_TEE_PARCEL_ACCESS_W BIT(30) +#define RPMI_TEE_PARCEL_ACCESS_X BIT(31) + +/* MEM_PARCEL_CREATE flags (Table 200). */ +#define RPMI_TEE_PARCEL_CREATE_FLAG_MULTI_SEGMENT BIT(31) +#define RPMI_TEE_PARCEL_CREATE_FLAG_OWNER_XFER BIT(30) + +/* Length of the parcel LABEL field (Table 200). */ +#define RPMI_TEE_PARCEL_LABEL_LEN 16 + +/* + * A block list entry covers a run of physically contiguous 4kB pages + * (Table 198): + * BLOCK_HIGH =3D page-frame number [51:20] + * BLOCK_LOW =3D (page-frame number [19:0] << 12) | (page count - 1) + * so a single block spans at most 4096 pages (16MB). + */ +#define RPMI_TEE_PARCEL_BLOCK_MAX_PAGES 4096 + +static inline __le32 rpmi_tee_block_high(u64 pfn) +{ + return cpu_to_le32((u32)(pfn >> 20)); +} + +static inline __le32 rpmi_tee_block_low(u64 pfn, u32 npages) +{ + return cpu_to_le32(((u32)(pfn & 0xfffff) << 12) | (npages - 1)); +} + +/* + * MEM_PARCEL_CREATE request (Table 200): a fixed header followed by + * receiver_id[receiver_cnt], access[receiver_cnt], block_high[block_cnt] = and + * block_low[block_cnt]. + */ +struct rpmi_tee_mem_parcel_create_req { + __le32 creator_id; + __le32 creator_access; + __le32 receiver_cnt; + __le32 flags; + __le32 nonce; + __le32 block_cnt; + u8 label[RPMI_TEE_PARCEL_LABEL_LEN]; + __le32 data[]; +}; + +struct rpmi_tee_mem_parcel_create_resp { + __le32 status; + __le32 mem_parcel_id; +}; + +/* MEM_PARCEL_RECLAIM request (Table 206) / response (Table 207). */ +struct rpmi_tee_mem_parcel_reclaim_req { + __le32 mem_parcel_id; +}; + +struct rpmi_tee_mem_parcel_reclaim_resp { + __le32 status; + __le32 flags; +}; + #endif /* __OPTEE_RISCV_H */ --=20 2.34.1 From nobody Fri Sep 25 12:38:50 2026 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 43FB735FF6E for ; Sat, 12 Sep 2026 10:15:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789208150; cv=none; b=da8TI6v4mUkDlznS4CPosE4FZpjO4B0kdSiS461QQrX/B+YMJG1IS6Hl86yoan1+nNSfIHiaN+z6gArPJub04RGaVEd6z13NZhz+5OaJ80ZgGlLKTjV/+EflnZgmB32f4BBH1rb+aEtM/FJG5Gxz5bSak0os3XC+LkthdCBdJc0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789208150; c=relaxed/simple; bh=nbmyEVTc4+Ww2tjJ+SxB0dnh0CfPx4aQRKXHop6+iNc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mr4UyId2AOuiKv0Dy1U0KwqIzCS+N56XdcaAZrpokkyffjjc6OElZxykhHlKrAJoAwXbz5X5jF3ihxdMp6amFMLEDr3k8wgGmaau29/aeFl6Tm2U5L+sBXlG8Ll4lRt85pddWpjxP5wjDMPhvbTYJZr4J6Gme/Ea9UyUgIowvoA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=IKhV9cEw; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=VQbagFJt; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="IKhV9cEw"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="VQbagFJt" Received: from pps.filterd (m0279872.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 68C853ZN1803905 for ; Sat, 12 Sep 2026 10:15:48 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= zIuGB8S7sRqJtqaXIx6R8EAbbBn7m6GmghtV+o0/jPY=; b=IKhV9cEworVEOEwW gk6s/AjMqe1VEHdXDf6OW1iibkSxE39kSVan21oa2dvnbSCWnDHoIjrQ2diJxQmY YxfYT9yfzY6U1+a1grvJUlkzeWwZnosPxX0ZE3OXoZXOfNTyBrvl4ZqLW5Y3Z/h0 ggOEKIPlLrs2YU2oGI0YSBvre/dgljMoYrgeDJ60MHeN8pun6EP8vvXA65/a6z72 rVrsmCe963u+12MIiYuQY3RSPDsIrakxpNh6jN+rfpMynrU5paHAavftKC24lJ74 mnlPtLyAdqvKVO6/EV0/XjcgW+F6b3rLapZ2viLj5AiLF8JJxN5sOGsGOWrVohf+ JDl3Aw== Received: from mail-pg1-f197.google.com (mail-pg1-f197.google.com [209.85.215.197]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4gmy9c8nyy-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Sat, 12 Sep 2026 10:15:47 +0000 (GMT) Received: by mail-pg1-f197.google.com with SMTP id 41be03b00d2f7-cc21bc2923fso1819272a12.2 for ; Sat, 12 Sep 2026 03:15:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1789208132; x=1789812932; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=zIuGB8S7sRqJtqaXIx6R8EAbbBn7m6GmghtV+o0/jPY=; b=VQbagFJtlxJhM78N7lsWS7c1lE1VcaF4UfnuJhlQHvUjbQrtS5EVCeFGCUfBI0qSqD biwB+0nzADkVpMhH6ccng7HZVT3mf3CC1i2LUgR0kCP/FWulqn0Z7WGN229cexfPTFLj m7JtGzbyVjygqOQFI48Tj4cZwUHrSKYIUQMul0SD0UzCLBxsaQyqGjoVJJ9RAexENo+s ko2xcfKgME3HVIynIcLtlomMR28XrtZrdb3E+Y/YWeAJ6+xCoAaMCi+V8ndoPvFF9Sgo b/RfHGrtNlibVLb2PlYpyCEAYDM5XrDifd4Hv0jZP6tqZHEvAmnk3how/rMA357Y5ce2 jbyg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789208132; x=1789812932; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=zIuGB8S7sRqJtqaXIx6R8EAbbBn7m6GmghtV+o0/jPY=; b=jZ1mhhRyHJEuc+B6oEJQTUmiOsJvzrKhUTi5tECBS/VaeZae18vhHQi9FImkm4KhHN rBsQ44ygC7EigyV//A6Z838dV3sIKH2APexjxevsW5nsP/DTSuU0vrpRUK+E7P+ZouRa Yyz07v0PmeZ+5iAiFGVlfc6O0TT1DBQLBcuZVFby+ac8iZ9RTbnHsug6lz+bUhX1Puyl 0FeYcJuv82w2XVtHhCHyf7CRvWE2pHkFz+P51XIZVm9L6cmNdnChJPi29MNMCzFbXJiv ZITD9jiVtUQPQItyKfCDoK3ET3aH251qHl9VVFybGdt0ygO3yWOPQ89AQ8Qu/ZC2gNVf MQdw== X-Forwarded-Encrypted: i=1; AKwUvBzisGn8fsLeLBJ1vC8oZX/L5nRR4U6AS7qxuSpw6lsFn68gYj1G+OOEr4FcftaeIKi7lcyezIdpHBFiR2s=@vger.kernel.org X-Gm-Message-State: AFuF++ns/BTusdJjiijM55pWWMH6QCHJV3CcF3kbsy5lbwRoLP2vv8Mw bOTASakP2AszPDZbxS3MIzb7QFaO8Iv+XkkTtuI7Q04M+GXsQb982gXQR+Hp5M9AYGSRNgjOPi3 Phqt3VJScYdZOelraKxIb96FQOdDdTmU3E5lEShSTXZ9bUAY6czRQHUb/HvoLw0byfA== X-Gm-Gg: AYBFou1e8e/zIZ1/nrk51P8d8Vlvdeo7RIKuHYJl1F4yUNnWbsh7GKguGWwYbiLjVWi 5vXiokArA/BdPir19G+y8Nv1DRaJXgllyHZ7I+aLQcYSukYwX1cIsi22W67Ln7Wc/dty3RTEQkE Ag2t95mfd4OKXfn84FIpiPPgDPA1C7dlMGw90NaY8uNIIkMb0k7Qbq3SQpKPFAWsyC5NkLp6VrT XX+Vq49tSKuyzyM7xQu+/s5yfTNrhz6ICayUSi+h8/XwQtXHUJt2Bos0f1uwyjnsUIb2eJPUWP8 fgpDSGh6F5ntBtTh4KdyZcDwnvq3aQcuZH0qrldcWNKdM78FbTlz7cLA5idaEsR2A52erqIJAzw KzMNTXB5Cqozrq1PlAbfGz5losyZSQ5ttDHCUHC3rIbZOkjK6eKrWZ054/9w= X-Received: by 2002:a17:90b:52cd:b0:385:393e:7124 with SMTP id 98e67ed59e1d1-39dbc699006mr4249278a91.14.1789208131969; Sat, 12 Sep 2026 03:15:31 -0700 (PDT) X-Received: by 2002:a17:90b:52cd:b0:385:393e:7124 with SMTP id 98e67ed59e1d1-39dbc699006mr4249221a91.14.1789208131506; Sat, 12 Sep 2026 03:15:31 -0700 (PDT) Received: from hu-azarrabi-lv.qualcomm.com (Global_NAT1.qualcomm.com. [129.46.96.20]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-33baf0ea9a1sm10340085eec.8.2026.09.12.03.15.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Sep 2026 03:15:30 -0700 (PDT) From: Amirreza Zarrabi Date: Sat, 12 Sep 2026 03:15:14 -0700 Subject: [PATCH RFC 3/5] optee: riscv: enable persistent shared argument cache Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260912-rpmi-tee-service-grp-dev-v1-3-1d1d35c2a859@oss.qualcomm.com> References: <20260912-rpmi-tee-service-grp-dev-v1-0-1d1d35c2a859@oss.qualcomm.com> In-Reply-To: <20260912-rpmi-tee-service-grp-dev-v1-0-1d1d35c2a859@oss.qualcomm.com> To: Jens Wiklander , Sumit Garg , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Rahul Pathak , Anup Patel , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, op-tee@lists.trustedfirmware.org, linux-riscv@lists.infradead.org, devicetree@vger.kernel.org, Amirreza Zarrabi X-Mailer: b4 0.13.0 X-Proofpoint-GUID: yi62RDfjxrSEXMGehQEqRYw1kCNq4IYo X-Authority-Analysis: v=2.4 cv=Pv4G/AM3 c=1 sm=1 tr=0 ts=6aa52654 cx=c_pps a=rz3CxIlbcmazkYymdCej/Q==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17 a=IkcTkHD0fZMA:10 a=VdqzKS8jKosA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=yx91gb_oNiZeI1HMLzn7:22 a=EUspDBNiAAAA:8 a=hYfsqUzT0y0sb8bvQO0A:9 a=QEXdDO2ut3YA:10 a=bFCP_H2QrGi7Okbo017w:22 X-Proofpoint-Spam-Info: AW1haW4tMjYwOTEyMDE0NiBTYWx0ZWRfX3YX8y4PPGf2k HBXWxHe3f9T/Xs9qvXtMjFzhDYQV4Jp8d8++LGZwyKg1ttn/a63DNwemuvP7P/dwjmblGLxRRC1 eEl1XZ1h3eFApt0nNUWW9FjNsKxEYM8= X-Proofpoint-ORIG-GUID: yi62RDfjxrSEXMGehQEqRYw1kCNq4IYo X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTEyMDE0NiBTYWx0ZWRfX84ecNDv7vDay svJIrR5K6drQ0AWEms4cfy6LvUfSvWrzsPBq+Z1u/dHshTJ43WlDBacSmnzIDDz/JRao7e2Flp2 p/Htrev6Db0WdTxZiYrMyoazkNX2Pmllt/Q/5Z+jgRAdjAp0eJ2xOONPnYz2FKALCmIB0EEnUBm rvE463acJysTQk7IM1dYU2GPtVj80pxiAUL/NEK8eUaWiWqtM10k24rk4kUrDSoQLAzcQRjFum3 2k4F0uR81eYv2I8Vq14bHXPhY2cYxHL4e2T9J+8AYPB0teKD68Z6vDK4AwrPOJ4tH7CKZux4hny 7R+0U5SpqfZyBfYs7FT36Ddx7+k3gR+LDMk/ydNPVGVE5XICwBWssSx5Pz5h18YPStVjlHuifkN OVA1OJpQjxZ70DXBBcJUXAgYGQ7B2l5FQ/ntT5T6WqJMoYW8Hztsi1/KVU3CI6hy5tagmoWZ2Im egEwZ+Rn4dRiLaD+0uA== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-09-12_03,2026-09-11_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 bulkscore=0 adultscore=0 suspectscore=0 malwarescore=0 priorityscore=1501 spamscore=0 clxscore=1015 impostorscore=0 lowpriorityscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2609040000 definitions=main-2609120146 Use the OP-TEE shared argument cache when secure world advertises OPTEE_ABI_SEC_CAP_ARG_OFFSET. In this mode the argument structure can reside at an offset within an already registered parcel-backed shared-memory buffer, allowing the same buffer to be reused across calls instead of creating and reclaiming a parcel for each call. Signed-off-by: Amirreza Zarrabi --- drivers/tee/optee/optee_riscv.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/tee/optee/optee_riscv.c b/drivers/tee/optee/optee_risc= v.c index 36115326486d..72c9eb85f4fe 100644 --- a/drivers/tee/optee/optee_riscv.c +++ b/drivers/tee/optee/optee_riscv.c @@ -1149,6 +1149,7 @@ static int optee_riscv_probe(struct platform_device *= pdev) struct tee_device *teedev; struct tee_context *ctx; struct mbox_client *client; + u32 arg_cache_flags =3D 0; struct optee *optee; u32 sec_caps; unsigned int nr_cpus; @@ -1219,6 +1220,15 @@ static int optee_riscv_probe(struct platform_device = *pdev) goto err_free_channels; } =20 + /* + * If OP-TEE can read the argument struct from an offset into a shared + * memory buffer, cache and reuse one buffer across calls instead of + * creating a fresh parcel per call. This is the persistent pool that + * matches the FF-A OPTEE_FFA_SEC_CAP_ARG_OFFSET path. + */ + if (sec_caps & OPTEE_ABI_SEC_CAP_ARG_OFFSET) + arg_cache_flags |=3D OPTEE_SHM_ARG_SHARED; + pool =3D optee_riscv_shm_pool_alloc_pages(); if (IS_ERR(pool)) { rc =3D PTR_ERR(pool); @@ -1266,7 +1276,7 @@ static int optee_riscv_probe(struct platform_device *= pdev) atomic_set(&optee->riscv.next_nonce, 0); optee_cq_init(&optee->call_queue, 0); optee_supp_init(&optee->supp); - optee_shm_arg_cache_init(optee, 0); + optee_shm_arg_cache_init(optee, arg_cache_flags); mutex_init(&optee->rpmb_dev_mutex); platform_set_drvdata(pdev, optee); =20 --=20 2.34.1 From nobody Fri Sep 25 12:38:50 2026 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 67EC642885F for ; Sat, 12 Sep 2026 10:15:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789208150; cv=none; b=ugq8rGyRJJIvOsLSz89BhX23vwokLoCFQStylUI5gT12I5nxc91/MTBXrxxFcvW2U8fA+hH2qaRsx3sT2m9pSdiQkDOMiS9zrllkBxX/aM8zyVWhulZTm2e8vXLrGZWgLikw+yhFUQqjeXRgnZ0Ucz0ASQlCEUiI2slFnvqj670= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789208150; c=relaxed/simple; bh=SjmSpxqAuYgtpzBQ9XDeV2ABXwKg7pySTt9lVRCGSis=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=E5++8mBsfsLoupmXLEundGGf3+CPiswZnwVuVObWo29QLAJ50hWnd/TlseGiLahCaslT9s5Il9Qif9Sm78SEsetPN7tK8uWmqxIai1XQFy+GjoEVN3lwvGLkg+9YSlOoKv+qDXi0Wss22iSJi1stoFQlAHQsK7v9FWEZsCbE9iE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=IuWV02fB; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=dTXEEg7R; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="IuWV02fB"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="dTXEEg7R" Received: from pps.filterd (m0279872.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 68C856Wx1803989 for ; Sat, 12 Sep 2026 10:15:47 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= 01tozVF7OH7LwFf5hthHRqzoedWJYa1DR1n732zt2Cc=; b=IuWV02fBiHX7623D 1dnEXnByTSVhDafzQO0XKrurq8MLCqISde3Lov7C14phfKnsuQkzZhepQjIErNRV ZQngfx0SGzgiq7ilm22kgwCGYVXu7D09QdS198iVBT0S0Lo2rO7WSzVi/QM/48V8 upj6f5/y+BHX55mbIw+Ka2d7OdxdQSDLId/1URxwQliWl7yghoH37g1+0wqSIsBv a0ncNOv1sXBfG/DKk0XTjTAGMpbvjp6njw5G7u/sNmRPH2NsysdG/HNcfiOcg5UI exxqW4L+ZEeGkf/NGwRzBUYnDQbcuUxlTKf2OOe8mnTHyZBygQ/q0aGVKjZrR1xQ fMdHUw== Received: from mail-pj1-f72.google.com (mail-pj1-f72.google.com [209.85.216.72]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4gmy9c8p04-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Sat, 12 Sep 2026 10:15:39 +0000 (GMT) Received: by mail-pj1-f72.google.com with SMTP id 98e67ed59e1d1-38f283baf1fso2094171a91.3 for ; Sat, 12 Sep 2026 03:15:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1789208133; x=1789812933; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=01tozVF7OH7LwFf5hthHRqzoedWJYa1DR1n732zt2Cc=; b=dTXEEg7ReVG/QcIlI6jxFQA8IcEbdWgqXx2hGpIPdNPujR5cVET0eiU+DUxm+3HrXD 5DW8hDRyOvHpvaI07zDlTur8Ps4OOCYlRuaLkwc8CdxSfwr+ZwYdr8Ieq8rJOiKtiEhx DWkYjPnX6uc1t6pQN5A7Jytyy6sKCazwKLvuYDDM2ZQ5P/lXD9TAOLvSql11dBNy2aqQ QkpabRXzIzfGS1LPIsi5zsOlrNKhvstWSfvXox6gWzKMRVm1W5uMcDxyMdW7IL10Wwia 9GWxMCezEaS9xjAQgqnoOvOFyr+u6gLSv83gQFbTJNK1aFh0XGC3jegpZt5J4qKuubR7 eh/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789208133; x=1789812933; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=01tozVF7OH7LwFf5hthHRqzoedWJYa1DR1n732zt2Cc=; b=QHCWpkVRsDt+TMFfOpLQMCPLjsOldSALv6gzHDMZynK4UDylYa/4MI7j6BvZHXEvry rVBM3/rfC4v6EK6lqMHL1GdW6CnQYgDcbh2ZzYCuS/b9MizAPjYoHlw8X8CN1k5v+Yso JBS6sf5HURUjqrt2GhOLl/J11CO53fGBlgxCBX2/ClG7SIudObPLbV+4Sougjz+QMdrM vZa8B/9hLEWKcKH0tR2Lj+qw3cuUvwP7oMPVzphL7NdJwNoOrBr9V17sxWQOx5GP6z+k 3u9RQqgJ00udeFLI1uJYyj7gJ+ucpYe5TtGm93Bdy9wPJpK1Jk43srjiAZx7oJJlgMGF XFig== X-Forwarded-Encrypted: i=1; AKwUvBxtDLZZ2gfq/XpJI6rMxsjL1M4/VQNd/mJsjuyF3fp/HAlUqUVMORSqoiZdlKaa3lLyOkNJ2KipkFAXal8=@vger.kernel.org X-Gm-Message-State: AFuF++lrPfiewCgUrOA7uDdHamwjXyv01wdU8jIIcVXHw6zWTGHbTY8c VufyGM92j+/eQg6Zt2xLhrx1Yl/ML4HmEz18UM5NZkSJJiYh/UEAzWRk7ioJxVp/1To36slzWt7 6iJa6SYVqzRPJOhl38V5BJiM95nkTMFv7Brhiuhcd37E4O5BdQbA9c1to5j5fDrYuuw== X-Gm-Gg: AYBFou3YpqCtv4Ue6U2xePNo+cCIbg4jx+shmT8y4QVBqqTMddwBiNdUIik9iyR/YZL C4QBN74RzcMXYpP7xijjNYQ1uewgCZtaQ15R+h1nXYBbrpvlA4kwgO15u3Ikya/ZWGOMoNTBDw9 mV4InM/UDXzux0LjoTtXL51rASn0BxPsVRiiD/8nSs7DPY+9N1nmfeaYAfbrdj7K7gX1lm8B1w6 wHrLQPJ7ilu2QRDWfGzTBzFqor2laBCy22+ZUPuh8pc0zu4WrUCifaO8aOsAsAkZRZe4osvoImA JY7UzlctNpRXpiRq6GHK0QtMadmrKvsRFSFIj58cqRGSzb3iK61VDVBUiYY6VuG2Qw+y/8sqrXQ /SkNr2lXV0+Qc5Aw7Y40wBM6eUeKG55qvOooZRIb3wwhlEy5tQXYXFP9YgBY= X-Received: by 2002:a17:90b:1d45:b0:398:9be9:ab8f with SMTP id 98e67ed59e1d1-39d9c21cf40mr13833514a91.20.1789208133242; Sat, 12 Sep 2026 03:15:33 -0700 (PDT) X-Received: by 2002:a17:90b:1d45:b0:398:9be9:ab8f with SMTP id 98e67ed59e1d1-39d9c21cf40mr13833448a91.20.1789208132722; Sat, 12 Sep 2026 03:15:32 -0700 (PDT) Received: from hu-azarrabi-lv.qualcomm.com (Global_NAT1.qualcomm.com. [129.46.96.20]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-33baf0ea9a1sm10340085eec.8.2026.09.12.03.15.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Sep 2026 03:15:32 -0700 (PDT) From: Amirreza Zarrabi Date: Sat, 12 Sep 2026 03:15:15 -0700 Subject: [PATCH RFC 4/5] optee: riscv: add asynchronous notifications over the signal bus Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260912-rpmi-tee-service-grp-dev-v1-4-1d1d35c2a859@oss.qualcomm.com> References: <20260912-rpmi-tee-service-grp-dev-v1-0-1d1d35c2a859@oss.qualcomm.com> In-Reply-To: <20260912-rpmi-tee-service-grp-dev-v1-0-1d1d35c2a859@oss.qualcomm.com> To: Jens Wiklander , Sumit Garg , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Rahul Pathak , Anup Patel , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, op-tee@lists.trustedfirmware.org, linux-riscv@lists.infradead.org, devicetree@vger.kernel.org, Amirreza Zarrabi X-Mailer: b4 0.13.0 X-Proofpoint-GUID: j_v8C-ABNmjKjeF6CEdzbkgle9H2agc7 X-Authority-Analysis: v=2.4 cv=Pv4G/AM3 c=1 sm=1 tr=0 ts=6aa5264d cx=c_pps a=RP+M6JBNLl+fLTcSJhASfg==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17 a=IkcTkHD0fZMA:10 a=VdqzKS8jKosA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=yx91gb_oNiZeI1HMLzn7:22 a=EUspDBNiAAAA:8 a=C3oiFVa1e18yrY4R6uUA:9 a=QEXdDO2ut3YA:10 a=iS9zxrgQBfv6-_F4QbHw:22 X-Proofpoint-Spam-Info: AW1haW4tMjYwOTEyMDE0NiBTYWx0ZWRfX7zkr/HClZrrn Zha0YaLcsypnXKJo1pCFr9hS9drAI/yKw1pP6BIPsDk9VFYBAUNJjzgn8IaspgN2PHQWGYC56/h xEb1w9i2oJgQMddMgAUBR8MZGDL8PCA= X-Proofpoint-ORIG-GUID: j_v8C-ABNmjKjeF6CEdzbkgle9H2agc7 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTEyMDE0NiBTYWx0ZWRfXwbJ4Iru1UAHy 5r0YqK6Bhkx15F2tdpM0nupt9e8YeW2lLW4TKpUJjDDDA/FcacjCWJzC/kySyKJl82nKac57HLV rkF/CG1ShbNxjDDBjDB5s3MVLxa259MB0JW1CeZic3tumLtm1i/d6ebFyZZARl3dWUXVtATAzbT wrC6277zjdqibqVupffEXKLyxiEMSVGoYQUnJ3E6Cp4q5pQiDYjaujiQ025XYv2W5ogcXx9nGug BdkC5UyLumEp1Qerq2FvGGyNpdinnZd/jOTsI70giMya9vkEs27DGR350QnOMiGr4yv7cvoTnwL 3fkVW4JWN2d602UC53OHlH+fj3skkewmA9QaTlyEmZ8nCPQg0JsK1vcVv8/llr7Whr9W4hvWlmQ kfqvmsE40Ws3nyYZSM+cFK6/BV4jfg9qMahY5XsNgQ0ThoJeUA4xDD+vEs0ZVyIMhnr/MsMF327 Co3pPnaLEbPwgDvGWhQ== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-09-12_03,2026-09-11_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 bulkscore=0 adultscore=0 suspectscore=0 malwarescore=0 priorityscore=1501 spamscore=0 clxscore=1015 impostorscore=0 lowpriorityscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2609040000 definitions=main-2609120146 Add asynchronous notification support using the RPMI TEE signal bus. Set up a signal bus between OP-TEE and Linux and use the platform interrupt as the availability doorbell. When signalled, retrieve pending signals and pass normal notification values to optee_notif_send(). Reserve one signal value for requesting the OP-TEE bottom-half handler. Enable this only when secure world advertises asynchronous notification support. Signed-off-by: Amirreza Zarrabi --- drivers/tee/optee/optee_private.h | 11 ++ drivers/tee/optee/optee_riscv.c | 251 ++++++++++++++++++++++++++++++++++= ++++ drivers/tee/optee/optee_riscv.h | 64 ++++++++++ 3 files changed, 326 insertions(+) diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_pr= ivate.h index cf878b8178f9..2ec53bd330a1 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -181,6 +181,12 @@ struct optee_ffa { * @next_nonce: monotonic nonce source for memory parcel creation * @mutex: serializes access to @global_ids * @global_ids: memory parcel id to tee_shm translation table + * @notif_wq: workqueue for signal-bus asynchronous notification + * @notif_work: work for signal-bus asynchronous notification + * @signal_irq: availability doorbell IRQ, or 0 if async notif unused + * @sender_signals: number of signals OP-TEE may raise to the REE + * @bottom_half_value: signal value that requests an RPC bottom half, or + * U32_MAX if async notif is unused * * This is the RISC-V analog of struct optee_ffa: communication with secure * world OP-TEE OS rides the RPMI TEE service group (RPMI spec section 4.1= 6) @@ -196,6 +202,11 @@ struct optee_riscv { /* Serializes access to @global_ids */ struct mutex mutex; struct rhashtable global_ids; + struct workqueue_struct *notif_wq; + struct work_struct notif_work; + unsigned int signal_irq; + u32 sender_signals; + u32 bottom_half_value; }; =20 struct optee; diff --git a/drivers/tee/optee/optee_riscv.c b/drivers/tee/optee/optee_risc= v.c index 72c9eb85f4fe..b9bb813adef5 100644 --- a/drivers/tee/optee/optee_riscv.c +++ b/drivers/tee/optee/optee_riscv.c @@ -28,6 +28,7 @@ =20 #include #include +#include #include #include #include @@ -46,6 +47,9 @@ #include "optee_riscv.h" #include "optee_rpc_cmd.h" =20 +static int optee_riscv_probe_feature(struct optee *optee, u32 feature_id, + u32 *value); + /* * Low level RPMI TEE service group transport over the SBI MPXY mailbox. * @@ -852,6 +856,242 @@ static int optee_riscv_do_call_with_arg(struct tee_co= ntext *ctx, return optee_riscv_yielding_call(ctx, in, rpc_arg, system_thread); } =20 +/* + * 5b. Asynchronous notification over the signal bus + * + * The TEE service group defines no framework notification events (RPMI sp= ec + * section 4.16.2), so OP-TEE signals the REE asynchronously over the sign= al + * bus (services 0x05-0x08). This is the RISC-V analog of the FF-A + * notification path (optee_ffa_async_notif_init / notif_callback): OP-TEE + * raises a signal, the framework rings an availability doorbell delivered= as + * a System MSI or System IRQ, and the REE retrieves the pending signals w= ith + * TEE_SIGNAL_RETRIEVE. A retrieved signal value is the OP-TEE async + * notification key; the reserved top value requests an RPC bottom half. + */ + +static void notif_work_fn(struct work_struct *work) +{ + struct optee_riscv *optee_riscv =3D container_of(work, struct optee_riscv, + notif_work); + struct optee *optee =3D container_of(optee_riscv, struct optee, riscv); + + optee_do_bottom_half(optee->ctx); +} + +/* + * Drain all pending signals from the framework and dispatch them. Returns + * true if an RPC bottom half was requested by OP-TEE. TEE_SIGNAL_RETRIEVE + * returns the signals of one bus per call and sets MORE_AVAILABLE while o= ther + * buses still have pending signals, so loop until it is clear. + */ +static bool optee_riscv_retrieve_signals(struct optee *optee) +{ + bool do_bottom_half =3D false; + size_t max_signals =3D optee->riscv.sender_signals; + struct rpmi_tee_signal_retrieve_resp *rx; + struct rpmi_mbox_message msg; + size_t rx_len; + u32 flags; + + rx_len =3D struct_size(rx, signal, max_signals); + rx =3D kzalloc(rx_len, GFP_KERNEL); + if (!rx) + return false; + + do { + u32 status, n, i; + + rpmi_mbox_init_send_with_response(&msg, + RPMI_TEE_SRV_SIGNAL_RETRIEVE, + NULL, 0, rx, rx_len); + if (optee_riscv_send(optee, &msg)) + break; + + status =3D le32_to_cpu(rx->status); + if (status =3D=3D (u32)RPMI_ERR_NO_DATA) + break; + if (status) + break; + + n =3D min_t(u32, le32_to_cpu(rx->signal_len), max_signals); + for (i =3D 0; i < n; i++) { + u32 value =3D le32_to_cpu(rx->signal[i]); + + if (value =3D=3D OPTEE_ABI_ASYNC_NOTIF_BOTTOM_HALF) + do_bottom_half =3D true; + else + optee_notif_send(optee, value); + } + + flags =3D le32_to_cpu(rx->flags); + } while (flags & RPMI_TEE_SIGNAL_RETRIEVE_MORE_AVAILABLE); + + kfree(rx); + + return do_bottom_half; +} + +static irqreturn_t notif_irq_handler(int irq, void *dev_id) +{ + struct optee *optee =3D dev_id; + + if (optee_riscv_retrieve_signals(optee)) + queue_work(optee->riscv.notif_wq, &optee->riscv.notif_work); + + return IRQ_HANDLED; +} + +/* + * Arm the OP-TEE asynchronous notification subsystem (OPTEE_ABI_ENABLE_AS= YNC_NOTIF + * blocking call, the mirror of FF-A's OPTEE_FFA_ENABLE_ASYNC_NOTIF). The = reserved + * bottom-half signal value is handed to OP-TEE so that a raise of that va= lue is + * understood as a request to run the driver bottom half rather than as a = plain + * notification key. + */ +static int optee_riscv_enable_async_notif(struct optee *optee) +{ + u64 in[RPMI_TEE_OPTEE_CALL_REGS] =3D { OPTEE_ABI_ENABLE_ASYNC_NOTIF, + optee->riscv.bottom_half_value }; + u64 out[RPMI_TEE_OPTEE_RESP_REGS] =3D { }; + int rc; + + rc =3D optee_riscv_tee_call(optee, in, out); + if (rc) + return rc; + if (out[0]) + return -EINVAL; + + return 0; +} + +/* + * Set up the signal bus with OP-TEE (TEE_SIGNAL_BUS_SETUP, service 0x05) = and + * request the availability doorbell IRQ. The bus must be set up by the REE + * (RPMI spec section 4.16.7) and is sized so every OP-TEE async notificat= ion + * value, plus the reserved bottom-half value, maps to a distinct signal t= hat + * OP-TEE may raise. + */ +static int optee_riscv_setup_signal_bus(struct optee *optee) +{ + struct rpmi_tee_signal_bus_setup_req tx =3D { + .target_id =3D cpu_to_le32(RPMI_TEE_ENDPOINT_OPTEE), + .bus_width =3D cpu_to_le32(OPTEE_ABI_ASYNC_NOTIF_BUS_WIDTH), + /* + * SENDER_SIGNALS (RPMI spec Table 190) is the number of signals + * reserved for us, the sender, to receive: signals 0 <=3D x < N + * are raised by the target (OP-TEE) and read by us. We only + * ever receive notifications from OP-TEE and never raise any, so + * reserve the whole bus for OP-TEE to raise. + */ + .sender_signals =3D cpu_to_le32(OPTEE_ABI_ASYNC_NOTIF_BUS_WIDTH), + }; + struct rpmi_tee_signal_bus_setup_resp rx =3D { }; + struct rpmi_mbox_message msg; + int ret; + + rpmi_mbox_init_send_with_response(&msg, RPMI_TEE_SRV_SIGNAL_BUS_SETUP, + &tx, sizeof(tx), &rx, sizeof(rx)); + ret =3D optee_riscv_send(optee, &msg); + if (ret) + return ret; + if (rx.status) + return rpmi_to_linux_error(le32_to_cpu(rx.status)); + + return 0; +} + +static void optee_riscv_teardown_signal_bus(struct optee *optee) +{ + struct rpmi_tee_signal_bus_teardown_req tx =3D { + .target_id =3D cpu_to_le32(RPMI_TEE_ENDPOINT_OPTEE), + }; + struct rpmi_tee_signal_bus_teardown_resp rx =3D { }; + struct rpmi_mbox_message msg; + + rpmi_mbox_init_send_with_response(&msg, + RPMI_TEE_SRV_SIGNAL_BUS_TEARDOWN, + &tx, sizeof(tx), &rx, sizeof(rx)); + optee_riscv_send(optee, &msg); +} + +/* + * Discover and enable asynchronous notification. Probe the SIGNAL_BUS + * feature word: bits [1:0] give the doorbell transport (System MSI or Sys= tem + * IRQ), [11:2] the maximum bus width and [31:12] the doorbell index. On t= his + * platform the doorbell is wired to the platform device as its interrupt,= so + * the index is resolved through the DT and requested with platform_get_ir= q(). + */ +static int optee_riscv_async_notif_init(struct platform_device *pdev, + struct optee *optee) +{ + u32 feat =3D 0; + int irq, rc; + + rc =3D optee_riscv_probe_feature(optee, RPMI_TEE_FEAT_SIGNAL_BUS, &feat); + if (rc) + return rc; + + if (RPMI_TEE_SIGNAL_BUS_TRANSPORT(feat) =3D=3D RPMI_TEE_SIGNAL_BUS_NONE) + return -EOPNOTSUPP; + if (RPMI_TEE_SIGNAL_BUS_WIDTH(feat) < OPTEE_ABI_ASYNC_NOTIF_BUS_WIDTH) + return -EOPNOTSUPP; + + irq =3D platform_get_irq_optional(pdev, 0); + if (irq < 0) + return irq; + + INIT_WORK(&optee->riscv.notif_work, notif_work_fn); + optee->riscv.notif_wq =3D create_workqueue("optee_notification"); + if (!optee->riscv.notif_wq) { + rc =3D -ENOMEM; + goto err; + } + + optee->riscv.sender_signals =3D OPTEE_ABI_ASYNC_NOTIF_BUS_WIDTH; + + rc =3D optee_riscv_setup_signal_bus(optee); + if (rc) + goto err_wq; + + rc =3D request_threaded_irq(irq, NULL, notif_irq_handler, IRQF_ONESHOT, + "optee_notification", optee); + if (rc) + goto err_bus; + optee->riscv.signal_irq =3D irq; + optee->riscv.bottom_half_value =3D OPTEE_ABI_ASYNC_NOTIF_BOTTOM_HALF; + + rc =3D optee_riscv_enable_async_notif(optee); + if (rc) + goto err_irq; + + return 0; + +err_irq: + free_irq(irq, optee); + optee->riscv.signal_irq =3D 0; +err_bus: + optee_riscv_teardown_signal_bus(optee); +err_wq: + destroy_workqueue(optee->riscv.notif_wq); + optee->riscv.notif_wq =3D NULL; +err: + optee->riscv.sender_signals =3D 0; + optee->riscv.bottom_half_value =3D U32_MAX; + + return rc; +} + +static void optee_riscv_async_notif_uninit(struct optee *optee) +{ + if (optee->riscv.bottom_half_value =3D=3D U32_MAX) + return; + + free_irq(optee->riscv.signal_irq, optee); + optee_riscv_teardown_signal_bus(optee); + destroy_workqueue(optee->riscv.notif_wq); + optee->riscv.notif_wq =3D NULL; +} + /* * 6. Driver initialization * @@ -1238,6 +1478,7 @@ static int optee_riscv_probe(struct platform_device *= pdev) =20 optee->ops =3D &optee_riscv_ops; optee->rpc_param_count =3D rpc_param_count; + optee->riscv.bottom_half_value =3D U32_MAX; =20 if (IS_REACHABLE(CONFIG_RPMB) && (sec_caps & OPTEE_ABI_SEC_CAP_RPMB_PROBE)) @@ -1291,6 +1532,13 @@ static int optee_riscv_probe(struct platform_device = *pdev) if (rc) goto err_close_ctx; =20 + if (sec_caps & OPTEE_ABI_SEC_CAP_ASYNC_NOTIF) { + rc =3D optee_riscv_async_notif_init(pdev, optee); + if (rc) + dev_warn(dev, "Failed to initialize async notifications: %d\n", + rc); + } + rc =3D optee_enumerate_devices(PTA_CMD_GET_DEVICES); if (rc) goto err_unregister_devices; @@ -1306,6 +1554,7 @@ static int optee_riscv_probe(struct platform_device *= pdev) =20 err_unregister_devices: optee_unregister_devices(); + optee_riscv_async_notif_uninit(optee); optee_notif_uninit(optee); err_close_ctx: teedev_close_context(ctx); @@ -1334,6 +1583,8 @@ static void optee_riscv_remove(struct platform_device= *pdev) { struct optee *optee =3D platform_get_drvdata(pdev); =20 + optee_riscv_async_notif_uninit(optee); + optee_remove_common(optee); =20 mutex_destroy(&optee->riscv.mutex); diff --git a/drivers/tee/optee/optee_riscv.h b/drivers/tee/optee/optee_risc= v.h index 2cdbb1fb4eab..33a714b79f98 100644 --- a/drivers/tee/optee/optee_riscv.h +++ b/drivers/tee/optee/optee_riscv.h @@ -82,6 +82,70 @@ enum rpmi_tee_feature_id { #define RPMI_TEE_MEMORY_SHARE_TEE_ONLY 1 #define RPMI_TEE_MEMORY_SHARE_FULL 2 =20 +/* + * SIGNAL_BUS feature word encoding (RPMI spec Table 182, feature id 4). + * + * The TEE service group defines no framework notification events + * (RPMI spec section 4.16.2), so asynchronous notification from OP-TEE ri= des + * the signal bus (services 0x05-0x08) instead. The SIGNAL_BUS feature word + * describes both how the availability doorbell is delivered and the shape= of + * the bus: + * [1:0] transport: 0 unsupported, 1 System MSI, 2 System IRQ + * [11:2] maximum bus width (number of signals per endpoint pair) + * [31:12] System MSI index or System IRQ index of the availability door= bell + */ +#define RPMI_TEE_SIGNAL_BUS_TRANSPORT(v) ((v) & GENMASK(1, 0)) +#define RPMI_TEE_SIGNAL_BUS_WIDTH(v) (((v) & GENMASK(11, 2)) >> 2) +#define RPMI_TEE_SIGNAL_BUS_INDEX(v) (((v) & GENMASK(31, 12)) >> 12) + +#define RPMI_TEE_SIGNAL_BUS_NONE 0 +#define RPMI_TEE_SIGNAL_BUS_MSI 1 +#define RPMI_TEE_SIGNAL_BUS_SYSIRQ 2 + +/* + * Signal bus wire encodings (RPMI spec section 4.16.7-4.16.10, + * Tables 190-197). The bus is always set up by the REE; signals + * 0 <=3D x < sender_signals are raised by the target (OP-TEE) and read by= us. + */ +struct rpmi_tee_signal_bus_setup_req { + __le32 target_id; + __le32 bus_width; + __le32 sender_signals; +}; + +struct rpmi_tee_signal_bus_setup_resp { + __le32 status; +}; + +struct rpmi_tee_signal_bus_teardown_req { + __le32 target_id; +}; + +struct rpmi_tee_signal_bus_teardown_resp { + __le32 status; +}; + +/* TEE_SIGNAL_RETRIEVE response (Table 197); request carries no data. */ +#define RPMI_TEE_SIGNAL_RETRIEVE_MORE_AVAILABLE BIT(31) + +struct rpmi_tee_signal_retrieve_resp { + __le32 status; + __le32 flags; + __le32 target_id; + __le32 signal_len; + __le32 signal[]; +}; + +/* + * Asynchronous notification signal assignment (frozen contract with secure + * world OP-TEE). A raised signal value is the OP-TEE async notification k= ey + * verbatim: values 0 <=3D x < OPTEE_ABI_MAX_ASYNC_NOTIF_VALUE are deliver= ed to + * optee_notif_send(), and the reserved top value requests an RPC bottom h= alf. + * The bus is therefore sized one wider than the maximum notification valu= e. + */ +#define OPTEE_ABI_ASYNC_NOTIF_BOTTOM_HALF OPTEE_ABI_MAX_ASYNC_NOTIF_VALUE +#define OPTEE_ABI_ASYNC_NOTIF_BUS_WIDTH (OPTEE_ABI_MAX_ASYNC_NOTIF_VALUE = + 1) + /* TEE_PROBE_FEATURES request (Table 183) / response (Table 184). */ struct rpmi_tee_probe_features_req { __le32 feature_id; --=20 2.34.1 From nobody Fri Sep 25 12:38:50 2026 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B5AB8425CF0 for ; Sat, 12 Sep 2026 10:15:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789208139; cv=none; b=O21h37gz/cViss4PxrHmZbNGlCIuV9tjuLw01Xz1L1FXQ9j+SJI1jevuWm8ypjJTWVSinLN1WyFBzEzPuex3iDcy2E7pjhFAJeDmG+XQ4BuqbNQXzcrT3dzAwWJPh3+D0gMfhBIo8PYgA54MMNLmDmu9w3J6ytFU+02/yxqgznM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789208139; c=relaxed/simple; bh=48SRyTLQwb6N0QIS0UsPI0LsEuN5TTV58p7/i+2YBbM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Sx/kFbry2AgQn5gWzY0VtNTDe3GZ8/VQSIXkVeBYp+1xmt6D7BA53YWynPYX4XWCJuL+SzSXl5GYWgPh9I/kdg8GQdRuJLrFMybUmhyM7XfxV80quMmHjWmNESDP+E0N1+Ksx9qp+V6HBBMLMFyHejh5BCogofyeKgEl40/OUlY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=h9P10Eq/; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=HDK5+LEW; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="h9P10Eq/"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="HDK5+LEW" Received: from pps.filterd (m0279871.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 68C8531X3019605 for ; Sat, 12 Sep 2026 10:15:36 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= fvGdQtR+Qwoj5VESRUaaVEODegCn4Sli4jhlqF7Rgls=; b=h9P10Eq/EjHe7DFE AHgtUu+UIQ9wbQglsmtTmEED1LS3t9Jq2HDfhzSlGFoAMdZWvziEZf+Xbuz1CSkl uHzWeZY3qegkmYQkSu4W9Tjjkp+sOq0Hcl59jMrptzK4lNfhTlNmvUA9k83gkFNT Z3+6pocgFldsyLB5gwj5JFlGAT/xQC/OxwM6k1ZTxoyI1ATMNZDUQE5AUcvuBO4H /C+arjehUGRr+Kpi87yn0uq5DuuxCnZAzX39PSee4MeIdkcK7af2wBMmeb1P3K/6 9YbX89jsZyIjFZMnCBSsTaCyufqdm3usdlxa9Ig5MDKkZ/vwBqGXW9bfkARkjh+N /lPZZw== Received: from mail-pj1-f70.google.com (mail-pj1-f70.google.com [209.85.216.70]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4gmy9dgp8s-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Sat, 12 Sep 2026 10:15:36 +0000 (GMT) Received: by mail-pj1-f70.google.com with SMTP id 98e67ed59e1d1-398fe469aa0so3077154a91.2 for ; Sat, 12 Sep 2026 03:15:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1789208135; x=1789812935; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=fvGdQtR+Qwoj5VESRUaaVEODegCn4Sli4jhlqF7Rgls=; b=HDK5+LEWsSIbi2SfLCzMdDsRjFQ28FuGKgS7XmWTaNVj5eGNCdtYrdI4Gz09bHBPxu oPWkmbhbYoF5AohvLm9DYPi+u4bR+x+LvJowc4ZiM6RuS4/VVmnYLAMgGfJNcfRtIthw EAjKeHnDjkztD+XHRgAb7M/Wdpwirvfl6bLI+tX6nEKxx6SUuKiPcrv10PO3bh1ZRg0C kcvpw6CiAhQ/Qft3SdDqJcMN6S1gYVsyo2Nfk0LSNKScILHZSsg1whT/vA1viQA4pNJE vbXzsxC/046fA59YRkzBBoHug0CRtG3XXA08FN6OfaYv6ChaHezUh0HqTSrN0K7znbLb 8WFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789208135; x=1789812935; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=fvGdQtR+Qwoj5VESRUaaVEODegCn4Sli4jhlqF7Rgls=; b=n+LbxKjGzlVLTq6FxBLpj4odmm6b8p4VQxz6a0KvG3cCeoK7UZdPWtn/5v7aDhh44w uNky7o7A9hUBNJdQDqM7ouDXa3+1vYNiHUiWbytlxcltDZ5uSSkzIJvkqK6NpqbIRCSj 93C+8P6WpRetY9zWEVDVpz8X155Y++Qnb6u9EaouvzYxkUD/PM1+vv1pjQ2898Dl9C6j F8zygPHE+9HhAtMQqZEz0oXZF6JEL5SHlBdAn67X9Obz3ZHzRJweLCzznRUGoqH7BG6A YYWyBSya6xpXH3TCO/jDlXBXrS+GuweG0zG9qOMFc/I5H5VAbuseuTFQOX8FsgxEMiJg dzpw== X-Forwarded-Encrypted: i=1; AKwUvBx+PCFcZLCNJnMP8mlgPxDZzo94gVrSbS/733CsiabIqiWltVLOnga37Dox8oOYnCjs7oMf6PC5Y6v5++0=@vger.kernel.org X-Gm-Message-State: AFuF++mMYOcitofl1mgRJ6j1XHAHOo1MwkexcFaElzvQOyHrcAYQOqsk n/n0EocAFexZeMxApoxNJk/ajAa2KYk1mg2rqUQrk8QtVNUZ/jYbf5I+7bPHxz9+7OoSzHzXLd0 t8ziztcr3HSB0m+HMx/n3qMnNGBfq5mvyeuPTYpdLU81naACBnW0Z6cd4gtMzrTj32g== X-Gm-Gg: AYBFou2aG43T1+rWumIwUtkzjz+WE+u4FuzwZVlEsNlbcPWImrdP0JwXW1Fek9ghqf2 1TDfiAsT8fUhF1XjUqWTvxxloCN87AnzaSmnUuFatop0ynPc0YnZpPQZrQZzETXyWxdVU+nkGJt ARIUTVdbOjrlquqxB/V/v4fOC/gDgbRv6+zLYUrWzyYwdDR1J9r3wqVg+BouQfWYi77rgQ42XiX T2vOLDZ7DLh+xHWN1jLT3X4wh4ugsGDfQTWpB94C7ljwkoEouB5/IpCEOrCdxsKWKBl9J0+khSX nbNJnj7GsF190nTm+KABO0TdPnR176qZ5ZqVx20VzgXhx5GsnCxSnSsTn4ARyusc7aFO8OeusOw cAwhiG1uiq1CSIu/6X4MqJIXsb1HmcHyo86ia4nwnMW5e+8Mkvxg87cPytvc= X-Received: by 2002:a17:90a:d2cb:b0:37f:ed7e:7e42 with SMTP id 98e67ed59e1d1-39d9c234851mr13405563a91.14.1789208135078; Sat, 12 Sep 2026 03:15:35 -0700 (PDT) X-Received: by 2002:a17:90a:d2cb:b0:37f:ed7e:7e42 with SMTP id 98e67ed59e1d1-39d9c234851mr13405513a91.14.1789208134601; Sat, 12 Sep 2026 03:15:34 -0700 (PDT) Received: from hu-azarrabi-lv.qualcomm.com (Global_NAT1.qualcomm.com. [129.46.96.20]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-33baf0ea9a1sm10340085eec.8.2026.09.12.03.15.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Sep 2026 03:15:34 -0700 (PDT) From: Amirreza Zarrabi Date: Sat, 12 Sep 2026 03:15:16 -0700 Subject: [PATCH RFC 5/5] dt-bindings: tee: add RISC-V RPMI TEE transport Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260912-rpmi-tee-service-grp-dev-v1-5-1d1d35c2a859@oss.qualcomm.com> References: <20260912-rpmi-tee-service-grp-dev-v1-0-1d1d35c2a859@oss.qualcomm.com> In-Reply-To: <20260912-rpmi-tee-service-grp-dev-v1-0-1d1d35c2a859@oss.qualcomm.com> To: Jens Wiklander , Sumit Garg , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Rahul Pathak , Anup Patel , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, op-tee@lists.trustedfirmware.org, linux-riscv@lists.infradead.org, devicetree@vger.kernel.org, Amirreza Zarrabi X-Mailer: b4 0.13.0 X-Proofpoint-GUID: ynXgzwClqiFysxBaMVCK0AhRy89nFnCs X-Proofpoint-ORIG-GUID: ynXgzwClqiFysxBaMVCK0AhRy89nFnCs X-Authority-Analysis: v=2.4 cv=NelzRGD4 c=1 sm=1 tr=0 ts=6aa52648 cx=c_pps a=0uOsjrqzRL749jD1oC5vDA==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17 a=IkcTkHD0fZMA:10 a=VdqzKS8jKosA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=3WHJM1ZQz_JShphwDgj5:22 a=gEfo2CItAAAA:8 a=V1jnuoLLAAAA:20 a=EUspDBNiAAAA:8 a=VwQbUJbxAAAA:8 a=b45o4kL6AAAA:8 a=UjdUaUu09JUVB5va2ocA:9 a=QEXdDO2ut3YA:10 a=mQ_c8vxmzFEMiUWkPHU9:22 a=sptkURWiP4Gy88Gu7hUp:22 a=dhdsR-PFWuPJUldTnwXm:22 a=bA3UWDv6hWIuX7UZL3qL:22 X-Proofpoint-Spam-Info: AW1haW4tMjYwOTEyMDE0NiBTYWx0ZWRfXwWwnGg4nUGga Vlw2mLk+2Bi0ix1Eq2CzL9SVcgNSy2zSpvJBifmfKGUclkKh1Zv3X3UlGrM2lOTqV8UeMykTBh5 tcnmG+rXlZt4uqykxeNgeZSv19gzlCM= X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTEyMDE0NiBTYWx0ZWRfX9P9sGjnSPgv9 XHC3Spau/nt6nSnYwbVxD3DTICjwWyTaea7F5TboHThMzOZBcnPimLU/ugdjzexeDNlqR+LkZkS w9Fj7+5ij00UQGML+CSPjS2eGS+p7mhyKcnRsK/y2w5O5zDTkAwb8bmwJWt9HnCExB0FM/jNsvt g1viahZlD1YZQG41TNFAW0Q4jiUjmbJ+rqrSbt+90bEvtehsoGBcqr7og2cDOwnALju2ClW8EJb sXjch2w2Ht23fpVRpPVMia413La2zcsBcFfJxXY8B22bi3G+wDtKmAOBFAyGNCrwF9k9y1+8q/1 yCVMdDppcAEioXsJSdMELWh4p4SSeYIqmRO/t9Fy9tvKqJVk5T7ckV4U+EaYAK3slbXMUUBjPl2 uJGsnTMvvIVfEXTRgjnt/b6sb/OGGd7mlcdC+nGqRhE+1/wJO1DbMQUT66Yi1ZSCMLpEKTPqP4O hJa3HchRbFB55GzJHJQ== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-09-12_03,2026-09-11_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 adultscore=0 impostorscore=0 priorityscore=1501 clxscore=1015 spamscore=0 malwarescore=0 suspectscore=0 lowpriorityscore=0 phishscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2609040000 definitions=main-2609120146 Add a device-tree binding for the OP-TEE RISC-V transport using the RPMI TEE service group over SBI MPXY. Describe one mailbox channel per hart and an optional interrupt used as the availability doorbell for asynchronous notifications. Add the binding to the existing OP-TEE MAINTAINERS entry. Signed-off-by: Amirreza Zarrabi --- .../bindings/tee/riscv,rpmi-mpxy-tee.yaml | 65 ++++++++++++++++++= ++++ MAINTAINERS | 1 + 2 files changed, 66 insertions(+) diff --git a/Documentation/devicetree/bindings/tee/riscv,rpmi-mpxy-tee.yaml= b/Documentation/devicetree/bindings/tee/riscv,rpmi-mpxy-tee.yaml new file mode 100644 index 000000000000..8f6ff313fd42 --- /dev/null +++ b/Documentation/devicetree/bindings/tee/riscv,rpmi-mpxy-tee.yaml @@ -0,0 +1,65 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/tee/riscv,rpmi-mpxy-tee.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: RISC-V RPMI TEE service group based message proxy + +maintainers: + - Amirreza Zarrabi + +description: | + The RISC-V Platform Management Interface (RPMI) [1] defines a messaging + protocol which is modular and extensible. The supervisor software can + send/receive RPMI messages via the SBI MPXY extension [2] or some dedica= ted + supervisor-mode RPMI transport. + + The RPMI specification [1] defines a TEE service group which is the RISC= -V + analog of Arm FF-A: OP-TEE and the rich execution environment (REE, i.e. + Linux) are peer endpoints and the RPMI framework (machine mode firmware) + mediates every message. Entering OP-TEE on a hart runs it on that hart u= ntil + it responds, so the SBI implementation provides one SBI MPXY channel per + hart; all of them are listed, in hart order, on a single node. + + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + References + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + + [1] RISC-V Platform Management Interface (RPMI) v1.0 (or higher) + https://github.com/riscv-non-isa/riscv-rpmi/releases + + [2] RISC-V Supervisor Binary Interface (SBI) v3.0 (or higher) + https://github.com/riscv-non-isa/riscv-sbi-doc/releases + +properties: + compatible: + const: riscv,rpmi-mpxy-tee + + mboxes: + minItems: 1 + description: + One SBI MPXY channel implementing the RPMI TEE service group per har= t, + listed in the same order as the CPU nodes. + + interrupts: + maxItems: 1 + description: + Availability doorbell raised by OP-TEE to signal asynchronous + notifications over the RPMI TEE signal bus. Optional; when absent + asynchronous notification is disabled. + +required: + - compatible + - mboxes + +additionalProperties: false + +examples: + - | + tee { + compatible =3D "riscv,rpmi-mpxy-tee"; + mboxes =3D <&mpxy_mbox 0x10 0x0>, <&mpxy_mbox 0x11 0x0>; + }; +... diff --git a/MAINTAINERS b/MAINTAINERS index 207a6e2db70c..7d0e550085b2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20577,6 +20577,7 @@ M: Jens Wiklander L: op-tee@lists.trustedfirmware.org (moderated for non-subscribers) S: Maintained F: Documentation/ABI/testing/sysfs-bus-optee-devices +F: Documentation/devicetree/bindings/tee/riscv,rpmi-mpxy-tee.yaml F: drivers/tee/optee/ =20 OP-TEE RANDOM NUMBER GENERATOR (RNG) DRIVER --=20 2.34.1