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