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