blob: d8d49cab178a89d5d0f362ae4c6ce6372ac545ba [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=================
Balint Dobszayfe29e2b2022-09-27 15:41:30 +020058SP images are either embedded into the OP-TEE image or loaded from the FIP by
59BL2. This makes it possible to start SPs during boot, before the rich OS is
60available in the normal world. ``ldelf`` is used to load and initialise the SPs.
Jelle Sels3ef999a2021-03-29 09:35:37 +020061
62Starting SPs
63------------
64SPs are loaded and started as the last step in OP-TEE's initialisation process.
65This is done by adding ``sp_init_all()`` to the ``boot_final`` initcall level.
66
67.. uml::
68 :width: 800
69
70 autoactivate on
71 thread_optee_smc_a64.s -> boot_final
72 boot_final -> secure_partition.c: sp_init_all()
73 loop for each SP
74 secure_partition.c -> secure_partition.c: sp_init_uuid()
75 return
76 end
77 return
78 return
79 autoactivate off
80 thread_optee_smc_a64.s -> thread_optee_smc_a64.s: thread_ffa_msg_wait()
81 thread_optee_smc_a64.s -> thread_optee_smc_a64.s: ffa_msg_loop()
82 autoactivate off
83 thread_optee_smc_a64.s -> SPMD: SMC
84
85:``sp_init_all()``: Initialise all SPs which have been added by the
86 ``SP_PATHS`` compiler option and run them
87:``thread_ffa_msg_wait()``: All SPs are loaded and started. A
88 ``FFA_MSG_WAIT`` message is sent to the Normal
89 World.
90
91
92Each SP is loaded into the system using ``ldelf`` and started. This is based
93around the same process as loading the early TAs.
94All SPs are run after they are loaded and run until a ``FFA_MSG_WAIT`` is sent
95by the SP.
96
97
98.. uml::
99
100 autoactivate on
101 secure_partition.c -> secure_partition.c: sp_init_uuid()
102 secure_partition.c -> secure_partition.c: sp_open_session()
103 secure_partition.c -> secure_partition.c: find_sp()
104 return
105 secure_partition.c -> secure_partition.c: sp_create_session()
106 return
107 secure_partition.c -> secure_partition.c: ldelf_load_ldelf()
108 return
109 secure_partition.c -> secure_partition.c: ldlelf_init_with_ldelf()
110 return
111 secure_partition.c -> secure_partition.c: sp_init_set_registers()
112 return
113 return
114 secure_partition.c -> secure_partition.c: enter_sp()
115 return
116 secure_partition.c -> secure_partition.c: sp_msg_handler()
117 return
118 return
119
120:``init_with_ldelf()``: Load the SP
121:``sp_init_info()``: Initialise the ``struct ffa_init_info``. The
122 ``struct ffa_init_info`` is passed to the SP
123 during it first run.
124:``sp_init_set_registers()``: Initialise the registers of the SP
125:``sp_msg_handler()``: Handle the SPs FF-A message
126
127Once all SPs are loaded and started we return to the SPMD and the Normal World
128is booted.
129
130
131SP message handling
132-------------------
133
134The SPMC is split into 2 main message handlers:
135
136:``thread_spmc_msg_recv()`` thread_spmc.c: Used to handle message coming
137 from the Normal World.
138:``sp_msg_handler()`` spmc_sp_handler.c: Used to handle message where
139 the source or the destination
140 is a SP.
141
142When a ``FFA_MSG_SEND_DIRECT_REQ`` message is received by the SPMC from the
143Normal World, a new thread is started.
144The FF-A message is passed to the thread and it will call the
145``sp_msg_handler()`` function.
146
147Whenever the SPMC (``sp_msg_handler()``) receives a message not intended for
148one of the SPs, it will exit the thread and return to the Normal World
149passing the FF-A message.
150
151Currently only a ``FFA_MSG_SEND_DIRECT_REQ`` can be passed from the Normal
152World to a SP.
153
154.. uml::
155 :width: 800
156
157 skinparam backgroundcolor transparent
158 participant "None-secure world" as None_secure_world
159
160 box "S-EL3"
161 participant SPMD
162 end box
163
164 box "S-EL1"
165 participant thread_spmc
166 participant spmc_sp_handler
167 end box
168
169
170 box "S-EL0"
171 participant SP
172 end box
173
174 autoactivate on
175 None_secure_world -> SPMD: FFA_MSG_SEND_DIRECT_REQ \n <font color=red>SMC
176 SPMD -> thread_spmc: thread_spmc_msg_recv() \n <font color=red>ERET
177
178 thread_spmc -> spmc_sp_handler : spmc_sp_start_thread()
179 == thread ==
180 spmc_sp_handler -> spmc_sp_handler : sp_msg_handler()
181
182 loop FF-A dst != NSW
183 spmc_sp_handler -> spmc_sp_handler: ffa_handle_sp_direct_req()
184 spmc_sp_handler -> spmc_sp_handler: enter_sp()
185 spmc_sp_handler -> spmc_sp_handler: sp_enter_invoke_cmd()
186 autoactivate off
187 spmc_sp_handler -> SP: __thread_enter_user_mode() \n <font color=red>ERET
188 activate SP
189
190 SP -> spmc_sp_handler : (FF-A message) sp_handle_svc() \n <font color=red>SVC
191 deactivate SP
192 activate spmc_sp_handler
193 spmc_sp_handler -> spmc_sp_handler: Store SP context
194 spmc_sp_handler -> spmc_sp_handler: return to sp_enter_invoke_cmd()
195 deactivate spmc_sp_handler
196 spmc_sp_handler -> spmc_sp_handler: Retrieve FF-A message from SP context
197 return
198 return
199 return
200 end
201 return
202 == End of thread ==
203 return
204 return \n <font color=red>SMC
205 return FFA_MSG_SEND_DIRECT_RESP \n <font color=red>ERET
206
207
208Every message received by the SPMC from the Normal World is handled in the
209``thread_spmc_msg_recv()`` function.
210
211When entering a SP we need to be running in a OP-TEE thread. This is needed to
212be able to push the TS session (We push the TS session to get access to the SP
213memory).
214Currently the only possibility to enter a SP from the Normal world is via a
215``FFA_MSG_SEND_DIRECT_REQ``. Whenever we receive a ``FFA_MSG_SEND_DIRECT_REQ``
216message which doesn't have OP-TEE as the endpoint-id, we start a thread and
217forward the FF-A message to the ``sp_msg_handler()``.
218
219The ``sp_msg_handler()`` is responsible for all messages coming or going
220to/from a SP. It runs in a while loop and will handle every message until it
221comes across a messages which is not intended for the secure world.
222After a message is handled by the SPMC or when it needs to be forwarded to a SP,
223``sp_enter()`` is called.
224``sp_enter()`` will copy the FF-A arguments and resume the SP.
225
226When the SPMC needs to have access to the SPs memory, it will call
227``ts_push_current_session()`` to gain access and ``ts_pop_current_session()``
228to release the access.
229
230Running and exiting SPs
231-----------------------
232
233The SPMC resumes/starts the SP by calling the ``sp_enter()``. This will set up
234the SP context and jump into S-EL0.
235Whenever the SP performs a system call it will end up in ``sp_handle_svc()``.
236``sp_handle_svc()`` stores the current context of the SP and makes sure that we
237don't return to S-EL0 but instead returns to S-EL1 back to ``sp_enter()``.
238``sp_enter()`` will pass the FF-A registers (x0-x7) to
239``spmc_sp_msg_handler()``. This will process the FF-A message.
240
241
242RxTx buffer managment
243---------------------
244RxTx buffers are used by the SPMC to exchange information between an endpoint
245and the SPMC. The rxtx_buf struct is used by the SPMC for abstracting buffer
246management.
247Every SP has a ``struct rxtx_buf`` wich will be passed to every function that
248needs access to the rxtx buffer.
249A separate ``struct rxtx_buf`` is defined for the Normal World, which gives
250access to the Normal World buffers.
251
252
253Configuration
254=============
255
Balint Dobszayfe29e2b2022-09-27 15:41:30 +0200256SPMC config options
257---------------------------
Jelle Sels3ef999a2021-03-29 09:35:37 +0200258
Balint Dobszayfe29e2b2022-09-27 15:41:30 +0200259To configure OP-TEE as a S-EL1 SPMC with Secure Partition support, the following
260flags should be set for optee_os:
Jelle Sels3ef999a2021-03-29 09:35:37 +0200261
Balint Dobszayfe29e2b2022-09-27 15:41:30 +0200262- ``CFG_CORE_SEL1_SPMC=y``
263- ``CFG_SECURE_PARTITION=y``
264- ``CFG_DT=y``
265- ``CFG_MAP_EXT_DT_SECURE=y``
Jelle Sels3ef999a2021-03-29 09:35:37 +0200266
Balint Dobszayfe29e2b2022-09-27 15:41:30 +0200267Furthermore TF-A should be configured as the SPMD, expecting a S-EL1 SPMC:
Jelle Sels3ef999a2021-03-29 09:35:37 +0200268
Balint Dobszayfe29e2b2022-09-27 15:41:30 +0200269- ``SPD=spmd``
270- ``SPMD_SPM_AT_SEL2=0``
271- ``ARM_SPMC_MANIFEST_DTS=<path to SPMC manifest dts>``
272
273SP loading mechanism
274---------------------
275
276OP-TEE SPMC supports two methods for finding and loading the SP executable
277images. Currently only ELF executables are supported. In the build repo the
278loading method can be selected with the SP_PACKAGING_METHOD option.
279
280Embedded SP
281^^^^^^^^^^^
282
283In this case the early TA mechanism of optee_os is reused: the SP ELF files are
284embedded into the main OP-TEE binary. Each ELF should start with a specific
285section (.sp_head) containing a struct which describes the SP (UUID, stack size,
286etc.). The images can be added to optee_os using the ``SP_PATHS`` config option,
287the build repo will set this up automatically when
288``SP_PACKAGING_METHOD=embedded`` is selected. The images passed in ``SP_PATHS``
289are processed by ``ts_bin_to_c.py`` in optee_os and linked into the main binary.
290At runtime the ``for_each_secure_partition()`` macro can iterate through these
291images, so a particular SP can be found by UUID and then loaded by ldelf.
292
293The SP manifest file `[1]`_ used by the SPMC to setup SPs is also handled by
294``ts_bin_to_c.py``, it will be concatenated to the end of the SP ELF.
295
296FIP SP
297^^^^^^
298
299In this case the SP ELF files and the corresponding SP manifest DTs are
300encapsulated into SP packages and packed into the FIP. The goal of providing
301this alternative flow is to make updating SPs easier (independent of the main
302OP-TEE binary) and to get aligned with Hafnium (S-EL2 SPMC). For more
303information about the FIP, please refer to the TF-A documentation `[2]`_. The SP
304packaging process and the package format is provided by TF-A, detailed
305description is available at `[3]`_. In the build repo this method can be
306selected by ``SP_PACKAGING_METHOD=fip``, it covers all the necessary setup
307automatically. In case of using another buildsystem, the following steps should
308be implemented:
309
310- TF-A config ``SP_LAYOUT_FILE``: provide a JSON file which describes the SPs
311 (path to SP executable and corresponding DT, example `[4]`_). The TF-A
312 buildsystem will create the SP packages (using sptool) based on this and pack
313 them into the FIP.
314
315- TF-A config ``ARM_BL2_SP_LIST_DTS``: provide a DT snippet which describes the
316 SPs' UUIDs and load addresses (example: `[5]`_). This will be injected into
317 the SP list in ``TB_FW_CONFIG`` DT of TF-A, and BL2 will load the SP packages
318 based on this. Note that BL2 doesn't automatically load all images from the
319 FIP: it's necessary to explicitly define them in ``TB_FW_CONFIG`` (using this
320 injected snippet or manually editing the DT).
321
322- TF-A config ``ARM_SPMC_MANIFEST_DTS``: provide the SPMC manifest (example:
323 `[6]`_). This DT is passed to the SPMC as a boot argument (in the TF-A naming
324 convention this is the ``TOS_FW_CONFIG``). It should contain the list of SP
325 packages and their load addresses in the ``compatible = "arm,sp_pkg"`` node.
326
327At boot optee_os will parse the SP package load addresses from the SPMC manifest
328and find the SP packages already loaded by BL2. Iterating through the SP
329packages, based on the SP package header in each package it will map the SP
330executable image and the corresponding manifest DT and collect these to the
331``fip_sp_list`` list. Later when initialising the SPs, the ``for_each_fip_sp``
332macro is used to iterate this list and load the executables using ldelf, just
333like for the embedded SP case.
334
335.. _[1]:
336
337[1] https://trustedfirmware-a.readthedocs.io/en/v2.6/components/ffa-manifest-binding.html
338
339.. _[2]:
340
341[2] https://trustedfirmware-a.readthedocs.io/en/v2.6/design/firmware-design.html#firmware-image-package-fip
342
343.. _[3]:
344
345[3] https://trustedfirmware-a.readthedocs.io/en/v2.6/components/secure-partition-manager.html#secure-partition-packages
346
347.. _[4]:
348
349[4] https://trustedfirmware-a.readthedocs.io/en/v2.6/components/secure-partition-manager.html#describing-secure-partitions
350
351.. _[5]:
352
353[5] https://github.com/OP-TEE/build/blob/master/fvp/bl2_sp_list.dtsi
354
355.. _[6]:
356
357[6] https://github.com/OP-TEE/build/blob/master/fvp/spmc_manifest.dts