1Exception Handling Framework in Trusted Firmware-A 2================================================== 3 4 5 6 7.. contents:: 8 :depth: 2 9 10.. |EHF| replace:: Exception Handling Framework 11.. |TF-A| replace:: Trusted Firmware-A 12 13This document describes various aspects of handling exceptions by Runtime 14Firmware (BL31) that are targeted at EL3, other than SMCs. The |EHF| takes care 15of the following exceptions when targeted at EL3: 16 17- Interrupts 18- Synchronous External Aborts 19- Asynchronous External Aborts 20 21|TF-A|'s handling of synchronous ``SMC`` exceptions raised from lower ELs is 22described in the `Firmware Design document`__. However, the |EHF| changes the 23semantics of `interrupt handling`__ and `synchronous exceptions`__ other than 24SMCs. 25 26.. __: firmware-design.rst#handling-an-smc 27.. __: `Interrupt handling`_ 28.. __: `Effect on SMC calls`_ 29 30The |EHF| is selected by setting the build option ``EL3_EXCEPTION_HANDLING`` to 31``1``, and is only available for AArch64 systems. 32 33Introduction 34------------ 35 36Through various control bits in the ``SCR_EL3`` register, the Arm architecture 37allows for asynchronous exceptions to be routed to EL3. As described in the 38`Interrupt Framework Design`_ document, depending on the chosen interrupt 39routing model, TF-A appropriately sets the ``FIQ`` and ``IRQ`` bits of 40``SCR_EL3`` register to effect this routing. For most use cases, other than for 41the purpose of facilitating context switch between Normal and Secure worlds, 42FIQs and IRQs routed to EL3 are not required to be handled in EL3. 43 44However, the evolving system and standards landscape demands that various 45exceptions are targeted at and handled in EL3. For instance: 46 47- Starting with ARMv8.2 architecture extension, many RAS features have been 48 introduced to the Arm architecture. With RAS features implemented, various 49 components of the system may use one of the asynchronous exceptions to signal 50 error conditions to PEs. These error conditions are of critical nature, and 51 it's imperative that corrective or remedial actions are taken at the earliest 52 opportunity. Therefore, a *Firmware-first Handling* approach is generally 53 followed in response to RAS events in the system. 54 55- The Arm `SDEI specification`_ defines interfaces through which Normal world 56 interacts with the Runtime Firmware in order to request notification of 57 system events. The SDEI specification requires that these events are notified 58 even when the Normal world executes with the exceptions masked. This too 59 implies that firmware-first handling is required, where the events are first 60 received by the EL3 firmware, and then dispatched to Normal world through 61 purely software mechanism. 62 63For |TF-A|, firmware-first handling means that asynchronous exceptions are 64suitably routed to EL3, and the Runtime Firmware (BL31) is extended to include 65software components that are capable of handling those exceptions that target 66EL3. These components—referred to as *dispatchers* [#spd]_ in general—may 67choose to: 68 69.. _delegation-use-cases: 70 71- Receive and handle exceptions entirely in EL3, meaning the exceptions 72 handling terminates in EL3. 73 74- Receive exceptions, but handle part of the exception in EL3, and delegate the 75 rest of the handling to a dedicated software stack running at lower Secure 76 ELs. In this scheme, the handling spans various secure ELs. 77 78- Receive exceptions, but handle part of the exception in EL3, and delegate 79 processing of the error to dedicated software stack running at lower secure 80 ELs (as above); additionally, the Normal world may also be required to 81 participate in the handling, or be notified of such events (for example, as 82 an SDEI event). In this scheme, exception handling potentially and maximally 83 spans all ELs in both Secure and Normal worlds. 84 85On any given system, all of the above handling models may be employed 86independently depending on platform choice and the nature of the exception 87received. 88 89.. [#spd] Not to be confused with `Secure Payload Dispatcher`__, which is an 90 EL3 component that operates in EL3 on behalf of Secure OS. 91 92.. __: firmware-design.rst#secure-el1-payloads-and-dispatchers 93 94The role of Exception Handling Framework 95---------------------------------------- 96 97Corollary to the use cases cited above, the primary role of the |EHF| is to 98facilitate firmware-first handling of exceptions on Arm systems. The |EHF| thus 99enables multiple exception dispatchers in runtime firmware to co-exist, register 100for, and handle exceptions targeted at EL3. This section outlines the basics, 101and the rest of this document expands the various aspects of the |EHF|. 102 103In order to arbitrate exception handling among dispatchers, the |EHF| operation 104is based on a priority scheme. This priority scheme is closely tied to how the 105Arm GIC architecture defines it, although it's applied to non-interrupt 106exceptions too (SErrors, for example). 107 108The platform is required to `partition`__ the Secure priority space into 109priority levels as applicable for the Secure software stack. It then assigns the 110dispatchers to one or more priority levels. The dispatchers then register 111handlers for the priority levels at runtime. A dispatcher can register handlers 112for more than one priority level. 113 114.. __: `Partitioning priority levels`_ 115 116 117.. _ehf-figure: 118 119.. image:: ../draw.io/ehf.svg 120 121A priority level is *active* when a handler at that priority level is currently 122executing in EL3, or has delegated the execution to a lower EL. For interrupts, 123this is implicit when an interrupt is targeted and acknowledged at EL3, and the 124priority of the acknowledged interrupt is used to match its registered handler. 125The priority level is likewise implicitly deactivated when the interrupt 126handling concludes by EOIing the interrupt. 127 128Non-interrupt exceptions (SErrors, for example) don't have a notion of priority. 129In order for the priority arbitration to work, the |EHF| provides APIs in order 130for these non-interrupt exceptions to assume a priority, and to interwork with 131interrupts. Dispatchers handling such exceptions must therefore explicitly 132activate and deactivate the respective priority level as and when they're 133handled or delegated. 134 135Because priority activation and deactivation for interrupt handling is implicit 136and involves GIC priority masking, it's impossible for a lower priority 137interrupt to preempt a higher priority one. By extension, this means that a 138lower priority dispatcher cannot preempt a higher-priority one. Priority 139activation and deactivation for non-interrupt exceptions, however, has to be 140explicit. The |EHF| therefore disallows for lower priority level to be activated 141whilst a higher priority level is active, and would result in a panic. 142Likewise, a panic would result if it's attempted to deactivate a lower priority 143level when a higher priority level is active. 144 145In essence, priority level activation and deactivation conceptually works like a 146stack—priority levels stack up in strictly increasing fashion, and need to be 147unstacked in strictly the reverse order. For interrupts, the GIC ensures this is 148the case; for non-interrupts, the |EHF| monitors and asserts this. See 149`Transition of priority levels`_. 150 151Interrupt handling 152------------------ 153 154The |EHF| is a client of *Interrupt Management Framework*, and registers the 155top-level handler for interrupts that target EL3, as described in the `Interrupt 156Framework Design`_ document. This has the following implications. 157 158- On GICv3 systems, when executing in S-EL1, pending Non-secure interrupts of 159 sufficient priority are signalled as FIQs, and therefore will be routed to 160 EL3. As a result, S-EL1 software cannot expect to handle Non-secure 161 interrupts at S-EL1. Essentially, this deprecates the routing mode described 162 as `CSS=0, TEL3=0`__. 163 164 .. __: interrupt-framework-design.rst#el3-interrupts 165 166 In order for S-EL1 software to handle Non-secure interrupts while having 167 |EHF| enabled, the dispatcher must adopt a model where Non-secure interrupts 168 are received at EL3, but are then `synchronously`__ handled over to S-EL1. 169 170 .. __: interrupt-framework-design.rst#secure-payload 171 172- On GICv2 systems, it's required that the build option ``GICV2_G0_FOR_EL3`` is 173 set to ``1`` so that *Group 0* interrupts target EL3. 174 175- While executing in Secure world, |EHF| sets GIC Priority Mask Register to the 176 lowest Secure priority. This means that no Non-secure interrupts can preempt 177 Secure execution. See `Effect on SMC calls`_ for more details. 178 179As mentioned above, with |EHF|, the platform is required to partition *Group 0* 180interrupts into distinct priority levels. A dispatcher that chooses to receive 181interrupts can then *own* one or more priority levels, and register interrupt 182handlers for them. A given priority level can be assigned to only one handler. A 183dispatcher may register more than one priority level. 184 185Dispatchers are assigned interrupt priority levels in two steps: 186 187Partitioning priority levels 188~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 189 190Interrupts are associated to dispatchers by way of grouping and assigning 191interrupts to a priority level. In other words, all interrupts that are to 192target a particular dispatcher should fall in a particular priority level. For 193priority assignment: 194 195- Of the 8 bits of priority that Arm GIC architecture permits, bit 7 must be 0 196 (secure space). 197 198- Depending on the number of dispatchers to support, the platform must choose 199 to use the top *n* of the 7 remaining bits to identify and assign interrupts 200 to individual dispatchers. Choosing *n* bits supports up to 2\ :sup:`n` 201 distinct dispatchers. For example, by choosing 2 additional bits (i.e., bits 202 6 and 5), the platform can partition into 4 secure priority ranges: ``0x0``, 203 ``0x20``, ``0x40``, and ``0x60``. See `Interrupt handling example`_. 204 205Note: 206 207 The Arm GIC architecture requires that a GIC implementation that supports two 208 security states must implement at least 32 priority levels; i.e., at least 5 209 upper bits of the 8 bits are writeable. In the scheme described above, when 210 choosing *n* bits for priority range assignment, the platform must ensure 211 that at least ``n+1`` top bits of GIC priority are writeable. 212 213The priority thus assigned to an interrupt is also used to determine the 214priority of delegated execution in lower ELs. Delegated execution in lower EL is 215associated with a priority level chosen with ``ehf_activate_priority()`` API 216(described `later`__). The chosen priority level also determines the interrupts 217masked while executing in a lower EL, therefore controls preemption of delegated 218execution. 219 220.. __: `ehf-apis`_ 221 222The platform expresses the chosen priority levels by declaring an array of 223priority level descriptors. Each entry in the array is of type 224``ehf_pri_desc_t``, and declares a priority level, and shall be populated by the 225``EHF_PRI_DESC()`` macro. 226 227Note: 228 229 The macro ``EHF_PRI_DESC()`` installs the descriptors in the array at a 230 computed index, and not necessarily where the macro is placed in the array. 231 The size of the array might therefore be larger than what it appears to be. 232 The ``ARRAY_SIZE()`` macro therefore should be used to determine the size of 233 array. 234 235Finally, this array of descriptors is exposed to |EHF| via the 236``EHF_REGISTER_PRIORITIES()`` macro. 237 238Refer to the `Interrupt handling example`_ for usage. See also: `Interrupt 239Prioritisation Considerations`_. 240 241Programming priority 242~~~~~~~~~~~~~~~~~~~~ 243 244The text in `Partitioning priority levels`_ only describes how the platform 245expresses the required levels of priority. It however doesn't choose interrupts 246nor program the required priority in GIC. 247 248The `Firmware Design guide`__ explains methods for configuring secure 249interrupts. |EHF| requires the platform to enumerate interrupt properties (as 250opposed to just numbers) of Secure interrupts. The priority of secure interrupts 251must match that as determined in the `Partitioning priority levels`_ section above. 252 253.. __: firmware-design.rst#configuring-secure-interrupts 254 255See `Limitations`_, and also refer to `Interrupt handling example`_ for 256illustration. 257 258Registering handler 259------------------- 260 261Dispatchers register handlers for their priority levels through the following 262API: 263 264.. code:: c 265 266 int ehf_register_priority_handler(int pri, ehf_handler_t handler) 267 268The API takes two arguments: 269 270- The priority level for which the handler is being registered; 271 272- The handler to be registered. The handler must be aligned to 4 bytes. 273 274If a dispatcher owns more than one priority levels, it has to call the API for 275each of them. 276 277The API will succeed, and return ``0``, only if: 278 279- There exists a descriptor with the priority level requested. 280 281- There are no handlers already registered by a previous call to the API. 282 283Otherwise, the API returns ``-1``. 284 285The interrupt handler should have the following signature: 286 287.. code:: c 288 289 typedef int (*ehf_handler_t)(uint32_t intr_raw, uint32_t flags, void *handle, 290 void *cookie); 291 292The parameters are as obtained from the top-level `EL3 interrupt handler`__. 293 294.. __: interrupt-framework-design.rst#el3-runtime-firmware 295 296The `SDEI dispatcher`__, for example, expects the platform to allocate two 297different priority levels—``PLAT_SDEI_CRITICAL_PRI``, and 298``PLAT_SDEI_NORMAL_PRI``—and registers the same handler to handle both levels. 299 300.. __: sdei.rst 301 302Interrupt handling example 303-------------------------- 304 305The following annotated snippet demonstrates how a platform might choose to 306assign interrupts to fictitious dispatchers: 307 308.. code:: c 309 310 #include <common/interrupt_props.h> 311 #include <drivers/arm/gic_common.h> 312 #include <exception_mgmt.h> 313 314 ... 315 316 /* 317 * This platform uses 2 bits for interrupt association. In total, 3 upper 318 * bits are in use. 319 * 320 * 7 6 5 3 0 321 * .-.-.-.----------. 322 * |0|b|b| ..0.. | 323 * '-'-'-'----------' 324 */ 325 #define PLAT_PRI_BITS 2 326 327 /* Priorities for individual dispatchers */ 328 #define DISP0_PRIO 0x00 /* Not used */ 329 #define DISP1_PRIO 0x20 330 #define DISP2_PRIO 0x40 331 #define DISP3_PRIO 0x60 332 333 /* Install priority level descriptors for each dispatcher */ 334 ehf_pri_desc_t plat_exceptions[] = { 335 EHF_PRI_DESC(PLAT_PRI_BITS, DISP1_PRIO), 336 EHF_PRI_DESC(PLAT_PRI_BITS, DISP2_PRIO), 337 EHF_PRI_DESC(PLAT_PRI_BITS, DISP3_PRIO), 338 }; 339 340 /* Expose priority descriptors to Exception Handling Framework */ 341 EHF_REGISTER_PRIORITIES(plat_exceptions, ARRAY_SIZE(plat_exceptions), 342 PLAT_PRI_BITS); 343 344 ... 345 346 /* List interrupt properties for GIC driver. All interrupts target EL3 */ 347 const interrupt_prop_t plat_interrupts[] = { 348 /* Dispatcher 1 owns interrupts d1_0 and d1_1, so assigns priority DISP1_PRIO */ 349 INTR_PROP_DESC(d1_0, DISP1_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), 350 INTR_PROP_DESC(d1_1, DISP1_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), 351 352 /* Dispatcher 2 owns interrupts d2_0 and d2_1, so assigns priority DISP2_PRIO */ 353 INTR_PROP_DESC(d2_0, DISP2_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), 354 INTR_PROP_DESC(d2_1, DISP2_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), 355 356 /* Dispatcher 3 owns interrupts d3_0 and d3_1, so assigns priority DISP3_PRIO */ 357 INTR_PROP_DESC(d3_0, DISP3_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), 358 INTR_PROP_DESC(d3_1, DISP3_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), 359 }; 360 361 ... 362 363 /* Dispatcher 1 registers its handler */ 364 ehf_register_priority_handler(DISP1_PRIO, disp1_handler); 365 366 /* Dispatcher 2 registers its handler */ 367 ehf_register_priority_handler(DISP2_PRIO, disp2_handler); 368 369 /* Dispatcher 3 registers its handler */ 370 ehf_register_priority_handler(DISP3_PRIO, disp3_handler); 371 372 ... 373 374See also the `Build-time flow`_ and the `Run-time flow`_. 375 376Activating and Deactivating priorities 377-------------------------------------- 378 379A priority level is said to be *active* when an exception of that priority is 380being handled: for interrupts, this is implied when the interrupt is 381acknowledged; for non-interrupt exceptions, such as SErrors or `SDEI explicit 382dispatches`__, this has to be done via calling ``ehf_activate_priority()``. See 383`Run-time flow`_. 384 385.. __: sdei.rst#explicit-dispatch-of-events 386 387Conversely, when the dispatcher has reached a logical resolution for the cause 388of the exception, the corresponding priority level ought to be deactivated. As 389above, for interrupts, this is implied when the interrupt is EOId in the GIC; 390for other exceptions, this has to be done via calling 391``ehf_deactivate_priority()``. 392 393Thanks to `different provisions`__ for exception delegation, there are 394potentially more than one work flow for deactivation: 395 396.. __: `delegation-use-cases`_ 397 398.. _deactivation workflows: 399 400- The dispatcher has addressed the cause of the exception, and decided to take 401 no further action. In this case, the dispatcher's handler deactivates the 402 priority level before returning to the |EHF|. Runtime firmware, upon exit 403 through an ``ERET``, resumes execution before the interrupt occurred. 404 405- The dispatcher has to delegate the execution to lower ELs, and the cause of 406 the exception can be considered resolved only when the lower EL returns 407 signals complete (via an ``SMC``) at a future point in time. The following 408 sequence ensues: 409 410 #. The dispatcher calls ``setjmp()`` to setup a jump point, and arranges to 411 enter a lower EL upon the next ``ERET``. 412 413 #. Through the ensuing ``ERET`` from runtime firmware, execution is delegated 414 to a lower EL. 415 416 #. The lower EL completes its execution, and signals completion via an 417 ``SMC``. 418 419 #. The ``SMC`` is handled by the same dispatcher that handled the exception 420 previously. Noticing the conclusion of exception handling, the dispatcher 421 does ``longjmp()`` to resume beyond the previous jump point. 422 423As mentioned above, the |EHF| provides the following APIs for activating and 424deactivating interrupt: 425 426.. _ehf-apis: 427 428- ``ehf_activate_priority()`` activates the supplied priority level, but only 429 if the current active priority is higher than the given one; otherwise 430 panics. Also, to prevent interruption by physical interrupts of lower 431 priority, the |EHF| programs the *Priority Mask Register* corresponding to 432 the PE to the priority being activated. Dispatchers typically only need to 433 call this when handling exceptions other than interrupts, and it needs to 434 delegate execution to a lower EL at a desired priority level. 435 436- ``ehf_deactivate_priority()`` deactivates a given priority, but only if the 437 current active priority is equal to the given one; otherwise panics. |EHF| 438 also restores the *Priority Mask Register* corresponding to the PE to the 439 priority before the call to ``ehf_activate_priority()``. Dispatchers 440 typically only need to call this after handling exceptions other than 441 interrupts. 442 443The calling of APIs are subject to allowed `transitions`__. See also the 444`Run-time flow`_. 445 446.. __: `Transition of priority levels`_ 447 448Transition of priority levels 449----------------------------- 450 451The |EHF| APIs ``ehf_activate_priority()`` and ``ehf_deactivate_priority()`` can 452be called to transition the current priority level on a PE. A given sequence of 453calls to these APIs are subject to the following conditions: 454 455- For activation, the |EHF| only allows for the priority to increase (i.e. 456 numeric value decreases); 457 458- For deactivation, the |EHF| only allows for the priority to decrease (i.e. 459 numeric value increases). Additionally, the priority being deactivated is 460 required to be the current priority. 461 462If these are violated, a panic will result. 463 464Effect on SMC calls 465------------------- 466 467In general, Secure execution is regarded as more important than Non-secure 468execution. As discussed elsewhere in this document, EL3 execution, and any 469delegated execution thereafter, has the effect of raising GIC's priority 470mask—either implicitly by acknowledging Secure interrupts, or when dispatchers 471call ``ehf_activate_priority()``. As a result, Non-secure interrupts cannot 472preempt any Secure execution. 473 474SMCs from Non-secure world are synchronous exceptions, and are mechanisms for 475Non-secure world to request Secure services. They're broadly classified as 476*Fast* or *Yielding* (see `SMCCC`__). 477 478.. __: `http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html` 479 480- *Fast* SMCs are atomic from the caller's point of view. I.e., they return 481 to the caller only when the Secure world has finished serving the request. 482 Any Non-secure interrupts that become pending meanwhile cannot preempt Secure 483 execution. 484 485- *Yielding* SMCs carry the semantics of a preemptible, lower-priority request. 486 A pending Non-secure interrupt can preempt Secure execution handling a 487 Yielding SMC. I.e., the caller might observe a Yielding SMC returning when 488 either: 489 490 #. Secure world completes the request, and the caller would find ``SMC_OK`` 491 as the return code. 492 493 #. A Non-secure interrupt preempts Secure execution. Non-secure interrupt is 494 handled, and Non-secure execution resumes after ``SMC`` instruction. 495 496 The dispatcher handling a Yielding SMC must provide a different return code 497 to the Non-secure caller to distinguish the latter case. This return code, 498 however, is not standardised (unlike ``SMC_UNKNOWN`` or ``SMC_OK``, for 499 example), so will vary across dispatchers that handle the request. 500 501For the latter case above, dispatchers before |EHF| expect Non-secure interrupts 502to be taken to S-EL1 [#irq]_, so would get a chance to populate the designated 503preempted error code before yielding to Non-secure world. 504 505The introduction of |EHF| changes the behaviour as described in `Interrupt 506handling`_. 507 508When |EHF| is enabled, in order to allow Non-secure interrupts to preempt 509Yielding SMC handling, the dispatcher must call ``ehf_allow_ns_preemption()`` 510API. The API takes one argument, the error code to be returned to the Non-secure 511world upon getting preempted. 512 513.. [#irq] In case of GICv2, Non-secure interrupts while in S-EL1 were signalled 514 as IRQs, and in case of GICv3, FIQs. 515 516Build-time flow 517--------------- 518 519Please refer to the `figure`__ above. 520 521.. __: `ehf-figure`_ 522 523The build-time flow involves the following steps: 524 525#. Platform assigns priorities by installing priority level descriptors for 526 individual dispatchers, as described in `Partitioning priority levels`_. 527 528#. Platform provides interrupt properties to GIC driver, as described in 529 `Programming priority`_. 530 531#. Dispatcher calling ``ehf_register_priority_handler()`` to register an 532 interrupt handler. 533 534Also refer to the `Interrupt handling example`_. 535 536Run-time flow 537------------- 538 539.. _interrupt-flow: 540 541The following is an example flow for interrupts: 542 543#. The GIC driver, during initialization, iterates through the platform-supplied 544 interrupt properties (see `Programming priority`_), and configures the 545 interrupts. This programs the appropriate priority and group (Group 0) on 546 interrupts belonging to different dispatchers. 547 548#. The |EHF|, during its initialisation, registers a top-level interrupt handler 549 with the `Interrupt Management Framework`__ for EL3 interrupts. This also 550 results in setting the routing bits in ``SCR_EL3``. 551 552 .. __: interrupt-framework-design.rst#el3-runtime-firmware 553 554#. When an interrupt belonging to a dispatcher fires, GIC raises an EL3/Group 0 555 interrupt, and is taken to EL3. 556 557#. The top-level EL3 interrupt handler executes. The handler acknowledges the 558 interrupt, reads its *Running Priority*, and from that, determines the 559 dispatcher handler. 560 561#. The |EHF| programs the *Priority Mask Register* of the PE to the priority of 562 the interrupt received. 563 564#. The |EHF| marks that priority level *active*, and jumps to the dispatcher 565 handler. 566 567#. Once the dispatcher handler finishes its job, it has to immediately 568 *deactivate* the priority level before returning to the |EHF|. See 569 `deactivation workflows`_. 570 571.. _non-interrupt-flow: 572 573The following is an example flow for exceptions that targets EL3 other than 574interrupt: 575 576#. The platform provides handlers for the specific kind of exception. 577 578#. The exception arrives, and the corresponding handler is executed. 579 580#. The handler calls ``ehf_activate_priority()`` to activate the required 581 priority level. This also has the effect of raising GIC priority mask, thus 582 preventing interrupts of lower priority from preempting the handling. The 583 handler may choose to do the handling entirely in EL3 or delegate to a lower 584 EL. 585 586#. Once exception handling concludes, the handler calls 587 ``ehf_deactivate_priority()`` to deactivate the priority level activated 588 earlier. This also has the effect of lowering GIC priority mask to what it 589 was before. 590 591Interrupt Prioritisation Considerations 592--------------------------------------- 593 594The GIC priority scheme, by design, prioritises Secure interrupts over Normal 595world ones. The platform further assigns relative priorities amongst Secure 596dispatchers through |EHF|. 597 598As mentioned in `Partitioning priority levels`_, interrupts targeting distinct 599dispatchers fall in distinct priority levels. Because they're routed via the 600GIC, interrupt delivery to the PE is subject to GIC prioritisation rules. In 601particular, when an interrupt is being handled by the PE (i.e., the interrupt is 602in *Active* state), only interrupts of higher priority are signalled to the PE, 603even if interrupts of same or lower priority are pending. This has the side 604effect of one dispatcher being starved of interrupts by virtue of another 605dispatcher handling its (higher priority) interrupts. 606 607The |EHF| doesn't enforce a particular prioritisation policy, but the platform 608should carefully consider the assignment of priorities to dispatchers integrated 609into runtime firmware. The platform should sensibly delineate priority to 610various dispatchers according to their nature. In particular, dispatchers of 611critical nature (RAS, for example) should be assigned higher priority than 612others (SDEI, for example); and within SDEI, Critical priority SDEI should be 613assigned higher priority than Normal ones. 614 615Limitations 616----------- 617 618The |EHF| has the following limitations: 619 620- Although there could be up to 128 Secure dispatchers supported by the GIC 621 priority scheme, the size of descriptor array exposed with 622 ``EHF_REGISTER_PRIORITIES()`` macro is currently limited to 32. This serves most 623 expected use cases. This may be expanded in the future, should use cases 624 demand so. 625 626- The platform must ensure that the priority assigned to the dispatcher in the 627 exception descriptor and the programmed priority of interrupts handled by the 628 dispatcher match. The |EHF| cannot verify that this has been followed. 629 630---- 631 632*Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.* 633 634.. _Interrupt Framework Design: interrupt-framework-design.rst 635.. _SDEI specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf 636