From: Marouene Boubakri marouene.boubakri@oss.nxp.com
The OP-TEE driver reaches OP-TEE through the SMC ABI or the FF-A ABI, both specific to Arm, and the TEE subsystem and the OP-TEE driver depend on HAVE_ARM_SMCCC. On RISC-V there is no SMC instruction: OP-TEE runs in a domain isolated by the M-mode firmware and is reached through the RISC-V Platform Management Interface (RPMI), carried on an SBI Message Proxy (MPXY) channel, for which Linux already has a mailbox driver.
This series only puts the build plumbing in place for a third ABI next to the SMC and FF-A ones:
- patch 1 builds the Arm-specific code of the driver only on Arm: smc_abi.c when HAVE_ARM_SMCCC is set and ffa_abi.c when ARM_FFA_TRANSPORT is enabled, with stubs for their registration otherwise. The SMCCC header, the SMC and FF-A specific types and the SMC RPC register parameters in optee_private.h are kept under the same conditions, so that nothing Arm-specific is left in the common part of the driver;
- patch 2 adds an RPMI ABI placeholder: an OPTEE_RPMI_ABI option built when the MPXY mailbox driver is enabled, rpmi_abi.c and its registration from the driver core. The transport is not implemented, so the registration fails with -EOPNOTSUPP;
- patch 3 lets the TEE subsystem and the OP-TEE driver be enabled on RISC-V, and teaches the memory type check of the driver about the RISC-V page attributes, without which the driver does not build there. It is kept separate as it changes the dependencies of the subsystem-wide TEE menu.
There is no functional change. On Arm, OPTEE still depends on HAVE_ARM_SMCCC and the SMC and FF-A ABIs are built whenever they can be registered. On RISC-V the driver builds without any Arm-specific code but no ABI registers, so it does not load. The RPMI transport will be implemented on top of this in a separate series.
Testing: [TODO before posting: riscv64 defconfig plus TEE/OP-TEE, built-in and as modules, and arm64 defconfig plus OP-TEE with FF-A built-in, modular and disabled, with W=1 at every step of the series.]
Marouene Boubakri (3): tee: optee: build the Arm-specific code only on Arm tee: optee: add an RPMI ABI placeholder tee: optee: allow enabling the driver on RISC-V
drivers/tee/Kconfig | 2 +- drivers/tee/optee/Kconfig | 10 +++++- drivers/tee/optee/Makefile | 5 +-- drivers/tee/optee/call.c | 8 +++++ drivers/tee/optee/core.c | 8 +++-- drivers/tee/optee/notif.c | 1 - drivers/tee/optee/optee_private.h | 52 ++++++++++++++++++++++++++++++- drivers/tee/optee/rpmi_abi.c | 23 ++++++++++++++ 8 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 drivers/tee/optee/rpmi_abi.c
base-commit: 827751b699b79a6e569983359c02dce67f81b94c
From: Marouene Boubakri marouene.boubakri@oss.nxp.com
The OP-TEE driver reaches OP-TEE through the SMC ABI or the FF-A ABI, both specific to Arm, yet builds both unconditionally together with the SMC Calling Convention definitions they rely on: ffa_abi.c only checks at runtime whether the FF-A transport is reachable, and optee_private.h includes <linux/arm-smccc.h> and defines the SMC and FF-A specific types for every file of the driver. This is fine as long as the driver depends on HAVE_ARM_SMCCC, but it keeps the driver from being built for an architecture without SMCCC, such as RISC-V.
Build smc_abi.c only when HAVE_ARM_SMCCC is set and ffa_abi.c only when ARM_FFA_TRANSPORT is enabled, and provide stubs for their registration otherwise, so that it fails with -EOPNOTSUPP as the FF-A ABI already does when the FF-A transport is not reachable. Keep the SMCCC header, the SMC invoke function type, the SMC and FF-A specific structures and the SMC RPC register parameters in optee_private.h under the same conditions, and drop the unused <linux/arm-smccc.h> include from notif.c.
No functional change: OPTEE still depends on HAVE_ARM_SMCCC, and ffa_abi.c is still built whenever the FF-A ABI can be registered.
Signed-off-by: Marouene Boubakri marouene.boubakri@oss.nxp.com --- drivers/tee/optee/Makefile | 4 ++-- drivers/tee/optee/notif.c | 1 - drivers/tee/optee/optee_private.h | 39 ++++++++++++++++++++++++++++++- 3 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile index ad7049c1c107..183cdde1ac04 100644 --- a/drivers/tee/optee/Makefile +++ b/drivers/tee/optee/Makefile @@ -7,8 +7,8 @@ optee-objs += rpc.o optee-objs += protmem.o optee-objs += supp.o optee-objs += device.o -optee-objs += smc_abi.o -optee-objs += ffa_abi.o +optee-$(CONFIG_HAVE_ARM_SMCCC) += smc_abi.o +optee-$(CONFIG_ARM_FFA_TRANSPORT) += ffa_abi.o
# for tracing framework to find optee_trace.h CFLAGS_smc_abi.o := -I$(src) diff --git a/drivers/tee/optee/notif.c b/drivers/tee/optee/notif.c index 6e85f2f5c516..68014222d7be 100644 --- a/drivers/tee/optee/notif.c +++ b/drivers/tee/optee/notif.c @@ -5,7 +5,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/arm-smccc.h> #include <linux/errno.h> #include <linux/slab.h> #include <linux/spinlock.h> diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h index aefe1e6f5689..94a4f251f5cf 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -6,7 +6,6 @@ #ifndef OPTEE_PRIVATE_H #define OPTEE_PRIVATE_H
-#include <linux/arm-smccc.h> #include <linux/notifier.h> #include <linux/rhashtable.h> #include <linux/rpmb.h> @@ -15,6 +14,10 @@ #include <linux/types.h> #include "optee_msg.h"
+#ifdef CONFIG_HAVE_ARM_SMCCC +#include <linux/arm-smccc.h> +#endif + #define DRIVER_NAME "optee"
#define OPTEE_MAX_ARG_SIZE 1024 @@ -42,10 +45,12 @@ */ #define OPTEE_DEFAULT_MAX_NOTIF_VALUE 255
+#ifdef CONFIG_HAVE_ARM_SMCCC typedef void (optee_invoke_fn)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, struct arm_smccc_res *); +#endif
/** * struct optee_call_waiter - TEE entry may need to wait for a free TEE thread @@ -119,6 +124,7 @@ struct optee_supp { struct completion reqs_c; };
+#ifdef CONFIG_HAVE_ARM_SMCCC /** * struct optee_pcpu - per cpu notif private struct passed to work functions * @optee: optee device reference @@ -149,7 +155,9 @@ struct optee_smc { struct work_struct notif_pcpu_work; unsigned int notif_cpuhp_state; }; +#endif
+#if IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT) /** * struct optee_ffa - FFA communication struct * @ffa_dev: FFA device, contains the destination id, the id of @@ -170,6 +178,7 @@ struct optee_ffa { struct workqueue_struct *notif_wq; struct work_struct notif_work; }; +#endif
struct optee;
@@ -257,8 +266,12 @@ struct optee { const struct optee_ops *ops; struct tee_context *ctx; union { +#ifdef CONFIG_HAVE_ARM_SMCCC struct optee_smc smc; +#endif +#if IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT) struct optee_ffa ffa; +#endif }; struct optee_shm_arg_cache shm_arg_cache; struct optee_call_queue call_queue; @@ -290,6 +303,7 @@ struct optee_context_data { struct list_head sess_list; };
+#ifdef CONFIG_HAVE_ARM_SMCCC struct optee_rpc_param { u32 a0; u32 a1; @@ -300,6 +314,7 @@ struct optee_rpc_param { u32 a6; u32 a7; }; +#endif
/* Holds context that is preserved during one STD call */ struct optee_call_ctx { @@ -422,9 +437,31 @@ static inline void reg_pair_from_64(u32 *reg0, u32 *reg1, u64 val) }
/* Registration of the ABIs */ +#ifdef CONFIG_HAVE_ARM_SMCCC int optee_smc_abi_register(void); void optee_smc_abi_unregister(void); +#else +static inline int optee_smc_abi_register(void) +{ + return -EOPNOTSUPP; +} + +static inline void optee_smc_abi_unregister(void) +{ +} +#endif +#if IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT) int optee_ffa_abi_register(void); void optee_ffa_abi_unregister(void); +#else +static inline int optee_ffa_abi_register(void) +{ + return -EOPNOTSUPP; +} + +static inline void optee_ffa_abi_unregister(void) +{ +} +#endif
#endif /*OPTEE_PRIVATE_H*/
base-commit: 827751b699b79a6e569983359c02dce67f81b94c
From: Marouene Boubakri marouene.boubakri@oss.nxp.com
On RISC-V there is no SMC Calling Convention: OP-TEE runs in a domain isolated by the M-mode firmware and is reached through the RISC-V Platform Management Interface (RPMI), carried on an SBI Message Proxy (MPXY) channel.
Add the skeleton of an RPMI ABI next to the SMC and FF-A ABIs so that the build plumbing is in place: an OPTEE_RPMI_ABI option, built when the MPXY mailbox driver is enabled, rpmi_abi.c and its registration from the driver core. The transport itself is not implemented yet, so optee_rpmi_abi_register() fails with -EOPNOTSUPP and the driver keeps probing through its other ABIs only.
Signed-off-by: Marouene Boubakri marouene.boubakri@oss.nxp.com --- drivers/tee/optee/Kconfig | 8 ++++++++ drivers/tee/optee/Makefile | 1 + drivers/tee/optee/core.c | 8 ++++++-- drivers/tee/optee/optee_private.h | 13 +++++++++++++ drivers/tee/optee/rpmi_abi.c | 23 +++++++++++++++++++++++ 5 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 drivers/tee/optee/rpmi_abi.c
diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig index 50d2051f7f20..0eaedb34673d 100644 --- a/drivers/tee/optee/Kconfig +++ b/drivers/tee/optee/Kconfig @@ -9,6 +9,14 @@ config OPTEE This implements the OP-TEE Trusted Execution Environment (TEE) driver.
+config OPTEE_RPMI_ABI + bool + depends on OPTEE && RISCV_SBI_MPXY_MBOX + default y + help + Reach OP-TEE through the RISC-V Platform Management Interface + (RPMI) carried on an SBI Message Proxy (MPXY) channel. + config OPTEE_INSECURE_LOAD_IMAGE bool "Load OP-TEE image as firmware" default n diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile index 183cdde1ac04..a588f6f4cb2f 100644 --- a/drivers/tee/optee/Makefile +++ b/drivers/tee/optee/Makefile @@ -9,6 +9,7 @@ optee-objs += supp.o optee-objs += device.o optee-$(CONFIG_HAVE_ARM_SMCCC) += smc_abi.o optee-$(CONFIG_ARM_FFA_TRANSPORT) += ffa_abi.o +optee-$(CONFIG_OPTEE_RPMI_ABI) += rpmi_abi.o
# for tracing framework to find optee_trace.h CFLAGS_smc_abi.o := -I$(src) diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index a52c1f498b99..42a8bcab0cb8 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -220,6 +220,7 @@ void optee_remove_common(struct optee *optee)
static int smc_abi_rc; static int ffa_abi_rc; +static int rpmi_abi_rc; static bool intf_is_regged;
static int __init optee_core_init(void) @@ -245,9 +246,10 @@ static int __init optee_core_init(void)
smc_abi_rc = optee_smc_abi_register(); ffa_abi_rc = optee_ffa_abi_register(); + rpmi_abi_rc = optee_rpmi_abi_register();
- /* 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 && rpmi_abi_rc) { if (IS_REACHABLE(CONFIG_RPMB)) { rpmb_interface_unregister(&rpmb_class_intf); intf_is_regged = false; @@ -268,6 +270,8 @@ static void __exit optee_core_exit(void)
if (!smc_abi_rc) optee_smc_abi_unregister(); + if (!rpmi_abi_rc) + optee_rpmi_abi_unregister(); if (!ffa_abi_rc) optee_ffa_abi_unregister(); } diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h index 94a4f251f5cf..5b57d69f1f34 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -463,5 +463,18 @@ static inline void optee_ffa_abi_unregister(void) { } #endif +#if IS_ENABLED(CONFIG_OPTEE_RPMI_ABI) +int optee_rpmi_abi_register(void); +void optee_rpmi_abi_unregister(void); +#else +static inline int optee_rpmi_abi_register(void) +{ + return -EOPNOTSUPP; +} + +static inline void optee_rpmi_abi_unregister(void) +{ +} +#endif
#endif /*OPTEE_PRIVATE_H*/ diff --git a/drivers/tee/optee/rpmi_abi.c b/drivers/tee/optee/rpmi_abi.c new file mode 100644 index 000000000000..01d08892eb55 --- /dev/null +++ b/drivers/tee/optee/rpmi_abi.c @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2026 NXP + * + * OP-TEE ABI over the RISC-V Platform Management Interface (RPMI), + * carried on an SBI Message Proxy (MPXY) channel. + * + * This is a placeholder: the transport is not implemented yet, so the + * ABI never registers and the driver only probes through its other ABIs. + */ + +#include <linux/errno.h> + +#include "optee_private.h" + +int optee_rpmi_abi_register(void) +{ + return -EOPNOTSUPP; +} + +void optee_rpmi_abi_unregister(void) +{ +}
From: Marouene Boubakri marouene.boubakri@oss.nxp.com
The TEE subsystem and the OP-TEE driver depend on HAVE_ARM_SMCCC, so neither can be enabled on RISC-V, where OP-TEE is reached through the RISC-V Platform Management Interface (RPMI) over an SBI Message Proxy (MPXY) channel instead of the SMC Calling Convention.
Now that the Arm-specific code of the driver is only built on Arm and the driver has an RPMI ABI, let TEE and OPTEE be enabled when the SBI MPXY mailbox driver is.
optee_check_mem_type() only lets normal cacheable memory be registered with OP-TEE, since OP-TEE maps registered pages as such and must not observe mismatched memory attributes, and it only knows the Arm page attributes. On RISC-V the memory type of a mapping is encoded in the Svpbmt bits of the PTE (or their T-Head equivalent selected at runtime by the _PAGE_MTMASK alternative): normal cacheable memory (PMA) has them cleared, pgprot_writecombine() and pgprot_noncached() set them. Without Svpbmt the memory type is defined by the PMAs alone, _PAGE_MTMASK is empty and every mapping passes the check, as there is nothing else to inspect.
Signed-off-by: Marouene Boubakri marouene.boubakri@oss.nxp.com --- drivers/tee/Kconfig | 2 +- drivers/tee/optee/Kconfig | 2 +- drivers/tee/optee/call.c | 8 ++++++++ 3 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/tee/Kconfig b/drivers/tee/Kconfig index 98c3ad083940..6434204d899e 100644 --- a/drivers/tee/Kconfig +++ b/drivers/tee/Kconfig @@ -2,7 +2,7 @@ # Generic Trusted Execution Environment Configuration menuconfig TEE tristate "Trusted Execution Environment support" - depends on HAVE_ARM_SMCCC || COMPILE_TEST || CPU_SUP_AMD + depends on HAVE_ARM_SMCCC || COMPILE_TEST || CPU_SUP_AMD || RISCV_SBI_MPXY_MBOX select CRYPTO_LIB_SHA1 select DMA_SHARED_BUFFER select GENERIC_ALLOCATOR diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig index 0eaedb34673d..8998b64df5c7 100644 --- a/drivers/tee/optee/Kconfig +++ b/drivers/tee/optee/Kconfig @@ -2,7 +2,7 @@ # OP-TEE Trusted Execution Environment Configuration config OPTEE tristate "OP-TEE" - depends on HAVE_ARM_SMCCC + depends on HAVE_ARM_SMCCC || RISCV_SBI_MPXY_MBOX depends on MMU depends on RPMB || !RPMB help diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c index e046aff61828..c29bff224848 100644 --- a/drivers/tee/optee/call.c +++ b/drivers/tee/optee/call.c @@ -604,6 +604,14 @@ static bool is_normal_memory(pgprot_t p) #elif defined(CONFIG_ARM64) return ((pgprot_val(p) & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL)) || ((pgprot_val(p) & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL_TAGGED)); +#elif defined(CONFIG_RISCV) + /* + * Svpbmt, or the T-Head equivalent, encodes non-cacheable and I/O + * memory in the memory type bits of the PTE, normal cacheable memory + * (PMA) has them cleared. Without Svpbmt the memory type only comes + * from the PMAs, the mask is empty and all mappings pass the check. + */ + return !(pgprot_val(p) & _PAGE_MTMASK); #else #error "Unsupported architecture" #endif
From: Marouene Boubakri marouene.boubakri@oss.nxp.com
The OP-TEE driver reaches OP-TEE through the SMC ABI or the FF-A ABI, both specific to Arm, and the TEE subsystem and the OP-TEE driver depend on HAVE_ARM_SMCCC. On RISC-V there is no SMC instruction: OP-TEE runs in a domain isolated by the M-mode firmware and is reached through the RISC-V Platform Management Interface (RPMI), carried on an SBI Message Proxy (MPXY) channel, for which Linux already has a mailbox driver.
This series only puts the build plumbing in place for a third ABI next to the SMC and FF-A ones:
- patch 1 builds the Arm-specific code of the driver only on Arm: smc_abi.c when HAVE_ARM_SMCCC is set and ffa_abi.c when ARM_FFA_TRANSPORT is enabled, with stubs for their registration otherwise. The SMCCC header, the SMC and FF-A specific types and the SMC RPC register parameters in optee_private.h are kept under the same conditions, so that nothing Arm-specific is left in the common part of the driver;
- patch 2 adds an RPMI ABI placeholder: an OPTEE_RPMI_ABI option built when the MPXY mailbox driver is enabled, rpmi_abi.c and its registration from the driver core. The transport is not implemented, so the registration fails with -EOPNOTSUPP;
- patch 3 lets the TEE subsystem and the OP-TEE driver be enabled on RISC-V, and teaches the memory type check of the driver about the RISC-V page attributes, without which the driver does not build there. It is kept separate as it changes the dependencies of the subsystem-wide TEE menu.
There is no functional change. On Arm, OPTEE still depends on HAVE_ARM_SMCCC and the SMC and FF-A ABIs are built whenever they can be registered. On RISC-V the driver builds without any Arm-specific code but no ABI registers, so it does not load. The RPMI transport will be implemented on top of this in a separate series.
Testing: Tested with the configurations below, riscv64 and arm64, built-in and as modules, and W=1 at every step of the series.
- riscv64, minimal config + CONFIG_TEE=y CONFIG_OPTEE=y - riscv64, minimal config + CONFIG_TEE=m CONFIG_OPTEE=m - arm64, minimal config + CONFIG_OPTEE=y CONFIG_ARM_FFA_TRANSPORT=y - arm64, minimal config + CONFIG_OPTEE=y CONFIG_ARM_FFA_TRANSPORT=m - arm64, minimal config + CONFIG_OPTEE=y CONFIG_ARM_FFA_TRANSPORT=n
Marouene Boubakri (3): tee: optee: build the Arm-specific code only on Arm tee: optee: add an RPMI ABI placeholder tee: optee: allow enabling the driver on RISC-V
drivers/tee/Kconfig | 2 +- drivers/tee/optee/Kconfig | 10 +++++- drivers/tee/optee/Makefile | 5 +-- drivers/tee/optee/call.c | 8 +++++ drivers/tee/optee/core.c | 8 +++-- drivers/tee/optee/notif.c | 1 - drivers/tee/optee/optee_private.h | 52 ++++++++++++++++++++++++++++++- drivers/tee/optee/rpmi_abi.c | 23 ++++++++++++++ 8 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 drivers/tee/optee/rpmi_abi.c
From: Marouene Boubakri marouene.boubakri@oss.nxp.com
The OP-TEE driver reaches OP-TEE through the SMC ABI or the FF-A ABI, both specific to Arm, yet builds both unconditionally together with the SMC Calling Convention definitions they rely on: ffa_abi.c only checks at runtime whether the FF-A transport is reachable, and optee_private.h includes <linux/arm-smccc.h> and defines the SMC and FF-A specific types for every file of the driver. This is fine as long as the driver depends on HAVE_ARM_SMCCC, but it keeps the driver from being built for an architecture without SMCCC, such as RISC-V.
Build smc_abi.c only when HAVE_ARM_SMCCC is set and ffa_abi.c only when ARM_FFA_TRANSPORT is enabled, and provide stubs for their registration otherwise, so that it fails with -EOPNOTSUPP as the FF-A ABI already does when the FF-A transport is not reachable. Keep the SMCCC header, the SMC invoke function type, the SMC and FF-A specific structures and the SMC RPC register parameters in optee_private.h under the same conditions, and drop the unused <linux/arm-smccc.h> include from notif.c.
No functional change: OPTEE still depends on HAVE_ARM_SMCCC, and ffa_abi.c is still built whenever the FF-A ABI can be registered.
Signed-off-by: Marouene Boubakri marouene.boubakri@oss.nxp.com --- drivers/tee/optee/Makefile | 4 ++-- drivers/tee/optee/notif.c | 1 - drivers/tee/optee/optee_private.h | 39 ++++++++++++++++++++++++++++++- 3 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile index ad7049c1c107..183cdde1ac04 100644 --- a/drivers/tee/optee/Makefile +++ b/drivers/tee/optee/Makefile @@ -7,8 +7,8 @@ optee-objs += rpc.o optee-objs += protmem.o optee-objs += supp.o optee-objs += device.o -optee-objs += smc_abi.o -optee-objs += ffa_abi.o +optee-$(CONFIG_HAVE_ARM_SMCCC) += smc_abi.o +optee-$(CONFIG_ARM_FFA_TRANSPORT) += ffa_abi.o
# for tracing framework to find optee_trace.h CFLAGS_smc_abi.o := -I$(src) diff --git a/drivers/tee/optee/notif.c b/drivers/tee/optee/notif.c index 6e85f2f5c516..68014222d7be 100644 --- a/drivers/tee/optee/notif.c +++ b/drivers/tee/optee/notif.c @@ -5,7 +5,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/arm-smccc.h> #include <linux/errno.h> #include <linux/slab.h> #include <linux/spinlock.h> diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h index aefe1e6f5689..94a4f251f5cf 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -6,7 +6,6 @@ #ifndef OPTEE_PRIVATE_H #define OPTEE_PRIVATE_H
-#include <linux/arm-smccc.h> #include <linux/notifier.h> #include <linux/rhashtable.h> #include <linux/rpmb.h> @@ -15,6 +14,10 @@ #include <linux/types.h> #include "optee_msg.h"
+#ifdef CONFIG_HAVE_ARM_SMCCC +#include <linux/arm-smccc.h> +#endif + #define DRIVER_NAME "optee"
#define OPTEE_MAX_ARG_SIZE 1024 @@ -42,10 +45,12 @@ */ #define OPTEE_DEFAULT_MAX_NOTIF_VALUE 255
+#ifdef CONFIG_HAVE_ARM_SMCCC typedef void (optee_invoke_fn)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, struct arm_smccc_res *); +#endif
/** * struct optee_call_waiter - TEE entry may need to wait for a free TEE thread @@ -119,6 +124,7 @@ struct optee_supp { struct completion reqs_c; };
+#ifdef CONFIG_HAVE_ARM_SMCCC /** * struct optee_pcpu - per cpu notif private struct passed to work functions * @optee: optee device reference @@ -149,7 +155,9 @@ struct optee_smc { struct work_struct notif_pcpu_work; unsigned int notif_cpuhp_state; }; +#endif
+#if IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT) /** * struct optee_ffa - FFA communication struct * @ffa_dev: FFA device, contains the destination id, the id of @@ -170,6 +178,7 @@ struct optee_ffa { struct workqueue_struct *notif_wq; struct work_struct notif_work; }; +#endif
struct optee;
@@ -257,8 +266,12 @@ struct optee { const struct optee_ops *ops; struct tee_context *ctx; union { +#ifdef CONFIG_HAVE_ARM_SMCCC struct optee_smc smc; +#endif +#if IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT) struct optee_ffa ffa; +#endif }; struct optee_shm_arg_cache shm_arg_cache; struct optee_call_queue call_queue; @@ -290,6 +303,7 @@ struct optee_context_data { struct list_head sess_list; };
+#ifdef CONFIG_HAVE_ARM_SMCCC struct optee_rpc_param { u32 a0; u32 a1; @@ -300,6 +314,7 @@ struct optee_rpc_param { u32 a6; u32 a7; }; +#endif
/* Holds context that is preserved during one STD call */ struct optee_call_ctx { @@ -422,9 +437,31 @@ static inline void reg_pair_from_64(u32 *reg0, u32 *reg1, u64 val) }
/* Registration of the ABIs */ +#ifdef CONFIG_HAVE_ARM_SMCCC int optee_smc_abi_register(void); void optee_smc_abi_unregister(void); +#else +static inline int optee_smc_abi_register(void) +{ + return -EOPNOTSUPP; +} + +static inline void optee_smc_abi_unregister(void) +{ +} +#endif +#if IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT) int optee_ffa_abi_register(void); void optee_ffa_abi_unregister(void); +#else +static inline int optee_ffa_abi_register(void) +{ + return -EOPNOTSUPP; +} + +static inline void optee_ffa_abi_unregister(void) +{ +} +#endif
#endif /*OPTEE_PRIVATE_H*/
From: Marouene Boubakri marouene.boubakri@oss.nxp.com
On RISC-V there is no SMC Calling Convention: OP-TEE runs in a domain isolated by the M-mode firmware and is reached through the RISC-V Platform Management Interface (RPMI), carried on an SBI Message Proxy (MPXY) channel.
Add the skeleton of an RPMI ABI next to the SMC and FF-A ABIs so that the build plumbing is in place: an OPTEE_RPMI_ABI option, built when the MPXY mailbox driver is enabled, rpmi_abi.c and its registration from the driver core. The transport itself is not implemented yet, so optee_rpmi_abi_register() fails with -EOPNOTSUPP and the driver keeps probing through its other ABIs only.
Signed-off-by: Marouene Boubakri marouene.boubakri@oss.nxp.com --- drivers/tee/optee/Kconfig | 8 ++++++++ drivers/tee/optee/Makefile | 1 + drivers/tee/optee/core.c | 8 ++++++-- drivers/tee/optee/optee_private.h | 13 +++++++++++++ drivers/tee/optee/rpmi_abi.c | 23 +++++++++++++++++++++++ 5 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 drivers/tee/optee/rpmi_abi.c
diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig index 50d2051f7f20..0eaedb34673d 100644 --- a/drivers/tee/optee/Kconfig +++ b/drivers/tee/optee/Kconfig @@ -9,6 +9,14 @@ config OPTEE This implements the OP-TEE Trusted Execution Environment (TEE) driver.
+config OPTEE_RPMI_ABI + bool + depends on OPTEE && RISCV_SBI_MPXY_MBOX + default y + help + Reach OP-TEE through the RISC-V Platform Management Interface + (RPMI) carried on an SBI Message Proxy (MPXY) channel. + config OPTEE_INSECURE_LOAD_IMAGE bool "Load OP-TEE image as firmware" default n diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile index 183cdde1ac04..a588f6f4cb2f 100644 --- a/drivers/tee/optee/Makefile +++ b/drivers/tee/optee/Makefile @@ -9,6 +9,7 @@ optee-objs += supp.o optee-objs += device.o optee-$(CONFIG_HAVE_ARM_SMCCC) += smc_abi.o optee-$(CONFIG_ARM_FFA_TRANSPORT) += ffa_abi.o +optee-$(CONFIG_OPTEE_RPMI_ABI) += rpmi_abi.o
# for tracing framework to find optee_trace.h CFLAGS_smc_abi.o := -I$(src) diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index a52c1f498b99..42a8bcab0cb8 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -220,6 +220,7 @@ void optee_remove_common(struct optee *optee)
static int smc_abi_rc; static int ffa_abi_rc; +static int rpmi_abi_rc; static bool intf_is_regged;
static int __init optee_core_init(void) @@ -245,9 +246,10 @@ static int __init optee_core_init(void)
smc_abi_rc = optee_smc_abi_register(); ffa_abi_rc = optee_ffa_abi_register(); + rpmi_abi_rc = optee_rpmi_abi_register();
- /* 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 && rpmi_abi_rc) { if (IS_REACHABLE(CONFIG_RPMB)) { rpmb_interface_unregister(&rpmb_class_intf); intf_is_regged = false; @@ -268,6 +270,8 @@ static void __exit optee_core_exit(void)
if (!smc_abi_rc) optee_smc_abi_unregister(); + if (!rpmi_abi_rc) + optee_rpmi_abi_unregister(); if (!ffa_abi_rc) optee_ffa_abi_unregister(); } diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h index 94a4f251f5cf..5b57d69f1f34 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -463,5 +463,18 @@ static inline void optee_ffa_abi_unregister(void) { } #endif +#if IS_ENABLED(CONFIG_OPTEE_RPMI_ABI) +int optee_rpmi_abi_register(void); +void optee_rpmi_abi_unregister(void); +#else +static inline int optee_rpmi_abi_register(void) +{ + return -EOPNOTSUPP; +} + +static inline void optee_rpmi_abi_unregister(void) +{ +} +#endif
#endif /*OPTEE_PRIVATE_H*/ diff --git a/drivers/tee/optee/rpmi_abi.c b/drivers/tee/optee/rpmi_abi.c new file mode 100644 index 000000000000..01d08892eb55 --- /dev/null +++ b/drivers/tee/optee/rpmi_abi.c @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2026 NXP + * + * OP-TEE ABI over the RISC-V Platform Management Interface (RPMI), + * carried on an SBI Message Proxy (MPXY) channel. + * + * This is a placeholder: the transport is not implemented yet, so the + * ABI never registers and the driver only probes through its other ABIs. + */ + +#include <linux/errno.h> + +#include "optee_private.h" + +int optee_rpmi_abi_register(void) +{ + return -EOPNOTSUPP; +} + +void optee_rpmi_abi_unregister(void) +{ +}
From: Marouene Boubakri marouene.boubakri@oss.nxp.com
The TEE subsystem and the OP-TEE driver depend on HAVE_ARM_SMCCC, so neither can be enabled on RISC-V, where OP-TEE is reached through the RISC-V Platform Management Interface (RPMI) over an SBI Message Proxy (MPXY) channel instead of the SMC Calling Convention.
Now that the Arm-specific code of the driver is only built on Arm and the driver has an RPMI ABI, let TEE and OPTEE be enabled when the SBI MPXY mailbox driver is.
optee_check_mem_type() only lets normal cacheable memory be registered with OP-TEE, since OP-TEE maps registered pages as such and must not observe mismatched memory attributes, and it only knows the Arm page attributes. On RISC-V the memory type of a mapping is encoded in the Svpbmt bits of the PTE (or their T-Head equivalent selected at runtime by the _PAGE_MTMASK alternative): normal cacheable memory (PMA) has them cleared, pgprot_writecombine() and pgprot_noncached() set them. Without Svpbmt the memory type is defined by the PMAs alone, _PAGE_MTMASK is empty and every mapping passes the check, as there is nothing else to inspect.
Signed-off-by: Marouene Boubakri marouene.boubakri@oss.nxp.com --- drivers/tee/Kconfig | 2 +- drivers/tee/optee/Kconfig | 2 +- drivers/tee/optee/call.c | 8 ++++++++ 3 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/tee/Kconfig b/drivers/tee/Kconfig index 98c3ad083940..6434204d899e 100644 --- a/drivers/tee/Kconfig +++ b/drivers/tee/Kconfig @@ -2,7 +2,7 @@ # Generic Trusted Execution Environment Configuration menuconfig TEE tristate "Trusted Execution Environment support" - depends on HAVE_ARM_SMCCC || COMPILE_TEST || CPU_SUP_AMD + depends on HAVE_ARM_SMCCC || COMPILE_TEST || CPU_SUP_AMD || RISCV_SBI_MPXY_MBOX select CRYPTO_LIB_SHA1 select DMA_SHARED_BUFFER select GENERIC_ALLOCATOR diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig index 0eaedb34673d..8998b64df5c7 100644 --- a/drivers/tee/optee/Kconfig +++ b/drivers/tee/optee/Kconfig @@ -2,7 +2,7 @@ # OP-TEE Trusted Execution Environment Configuration config OPTEE tristate "OP-TEE" - depends on HAVE_ARM_SMCCC + depends on HAVE_ARM_SMCCC || RISCV_SBI_MPXY_MBOX depends on MMU depends on RPMB || !RPMB help diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c index e046aff61828..c29bff224848 100644 --- a/drivers/tee/optee/call.c +++ b/drivers/tee/optee/call.c @@ -604,6 +604,14 @@ static bool is_normal_memory(pgprot_t p) #elif defined(CONFIG_ARM64) return ((pgprot_val(p) & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL)) || ((pgprot_val(p) & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL_TAGGED)); +#elif defined(CONFIG_RISCV) + /* + * Svpbmt, or the T-Head equivalent, encodes non-cacheable and I/O + * memory in the memory type bits of the PTE, normal cacheable memory + * (PMA) has them cleared. Without Svpbmt the memory type only comes + * from the PMAs, the mask is empty and all mappings pass the check. + */ + return !(pgprot_val(p) & _PAGE_MTMASK); #else #error "Unsupported architecture" #endif
op-tee@lists.trustedfirmware.org