1################################## 2Secure Interrupt Integration Guide 3################################## 4 5************ 6Introduction 7************ 8 9This document describes how to enable an interrupt in TF-M. The target audiences 10are mainly platform integrators and Secure Partition developers. 11 12This document assumes that you have read the PSA Firmware Framework (FF-M) v1.0 13[1]_ and the FF-M v1.1 extensions [2]_ thus have knowlege on the terminologies 14such as Secure Partitions and manifests. 15 16************************ 17Interrupt Handling Model 18************************ 19 20TF-M supports the two interrupt handling model defined by FF-M: 21 22- First-Level Interrupt Handling (FLIH) 23 24 In this model, the interrupt handling is carried out immediately when the 25 interrupt exception happens. 26 27 The interrupt handling can optionally set an interrupt signal for the Secure 28 Partition Thread to have further data processing. 29 30- Second-Level Interrupt Handling (SLIH) 31 32 In this model, the interrupt handling is deferred after the interrupt 33 exception. The handling occurs in the Secure Partition Thread thus is subject 34 to scheduling. 35 36The FLIH supports handling an interrupt in a bounded time, but very limited APIs 37are allowed in the FLIH handling because the handling occurs in an special 38exception context. 39 40The SLIH is deferred and subject to scheduling but all Secure Partition APIs are 41allowed as the SLIH handling is in the Secure Partition Thread. 42 43Both the FLIH and the SLIH can be used by Secure Partitions which conform to 44Firmware Framework v1.1. 45 46While the SLIH is the only supported model for Secure Partitions which conform 47to Firmware Framework v1.0. 48 49Please refer to chapter 6.2 of FF-M v1.1 [1]_ for more details on the interrupt 50handling models. 51 52********************* 53Enabling an Interrupt 54********************* 55 56To enable an interrupt, you need to do the following: 57 58- Binding the interrupt to a Secure Partition. 59- Granting the Secure Partition access permissions to the device of the 60 interrupt. 61- Initializing the interrupt. 62- Integrating the interrupt handling function 63 64TF-M has two Test Partitions as good examples for both FLIH [3]_ and SLIH [4]_. 65See also `Enabling the Interrupt Tests`_ on how to integrate them to platforms. 66 67Binding an Interrupt to a Secure Partition 68========================================== 69 70To bind an interrupt to a Secure Partition, you need to add an item to the 71``irqs`` attribute of the Secure Partition manifest. 72``irqs`` is a list of Interrupt Request (IRQ) assigned to the Secure Partition. 73 74Secure Partitions are not allowed to share IRQs with other Secure Partitions. 75 76Different Firmware Framework versions have different definitions of manifest. 77 78FF-M v1.0 79--------- 80 81Here is an example manifest of Secure Partitions conform to Firmware Framework 82version 1.0: 83 84.. code-block:: yaml 85 86 { 87 "irqs": [ 88 { 89 "source": 5, 90 "signal": "DUAL_TIMER_SIGNAL" 91 }, 92 { 93 "source": "TIMER_1_SOURCE", 94 "signal": "TIMER_1_SIGNAL" 95 } 96 ] 97 } 98 99- source 100 101 Required, Unique. 102 103 The ``source`` is a string that identifies the interrupt source. 104 It can be a valid exception number or a symbolic name defined in platform codes. 105 106- signal 107 108 Required, Unique. 109 110 The ``signal`` attribute is a symbolic name used by TF-M to identify which 111 interrupt is asserted. 112 It is also used by the Secure Partition to receive the interrupt signal by 113 calling ``psa_wait`` for interrupt handling. 114 115 It is defined in the Secure Partition header file 116 ``<psa_manifest/manifestfilename.h>`` generated by TF-M: 117 118 .. code-block:: c 119 120 #define signal VALUE 121 122The interrupt handling model is SLIH by default as it is the only supported one 123for FF-M v1.0. 124 125FF-M v1.1 126--------- 127 128Here is an example manifest of Secure Partitions conform to Firmware Framework 129version 1.1: 130 131.. code-block:: yaml 132 133 { 134 "irqs": [ 135 { 136 "source" : "TIMER_1_SOURCE", 137 "name" : "TIMER_1", 138 "handling": "FLIH" 139 }, 140 { 141 "source" : 5, 142 "name" : "DUAL_TIMER", 143 "handling": "SLIH" 144 } 145 ] 146 } 147 148- source 149 150 The ``source`` is the same as the one in Firmware Framework Version 1.0. 151 152- name 153 154 Required, Unique. 155 156 The ``name`` is used to construct the following two elements: 157 158 - the interrupt signal symbol: ``{{name}}_SIGNAL``, the equivalent of 159 ``signal`` in FF-M v1.0 160 - the FLIH Function for handling ``FLIH`` IRQs provided by Secure Partition: 161 162 ``psa_flih_result_t {{name}}_flih(void);`` 163 164 It is also declared in ``<psa_manifest/manifestfilename.h>``. 165 166- handling 167 168 Required. 169 170 The ``handling`` attribute specifies the interrupt handling model and must 171 have one of the following values: 172 173 - ``FLIH`` - First-Level Interrupt Handling 174 - ``SLIH`` - Second-Level Interrupt Handling 175 176Granting Permissions to Devices for Secure Partitions 177===================================================== 178 179A secure partition shall be granted two parts of permissions to access a device. 180One is the Memory Maped I/O (MMIO) region of the device. The other is the driver 181codes to access the device. 182 183The MMIO Regions 184---------------- 185 186You need to declare the MMIO region in the ``mmio_regions`` attributes in the 187Secure Partition manifest, to enable the Secure Partition to access it. 188 189An MMIO region can be described as either ``numbered_region`` or 190``named_region``. 191A numbered region consists of a ``base`` address and a ``size``. 192A named region consists of a string ``name`` to describe the region. 193 194Here is an example of named region: 195 196.. code-block:: yaml 197 198 { 199 "mmio_regions": [ 200 { 201 "name": "TFM_PERIPHERAL_TIMER0", 202 "permission": "READ-WRITE" 203 } 204 ] 205 } 206 207- name 208 209 Required. 210 211 The ``name`` attribute is a symbolic name defined by platforms. 212 It is a pointer to structure instance that usually includes the base address 213 and size of the region and some other platform specific attributes that are 214 required to set up permissions to the MMIO region. 215 216 The structure is defined by platforms and the name must be 217 ``struct platform_data_t``. 218 219- permission 220 221 Required. 222 223 The ``permission`` attribute must have one of the following values: 224 225 - ``READ-ONLY`` 226 - ``READ-WRITE`` 227 228The Device Drivers 229------------------ 230 231To give permissions of devices drivers to Secure Partitions, it is recommended 232to put the driver codes to the Partition's CMake library: 233 234.. code-block:: bash 235 236 target_sources(some_partition_lib 237 PRIVATE 238 some_driver_code.c 239 ) 240 241Initializing the Interrupts 242=========================== 243 244Platforms must define an interrupt initialization function for each Secure 245interrupt. 246 247The prototype of the function is: 248 249.. code-block:: c 250 251 enum tfm_hal_status_t {source_symbol}_init(void *p_pt, 252 const struct irq_load_info_t *p_ildi) 253 254The ``{source_symbol}`` is: 255 256- ``irq_{source}``, if the ``source`` attribute of the IRQ in Partition manifest 257 is a number 258- Lowercase of ``source`` attribute, if ``source`` is a symbolic name 259 260For example if the manifest declares ``"source": 5``, then the function name 261is ``irq_5_init``. 262If the mannifest declares ``"source" : "TIMER_1_IRQ"`` then the function 263name is ``timer_1_irq_init``. 264 265The function will be called by the Framework automatically during 266initialization. The function can be put in any source file that belongs to SPM, 267for example a ``tfm_interrupts.c`` added to the ``tfm_spm`` CMake target. 268 269The initialization of an interrupt must include: 270 271- setting the priority 272- ensuring that the interrupt targets the Secure State. 273- saving the interrupt information 274 275Setting Priority 276---------------- 277 278The priority of external interrupts must be in the following range: 279``(0, N / 2)``, where ``N`` is the number of configurable priorities. 280Smaller values have higher priorities. 281 282For example if the number of configurable priority of your interrupt controller 283is 16, you must use the priorities in range ``(0, 8)`` only, boundaries 284excluded. 285 286Note that these are not the values set into the interrupt controllers. 287Different platforms may have different values for those priorities. 288But if you use the ``NVIC_SetPriority`` function provided by CMSIS to set 289priorities, you can pass the values directly. 290 291Platforms have the flexibilities on the assignment of priorities. 292 293Targeting Interrupts to Secure 294------------------------------ 295 296In single core systems, platform integrators must ensure that the Secure 297interrupts target to Secure State by setting the Interrupt Controller. 298 299In multi-core systems, this might be optional. 300 301Saving the Interrupt Information 302-------------------------------- 303 304The initialization function is called during Partition loading with the 305following information: 306 307- ``p_pt`` - pointer to Partition runtime struct of the owner Partition 308- ``p_ildi`` - pointer to ``irq_load_info_t`` struct of the interrupt 309 310Platforms must save the information for the future use. 311See `Integrating the Interrupt Handling Function`_ for the usage. 312 313The easiest way is to save them in global variables for each interrupt. 314TF-M provides a struct for saving the information: 315 316.. code-block:: c 317 318 struct irq_t { 319 void *p_pt; 320 const struct irq_load_info_t *p_ildi; 321 }; 322 323Integrating the Interrupt Handling Function 324=========================================== 325 326TF-M provides an interrupt handling entry for Secure interrupts: 327 328.. code-block:: c 329 330 void spm_handle_interrupt(void *p_pt, const struct irq_load_info_t *p_ildi) 331 332The ``p_pt`` and ``p_ildi`` are the information passed to interrupt 333initialization functions and saved by platforms. 334 335Platforms should call this entry function in the interrupt handlers held in 336Vector Table with the information saved by the interrupt initialization 337functions. 338If the information is saved as global variables, then the interrupt handlers can 339be put in the same source file that contains the initialization functions. 340 341Here is an example: 342 343.. code-block:: c 344 345 void TFM_TIMER0_IRQ_Handler(void) /* The handler in Vector Table */ 346 { 347 spm_handle_interrupt(p_timer0_pt, p_tfm_timer0_irq_ldinf); 348 } 349 350**************************** 351Enabling the Interrupt Tests 352**************************** 353 354TF-M provides test suites for FLIH and SLIH interrupts respectively. 355They are disabled by default. 356 357.. note:: 358 359 FLIH interrupt test and SLIH interrupt test share the same timer 360 ``TFM_TIMER0_IRQ`` thus cannot be enabled at the same time. 361 362To enable the tests, please follow steps in the previous sections. 363In addition, you need to implement the following APIs of timer control: 364 365- ``void tfm_plat_test_secure_timer_start(void)`` 366- ``void tfm_plat_test_secure_timer_clear_intr(void)`` 367- ``void tfm_plat_test_secure_timer_stop(void)`` 368 369You shall also select the following flags in platform specific ``config.cmake`` 370to indicate that FLIH and SLIH interrupt tests are supported respectively. 371 372- ``PLATFORM_FLIH_IRQ_TEST_SUPPORT``: platform implements support of FLIH 373 interrupt tests 374- ``PLATFORM_SLIH_IRQ_TEST_SUPPORT``: platform implements support of SLIH 375 interrupt tests 376 377The following configurations control SLIH and FLIH interrupt tests: 378 379- ``TEST_NS_FLIH_IRQ`` 380- ``TEST_NS_SLIH_IRQ`` 381 382They can be enabled via build command line or via ``TEST_NS``. 383 384************************************ 385Migrating to Firmware Framework v1.1 386************************************ 387 388Please refer to ``Migrating Secure Partitions to version 1.1`` of FF-M v1.1 [1]_ 389. 390 391********** 392References 393********** 394 395.. [1] `FF-M v1.0 Specification <https://developer.arm.com/-/media/Files/pdf/PlatformSecurityArchitecture/Architect/DEN0063-PSA_Firmware_Framework-1.0.0-2.pdf?revision=2d1429fa-4b5b-461a-a60e-4ef3d8f7f4b4>`__ 396 397.. [2] `FF-M v1.1 Extention <https://documentation-service.arm.com/static/600067c09b9c2d1bb22cd1c5?token=>`__ 398 399.. [3] https://git.trustedfirmware.org/TF-M/tf-m-tests.git/tree/test/secure_fw/suites/spm/irq/service/tfm_flih_test_service 400 401.. [4] https://git.trustedfirmware.org/TF-M/tf-m-tests.git/tree/test/secure_fw/suites/spm/irq/service/tfm_slih_test_service 402 403-------------- 404 405*Copyright (c) 2021-2022, Arm Limited. All rights reserved.* 406*Copyright (c) 2022 Cypress Semiconductor Corporation (an Infineon company) 407or an affiliate of Cypress Semiconductor Corporation. All rights reserved.* 408