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