Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
221 changes: 221 additions & 0 deletions Documentation/devicetree/bindings/firmware/mbedtee,rpc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/firmware/mbedtee,rpc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: MbedTEE Trusted Execution Environment

maintainers:
- Xing Loong <xing.xl.loong@gmail.com>

description: |
MbedTEE is a Trusted Execution Environment for embedded systems.
This binding describes the shared-memory regions used for RPC
communication between the Linux REE driver and MbedTEE OS.

The REE and TEE CPUs sharing the RPC memory must be in a
hardware-coherent domain (same CPU cluster, coherent caches).

Two or three reserved-memory regions are required:

rpc-t2r-ring ring buffer for TEE-to-REE notifications (all platforms)
rpc-t2r-shm shared memory for TEE-to-REE RPC payloads (all platforms)
rpc-r2t-ring ring buffer for REE-to-TEE command submissions (RISC-V only)

On ARM/AArch64 the transport uses SMC calls; TEE-to-REE
notifications use a GIC SPI edge interrupt.

On RISC-V the TEE notifies the REE via IMSIC MSI; the REE submits
commands via shared-memory rpc-r2t-ring that the TEE polls. No
REE-to-TEE interrupt is used. No SBI ecall is involved.

properties:
$nodename:
const: mbedtee

compatible:
const: mbedtee,rpc

interrupts:
description:
GIC interrupt used by the TEE to notify the REE of pending RPC
responses (ARM/AArch64 only). Not present on RISC-V platforms which
use IMSIC platform MSI interrupts allocated dynamically at runtime.

msi-parent:
maxItems: 1
description:
IMSIC MSI controller used by the Linux driver to allocate the
TEE-to-REE notification interrupt on RISC-V platforms. Not present on
ARM/AArch64 platforms, which use the interrupts property.

memory-region:
minItems: 2
maxItems: 3
description:
References to reserved-memory regions for REE<->TEE communication.
Entries must match memory-region-names order.

memory-region-names:
minItems: 2
maxItems: 3
items:
enum:
- rpc-t2r-ring
- rpc-t2r-shm
- rpc-r2t-ring

required:
- compatible

allOf:
- if:
required:
- interrupts
then:
required:
- interrupts
- memory-region
- memory-region-names
properties:
msi-parent: false
memory-region:
minItems: 2
maxItems: 2
memory-region-names:
items:
- const: rpc-t2r-ring
- const: rpc-t2r-shm
else:
required:
- msi-parent
- memory-region
- memory-region-names
properties:
memory-region:
minItems: 3
maxItems: 3
memory-region-names:
items:
- const: rpc-t2r-ring
- const: rpc-t2r-shm
- const: rpc-r2t-ring

additionalProperties: false

examples:
- |
/* ARM TrustZone (SMC) */
#include <dt-bindings/interrupt-controller/arm-gic.h>
/ {
#address-cells = <2>;
#size-cells = <2>;

gic: interrupt-controller@2f000000 {
compatible = "arm,gic-v3";
reg = <0 0x2f000000 0 0x10000>,
<0 0x2f100000 0 0x200000>;
interrupt-controller;
#interrupt-cells = <3>;
};

reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;

mbedtee_t2r_ring: rpc-t2r-ring@85f10000 {
reg = <0 0x85f10000 0 0x20000>;
no-map;
};

mbedtee_t2r_shm: rpc-t2r-shm@85f30000 {
reg = <0 0x85f30000 0 0x40000>;
no-map;
};
};

firmware {
mbedtee {
compatible = "mbedtee,rpc";
interrupt-parent = <&gic>;
interrupts = <GIC_SPI 72 IRQ_TYPE_EDGE_RISING>;
memory-region = <&mbedtee_t2r_ring>, <&mbedtee_t2r_shm>;
memory-region-names = "rpc-t2r-ring", "rpc-t2r-shm";
};
};
};

- |
/* RISC-V IMSIC (ring-buffer polling REE->TEE, MSI TEE->REE) */
/ {
#address-cells = <2>;
#size-cells = <2>;

cpus {
#address-cells = <1>;
#size-cells = <0>;

cpu@0 {
device_type = "cpu";
reg = <0>;

cpu0_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
interrupt-controller;
#interrupt-cells = <1>;
};
};
};

imsic: interrupt-controller@28000000 {
compatible = "qemu,imsics", "riscv,imsics";
reg = <0 0x28000000 0 0x1000>;
interrupts-extended = <&cpu0_intc 9>;
interrupt-controller;
#interrupt-cells = <0>;
msi-controller;
#msi-cells = <0>;
riscv,num-ids = <255>;
};

reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;

rv_t2r_ring: rpc-t2r-ring@5f10000 {
reg = <0 0x5f10000 0 0x20000>;
no-map;
};

rv_t2r_shm: rpc-t2r-shm@5f30000 {
reg = <0 0x5f30000 0 0x40000>;
no-map;
};

rv_r2t_ring: rpc-r2t-ring@5f70000 {
reg = <0 0x5f70000 0 0x20000>;
no-map;
};
};

/*
* The riscv container avoids a duplicate /firmware/mbedtee path
* with the ARM example above when the DT checker concatenates
* examples into a single .dts.
*/
riscv {
firmware {
mbedtee {
compatible = "mbedtee,rpc";
msi-parent = <&imsic>;
memory-region = <&rv_t2r_ring>, <&rv_t2r_shm>,
<&rv_r2t_ring>;
memory-region-names = "rpc-t2r-ring", "rpc-t2r-shm",
"rpc-r2t-ring";
};
};
};
};
2 changes: 2 additions & 0 deletions Documentation/devicetree/bindings/vendor-prefixes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1019,6 +1019,8 @@ patternProperties:
description: Maxtor Corporation
"^mayqueen,.*":
description: Mayqueen Technologies Ltd.
"^mbedtee,.*":
description: MbedTEE Trusted Execution Environment project
"^mbvl,.*":
description: Mobiveil Inc.
"^mcube,.*":
Expand Down
1 change: 1 addition & 0 deletions Documentation/tee/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ TEE Subsystem
amd-tee
ts-tee
qtee
mbedtee
155 changes: 155 additions & 0 deletions Documentation/tee/mbedtee.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
.. SPDX-License-Identifier: GPL-2.0

==============================================
MbedTEE (Trusted Execution Environment)
==============================================

The MbedTEE driver supports MbedTEE-based TEEs on ARM TrustZone (SMC calls,
GIC SPI notifications) and RISC-V IMSIC (shared-memory polling, MSI
notifications) platforms.

The driver requires the REE and TEE CPUs that share the RPC shared memory to
be hardware coherent. In practice, the REE/TEE CPUs are expected to be in the
same CPU cluster, with coherent caches and shared visibility for the ring and
payload buffers.

Communication overview
======================

The driver communicates with the TEE using a fixed shared-memory RPC protocol
layered above the architecture-specific call mechanism.

ARM platforms (SMC)
-------------------

On ARM and AArch64 platforms, the driver uses ARM SMC Calling Convention
(SMCCC) to issue fast calls and yield calls to the TEE:

- **Fast calls** (MBEDTEE_RPC_OS_VERSION, MBEDTEE_RPC_SUPPORT_YIELD,
MBEDTEE_RPC_COMPLETE_TEE) are self-contained SMC calls that do
not rely on shared-memory RPC structures.

- **Yield calls** post the physical address of an ``rpc_cmd`` structure
in shared memory to the TEE. The TEE may issue RPC requests back to the
driver before the call completes; kernel-directed RPCs are handled
directly, while supplicant RPCs (filesystem and RPMB) are forwarded to
tee-supplicant.

TEE-to-REE notifications on ARM are delivered via a GIC SPI edge interrupt
specified in the device tree (``interrupts`` property).

RISC-V platforms
----------------

On RISC-V platforms, SMCCC is not available. Communication is split into two
directions:

- **REE to TEE (R2T)**: The driver submits commands by writing the physical
address of an ``rpc_cmd`` structure to a REE-to-TEE ring buffer
(``rpc-r2t-ring``). The TEE polls that ring for new commands. No interrupt
notification is sent; the protocol relies on TEE-side polling.

- **TEE to REE (T2R)**: The TEE writes an ``rpc_cmd`` into the TEE-to-REE
ring and raises an IMSIC MSI to notify the REE driver. The MSI is
allocated at runtime via the ``msi-parent`` DT property and its identity
is published in ``callee_imsic_id``; ``callee_hartid`` tracks the
target hart for migration during CPU hotplug. No SBI ecall is involved.

RISC-V REE-to-TEE polling rationale
-----------------------------------

The REE-to-TEE direction uses polling-only on RISC-V to avoid direct
notification interrupt writes from Linux to TEE-owned interrupt files.
This design is platform-independent and does not require ownership of
TEE-only hart interrupt files. The TEE-to-REE direction remains fully
functional via standard Linux MSI notifications and does not depend on
REE-to-TEE notification latency.

Shared memory regions
=====================

Two or three fixed shared memory regions are described in the device tree:

``rpc-t2r-ring``
Ring buffer used by the TEE to post RPC request notifications to the REE
driver. Present on all platforms.

``rpc-t2r-shm``
Shared memory region carrying the actual ``rpc_cmd`` payloads for
TEE-to-REE RPCs. Present on all platforms.

``rpc-r2t-ring``
Ring buffer used by the REE driver to submit commands to the TEE on
RISC-V IMSIC platforms.

RPC protocol
============

The TEE and REE communicate through the ``rpc_cmd`` structure in shared memory
and ring buffers::

struct rpc_cmd {
u32 id; /* RPC function ID */
u16 size; /* payload size in bytes */
u8 interrupted; /* set if wait was interrupted */
u8 reserved; /* explicit alignment padding */
s32 ret; /* return value */
u32 pad; /* explicit alignment padding */
u64 waiter_id; /* sync RPC request ID echoed on completion */
u64 shm; /* physical address of payload (sync RPC) */
u64 data[]; /* inline payload (async RPC) */
};

struct rpc_ringbuf {
u32 wr; /* producer write pointer */
u32 rd; /* consumer read pointer */
u32 callee_ready; /* callee ready flag */
u32 callee_imsic_id; /* RISC-V only: IMSIC local interrupt id */
u32 callee_hartid; /* RISC-V only: target hart-id for T2R notification */
u32 reserved; /* padding, must be zero */
u8 mem[];
};

For RISC-V T2R MSI, one MSI message targets one hart IMSIC file at a time.
The wire-visible state is split between ``callee_imsic_id`` and
``callee_hartid`` in the ring header; Linux may retarget the MSI across
online CPUs via ``irq_set_affinity()``, and the driver updates those fields
to match the selected hart.



Architecture diagram::

User space Kernel TEE side
~~~~~~~~~~ ~~~~~~ ~~~~~~~~~~~~
+--------+ +--------------+
| Client | | Trusted App |
+--------+ +--------------+
/\ /\
|| +------------+ ||
|| | MbedTEE- | \/
|| | supplicant | +--------------+
|| +------------+ | TEE Internal |
\/ /\ | API |
+-------+ || +--------------+
| TEE | || +---------+---------------+ | MbedTEE |
| Client| || | TEE | MbedTEE | | Trusted OS |
| API | \/ | subsys | client driver | +--------------+
+-------+-------------+-----+--------+----------+----+ |
| Generic TEE API | | RPC (cmd/ring)| |
| IOCTL (TEE_IOC_*) | | SMC / IMSIC | |
+---------------------------+ +---------------+--------------+

Device tree binding
===================

See Documentation/devicetree/bindings/firmware/mbedtee,rpc.yaml for the
complete device tree binding specification, including the RISC-V
``msi-parent`` requirement.

References
==========

- [1] MbedTEE project: https://github.com/mbedtee
- [2] ARM SMC Calling Convention: https://developer.arm.com/architectures/system-architectures/software-standards/smccc
- [3] RISC-V IMSIC specification: https://github.com/riscv/riscv-aia
Loading
Loading