aboutsummaryrefslogtreecommitdiff
path: root/docs/porting-guide.rst
blob: 0decf1a2ff4fb5c963529b3fab6acdbf383dd645 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
Trusted Firmware-A Tests - Porting Guide
========================================

.. section-numbering::
    :suffix: .

.. contents::

--------------

Introduction
------------

Please note that this document is incomplete.

Porting the TF-A Tests to a new platform involves making some mandatory and
optional modifications for both the cold and warm boot paths. Modifications
consist of:

*   Implementing a platform-specific function or variable,
*   Setting up the execution context in a certain way, or
*   Defining certain constants (for example #defines).

The platform-specific functions and variables are all declared in
``include/plat/common/platform.h``. The framework provides a default
implementation of variables and functions to fulfill the optional requirements.
These implementations are all weakly defined; they are provided to ease the
porting effort. Each platform port can override them with its own implementation
if the default implementation is inadequate.

Platform requirements
---------------------

The TF-A Tests rely on the following features to be present on the platform and
accessible from Normal World.

-  Watchdog
-  Non-Volatile Memory
-  System Timer

This also means that a platform port of the TF-A Tests must include software
drivers for those features.

Mandatory modifications
-----------------------

File : platform_def.h [mandatory]
`````````````````````````````````

Each platform must ensure that a header file of this name is in the system
include path with the following constants defined. This may require updating the
list of ``PLAT_INCLUDES`` in the ``platform.mk`` file. In the ARM FVP port, this
file is found in ``plat/arm/board/fvp/include/platform_def.h``.

-  **#define : PLATFORM_LINKER_FORMAT**

   Defines the linker format used by the platform, for example
   `elf64-littleaarch64` used by the FVP.

-  **#define : PLATFORM_LINKER_ARCH**

   Defines the processor architecture for the linker by the platform, for
   example `aarch64` used by the FVP.

-  **#define : PLATFORM_STACK_SIZE**

   Defines the stack memory available to each CPU. This constant is used by
   ``plat/common/aarch64/platform_mp_stack.S``.

-  **#define : PLATFORM_CLUSTER_COUNT**

   Defines the total number of clusters implemented by the platform in the
   system.

-  **#define : PLATFORM_CORE_COUNT**

   Defines the total number of CPUs implemented by the platform across all
   clusters in the system.

-  **#define : PLATFORM_NUM_AFFS**

   Defines the total number of nodes in the affinity hierarchy at all affinity
   levels used by the platform.

-  **#define : PLATFORM_MAX_AFFLVL**

   Defines the maximum number of affinity levels in the system that the platform
   implements.  ARMv8-A has support for 4 affinity levels. It is likely that
   hardware will implement fewer affinity levels. For example, the Base AEM FVP
   implements two clusters with a configurable number of CPUs.  It reports the
   maximum affinity level as 1.

-  **#define : PLAT_MAX_SPI_OFFSET_ID**

   Defines the offset of the last Shared Peripheral Interrupt supported by the
   TF-A Tests on this platform. SPI numbers are mapped onto GIC interrupt IDs,
   starting from interrupt ID 32. In other words, this offset ID corresponds to
   the last SPI number, to which 32 must be added to get the corresponding last
   GIC IRQ ID.

   E.g. If ``PLAT_MAX_SPI_OFFSET_ID`` is 10, this means that IRQ #42 is the last
   SPI.

-  **#define : PLAT_LOCAL_PSTATE_WIDTH**

   Defines the bit-field width of the local state in State-ID field of the
   power-state parameter. This macro will be used to compose the State-ID field
   given the local power state at different affinity levels.

-  **#define : PLAT_MAX_PWR_STATES_PER_LVL**

   Defines the maximum number of power states at a power domain level for the
   platform. This macro will be used by the ``PSCI_STAT_COUNT/RESIDENCY`` tests
   to determine the size of the array to allocate for storing the statistics.

-  **#define : TFTF_BASE**

   Defines the base address of the TFTF binary in DRAM. Used by the linker
   script to link the image at the right address. Must be aligned on a page-size
   boundary.

-  **#define : IRQ_PCPU_NS_TIMER**

   Defines the IRQ ID of the per-CPU Non-Secure timer of the platform.

-  **#define : IRQ_CNTPSIRQ1**

   Defines the IRQ ID of the System timer of the platform.

-  **#define : TFTF_NVM_OFFSET**

   The TFTF needs some Non-Volatile Memory to store persistent data. This
   defines the offset from the beginning of this memory that the TFTF can use.

-  **#define : TFTF_NVM_SIZE**

   Defines the size of the Non-Volatile Memory allocated for TFTF usage.

If the platform port uses the ARM Watchdog Module (`SP805`_) peripheral, the
following constant needs to be defined:

-  **#define : SP805_WDOG_BASE**

   Defines the base address of the `SP805`_ watchdog peripheral.

If the platform port uses the IO storage framework, the following constants
must also be defined:

-  **#define : MAX_IO_DEVICES**

   Defines the maximum number of registered IO devices. Attempting to register
   more devices than this value using ``io_register_device()`` will fail with
   ``IO_RESOURCES_EXHAUSTED``.

-  **#define : MAX_IO_HANDLES**

   Defines the maximum number of open IO handles. Attempting to open more IO
   entities than this value using ``io_open()`` will fail with
   ``IO_RESOURCES_EXHAUSTED``.

If the platform port uses the VExpress NOR flash driver (see
``drivers/io/vexpress_nor/``), the following constants must also be defined:

-  **#define : NOR_FLASH_BLOCK_SIZE**

   Defines the largest block size as seen by the software while writing to NOR
   flash.

Function : tftf_plat_arch_setup() [mandatory]
`````````````````````````````````````````````
::

    Argument : void
    Return   : void

This function performs any platform-specific and architectural setup that the
platform requires.

In both the ARM FVP and Juno ports, this function configures and enables the
MMU.

Function : tftf_early_platform_setup() [mandatory]
``````````````````````````````````````````````````

::

    Argument : void
    Return   : void

This function executes with the MMU and data caches disabled. It is only called
by the primary CPU. It is used to perform platform-specific actions very early
in the boot.

In both the ARM FVP and Juno ports, this function configures the console.

Function : tftf_platform_setup() [mandatory]
````````````````````````````````````````````

::

    Argument : void
    Return   : void

This function executes with the MMU and data caches enabled. It is responsible
for performing any remaining platform-specific setup that can occur after the
MMU and data cache have been enabled.

This function is also responsible for initializing the storage abstraction layer
used to access non-volatile memory for permanent storage of test results. It
also initialises the GIC and detects the platform topology using
platform-specific means.

Function : plat_get_nvm_handle() [mandatory]
````````````````````````````````````````````

::

    Argument : uintptr_t *
    Return   : void

It is needed if the platform port uses IO storage framework. This function is
responsible for getting the pointer to the initialised non-volatile memory
entity.

Function : tftf_plat_get_pwr_domain_tree_desc() [mandatory]
```````````````````````````````````````````````````````````

::

    Argument : void
    Return   : const unsigned char *

This function returns the platform topology description array in a suitable
format as expected by TFTF. The size of the array is expected to be
``PLATFORM_NUM_AFFS - PLATFORM_CORE_COUNT + 1``. The format used to describe
this array is :

1.  The first entry in the array specifies the number of power domains at the
    highest power level implemented in the platform. This caters for platforms
    where the power domain tree does not have a single root node e.g. the FVP
    which has two cluster power domains at the highest level (that is, 1).

2.  Each subsequent entry corresponds to a power domain and contains the number
    of power domains that are its direct children.

The array format is the same as the one used by Trusted Firmware-A and more
details of its description can be found in the Trusted Firmware-A documentation:
`docs/psci-pd-tree.rst`_.

Function : tftf_plat_get_mpidr() [mandatory]
````````````````````````````````````````````

::

    Argument : unsigned int
    Return   : uint64_t

This function converts a given `core_pos` into a valid MPIDR if the CPU is
present in the platform. The `core_pos` is a unique number less than the
``PLATFORM_CORE_COUNT`` returned by ``platform_get_core_pos()`` for a given
CPU. This API is used by the topology framework in TFTF to query the presence of
a CPU and, if present, returns the corresponding MPIDR for it. If the CPU
referred to by the `core_pos` is absent, then this function returns
``INVALID_MPID``.

Function : plat_get_state_prop() [mandatory]
````````````````````````````````````````````

::

    Argument : unsigned int
    Return   : const plat_state_prop_t *

This functions returns the ``plat_state_prop_t`` array for all the valid low
power states from platform for a specified affinity level and returns ``NULL``
for an invalid affinity level. The array is expected to be NULL-terminated.
This function is expected to be used by tests that need to compose the power
state parameter for use in ``PSCI_CPU_SUSPEND`` API or ``PSCI_STAT/RESIDENCY``
API.

Function : plat_fwu_io_setup() [mandatory]
``````````````````````````````````````````

::

    Argument : void
    Return   : void

This function initializes the IO system used by the firmware update.

Function : plat_arm_gic_init() [mandatory]
``````````````````````````````````````````

::

    Argument : void
    Return   : void

This function initializes the ARM Generic Interrupt Controller (GIC).

Function : platform_get_core_pos() [mandatory]
``````````````````````````````````````````````

::

    Argument : u_register_t
    Return   : unsigned int

This function returns a linear core ID from a MPID.

Function : plat_crash_console_init() [mandatory]
````````````````````````````````````````````````

::

    Argument : void
    Return   : int

This function initializes a platform-specific console for crash reporting.

Function : plat_crash_console_putc() [mandatory]
````````````````````````````````````````````````

::

    Argument : int
    Return   : int

This function prints a character on the platform-specific crash console.

Function : plat_crash_console_flush() [mandatory]
`````````````````````````````````````````````````

::

    Argument : void
    Return   : int

This function waits until all the characters of the platform-specific crash
console have been actually printed.

Optional modifications
----------------------

The following are helper functions implemented by the test framework that
perform common platform-specific tasks. A platform may choose to override these
definitions.

Function : platform_get_stack()
```````````````````````````````

::

    Argument : unsigned long
    Return   : unsigned long

This function returns the base address of the memory stack that has been
allocated for the CPU specified by MPIDR. The size of the stack allocated to
each CPU is specified by the platform defined constant ``PLATFORM_STACK_SIZE``.

Common implementation of this function is provided in
``plat/common/aarch64/platform_mp_stack.S``.

Function : plat_init_apiakey
````````````````````````````

::

    Argument : void
    Return   : uint64_t *

This function returns a pointer to an array with the values used to set the
``APIAKey{Hi,Lo}_EL1`` registers.

This function is only needed if ARMv8.3 pointer authentication is used by
building with ``ENABLE_PAUTH=1``.

Function : tftf_platform_end()
``````````````````````````````

::

    Argument : void
    Return   : void

This function performs any operation required by the platform to properly finish
the test session.

The default implementation sends an EOT (End Of Transmission) character on the
UART. This can be used to automatically shutdown the FVP models. When running on
real hardware, the UART output may be parsed by an external tool looking for
this character and rebooting the platform for example.

Function : tftf_plat_reset()
````````````````````````````

::

    Argument : void
    Return   : void

This function resets the platform.

The default implementation uses the ARM watchdog peripheral (`SP805`_) to
generate a watchdog timeout interrupt. This interrupt remains deliberately
unserviced, which eventually asserts the reset signal.

Storage abstraction layer
-------------------------

In order to improve platform independence and portability a storage abstraction
layer is used to store test results to non-volatile platform storage.

Each platform should register devices and their drivers via the Storage layer.
These drivers then need to be initialized in ``tftf_platform_setup()`` function.

It is mandatory to implement at least one storage driver. For the FVP and Juno
platforms the NOR Flash driver is provided as the default means to store test
results to storage. The storage layer is described in the header file
``include/lib/io_storage.h``. The implementation of the common library is in
``drivers/io/io_storage.c`` and the driver files are located in ``drivers/io/``.


Build Flags
-----------

-  **PLAT_TESTS_SKIP_LIST**

This build flag can be defined by the platform to control exclusion of some
testcases from the default test plan for a platform. If used this needs to
point to a text file which follows the following criteria:

  -  Contain a list of tests to skip for this platform.

  -  Specify 1 test per line, using the following format:

     ::

       testsuite_name/testcase_name

     where ``testsuite_name`` and ``testcase_name`` are the names that appear in
     the XML tests file.

  -  Alternatively, it is possible to disable a test suite entirely, which will
     disable all test cases part of this test suite. To do so, only specify the
     test suite name, omitting the ``/testcase_name`` part.

--------------

*Copyright (c) 2018-2019, Arm Limited. All rights reserved.*

.. _docs/psci-pd-tree.rst: https://github.com/ARM-software/arm-trusted-firmware/blob/master/docs/psci-pd-tree.rst
.. _SP805: https://static.docs.arm.com/ddi0270/b/DDI0270.pdf