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