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