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