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