1
2Realm Management Extension (RME)
3====================================
4
5FEAT_RME (or RME for short) is an Armv9-A extension and is one component of the
6`Arm Confidential Compute Architecture (Arm CCA)`_. TF-A supports RME starting
7from version 2.6. This chapter discusses the changes to TF-A to support RME and
8provides instructions on how to build and run TF-A with RME.
9
10RME support in TF-A
11---------------------
12
13The following diagram shows an Arm CCA software architecture with TF-A as the
14EL3 firmware. In the Arm CCA architecture there are two additional security
15states and address spaces: ``Root`` and ``Realm``. TF-A firmware runs in the
16Root world. In the realm world, a Realm Management Monitor firmware (RMM)
17manages the execution of Realm VMs and their interaction with the hypervisor.
18
19.. image:: ../resources/diagrams/arm-cca-software-arch.png
20
21RME is the hardware extension to support Arm CCA. To support RME, various
22changes have been introduced to TF-A. We discuss those changes below.
23
24Changes to translation tables library
25***************************************
26RME adds Root and Realm Physical address spaces. To support this, two new
27memory type macros, ``MT_ROOT`` and ``MT_REALM``, have been added to the
28:ref:`Translation (XLAT) Tables Library`. These macros are used to configure
29memory regions as Root or Realm respectively.
30
31.. note::
32
33 Only version 2 of the translation tables library supports the new memory
34 types.
35
36Changes to context management
37*******************************
38A new CPU context for the Realm world has been added. The existing
39:ref:`CPU context management API<PSCI Library Integration guide for Armv8-A
40AArch32 systems>` can be used to manage Realm context.
41
42Boot flow changes
43*******************
44In a typical TF-A boot flow, BL2 runs at Secure-EL1. However when RME is
45enabled, TF-A runs in the Root world at EL3. Therefore, the boot flow is
46modified to run BL2 at EL3 when RME is enabled. In addition to this, a
47Realm-world firmware (RMM) is loaded by BL2 in the Realm physical address
48space.
49
50The boot flow when RME is enabled looks like the following:
51
521. BL1 loads and executes BL2 at EL3
532. BL2 loads images including RMM
543. BL2 transfers control to BL31
554. BL31 initializes SPM (if SPM is enabled)
565. BL31 initializes RMM
576. BL31 transfers control to Normal-world software
58
59Granule Protection Tables (GPT) library
60*****************************************
61Isolation between the four physical address spaces is enforced by a process
62called Granule Protection Check (GPC) performed by the MMU downstream any
63address translation. GPC makes use of Granule Protection Table (GPT) in the
64Root world that describes the physical address space assignment of every
65page (granule). A GPT library that provides APIs to initialize GPTs and to
66transition granules between different physical address spaces has been added.
67More information about the GPT library can be found in the
68:ref:`Granule Protection Tables Library` chapter.
69
70RMM Dispatcher (RMMD)
71************************
72RMMD is a new standard runtime service that handles the switch to the Realm
73world. It initializes the RMM and handles Realm Management Interface (RMI)
74SMC calls from Non-secure and Realm worlds.
75
76There is a contract between RMM and RMMD that defines the arguments that the
77former needs to take in order to initialize and also the possible return values.
78This contract is defined in the RMM Boot Interface, which can be found at
79:ref:`rmm_el3_boot_interface`.
80
81There is also a specification of the runtime services provided by TF-A
82to RMM. This can be found at :ref:`runtime_services_and_interface`.
83
84Test Realm Payload (TRP)
85*************************
86TRP is a small test payload that runs at R-EL2 and implements a subset of
87the Realm Management Interface (RMI) commands to primarily test EL3 firmware
88and the interface between R-EL2 and EL3. When building TF-A with RME enabled,
89if a path to an RMM image is not provided, TF-A builds the TRP by default
90and uses it as RMM image.
91
92Building and running TF-A with RME
93------------------------------------
94
95This section describes how you can build and run TF-A with RME enabled.
96We assume you have all the :ref:`Prerequisites` to build TF-A.
97
98The following instructions show you how to build and run TF-A with RME
99for two scenarios:
100
101- Three-world execution: TF-A with TF-A Tests or Linux.
102
103  - NS (TF-A Test or Linux),
104  - Root (TF-A)
105  - Realm (RMM or TRP)
106
107- Four-world execution: TF-A, Hafnium and TF-A Tests or Linux.
108
109  - NS (TF-A Test or Linux),
110  - Root (TF-A)
111  - Realm (RMM or TRP)
112  - SPM (Hafnium)
113
114To run the tests, you need an FVP model. Please use the :ref:`latest version
115<Arm Fixed Virtual Platforms (FVP)>` of *FVP_Base_RevC-2xAEMvA* model.
116
117Three World Testing with TF-A Tests
118*************************************
119
120**1. Obtain and build TF-A Tests with Realm Payload**
121
122The full set of instructions to setup build host and build options for
123TF-A-Tests can be found in the `TFTF Getting Started`_.
124
125Use the following instructions to build TF-A with `TF-A Tests`_ as the
126non-secure payload (BL33).
127
128.. code:: shell
129
130 git clone https://git.trustedfirmware.org/TF-A/tf-a-tests.git
131 cd tf-a-tests
132 make CROSS_COMPILE=aarch64-none-elf- PLAT=fvp DEBUG=1 all pack_realm
133
134This produces a TF-A Tests binary (**tftf.bin**) with Realm payload packaged
135and **sp_layout.json** in the **build/fvp/debug** directory.
136
137**2. Obtain and build RMM Image**
138
139Please refer to the `RMM Getting Started`_ on how to setup
140Host Environment and build RMM.
141
142The below command shows how to build RMM using the default build options for FVP.
143
144.. code:: shell
145
146 git clone --recursive https://git.trustedfirmware.org/TF-RMM/tf-rmm.git
147 cd tf-rmm
148 cmake -DRMM_CONFIG=fvp_defcfg -S . -B build
149 cmake --build build
150
151This will generate **rmm.img** in **build** folder.
152
153**3. Build TF-A**
154
155The `TF-A Getting Started`_ has the necessary instructions to setup Host
156machine and build TF-A.
157
158To build for RME, set ``ENABLE_RME`` build option to 1 and provide the path to
159the RMM binary using the ``RMM`` build option.
160Currently, this feature is only supported for the FVP platform.
161
162.. note::
163
164 ENABLE_RME build option is currently experimental.
165
166If the ``RMM`` option is not used, then the Test Realm Payload (TRP) in TF-A
167will be built and used as the RMM.
168
169.. code:: shell
170
171 git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git
172 cd trusted-firmware-a
173 make CROSS_COMPILE=aarch64-none-elf- \
174 PLAT=fvp \
175 ENABLE_RME=1 \
176 RMM=<path/to/rmm.img> \
177 FVP_HW_CONFIG_DTS=fdts/fvp-base-gicv3-psci-1t.dts \
178 DEBUG=1 \
179 BL33=<path/to/tftf.bin> \
180 all fip
181
182This produces **bl1.bin** and **fip.bin** binaries in the **build/fvp/debug** directory.
183
184Running the tests for a 3 world FVP setup
185^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
186
187Use the following command to run the tests on FVP. TF-A Tests should boot
188and run the default tests including Realm world tests.
189
190.. code:: shell
191
192 FVP_Base_RevC-2xAEMvA                                          \
193 -C bp.refcounter.non_arch_start_at_default=1                   \
194 -C bp.secureflashloader.fname=<path/to/bl1.bin>                \
195 -C bp.flashloader0.fname=<path/to/fip.bin>                     \
196 -C bp.refcounter.use_real_time=0                               \
197 -C bp.ve_sysregs.exit_on_shutdown=1                            \
198 -C cache_state_modelled=1                                      \
199 -C bp.dram_size=2                                              \
200 -C bp.secure_memory=1                                          \
201 -C pci.pci_smmuv3.mmu.SMMU_ROOT_IDR0=3                         \
202 -C pci.pci_smmuv3.mmu.SMMU_ROOT_IIDR=0x43B                     \
203 -C pci.pci_smmuv3.mmu.root_register_page_offset=0x20000        \
204 -C cluster0.NUM_CORES=4                                        \
205 -C cluster0.PA_SIZE=48                                         \
206 -C cluster0.ecv_support_level=2                                \
207 -C cluster0.gicv3.cpuintf-mmap-access-level=2                  \
208 -C cluster0.gicv3.without-DS-support=1                         \
209 -C cluster0.gicv4.mask-virtual-interrupt=1                     \
210 -C cluster0.has_arm_v8-6=1                                     \
211 -C cluster0.has_amu=1                                          \
212 -C cluster0.has_branch_target_exception=1                      \
213 -C cluster0.rme_support_level=2                                \
214 -C cluster0.has_rndr=1                                         \
215 -C cluster0.has_v8_7_pmu_extension=2                           \
216 -C cluster0.max_32bit_el=-1                                    \
217 -C cluster0.stage12_tlb_size=1024                              \
218 -C cluster0.check_memory_attributes=0                          \
219 -C cluster0.ish_is_osh=1                                       \
220 -C cluster0.restriction_on_speculative_execution=2             \
221 -C cluster0.restriction_on_speculative_execution_aarch32=2     \
222 -C cluster1.NUM_CORES=4                                        \
223 -C cluster1.PA_SIZE=48                                         \
224 -C cluster1.ecv_support_level=2                                \
225 -C cluster1.gicv3.cpuintf-mmap-access-level=2                  \
226 -C cluster1.gicv3.without-DS-support=1                         \
227 -C cluster1.gicv4.mask-virtual-interrupt=1                     \
228 -C cluster1.has_arm_v8-6=1                                     \
229 -C cluster1.has_amu=1                                          \
230 -C cluster1.has_branch_target_exception=1                      \
231 -C cluster1.rme_support_level=2                                \
232 -C cluster1.has_rndr=1                                         \
233 -C cluster1.has_v8_7_pmu_extension=2                           \
234 -C cluster1.max_32bit_el=-1                                    \
235 -C cluster1.stage12_tlb_size=1024                              \
236 -C cluster1.check_memory_attributes=0                          \
237 -C cluster1.ish_is_osh=1                                       \
238 -C cluster1.restriction_on_speculative_execution=2             \
239 -C cluster1.restriction_on_speculative_execution_aarch32=2     \
240 -C pctl.startup=0.0.0.0                                        \
241 -C bp.smsc_91c111.enabled=1                                    \
242 -C bp.hostbridge.userNetworking=1
243
244The bottom of the output from *uart0* should look something like the following.
245
246.. code-block:: shell
247
248 ...
249
250 > Test suite 'FF-A Interrupt'
251                                                                Passed
252 > Test suite 'SMMUv3 tests'
253                                                                Passed
254 > Test suite 'PMU Leakage'
255                                                                Passed
256 > Test suite 'DebugFS'
257                                                                Passed
258 > Test suite 'RMI and SPM tests'
259                                                                Passed
260 > Test suite 'Realm payload at EL1'
261                                                                Passed
262 > Test suite 'Invalid memory access'
263                                                                Passed
264 ...
265
266Building TF-A with RME enabled Linux Kernel
267^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
268
269If an RME enabled Linux kernel and filesystem is available for testing,
270and a suitable NS boot loader is not available, then this option can be used to
271launch kernel directly after BL31:
272
273.. code-block:: shell
274
275 cd trusted-firmware-a
276 make CROSS_COMPILE=aarch64-none-elf- \
277 PLAT=fvp \
278 ENABLE_RME=1 \
279 RMM=<path/to/rmm.img> \
280 FVP_HW_CONFIG_DTS=fdts/fvp-base-gicv3-psci-1t.dts \
281 DEBUG=1 \
282 ARM_LINUX_KERNEL_AS_BL33=1 \
283 PRELOADED_BL33_BASE=0x84000000 \
284 all fip
285
286Boot and run the RME enabled Linux Kernel
287^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
288
289Use the following additional arguments to boot the kernel on FVP.
290
291.. code-block:: shell
292
293 --data cluster0.cpu0=<path_to_kernel_Image>@0x84000000         \
294 -C bp.virtioblockdevice.image_path=<path_to_rootfs.ext4>
295
296.. tip::
297
298 Set the FVP option `cache_state_modelled=0` to run Linux based tests much faster.
299
300Four-world execution with Hafnium and TF-A Tests
301*************************************************
302
303Four-world execution involves software components in each security state: root,
304secure, realm and non-secure. This section describes how to build TF-A
305with four-world support.
306
307We use TF-A as the root firmware, `Hafnium SPM`_ is the reference Secure world component
308and the software components for the other 2 worlds (Realm and Non-Secure)
309are as described in the previous section.
310
311**1. Obtain and build Hafnium**
312
313.. code:: shell
314
315 git clone --recurse-submodules https://git.trustedfirmware.org/hafnium/hafnium.git
316 cd hafnium
317 #  Use the default prebuilt LLVM/clang toolchain
318 PATH=$PWD/prebuilts/linux-x64/clang/bin:$PWD/prebuilts/linux-x64/dtc:$PATH
319
320Feature MTE needs to be disabled in Hafnium build, apply following patch to
321project/reference submodule
322
323.. code:: diff
324
325 diff --git a/BUILD.gn b/BUILD.gn
326 index cc6a78f..234b20a 100644
327 --- a/BUILD.gn
328 +++ b/BUILD.gn
329 @@ -83,7 +83,6 @@ aarch64_toolchains("secure_aem_v8a_fvp") {
330     pl011_base_address = "0x1c090000"
331     smmu_base_address = "0x2b400000"
332     smmu_memory_size = "0x100000"
333 -    enable_mte = "1"
334     plat_log_level = "LOG_LEVEL_INFO"
335   }
336 }
337
338.. code:: shell
339
340 make PROJECT=reference
341
342The Hafnium binary should be located at
343*out/reference/secure_aem_v8a_fvp_clang/hafnium.bin*
344
345**2. Build TF-A**
346
347Build TF-A with RME as well as SPM enabled.
348
349Use sp_layout.json previously generated in tf-a-test build.
350
351.. code:: shell
352
353 make CROSS_COMPILE=aarch64-none-elf- \
354 PLAT=fvp \
355 ENABLE_RME=1 \
356 FVP_HW_CONFIG_DTS=fdts/fvp-base-gicv3-psci-1t.dts \
357 SPD=spmd \
358 SPMD_SPM_AT_SEL2=1 \
359 BRANCH_PROTECTION=1 \
360 CTX_INCLUDE_PAUTH_REGS=1 \
361 DEBUG=1 \
362 SP_LAYOUT_FILE=<path/to/sp_layout.json> \
363 BL32=<path/to/hafnium.bin> \
364 BL33=<path/to/tftf.bin> \
365 RMM=<path/to/rmm.img> \
366 all fip
367
368Running the tests for a 4 world FVP setup
369^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
370
371Use the following arguments in addition to
372`Running the tests for a 3 world FVP setup`_ to run tests for 4 world setup.
373
374.. code:: shell
375
376 -C pci.pci_smmuv3.mmu.SMMU_AIDR=2              \
377 -C pci.pci_smmuv3.mmu.SMMU_IDR0=0x0046123B     \
378 -C pci.pci_smmuv3.mmu.SMMU_IDR1=0x00600002     \
379 -C pci.pci_smmuv3.mmu.SMMU_IDR3=0x1714         \
380 -C pci.pci_smmuv3.mmu.SMMU_IDR5=0xFFFF0475     \
381 -C pci.pci_smmuv3.mmu.SMMU_S_IDR1=0xA0000002   \
382 -C pci.pci_smmuv3.mmu.SMMU_S_IDR2=0            \
383 -C pci.pci_smmuv3.mmu.SMMU_S_IDR3=0
384
385.. _Arm Confidential Compute Architecture (Arm CCA): https://www.arm.com/why-arm/architecture/security-features/arm-confidential-compute-architecture
386.. _Arm Architecture Models website: https://developer.arm.com/tools-and-software/simulation-models/fixed-virtual-platforms/arm-ecosystem-models
387.. _TF-A Getting Started: https://trustedfirmware-a.readthedocs.io/en/latest/getting_started/index.html
388.. _TF-A Tests: https://trustedfirmware-a-tests.readthedocs.io/en/latest
389.. _TFTF Getting Started: https://trustedfirmware-a-tests.readthedocs.io/en/latest/getting_started/index.html
390.. _Hafnium SPM: https://www.trustedfirmware.org/projects/hafnium
391.. _RMM Getting Started: https://git.trustedfirmware.org/TF-RMM/tf-rmm.git/tree/docs/getting_started/index.rst
392