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