xref: /rk3399_ARM-atf/docs/components/exception-handling.rst (revision 8aa050554b996406231a66a048b56fa03ba220c8)
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