blob: 5f30cfd321c886f17e3196d7a690c5c4d36f61d8 [file] [log] [blame]
Jelle Sels3ef999a2021-03-29 09:35:37 +02001====
2SPMC
3====
4
5This document describes the SPMC (S-EL1) implementation for OP-TEE.
6More information on the SPMC can be found in the FF-A specification can be
7found in the
8`FF-A spec <https://developer.arm.com/documentation/den0077/latest>`_.
9
10.. toctree::
11 :numbered:
12
13SPMC Responsibilities
14=====================
15
16The SPMC is a critical component in the FF-A flow. Some of its major
17responsibilities are:
18
19- Initialisation and run-time management of the SPs:
20 The SPMC component is responsible for initialisation of the
21 Secure Partitions (loading the image, setting up the stack, heap, ...).
22- Routing messages between endpoints:
23 The SPMC is responsible for passing FF-A messages from normal world
24 to SPs and back. It also responsible for passing FF-A messages between
25 SPs.
26- Memory management:
27 The SPMC is responsible for the memory management of the SPs. Memory
28 can be shared between SPs and between a SP to the normal world.
29
30This document describes OP-TEE as a S-EL1 SPMC.
31
32Secure Partitions
33=================
34Secure Partitions (SPs) are the endpoints used in the FF-A protocol. When
35OP-TEE is used as a SPMC SPs run primarily inside S-EL0.
36
37OP-TEE will use FF-A for it transport layer when the OP-TEE ``CFG_CORE_FFA=y``
38configuration flag is enabled.
39The SPMC will expose the OP-TEE core, privileged mode, as an secure endpoint
40itself. This is used to handle all GlobalPlaform programming mode operations.
41All GlobalPlatform messages are encapsulated inside FF-A messages.
42The OP-TEE endpoint will unpack the messages and afterwards handle them as
43standard OP-TEE calls. This is needed as TF-A (S-EL3) does only allow
44FF-A messages to be passed to the secure world when the SPMD is enabled.
45
46SPs run from the initial boot of the system until power down and don't have any
47built-in session management compared to GPD TEE TAs. The only means of
48communicating with the outside world is through messages defined in the FF-A
49specification. The context of a SP is saved between executions.
50
51The
52`Trusted Service <https://www.trustedfirmware.org/projects/trusted-services/>`_
53repository includes the libsp libary which export all needed functions to build
54a S-EL0 SP. It also includes many examples of how to create and implement a SP.
55
56SPMC Program Flow
57=================
58SP images are stored in the OP-TEE image as early TAs are: the binary images are
59embedded in OP-TEE Core in a read-only data section.
60This makes it possible to load SPs during boot and no rich-os is needed in the
61normal world. ``ldelf`` is used to load and initialise the SPs.
62
63Starting SPs
64------------
65SPs are loaded and started as the last step in OP-TEE's initialisation process.
66This is done by adding ``sp_init_all()`` to the ``boot_final`` initcall level.
67
68.. uml::
69 :width: 800
70
71 autoactivate on
72 thread_optee_smc_a64.s -> boot_final
73 boot_final -> secure_partition.c: sp_init_all()
74 loop for each SP
75 secure_partition.c -> secure_partition.c: sp_init_uuid()
76 return
77 end
78 return
79 return
80 autoactivate off
81 thread_optee_smc_a64.s -> thread_optee_smc_a64.s: thread_ffa_msg_wait()
82 thread_optee_smc_a64.s -> thread_optee_smc_a64.s: ffa_msg_loop()
83 autoactivate off
84 thread_optee_smc_a64.s -> SPMD: SMC
85
86:``sp_init_all()``: Initialise all SPs which have been added by the
87 ``SP_PATHS`` compiler option and run them
88:``thread_ffa_msg_wait()``: All SPs are loaded and started. A
89 ``FFA_MSG_WAIT`` message is sent to the Normal
90 World.
91
92
93Each SP is loaded into the system using ``ldelf`` and started. This is based
94around the same process as loading the early TAs.
95All SPs are run after they are loaded and run until a ``FFA_MSG_WAIT`` is sent
96by the SP.
97
98
99.. uml::
100
101 autoactivate on
102 secure_partition.c -> secure_partition.c: sp_init_uuid()
103 secure_partition.c -> secure_partition.c: sp_open_session()
104 secure_partition.c -> secure_partition.c: find_sp()
105 return
106 secure_partition.c -> secure_partition.c: sp_create_session()
107 return
108 secure_partition.c -> secure_partition.c: ldelf_load_ldelf()
109 return
110 secure_partition.c -> secure_partition.c: ldlelf_init_with_ldelf()
111 return
112 secure_partition.c -> secure_partition.c: sp_init_set_registers()
113 return
114 return
115 secure_partition.c -> secure_partition.c: enter_sp()
116 return
117 secure_partition.c -> secure_partition.c: sp_msg_handler()
118 return
119 return
120
121:``init_with_ldelf()``: Load the SP
122:``sp_init_info()``: Initialise the ``struct ffa_init_info``. The
123 ``struct ffa_init_info`` is passed to the SP
124 during it first run.
125:``sp_init_set_registers()``: Initialise the registers of the SP
126:``sp_msg_handler()``: Handle the SPs FF-A message
127
128Once all SPs are loaded and started we return to the SPMD and the Normal World
129is booted.
130
131
132SP message handling
133-------------------
134
135The SPMC is split into 2 main message handlers:
136
137:``thread_spmc_msg_recv()`` thread_spmc.c: Used to handle message coming
138 from the Normal World.
139:``sp_msg_handler()`` spmc_sp_handler.c: Used to handle message where
140 the source or the destination
141 is a SP.
142
143When a ``FFA_MSG_SEND_DIRECT_REQ`` message is received by the SPMC from the
144Normal World, a new thread is started.
145The FF-A message is passed to the thread and it will call the
146``sp_msg_handler()`` function.
147
148Whenever the SPMC (``sp_msg_handler()``) receives a message not intended for
149one of the SPs, it will exit the thread and return to the Normal World
150passing the FF-A message.
151
152Currently only a ``FFA_MSG_SEND_DIRECT_REQ`` can be passed from the Normal
153World to a SP.
154
155.. uml::
156 :width: 800
157
158 skinparam backgroundcolor transparent
159 participant "None-secure world" as None_secure_world
160
161 box "S-EL3"
162 participant SPMD
163 end box
164
165 box "S-EL1"
166 participant thread_spmc
167 participant spmc_sp_handler
168 end box
169
170
171 box "S-EL0"
172 participant SP
173 end box
174
175 autoactivate on
176 None_secure_world -> SPMD: FFA_MSG_SEND_DIRECT_REQ \n <font color=red>SMC
177 SPMD -> thread_spmc: thread_spmc_msg_recv() \n <font color=red>ERET
178
179 thread_spmc -> spmc_sp_handler : spmc_sp_start_thread()
180 == thread ==
181 spmc_sp_handler -> spmc_sp_handler : sp_msg_handler()
182
183 loop FF-A dst != NSW
184 spmc_sp_handler -> spmc_sp_handler: ffa_handle_sp_direct_req()
185 spmc_sp_handler -> spmc_sp_handler: enter_sp()
186 spmc_sp_handler -> spmc_sp_handler: sp_enter_invoke_cmd()
187 autoactivate off
188 spmc_sp_handler -> SP: __thread_enter_user_mode() \n <font color=red>ERET
189 activate SP
190
191 SP -> spmc_sp_handler : (FF-A message) sp_handle_svc() \n <font color=red>SVC
192 deactivate SP
193 activate spmc_sp_handler
194 spmc_sp_handler -> spmc_sp_handler: Store SP context
195 spmc_sp_handler -> spmc_sp_handler: return to sp_enter_invoke_cmd()
196 deactivate spmc_sp_handler
197 spmc_sp_handler -> spmc_sp_handler: Retrieve FF-A message from SP context
198 return
199 return
200 return
201 end
202 return
203 == End of thread ==
204 return
205 return \n <font color=red>SMC
206 return FFA_MSG_SEND_DIRECT_RESP \n <font color=red>ERET
207
208
209Every message received by the SPMC from the Normal World is handled in the
210``thread_spmc_msg_recv()`` function.
211
212When entering a SP we need to be running in a OP-TEE thread. This is needed to
213be able to push the TS session (We push the TS session to get access to the SP
214memory).
215Currently the only possibility to enter a SP from the Normal world is via a
216``FFA_MSG_SEND_DIRECT_REQ``. Whenever we receive a ``FFA_MSG_SEND_DIRECT_REQ``
217message which doesn't have OP-TEE as the endpoint-id, we start a thread and
218forward the FF-A message to the ``sp_msg_handler()``.
219
220The ``sp_msg_handler()`` is responsible for all messages coming or going
221to/from a SP. It runs in a while loop and will handle every message until it
222comes across a messages which is not intended for the secure world.
223After a message is handled by the SPMC or when it needs to be forwarded to a SP,
224``sp_enter()`` is called.
225``sp_enter()`` will copy the FF-A arguments and resume the SP.
226
227When the SPMC needs to have access to the SPs memory, it will call
228``ts_push_current_session()`` to gain access and ``ts_pop_current_session()``
229to release the access.
230
231Running and exiting SPs
232-----------------------
233
234The SPMC resumes/starts the SP by calling the ``sp_enter()``. This will set up
235the SP context and jump into S-EL0.
236Whenever the SP performs a system call it will end up in ``sp_handle_svc()``.
237``sp_handle_svc()`` stores the current context of the SP and makes sure that we
238don't return to S-EL0 but instead returns to S-EL1 back to ``sp_enter()``.
239``sp_enter()`` will pass the FF-A registers (x0-x7) to
240``spmc_sp_msg_handler()``. This will process the FF-A message.
241
242
243RxTx buffer managment
244---------------------
245RxTx buffers are used by the SPMC to exchange information between an endpoint
246and the SPMC. The rxtx_buf struct is used by the SPMC for abstracting buffer
247management.
248Every SP has a ``struct rxtx_buf`` wich will be passed to every function that
249needs access to the rxtx buffer.
250A separate ``struct rxtx_buf`` is defined for the Normal World, which gives
251access to the Normal World buffers.
252
253
254Configuration
255=============
256
257Adding SPs to the Image
258-----------------------
259
260The following flags have to be enabled to enable the SPMC. The SP images
261themself are loaded by using the ``SP_PATHS`` flag.
262These should be added to the OP-TEE configuration inside the OP-TEE/build.git
263directory.
264
265.. code-block:: Make
266
267 OPTEE_OS_COMMON_FLAGS += CFG_CORE_FFA=y # Enable the FF-A transport layer
268 OPTEE_OS_COMMON_FLAGS += SP_PATHS="path/to/sp-xxx.elf path/to/sp-yyy.elf" # Add the SPs to the OP-TEE image
269 TF_A_FLAGS += SPD=spmd SPMD_SPM_AT_SEL2=0 # Build TF-A with the SPMD enabled and without S-EL2
270