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