* [RFC PATCH v1 1/6] mailbox: riscv-sbi-mpxy: add riscv_sbi_mpxy_mbox_call() for hart-local requests
2026-09-10 1:20 [RFC PATCH v1 0/6] tee: optee: RISC-V support over the RPMI TEE service group marouene.boubakri
@ 2026-09-10 1:20 ` marouene.boubakri
2026-09-10 1:20 ` [RFC PATCH v1 2/6] tee: optee: select the SMC ABI conduit from the firmware node match data marouene.boubakri
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: marouene.boubakri @ 2026-09-10 1:20 UTC (permalink / raw)
To: Jens Wiklander, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Jassi Brar,
Jonathan Corbet
Cc: Sumit Garg, devicetree, linux-kernel, op-tee, linux-doc,
linux-riscv, Marouene Boubakri
From: Marouene Boubakri <marouene.boubakri@oss.nxp.com>
An SBI MPXY message send is not queued in a hardware mailbox: it is an
ecall executed on the calling hart with the calling hart's shared memory
which returns once the SBI implementation has processed the message.
For most RPMI service groups that means forwarding the message to a
platform microcontroller, which takes a bounded time. Some message
protocols are instead processed on the calling hart itself, for example
when the SBI implementation forwards the message to another supervisor
domain and switches the hart to it until it responds (this is the model
of the TEE service group of RPMI v2.0, where TEE_CALL runs the target
TEE on the hart of the caller). Such processing is unbounded and
depends on interrupts reaching the other domain so that it can yield.
Sending such messages through mbox_send_message() is not an option: the
mailbox core calls the controller send_data() callback from msg_submit()
with the channel spinlock held and interrupts disabled. Every hart would
then serialize on a single spinlock, spinning with interrupts disabled
for the whole duration of a message processed on another hart, while
the calling hart would run the other domain with the channel lock held.
Add riscv_sbi_mpxy_mbox_call() which performs the RPMI transfer directly
in the calling context, bypassing the mailbox core queue and channel
lock. The channel must still be requested through the mailbox core so
that its ownership is tracked. Local interrupts are disabled around the
ecall since the per-hart shared memory is also used from hard interrupt
context by mbox_send_message() users such as the RPMI system MSI
irqchip; calls from different harts proceed in parallel because each
hart has its own shared memory.
Signed-off-by: Marouene Boubakri <marouene.boubakri@oss.nxp.com>
---
MAINTAINERS | 1 +
drivers/mailbox/riscv-sbi-mpxy-mbox.c | 60 +++++++++++++++++++++
include/linux/mailbox/riscv-sbi-mpxy-mbox.h | 23 ++++++++
3 files changed, 84 insertions(+)
create mode 100644 include/linux/mailbox/riscv-sbi-mpxy-mbox.h
diff --git a/MAINTAINERS b/MAINTAINERS
index c392ded53..44860f991 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -23581,6 +23581,7 @@ F: drivers/clk/clk-rpmi.c
F: drivers/irqchip/irq-riscv-rpmi-sysmsi.c
F: drivers/mailbox/riscv-sbi-mpxy-mbox.c
F: include/linux/mailbox/riscv-rpmi-message.h
+F: include/linux/mailbox/riscv-sbi-mpxy-mbox.h
RISC-V SPACEMIT SoC Support
M: Yixun Lan <dlan@kernel.org>
diff --git a/drivers/mailbox/riscv-sbi-mpxy-mbox.c b/drivers/mailbox/riscv-sbi-mpxy-mbox.c
index ea69c6b6b..2c80e6fd1 100644
--- a/drivers/mailbox/riscv-sbi-mpxy-mbox.c
+++ b/drivers/mailbox/riscv-sbi-mpxy-mbox.c
@@ -12,6 +12,7 @@
#include <linux/irqchip/riscv-imsic.h>
#include <linux/mailbox_controller.h>
#include <linux/mailbox/riscv-rpmi-message.h>
+#include <linux/mailbox/riscv-sbi-mpxy-mbox.h>
#include <linux/minmax.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -719,6 +720,65 @@ static const struct mbox_chan_ops mpxy_mbox_ops = {
.shutdown = mpxy_mbox_shutdown,
};
+/**
+ * riscv_sbi_mpxy_mbox_call() - Send an RPMI message directly on an MPXY channel
+ * @chan: SBI MPXY mailbox channel owned by the caller
+ * @msg: RPMI message of type RPMI_MBOX_MSG_TYPE_SEND_WITH_RESPONSE or
+ * RPMI_MBOX_MSG_TYPE_SEND_WITHOUT_RESPONSE
+ *
+ * An SBI MPXY message send is not queued anywhere: it is an ecall executed
+ * on the calling hart, using the calling hart's shared memory, which only
+ * returns once the SBI implementation has processed the message. For some
+ * message protocols that processing is unbounded because it runs on the
+ * calling hart itself, for example when the SBI implementation forwards
+ * the message to another supervisor domain and switches the hart to it
+ * until it responds (the RPMI TEE service group's TEE_CALL does this).
+ *
+ * Such messages must not go through mbox_send_message(): the mailbox core
+ * invokes the controller send_data() callback with the channel spinlock
+ * held and interrupts disabled, which would serialize all harts on a single
+ * lock and keep interrupts disabled on the calling hart for the whole
+ * duration of the call.
+ *
+ * This helper bypasses the mailbox core queue and channel lock and performs
+ * the transfer directly in the calling context. Only local interrupts are
+ * disabled around the ecall, because the per-hart shared memory can be used
+ * from hard interrupt context through mbox_send_message() by other clients.
+ * Calls from different harts run concurrently since each hart has its own
+ * shared memory.
+ *
+ * The caller must own @chan through mbox_request_channel() (or a variant of
+ * it) so that no other client can use the channel, and must not use
+ * mbox_send_message() on it concurrently.
+ *
+ * Return: 0 on success or a negative error code.
+ */
+int riscv_sbi_mpxy_mbox_call(struct mbox_chan *chan,
+ struct rpmi_mbox_message *msg)
+{
+ struct mpxy_mbox_channel *mchan;
+ unsigned long flags;
+
+ if (!chan || !chan->cl || !chan->mbox || !msg)
+ return -EINVAL;
+ if (chan->mbox->ops != &mpxy_mbox_ops)
+ return -EINVAL;
+ if (msg->type != RPMI_MBOX_MSG_TYPE_SEND_WITH_RESPONSE &&
+ msg->type != RPMI_MBOX_MSG_TYPE_SEND_WITHOUT_RESPONSE)
+ return -EINVAL;
+
+ mchan = chan->con_priv;
+ if (mchan->attrs.msg_proto_id != SBI_MPXY_MSGPROTO_RPMI_ID)
+ return -EOPNOTSUPP;
+
+ local_irq_save(flags);
+ mpxy_mbox_send_rpmi_data(mchan, msg);
+ local_irq_restore(flags);
+
+ return msg->error;
+}
+EXPORT_SYMBOL_GPL(riscv_sbi_mpxy_mbox_call);
+
/* ====== MPXY platform driver ===== */
static void mpxy_mbox_msi_write(struct msi_desc *desc, struct msi_msg *msg)
diff --git a/include/linux/mailbox/riscv-sbi-mpxy-mbox.h b/include/linux/mailbox/riscv-sbi-mpxy-mbox.h
new file mode 100644
index 000000000..4fb7b04cd
--- /dev/null
+++ b/include/linux/mailbox/riscv-sbi-mpxy-mbox.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2026 NXP */
+
+#ifndef _LINUX_RISCV_SBI_MPXY_MBOX_H_
+#define _LINUX_RISCV_SBI_MPXY_MBOX_H_
+
+#include <linux/errno.h>
+
+struct mbox_chan;
+struct rpmi_mbox_message;
+
+#if IS_ENABLED(CONFIG_RISCV_SBI_MPXY_MBOX)
+int riscv_sbi_mpxy_mbox_call(struct mbox_chan *chan,
+ struct rpmi_mbox_message *msg);
+#else
+static inline int riscv_sbi_mpxy_mbox_call(struct mbox_chan *chan,
+ struct rpmi_mbox_message *msg)
+{
+ return -ENODEV;
+}
+#endif
+
+#endif /* _LINUX_RISCV_SBI_MPXY_MBOX_H_ */
--
2.43.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 7+ messages in thread* [RFC PATCH v1 2/6] tee: optee: select the SMC ABI conduit from the firmware node match data
2026-09-10 1:20 [RFC PATCH v1 0/6] tee: optee: RISC-V support over the RPMI TEE service group marouene.boubakri
2026-09-10 1:20 ` [RFC PATCH v1 1/6] mailbox: riscv-sbi-mpxy: add riscv_sbi_mpxy_mbox_call() for hart-local requests marouene.boubakri
@ 2026-09-10 1:20 ` marouene.boubakri
2026-09-10 1:20 ` [RFC PATCH v1 3/6] tee: optee: teach the memory type check about RISC-V page attributes marouene.boubakri
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: marouene.boubakri @ 2026-09-10 1:20 UTC (permalink / raw)
To: Jens Wiklander, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Jassi Brar,
Jonathan Corbet
Cc: Sumit Garg, devicetree, linux-kernel, op-tee, linux-doc,
linux-riscv, Marouene Boubakri
From: Marouene Boubakri <marouene.boubakri@oss.nxp.com>
The SMC ABI is defined in terms of register arguments and return values
and does not depend on how they reach secure world: smc_abi.c already
abstracts the conduit behind optee_invoke_fn, only its selection is
hard-wired to the SMCCC "method" property of the "linaro,optee-tz" node.
Introduce struct optee_smc_conduit carried by the match data of the
firmware node, move the SMCCC specific wrappers and the "method"
property parsing into the SMCCC conduit and build that conduit only
when the architecture provides SMCCC (__arm_smccc_hvc() has no stub
when CONFIG_HAVE_ARM_SMCCC is not set).
This prepares for a conduit that carries the SMC ABI over RISC-V RPMI
messages. No functional change on Arm.
Signed-off-by: Marouene Boubakri <marouene.boubakri@oss.nxp.com>
---
drivers/tee/optee/smc_abi.c | 32 +++++++++++++++++++++++++++++---
1 file changed, 29 insertions(+), 3 deletions(-)
diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
index b8a2bdac3..221939f72 100644
--- a/drivers/tee/optee/smc_abi.c
+++ b/drivers/tee/optee/smc_abi.c
@@ -1464,6 +1464,20 @@ optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm)
return rc;
}
+/*
+ * struct optee_smc_conduit - conduit used to invoke the SMC ABI
+ * @init: probes the conduit and returns the function invoking the
+ * SMC ABI through it, or an ERR_PTR() on failure
+ *
+ * The SMC ABI is defined in terms of register arguments and return values
+ * (see optee_smc.h) but does not depend on how they reach secure world. A
+ * conduit is selected by the compatible string of the OP-TEE firmware node.
+ */
+struct optee_smc_conduit {
+ optee_invoke_fn *(*init)(struct device *dev);
+};
+
+#ifdef CONFIG_HAVE_ARM_SMCCC
/* Simple wrapper functions to be able to use a function pointer */
static void optee_smccc_smc(unsigned long a0, unsigned long a1,
unsigned long a2, unsigned long a3,
@@ -1483,7 +1497,7 @@ static void optee_smccc_hvc(unsigned long a0, unsigned long a1,
arm_smccc_hvc(a0, a1, a2, a3, a4, a5, a6, a7, res);
}
-static optee_invoke_fn *get_invoke_func(struct device *dev)
+static optee_invoke_fn *optee_smccc_conduit_init(struct device *dev)
{
const char *method;
@@ -1503,6 +1517,11 @@ static optee_invoke_fn *get_invoke_func(struct device *dev)
return ERR_PTR(-EINVAL);
}
+static const struct optee_smc_conduit optee_smccc_conduit = {
+ .init = optee_smccc_conduit_init,
+};
+#endif
+
/* optee_remove - Device Removal Routine
* @pdev: platform device information struct
*
@@ -1728,6 +1747,7 @@ static int optee_protmem_pool_init(struct optee *optee)
static int optee_probe(struct platform_device *pdev)
{
+ const struct optee_smc_conduit *conduit;
optee_invoke_fn *invoke_fn;
struct tee_shm_pool *pool = ERR_PTR(-EINVAL);
struct optee *optee = NULL;
@@ -1741,7 +1761,11 @@ static int optee_probe(struct platform_device *pdev)
u32 sec_caps;
int rc;
- invoke_fn = get_invoke_func(&pdev->dev);
+ conduit = device_get_match_data(&pdev->dev);
+ if (!conduit)
+ return -ENODEV;
+
+ invoke_fn = conduit->init(&pdev->dev);
if (IS_ERR(invoke_fn))
return PTR_ERR(invoke_fn);
@@ -1956,7 +1980,9 @@ static int optee_probe(struct platform_device *pdev)
}
static const struct of_device_id optee_dt_match[] = {
- { .compatible = "linaro,optee-tz" },
+#ifdef CONFIG_HAVE_ARM_SMCCC
+ { .compatible = "linaro,optee-tz", .data = &optee_smccc_conduit },
+#endif
{},
};
MODULE_DEVICE_TABLE(of, optee_dt_match);
--
2.43.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 7+ messages in thread* [RFC PATCH v1 3/6] tee: optee: teach the memory type check about RISC-V page attributes
2026-09-10 1:20 [RFC PATCH v1 0/6] tee: optee: RISC-V support over the RPMI TEE service group marouene.boubakri
2026-09-10 1:20 ` [RFC PATCH v1 1/6] mailbox: riscv-sbi-mpxy: add riscv_sbi_mpxy_mbox_call() for hart-local requests marouene.boubakri
2026-09-10 1:20 ` [RFC PATCH v1 2/6] tee: optee: select the SMC ABI conduit from the firmware node match data marouene.boubakri
@ 2026-09-10 1:20 ` marouene.boubakri
2026-09-10 1:20 ` [RFC PATCH v1 4/6] mailbox: riscv-rpmi-message: add TEE service group definitions marouene.boubakri
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: marouene.boubakri @ 2026-09-10 1:20 UTC (permalink / raw)
To: Jens Wiklander, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Jassi Brar,
Jonathan Corbet
Cc: Sumit Garg, devicetree, linux-kernel, op-tee, linux-doc,
linux-riscv, Marouene Boubakri
From: Marouene Boubakri <marouene.boubakri@oss.nxp.com>
optee_check_mem_type() only lets normal cacheable memory be registered
with secure world since OP-TEE maps registered pages as such and must
not observe mismatched memory 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/optee/call.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
index e046aff61..c29bff224 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
--
2.43.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 7+ messages in thread* [RFC PATCH v1 4/6] mailbox: riscv-rpmi-message: add TEE service group definitions
2026-09-10 1:20 [RFC PATCH v1 0/6] tee: optee: RISC-V support over the RPMI TEE service group marouene.boubakri
` (2 preceding siblings ...)
2026-09-10 1:20 ` [RFC PATCH v1 3/6] tee: optee: teach the memory type check about RISC-V page attributes marouene.boubakri
@ 2026-09-10 1:20 ` marouene.boubakri
2026-09-10 1:20 ` [RFC PATCH v1 5/6] dt-bindings: firmware: add OP-TEE over the RISC-V RPMI TEE service group marouene.boubakri
2026-09-10 1:20 ` [RFC PATCH v1 6/6] tee: optee: add a RISC-V conduit over the " marouene.boubakri
5 siblings, 0 replies; 7+ messages in thread
From: marouene.boubakri @ 2026-09-10 1:20 UTC (permalink / raw)
To: Jens Wiklander, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Jassi Brar,
Jonathan Corbet
Cc: Sumit Garg, devicetree, linux-kernel, op-tee, linux-doc,
linux-riscv, Marouene Boubakri
From: Marouene Boubakri <marouene.boubakri@oss.nxp.com>
The RPMI specification v2.0, currently in development on the main
branch of the specification repository, adds a TEE service group
(SERVICEGROUP_ID 0x0010) which lets a client in a Rich Execution
Environment invoke services in a Trusted Execution Environment through
the M-mode firmware or hypervisor implementing the group. Its TEE_CALL
service is a synchronous request whose target TEE executes on the hart
of the caller until a response is returned.
Add the service group ID and the service IDs, as defined in the
specification draft, so that TEE drivers can use them together with the
SBI MPXY mailbox driver.
Signed-off-by: Marouene Boubakri <marouene.boubakri@oss.nxp.com>
---
include/linux/mailbox/riscv-rpmi-message.h | 25 ++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/include/linux/mailbox/riscv-rpmi-message.h b/include/linux/mailbox/riscv-rpmi-message.h
index e135c6564..0530e1ddd 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
/* RPMI clock service IDs */
enum rpmi_clock_service_id {
@@ -119,6 +120,30 @@ enum rpmi_sysmsi_service_id {
RPMI_SYSMSI_SRV_ID_MAX_COUNT
};
+/* RPMI TEE service IDs */
+enum rpmi_tee_service_id {
+ RPMI_TEE_SRV_ENABLE_NOTIFICATION = 0x01,
+ RPMI_TEE_SRV_PROBE_FEATURES = 0x02,
+ RPMI_TEE_SRV_PROBE_SYSTEM = 0x03,
+ RPMI_TEE_SRV_EXIT = 0x04,
+ RPMI_TEE_SRV_SIGNAL_BUS_SETUP = 0x05,
+ RPMI_TEE_SRV_SIGNAL_BUS_TEARDOWN = 0x06,
+ RPMI_TEE_SRV_SIGNAL_RAISE = 0x07,
+ RPMI_TEE_SRV_SIGNAL_RETRIEVE = 0x08,
+ RPMI_TEE_SRV_MEMORY_PARCEL_CREATE = 0x09,
+ RPMI_TEE_SRV_MEMORY_PARCEL_ACCEPT = 0x0a,
+ RPMI_TEE_SRV_MEMORY_PARCEL_RELEASE = 0x0b,
+ RPMI_TEE_SRV_MEMORY_PARCEL_RECLAIM = 0x0c,
+ RPMI_TEE_SRV_MEMORY_SEGMENT_SEND = 0x0d,
+ RPMI_TEE_SRV_MEMORY_SEGMENT_RECEIVE = 0x0e,
+ RPMI_TEE_SRV_REGISTER_FOR_LIFECYCLE_INFO = 0x0f,
+ RPMI_TEE_SRV_ON_START_INFO = 0x10,
+ RPMI_TEE_SRV_ON_SHUTDOWN_INFO = 0x11,
+ RPMI_TEE_SRV_ON_CHANGED_INFO = 0x12,
+ RPMI_TEE_SRV_CALL = 0x13,
+ RPMI_TEE_SRV_ID_MAX_COUNT
+};
+
/* RPMI Linux mailbox attribute IDs */
enum rpmi_mbox_attribute_id {
RPMI_MBOX_ATTR_SPEC_VERSION,
--
2.43.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 7+ messages in thread* [RFC PATCH v1 5/6] dt-bindings: firmware: add OP-TEE over the RISC-V RPMI TEE service group
2026-09-10 1:20 [RFC PATCH v1 0/6] tee: optee: RISC-V support over the RPMI TEE service group marouene.boubakri
` (3 preceding siblings ...)
2026-09-10 1:20 ` [RFC PATCH v1 4/6] mailbox: riscv-rpmi-message: add TEE service group definitions marouene.boubakri
@ 2026-09-10 1:20 ` marouene.boubakri
2026-09-10 1:20 ` [RFC PATCH v1 6/6] tee: optee: add a RISC-V conduit over the " marouene.boubakri
5 siblings, 0 replies; 7+ messages in thread
From: marouene.boubakri @ 2026-09-10 1:20 UTC (permalink / raw)
To: Jens Wiklander, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Jassi Brar,
Jonathan Corbet
Cc: Sumit Garg, devicetree, linux-kernel, op-tee, linux-doc,
linux-riscv, Marouene Boubakri
From: Marouene Boubakri <marouene.boubakri@oss.nxp.com>
On RISC-V, OP-TEE runs as a supervisor domain isolated from the Rich
Execution Environment by the M-mode firmware. There is no SMC or HVC
instruction to reach it: the kernel invokes OP-TEE through the TEE
service group of the RISC-V Platform Management Interface (RPMI) v2.0,
carried on an SBI Message Proxy (MPXY) channel. Each call is a TEE_CALL
service request whose service data carries the register arguments of
the OP-TEE SMC ABI, so the ABI itself is unchanged from Arm.
Add a binding for such an OP-TEE instance. The compatible string keeps
the "linaro" vendor prefix of "linaro,optee-tz" which identifies the
OP-TEE reference implementation. The node references the MPXY mailbox
channel implementing the TEE service group, and carries the endpoint
identifiers assigned by the RPMI TEE framework to the REE and to OP-TEE
since the framework does not define any way for an endpoint to learn
them other than the optional TEE_PROBE_SYSTEM service, whose CBOR
encoded response cannot be parsed in the kernel.
Signed-off-by: Marouene Boubakri <marouene.boubakri@oss.nxp.com>
---
.../bindings/firmware/linaro,optee-rpmi.yaml | 79 +++++++++++++++++++
MAINTAINERS | 1 +
2 files changed, 80 insertions(+)
create mode 100644 Documentation/devicetree/bindings/firmware/linaro,optee-rpmi.yaml
diff --git a/Documentation/devicetree/bindings/firmware/linaro,optee-rpmi.yaml b/Documentation/devicetree/bindings/firmware/linaro,optee-rpmi.yaml
new file mode 100644
index 000000000..1c3dffc33
--- /dev/null
+++ b/Documentation/devicetree/bindings/firmware/linaro,optee-rpmi.yaml
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/firmware/linaro,optee-rpmi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: OP-TEE accessed through the RISC-V RPMI TEE service group
+
+maintainers:
+ - Marouene Boubakri <marouene.boubakri@oss.nxp.com>
+
+description: |
+ OP-TEE is a piece of software using hardware features to provide a Trusted
+ Execution Environment. On RISC-V, OP-TEE runs as a supervisor domain
+ isolated from the Rich Execution Environment (REE) by the M-mode firmware.
+
+ The REE reaches OP-TEE through the TEE service group of the RISC-V Platform
+ Management Interface (RPMI) [1], carried on a channel of the SBI Message
+ Proxy (MPXY) extension [2]. Each call into OP-TEE is a TEE_CALL service
+ request whose service data carries the register arguments of the OP-TEE
+ SMC ABI (drivers/tee/optee/optee_smc.h), as described in
+ drivers/tee/optee/optee_rpmi.h.
+
+ The RPMI TEE framework (the M-mode firmware) assigns an identifier to each
+ endpoint. The identifiers of the REE and of OP-TEE are required to
+ address TEE_CALL requests and are described here.
+
+ The compatible string uses the same "linaro" vendor prefix as
+ "linaro,optee-tz", which identifies the OP-TEE reference implementation.
+
+ [1] RISC-V Platform Management Interface (RPMI) v2.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:
+ $nodename:
+ const: optee
+
+ compatible:
+ const: linaro,optee-rpmi
+
+ mboxes:
+ maxItems: 1
+ description:
+ SBI MPXY channel implementing the RPMI TEE service group.
+
+ riscv,rpmi-tee-sender-id:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Endpoint identifier of the REE, used as SENDER_ID of the TEE_CALL
+ requests.
+
+ riscv,rpmi-tee-target-id:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Endpoint identifier of OP-TEE, used as TARGET_ID of the TEE_CALL
+ requests.
+
+required:
+ - compatible
+ - mboxes
+ - riscv,rpmi-tee-sender-id
+ - riscv,rpmi-tee-target-id
+
+additionalProperties: false
+
+examples:
+ - |
+ firmware {
+ optee {
+ compatible = "linaro,optee-rpmi";
+ mboxes = <&mpxy_mbox 0x10 0x0>;
+ riscv,rpmi-tee-sender-id = <0>;
+ riscv,rpmi-tee-target-id = <1>;
+ };
+ };
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index 44860f991..bf4884f34 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20415,6 +20415,7 @@ M: Jens Wiklander <jenswi@kernel.org>
L: op-tee@lists.trustedfirmware.org (moderated for non-subscribers)
S: Maintained
F: Documentation/ABI/testing/sysfs-bus-optee-devices
+F: Documentation/devicetree/bindings/firmware/linaro,optee-rpmi.yaml
F: drivers/tee/optee/
OP-TEE RANDOM NUMBER GENERATOR (RNG) DRIVER
--
2.43.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 7+ messages in thread* [RFC PATCH v1 6/6] tee: optee: add a RISC-V conduit over the RPMI TEE service group
2026-09-10 1:20 [RFC PATCH v1 0/6] tee: optee: RISC-V support over the RPMI TEE service group marouene.boubakri
` (4 preceding siblings ...)
2026-09-10 1:20 ` [RFC PATCH v1 5/6] dt-bindings: firmware: add OP-TEE over the RISC-V RPMI TEE service group marouene.boubakri
@ 2026-09-10 1:20 ` marouene.boubakri
5 siblings, 0 replies; 7+ messages in thread
From: marouene.boubakri @ 2026-09-10 1:20 UTC (permalink / raw)
To: Jens Wiklander, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Jassi Brar,
Jonathan Corbet
Cc: Sumit Garg, devicetree, linux-kernel, op-tee, linux-doc,
linux-riscv, Marouene Boubakri
From: Marouene Boubakri <marouene.boubakri@oss.nxp.com>
On RISC-V, OP-TEE runs as a supervisor domain isolated from the Rich
Execution Environment by the M-mode firmware. There is no SMC or HVC
instruction to reach it: the kernel invokes OP-TEE through the TEE
service group of the RISC-V Platform Management Interface (RPMI) v2.0,
whose TEE_CALL service is carried by the SBI Message Proxy (MPXY)
extension of SBI v3.0. The M-mode firmware implementing the service
group (the RPMI TEE framework) switches the calling hart to the OP-TEE
domain until OP-TEE responds, so a TEE_CALL behaves exactly like an
SMC: it runs on the calling hart and returns when OP-TEE completes the
call, requests an RPC or yields on a foreign interrupt.
Add a conduit for the SMC ABI which sends the register arguments a0-a7
of each invocation as the service data of a TEE_CALL request and takes
the return values a0-a3 from its service response, using the OP-TEE API
UID as the service UUID. The TEE_CALL request and response follow the
specification, only the content of the service data and of the service
response, which the specification leaves to the service, is defined
here. The message layout is in optee_rpmi.h which is kept in sync with
OP-TEE OS like optee_smc.h and optee_msg.h. The SMC ABI itself, the
message protocol, the RPC handling, dynamic and static shared memory
and notifications are unchanged.
The conduit binds to a "linaro,optee-rpmi" firmware node referencing the
MPXY mailbox channel and carrying the REE and OP-TEE endpoint
identifiers assigned by the framework. The channel is requested through
the mailbox core to claim it, and its RPMI attributes are checked at
probe, but TEE_CALL requests are sent with riscv_sbi_mpxy_mbox_call()
rather than mbox_send_message(): OP-TEE executes on the calling hart for
an unbounded time, which cannot happen under the mailbox channel
spinlock with interrupts disabled. Errors reported by the SBI
implementation or the framework, which mean that OP-TEE was not
reached, are converted into OPTEE_SMC_RETURN_EBUSY or
OPTEE_SMC_RETURN_ENOTAVAIL so that the callers see a failed call.
Signed-off-by: Marouene Boubakri <marouene.boubakri@oss.nxp.com>
---
Documentation/tee/op-tee.rst | 18 ++-
drivers/tee/Kconfig | 2 +-
drivers/tee/optee/Kconfig | 11 +-
drivers/tee/optee/Makefile | 1 +
drivers/tee/optee/optee_private.h | 3 +
drivers/tee/optee/optee_rpmi.h | 69 ++++++++++
drivers/tee/optee/rpmi_conduit.c | 203 ++++++++++++++++++++++++++++++
drivers/tee/optee/smc_abi.c | 9 ++
8 files changed, 312 insertions(+), 4 deletions(-)
create mode 100644 drivers/tee/optee/optee_rpmi.h
create mode 100644 drivers/tee/optee/rpmi_conduit.c
diff --git a/Documentation/tee/op-tee.rst b/Documentation/tee/op-tee.rst
index b0ac097d5..b56c32bf2 100644
--- a/Documentation/tee/op-tee.rst
+++ b/Documentation/tee/op-tee.rst
@@ -4,14 +4,24 @@
OP-TEE (Open Portable Trusted Execution Environment)
====================================================
-The OP-TEE driver handles OP-TEE [1] based TEEs. Currently it is only the ARM
-TrustZone based OP-TEE solution that is supported.
+The OP-TEE driver handles OP-TEE [1] based TEEs. The ARM TrustZone based
+OP-TEE solution and OP-TEE running as an isolated supervisor domain on
+RISC-V are supported.
Lowest level of communication with OP-TEE builds on ARM SMC Calling
Convention (SMCCC) [2], which is the foundation for OP-TEE's SMC interface
[3] used internally by the driver. Stacked on top of that is OP-TEE Message
Protocol [4].
+On RISC-V the SMC interface is unchanged but its register arguments and
+return values are carried by the TEE_CALL service of the TEE service group
+of the RISC-V Platform Management Interface (RPMI) [7], sent to the M-mode
+firmware on an SBI Message Proxy (MPXY) channel [8]. The M-mode firmware
+switches the calling hart to the OP-TEE domain until OP-TEE responds, so a
+call behaves like an SMC: it runs on the calling hart and returns when
+OP-TEE completes, requests an RPC or yields on a foreign interrupt. The
+message layout is described in drivers/tee/optee/optee_rpmi.h.
+
OP-TEE SMC interface provides the basic functions required by SMCCC and some
additional functions specific for OP-TEE. The most interesting functions are:
@@ -164,3 +174,7 @@ References
"TEE Client API Specification v1.0" and click download.
[6] https://trustedfirmware-a.readthedocs.io/en/latest/threat_model/threat_model.html
+
+[7] https://github.com/riscv-non-isa/riscv-rpmi/releases
+
+[8] https://github.com/riscv-non-isa/riscv-sbi-doc/releases
diff --git a/drivers/tee/Kconfig b/drivers/tee/Kconfig
index 98c3ad083..6434204d8 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 50d2051f7..0b6cd91a8 100644
--- a/drivers/tee/optee/Kconfig
+++ b/drivers/tee/optee/Kconfig
@@ -2,13 +2,22 @@
# 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 RISCV_SBI_MPXY_MBOX || !RISCV_SBI_MPXY_MBOX
depends on MMU
depends on RPMB || !RPMB
help
This implements the OP-TEE Trusted Execution Environment (TEE)
driver.
+config OPTEE_RPMI_CONDUIT
+ bool
+ depends on OPTEE && RISCV_SBI_MPXY_MBOX
+ default y
+ help
+ Reach OP-TEE through the TEE service group of the RISC-V Platform
+ Management Interface (RPMI) 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 ad7049c1c..4b5a868a9 100644
--- a/drivers/tee/optee/Makefile
+++ b/drivers/tee/optee/Makefile
@@ -9,6 +9,7 @@ optee-objs += supp.o
optee-objs += device.o
optee-objs += smc_abi.o
optee-objs += ffa_abi.o
+optee-$(CONFIG_OPTEE_RPMI_CONDUIT) += rpmi_conduit.o
# for tracing framework to find optee_trace.h
CFLAGS_smc_abi.o := -I$(src)
diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
index aefe1e6f5..b90359988 100644
--- a/drivers/tee/optee/optee_private.h
+++ b/drivers/tee/optee/optee_private.h
@@ -424,6 +424,9 @@ static inline void reg_pair_from_64(u32 *reg0, u32 *reg1, u64 val)
/* Registration of the ABIs */
int optee_smc_abi_register(void);
void optee_smc_abi_unregister(void);
+#if IS_ENABLED(CONFIG_OPTEE_RPMI_CONDUIT)
+optee_invoke_fn *optee_rpmi_conduit_init(struct device *dev);
+#endif
int optee_ffa_abi_register(void);
void optee_ffa_abi_unregister(void);
diff --git a/drivers/tee/optee/optee_rpmi.h b/drivers/tee/optee/optee_rpmi.h
new file mode 100644
index 000000000..89821255b
--- /dev/null
+++ b/drivers/tee/optee/optee_rpmi.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */
+/*
+ * Copyright 2026 NXP
+ */
+#ifndef OPTEE_RPMI_H
+#define OPTEE_RPMI_H
+
+#include <linux/types.h>
+#include <linux/uuid.h>
+
+/*
+ * This file defines how the OP-TEE SMC ABI (optee_smc.h) is carried by the
+ * TEE service group of the RISC-V Platform Management Interface (RPMI). It
+ * is kept in sync between secure world and the normal world driver.
+ *
+ * An invocation of the SMC ABI is a TEE_CALL service request sent to the
+ * RPMI TEE framework on an SBI MPXY channel where:
+ * - SENDER_ID identifies the REE endpoint and TARGET_ID the OP-TEE
+ * endpoint, both assigned by the framework,
+ * - SERVICE is OPTEE_RPMI_SERVICE_UUID in RFC 4122 byte order,
+ * - SERVICE_DATA carries the register arguments a0-a7 of the SMC ABI as
+ * little-endian 64-bit words.
+ *
+ * The SERVICE_RSP of the TEE_CALL response carries the return values a0-a3
+ * of the SMC ABI as little-endian 64-bit words. The STATUS of the response
+ * is set by the framework and is RPMI_SUCCESS whenever OP-TEE was reached,
+ * errors reported by OP-TEE itself are returned in a0 as usual.
+ */
+
+/*
+ * UUID identifying the OP-TEE API as a TEE_CALL service, the same value
+ * as returned by OPTEE_SMC_CALLS_UID (OPTEE_MSG_UID_0..3).
+ */
+#define OPTEE_RPMI_SERVICE_UUID \
+ UUID_INIT(0x384fb3e0, 0xe7f8, 0x11e3, \
+ 0xaf, 0x63, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b)
+
+#define OPTEE_RPMI_CALL_NUM_ARGS 8
+#define OPTEE_RPMI_CALL_NUM_RETS 4
+
+/**
+ * struct optee_rpmi_call_req - TEE_CALL request data invoking the SMC ABI
+ * @sender_id: SENDER_ID, endpoint identifier of the REE
+ * @target_id: TARGET_ID, endpoint identifier of OP-TEE
+ * @service: SERVICE, bytes of OPTEE_RPMI_SERVICE_UUID
+ * @data_len: SERVICE_DATA_LEN, sizeof(@args)
+ * @args: SERVICE_DATA, register arguments a0-a7 of the SMC ABI
+ */
+struct optee_rpmi_call_req {
+ __le32 sender_id;
+ __le32 target_id;
+ u8 service[UUID_SIZE];
+ __le32 data_len;
+ __le64 args[OPTEE_RPMI_CALL_NUM_ARGS];
+} __packed;
+
+/**
+ * struct optee_rpmi_call_rsp - TEE_CALL response data of the SMC ABI
+ * @status: STATUS, RPMI error code set by the framework
+ * @rsp_len: SERVICE_RSP_LEN, sizeof(@rets)
+ * @rets: SERVICE_RSP, return values a0-a3 of the SMC ABI
+ */
+struct optee_rpmi_call_rsp {
+ __le32 status;
+ __le32 rsp_len;
+ __le64 rets[OPTEE_RPMI_CALL_NUM_RETS];
+} __packed;
+
+#endif /*OPTEE_RPMI_H*/
diff --git a/drivers/tee/optee/rpmi_conduit.c b/drivers/tee/optee/rpmi_conduit.c
new file mode 100644
index 000000000..bc4ff975c
--- /dev/null
+++ b/drivers/tee/optee/rpmi_conduit.c
@@ -0,0 +1,203 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2026 NXP
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/arm-smccc.h>
+#include <linux/build_bug.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/mailbox_client.h>
+#include <linux/mailbox/riscv-rpmi-message.h>
+#include <linux/mailbox/riscv-sbi-mpxy-mbox.h>
+#include <linux/printk.h>
+#include <linux/property.h>
+#include <linux/types.h>
+#include <linux/uuid.h>
+#include "optee_private.h"
+#include "optee_rpmi.h"
+#include "optee_smc.h"
+
+/*
+ * This file implements the conduit carrying the SMC ABI over the TEE
+ * service group of the RISC-V Platform Management Interface (RPMI). Each
+ * invocation of the ABI is a TEE_CALL request sent on an SBI MPXY channel
+ * with the message layout described in optee_rpmi.h.
+ *
+ * The TEE_CALL request is not sent with mbox_send_message(): the target
+ * TEE executes on the calling hart until it responds, so the transfer is
+ * done with riscv_sbi_mpxy_mbox_call() which bypasses the mailbox core
+ * queue and channel lock. Calls from different harts run concurrently,
+ * exactly like SMCs do.
+ */
+
+static_assert(sizeof(struct optee_rpmi_call_req) == 92);
+static_assert(sizeof(struct optee_rpmi_call_rsp) == 40);
+
+/**
+ * struct optee_rpmi_conduit - RPMI TEE service group conduit
+ * @cl: mailbox client owning @chan
+ * @chan: SBI MPXY channel implementing the RPMI TEE service group
+ * @sender_id: endpoint identifier of the REE
+ * @target_id: endpoint identifier of OP-TEE
+ */
+struct optee_rpmi_conduit {
+ struct mbox_client cl;
+ struct mbox_chan *chan;
+ u32 sender_id;
+ u32 target_id;
+};
+
+/* Like the rest of the SMC ABI, at most a single OP-TEE instance is supported */
+static struct optee_rpmi_conduit optee_rpmi;
+
+static const uuid_t optee_rpmi_service_uuid = OPTEE_RPMI_SERVICE_UUID;
+
+static void optee_rpmi_invoke_fn(unsigned long a0, unsigned long a1,
+ unsigned long a2, unsigned long a3,
+ unsigned long a4, unsigned long a5,
+ unsigned long a6, unsigned long a7,
+ struct arm_smccc_res *res)
+{
+ struct optee_rpmi_call_req req = {
+ .sender_id = cpu_to_le32(optee_rpmi.sender_id),
+ .target_id = cpu_to_le32(optee_rpmi.target_id),
+ .data_len = cpu_to_le32(sizeof(req.args)),
+ .args = {
+ cpu_to_le64(a0), cpu_to_le64(a1), cpu_to_le64(a2),
+ cpu_to_le64(a3), cpu_to_le64(a4), cpu_to_le64(a5),
+ cpu_to_le64(a6), cpu_to_le64(a7),
+ },
+ };
+ struct optee_rpmi_call_rsp rsp = {};
+ struct rpmi_mbox_message msg;
+ int rc;
+
+ export_uuid(req.service, &optee_rpmi_service_uuid);
+
+ rpmi_mbox_init_send_with_response(&msg, RPMI_TEE_SRV_CALL,
+ &req, sizeof(req), &rsp, sizeof(rsp));
+ rc = riscv_sbi_mpxy_mbox_call(optee_rpmi.chan, &msg);
+ if (!rc) {
+ if (msg.data.out_response_len < sizeof(rsp.status))
+ rc = -EIO;
+ else
+ rc = rpmi_to_linux_error((s32)le32_to_cpu(rsp.status));
+ }
+ if (!rc && (msg.data.out_response_len < sizeof(rsp) ||
+ le32_to_cpu(rsp.rsp_len) != sizeof(rsp.rets)))
+ rc = -EIO;
+
+ if (rc) {
+ /*
+ * The SBI implementation or the RPMI TEE framework failed to
+ * deliver the call, OP-TEE was not reached. Report it in a0
+ * as the SMC ABI does for a call that could not be handled.
+ */
+ if (rc != -EBUSY)
+ pr_warn_ratelimited("TEE_CALL of 0x%lx failed: %d\n",
+ a0, rc);
+ res->a0 = rc == -EBUSY ? OPTEE_SMC_RETURN_EBUSY :
+ OPTEE_SMC_RETURN_ENOTAVAIL;
+ res->a1 = 0;
+ res->a2 = 0;
+ res->a3 = 0;
+ return;
+ }
+
+ res->a0 = le64_to_cpu(rsp.rets[0]);
+ res->a1 = le64_to_cpu(rsp.rets[1]);
+ res->a2 = le64_to_cpu(rsp.rets[2]);
+ res->a3 = le64_to_cpu(rsp.rets[3]);
+}
+
+static void optee_rpmi_conduit_release(void *data)
+{
+ struct optee_rpmi_conduit *conduit = data;
+
+ mbox_free_channel(conduit->chan);
+ conduit->chan = NULL;
+}
+
+static int optee_rpmi_get_attr(struct optee_rpmi_conduit *conduit,
+ enum rpmi_mbox_attribute_id id, u32 *value)
+{
+ struct rpmi_mbox_message msg;
+ int rc;
+
+ rpmi_mbox_init_get_attribute(&msg, id);
+ rc = rpmi_mbox_send_message(conduit->chan, &msg);
+ if (rc)
+ return rc;
+
+ *value = msg.attr.value;
+ return 0;
+}
+
+optee_invoke_fn *optee_rpmi_conduit_init(struct device *dev)
+{
+ struct optee_rpmi_conduit *conduit = &optee_rpmi;
+ u32 value;
+ int rc;
+
+ if (conduit->chan)
+ return ERR_PTR(-EBUSY);
+
+ rc = device_property_read_u32(dev, "riscv,rpmi-tee-sender-id",
+ &conduit->sender_id);
+ if (rc)
+ return ERR_PTR(dev_err_probe(dev, rc,
+ "missing \"riscv,rpmi-tee-sender-id\" property\n"));
+
+ rc = device_property_read_u32(dev, "riscv,rpmi-tee-target-id",
+ &conduit->target_id);
+ if (rc)
+ return ERR_PTR(dev_err_probe(dev, rc,
+ "missing \"riscv,rpmi-tee-target-id\" property\n"));
+
+ conduit->cl.dev = dev;
+ conduit->cl.tx_block = false;
+ conduit->cl.knows_txdone = true;
+ conduit->chan = mbox_request_channel(&conduit->cl, 0);
+ if (IS_ERR(conduit->chan)) {
+ rc = PTR_ERR(conduit->chan);
+ conduit->chan = NULL;
+ return ERR_PTR(dev_err_probe(dev, rc,
+ "failed to request MPXY channel\n"));
+ }
+
+ rc = devm_add_action_or_reset(dev, optee_rpmi_conduit_release, conduit);
+ if (rc)
+ return ERR_PTR(rc);
+
+ rc = optee_rpmi_get_attr(conduit, RPMI_MBOX_ATTR_SERVICEGROUP_ID,
+ &value);
+ if (rc)
+ return ERR_PTR(dev_err_probe(dev, rc,
+ "failed to read RPMI service group ID\n"));
+ if (value != RPMI_SRVGRP_TEE) {
+ dev_err(dev, "MPXY channel implements RPMI service group 0x%x, not TEE\n",
+ value);
+ return ERR_PTR(-ENODEV);
+ }
+
+ rc = optee_rpmi_get_attr(conduit, RPMI_MBOX_ATTR_MAX_MSG_DATA_SIZE,
+ &value);
+ if (rc)
+ return ERR_PTR(dev_err_probe(dev, rc,
+ "failed to read RPMI max message size\n"));
+ if (value < sizeof(struct optee_rpmi_call_req) ||
+ value < sizeof(struct optee_rpmi_call_rsp)) {
+ dev_err(dev, "MPXY channel message size %u is too small\n",
+ value);
+ return ERR_PTR(-EINVAL);
+ }
+
+ pr_info("using RPMI TEE service group, endpoints %u -> %u\n",
+ conduit->sender_id, conduit->target_id);
+
+ return optee_rpmi_invoke_fn;
+}
diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
index 221939f72..3d5d54526 100644
--- a/drivers/tee/optee/smc_abi.c
+++ b/drivers/tee/optee/smc_abi.c
@@ -1522,6 +1522,12 @@ static const struct optee_smc_conduit optee_smccc_conduit = {
};
#endif
+#if IS_ENABLED(CONFIG_OPTEE_RPMI_CONDUIT)
+static const struct optee_smc_conduit optee_rpmi_conduit = {
+ .init = optee_rpmi_conduit_init,
+};
+#endif
+
/* optee_remove - Device Removal Routine
* @pdev: platform device information struct
*
@@ -1982,6 +1988,9 @@ static int optee_probe(struct platform_device *pdev)
static const struct of_device_id optee_dt_match[] = {
#ifdef CONFIG_HAVE_ARM_SMCCC
{ .compatible = "linaro,optee-tz", .data = &optee_smccc_conduit },
+#endif
+#if IS_ENABLED(CONFIG_OPTEE_RPMI_CONDUIT)
+ { .compatible = "linaro,optee-rpmi", .data = &optee_rpmi_conduit },
#endif
{},
};
--
2.43.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 7+ messages in thread