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