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