xref: /rk3399_ARM-atf/docs/components/exception-handling.rst (revision 8aa050554b996406231a66a048b56fa03ba220c8)
1*8aa05055SPaul BeesleyException Handling Framework
2*8aa05055SPaul Beesley============================
340d553cfSPaul Beesley
440d553cfSPaul Beesley.. contents::
540d553cfSPaul Beesley    :depth: 2
640d553cfSPaul Beesley
740d553cfSPaul Beesley.. |EHF| replace:: Exception Handling Framework
840d553cfSPaul Beesley.. |TF-A| replace:: Trusted Firmware-A
940d553cfSPaul Beesley
1040d553cfSPaul BeesleyThis document describes various aspects of handling exceptions by Runtime
1140d553cfSPaul BeesleyFirmware (BL31) that are targeted at EL3, other than SMCs. The |EHF| takes care
1240d553cfSPaul Beesleyof the following exceptions when targeted at EL3:
1340d553cfSPaul Beesley
1440d553cfSPaul Beesley-  Interrupts
1540d553cfSPaul Beesley-  Synchronous External Aborts
1640d553cfSPaul Beesley-  Asynchronous External Aborts
1740d553cfSPaul Beesley
1840d553cfSPaul Beesley|TF-A|'s handling of synchronous ``SMC`` exceptions raised from lower ELs is
1940d553cfSPaul Beesleydescribed in the `Firmware Design document`__. However, the |EHF| changes the
2040d553cfSPaul Beesleysemantics of `interrupt handling`__ and `synchronous exceptions`__ other than
2140d553cfSPaul BeesleySMCs.
2240d553cfSPaul Beesley
2340d553cfSPaul Beesley.. __: firmware-design.rst#handling-an-smc
2440d553cfSPaul Beesley.. __: `Interrupt handling`_
2540d553cfSPaul Beesley.. __: `Effect on SMC calls`_
2640d553cfSPaul Beesley
2740d553cfSPaul BeesleyThe |EHF| is selected by setting the build option ``EL3_EXCEPTION_HANDLING`` to
2840d553cfSPaul Beesley``1``, and is only available for AArch64 systems.
2940d553cfSPaul Beesley
3040d553cfSPaul BeesleyIntroduction
3140d553cfSPaul Beesley------------
3240d553cfSPaul Beesley
3340d553cfSPaul BeesleyThrough various control bits in the ``SCR_EL3`` register, the Arm architecture
3440d553cfSPaul Beesleyallows for asynchronous exceptions to be routed to EL3. As described in the
3540d553cfSPaul Beesley`Interrupt Framework Design`_ document, depending on the chosen interrupt
3640d553cfSPaul Beesleyrouting model, TF-A appropriately sets the ``FIQ`` and ``IRQ`` bits of
3740d553cfSPaul Beesley``SCR_EL3`` register to effect this routing. For most use cases, other than for
3840d553cfSPaul Beesleythe purpose of facilitating context switch between Normal and Secure worlds,
3940d553cfSPaul BeesleyFIQs and IRQs routed to EL3 are not required to be handled in EL3.
4040d553cfSPaul Beesley
4140d553cfSPaul BeesleyHowever, the evolving system and standards landscape demands that various
4240d553cfSPaul Beesleyexceptions are targeted at and handled in EL3. For instance:
4340d553cfSPaul Beesley
4440d553cfSPaul Beesley-  Starting with ARMv8.2 architecture extension, many RAS features have been
4540d553cfSPaul Beesley   introduced to the Arm architecture. With RAS features implemented, various
4640d553cfSPaul Beesley   components of the system may use one of the asynchronous exceptions to signal
4740d553cfSPaul Beesley   error conditions to PEs. These error conditions are of critical nature, and
4840d553cfSPaul Beesley   it's imperative that corrective or remedial actions are taken at the earliest
4940d553cfSPaul Beesley   opportunity. Therefore, a *Firmware-first Handling* approach is generally
5040d553cfSPaul Beesley   followed in response to RAS events in the system.
5140d553cfSPaul Beesley
5240d553cfSPaul Beesley-  The Arm `SDEI specification`_ defines interfaces through which Normal world
5340d553cfSPaul Beesley   interacts with the Runtime Firmware in order to request notification of
5440d553cfSPaul Beesley   system events. The SDEI specification requires that these events are notified
5540d553cfSPaul Beesley   even when the Normal world executes with the exceptions masked. This too
5640d553cfSPaul Beesley   implies that firmware-first handling is required, where the events are first
5740d553cfSPaul Beesley   received by the EL3 firmware, and then dispatched to Normal world through
5840d553cfSPaul Beesley   purely software mechanism.
5940d553cfSPaul Beesley
6040d553cfSPaul BeesleyFor |TF-A|, firmware-first handling means that asynchronous exceptions are
6140d553cfSPaul Beesleysuitably routed to EL3, and the Runtime Firmware (BL31) is extended to include
6240d553cfSPaul Beesleysoftware components that are capable of handling those exceptions that target
6340d553cfSPaul BeesleyEL3. These components—referred to as *dispatchers* [#spd]_ in general—may
6440d553cfSPaul Beesleychoose to:
6540d553cfSPaul Beesley
6640d553cfSPaul Beesley.. _delegation-use-cases:
6740d553cfSPaul Beesley
6840d553cfSPaul Beesley-  Receive and handle exceptions entirely in EL3, meaning the exceptions
6940d553cfSPaul Beesley   handling terminates in EL3.
7040d553cfSPaul Beesley
7140d553cfSPaul Beesley-  Receive exceptions, but handle part of the exception in EL3, and delegate the
7240d553cfSPaul Beesley   rest of the handling to a dedicated software stack running at lower Secure
7340d553cfSPaul Beesley   ELs. In this scheme, the handling spans various secure ELs.
7440d553cfSPaul Beesley
7540d553cfSPaul Beesley-  Receive exceptions, but handle part of the exception in EL3, and delegate
7640d553cfSPaul Beesley   processing of the error to dedicated software stack running at lower secure
7740d553cfSPaul Beesley   ELs (as above); additionally, the Normal world may also be required to
7840d553cfSPaul Beesley   participate in the handling, or be notified of such events (for example, as
7940d553cfSPaul Beesley   an SDEI event). In this scheme, exception handling potentially and maximally
8040d553cfSPaul Beesley   spans all ELs in both Secure and Normal worlds.
8140d553cfSPaul Beesley
8240d553cfSPaul BeesleyOn any given system, all of the above handling models may be employed
8340d553cfSPaul Beesleyindependently depending on platform choice and the nature of the exception
8440d553cfSPaul Beesleyreceived.
8540d553cfSPaul Beesley
8640d553cfSPaul Beesley.. [#spd] Not to be confused with `Secure Payload Dispatcher`__, which is an
8740d553cfSPaul Beesley   EL3 component that operates in EL3 on behalf of Secure OS.
8840d553cfSPaul Beesley
8940d553cfSPaul Beesley.. __: firmware-design.rst#secure-el1-payloads-and-dispatchers
9040d553cfSPaul Beesley
9140d553cfSPaul BeesleyThe role of Exception Handling Framework
9240d553cfSPaul Beesley----------------------------------------
9340d553cfSPaul Beesley
9440d553cfSPaul BeesleyCorollary to the use cases cited above, the primary role of the |EHF| is to
9540d553cfSPaul Beesleyfacilitate firmware-first handling of exceptions on Arm systems. The |EHF| thus
9640d553cfSPaul Beesleyenables multiple exception dispatchers in runtime firmware to co-exist, register
9740d553cfSPaul Beesleyfor, and handle exceptions targeted at EL3. This section outlines the basics,
9840d553cfSPaul Beesleyand the rest of this document expands the various aspects of the |EHF|.
9940d553cfSPaul Beesley
10040d553cfSPaul BeesleyIn order to arbitrate exception handling among dispatchers, the |EHF| operation
10140d553cfSPaul Beesleyis based on a priority scheme. This priority scheme is closely tied to how the
10240d553cfSPaul BeesleyArm GIC architecture defines it, although it's applied to non-interrupt
10340d553cfSPaul Beesleyexceptions too (SErrors, for example).
10440d553cfSPaul Beesley
10540d553cfSPaul BeesleyThe platform is required to `partition`__ the Secure priority space into
10640d553cfSPaul Beesleypriority levels as applicable for the Secure software stack. It then assigns the
10740d553cfSPaul Beesleydispatchers to one or more priority levels. The dispatchers then register
10840d553cfSPaul Beesleyhandlers for the priority levels at runtime. A dispatcher can register handlers
10940d553cfSPaul Beesleyfor more than one priority level.
11040d553cfSPaul Beesley
11140d553cfSPaul Beesley.. __: `Partitioning priority levels`_
11240d553cfSPaul Beesley
11340d553cfSPaul Beesley
11440d553cfSPaul Beesley.. _ehf-figure:
11540d553cfSPaul Beesley
11640d553cfSPaul Beesley.. image:: ../draw.io/ehf.svg
11740d553cfSPaul Beesley
11840d553cfSPaul BeesleyA priority level is *active* when a handler at that priority level is currently
11940d553cfSPaul Beesleyexecuting in EL3, or has delegated the execution to a lower EL. For interrupts,
12040d553cfSPaul Beesleythis is implicit when an interrupt is targeted and acknowledged at EL3, and the
12140d553cfSPaul Beesleypriority of the acknowledged interrupt is used to match its registered handler.
12240d553cfSPaul BeesleyThe priority level is likewise implicitly deactivated when the interrupt
12340d553cfSPaul Beesleyhandling concludes by EOIing the interrupt.
12440d553cfSPaul Beesley
12540d553cfSPaul BeesleyNon-interrupt exceptions (SErrors, for example) don't have a notion of priority.
12640d553cfSPaul BeesleyIn order for the priority arbitration to work, the |EHF| provides APIs in order
12740d553cfSPaul Beesleyfor these non-interrupt exceptions to assume a priority, and to interwork with
12840d553cfSPaul Beesleyinterrupts. Dispatchers handling such exceptions must therefore explicitly
12940d553cfSPaul Beesleyactivate and deactivate the respective priority level as and when they're
13040d553cfSPaul Beesleyhandled or delegated.
13140d553cfSPaul Beesley
13240d553cfSPaul BeesleyBecause priority activation and deactivation for interrupt handling is implicit
13340d553cfSPaul Beesleyand involves GIC priority masking, it's impossible for a lower priority
13440d553cfSPaul Beesleyinterrupt to preempt a higher priority one. By extension, this means that a
13540d553cfSPaul Beesleylower priority dispatcher cannot preempt a higher-priority one. Priority
13640d553cfSPaul Beesleyactivation and deactivation for non-interrupt exceptions, however, has to be
13740d553cfSPaul Beesleyexplicit. The |EHF| therefore disallows for lower priority level to be activated
13840d553cfSPaul Beesleywhilst a higher priority level is active, and would result in a panic.
13940d553cfSPaul BeesleyLikewise, a panic would result if it's attempted to deactivate a lower priority
14040d553cfSPaul Beesleylevel when a higher priority level is active.
14140d553cfSPaul Beesley
14240d553cfSPaul BeesleyIn essence, priority level activation and deactivation conceptually works like a
14340d553cfSPaul Beesleystack—priority levels stack up in strictly increasing fashion, and need to be
14440d553cfSPaul Beesleyunstacked in strictly the reverse order. For interrupts, the GIC ensures this is
14540d553cfSPaul Beesleythe case; for non-interrupts, the |EHF| monitors and asserts this. See
14640d553cfSPaul Beesley`Transition of priority levels`_.
14740d553cfSPaul Beesley
14840d553cfSPaul BeesleyInterrupt handling
14940d553cfSPaul Beesley------------------
15040d553cfSPaul Beesley
15140d553cfSPaul BeesleyThe |EHF| is a client of *Interrupt Management Framework*, and registers the
15240d553cfSPaul Beesleytop-level handler for interrupts that target EL3, as described in the `Interrupt
15340d553cfSPaul BeesleyFramework Design`_ document. This has the following implications.
15440d553cfSPaul Beesley
15540d553cfSPaul Beesley-  On GICv3 systems, when executing in S-EL1, pending Non-secure interrupts of
15640d553cfSPaul Beesley   sufficient priority are signalled as FIQs, and therefore will be routed to
15740d553cfSPaul Beesley   EL3. As a result, S-EL1 software cannot expect to handle Non-secure
15840d553cfSPaul Beesley   interrupts at S-EL1. Essentially, this deprecates the routing mode described
15940d553cfSPaul Beesley   as `CSS=0, TEL3=0`__.
16040d553cfSPaul Beesley
16140d553cfSPaul Beesley   .. __: interrupt-framework-design.rst#el3-interrupts
16240d553cfSPaul Beesley
16340d553cfSPaul Beesley   In order for S-EL1 software to handle Non-secure interrupts while having
16440d553cfSPaul Beesley   |EHF| enabled, the dispatcher must adopt a model where Non-secure interrupts
16540d553cfSPaul Beesley   are received at EL3, but are then `synchronously`__ handled over to S-EL1.
16640d553cfSPaul Beesley
16740d553cfSPaul Beesley   .. __: interrupt-framework-design.rst#secure-payload
16840d553cfSPaul Beesley
16940d553cfSPaul Beesley-  On GICv2 systems, it's required that the build option ``GICV2_G0_FOR_EL3`` is
17040d553cfSPaul Beesley   set to ``1`` so that *Group 0* interrupts target EL3.
17140d553cfSPaul Beesley
17240d553cfSPaul Beesley-  While executing in Secure world, |EHF| sets GIC Priority Mask Register to the
17340d553cfSPaul Beesley   lowest Secure priority. This means that no Non-secure interrupts can preempt
17440d553cfSPaul Beesley   Secure execution. See `Effect on SMC calls`_ for more details.
17540d553cfSPaul Beesley
17640d553cfSPaul BeesleyAs mentioned above, with |EHF|, the platform is required to partition *Group 0*
17740d553cfSPaul Beesleyinterrupts into distinct priority levels. A dispatcher that chooses to receive
17840d553cfSPaul Beesleyinterrupts can then *own* one or more priority levels, and register interrupt
17940d553cfSPaul Beesleyhandlers for them. A given priority level can be assigned to only one handler. A
18040d553cfSPaul Beesleydispatcher may register more than one priority level.
18140d553cfSPaul Beesley
18240d553cfSPaul BeesleyDispatchers are assigned interrupt priority levels in two steps:
18340d553cfSPaul Beesley
18440d553cfSPaul BeesleyPartitioning priority levels
18540d553cfSPaul Beesley~~~~~~~~~~~~~~~~~~~~~~~~~~~~
18640d553cfSPaul Beesley
18740d553cfSPaul BeesleyInterrupts are associated to dispatchers by way of grouping and assigning
18840d553cfSPaul Beesleyinterrupts to a priority level. In other words, all interrupts that are to
18940d553cfSPaul Beesleytarget a particular dispatcher should fall in a particular priority level. For
19040d553cfSPaul Beesleypriority assignment:
19140d553cfSPaul Beesley
19240d553cfSPaul Beesley-  Of the 8 bits of priority that Arm GIC architecture permits, bit 7 must be 0
19340d553cfSPaul Beesley   (secure space).
19440d553cfSPaul Beesley
19540d553cfSPaul Beesley-  Depending on the number of dispatchers to support, the platform must choose
19640d553cfSPaul Beesley   to use the top *n* of the 7 remaining bits to identify and assign interrupts
19740d553cfSPaul Beesley   to individual dispatchers. Choosing *n* bits supports up to 2\ :sup:`n`
19840d553cfSPaul Beesley   distinct dispatchers. For example, by choosing 2 additional bits (i.e., bits
19940d553cfSPaul Beesley   6 and 5), the platform can partition into 4 secure priority ranges: ``0x0``,
20040d553cfSPaul Beesley   ``0x20``, ``0x40``, and ``0x60``. See `Interrupt handling example`_.
20140d553cfSPaul Beesley
20240d553cfSPaul BeesleyNote:
20340d553cfSPaul Beesley
20440d553cfSPaul Beesley   The Arm GIC architecture requires that a GIC implementation that supports two
20540d553cfSPaul Beesley   security states must implement at least 32 priority levels; i.e., at least 5
20640d553cfSPaul Beesley   upper bits of the 8 bits are writeable. In the scheme described above, when
20740d553cfSPaul Beesley   choosing *n* bits for priority range assignment, the platform must ensure
20840d553cfSPaul Beesley   that at least ``n+1`` top bits of GIC priority are writeable.
20940d553cfSPaul Beesley
21040d553cfSPaul BeesleyThe priority thus assigned to an interrupt is also used to determine the
21140d553cfSPaul Beesleypriority of delegated execution in lower ELs. Delegated execution in lower EL is
21240d553cfSPaul Beesleyassociated with a priority level chosen with ``ehf_activate_priority()`` API
21340d553cfSPaul Beesley(described `later`__). The chosen priority level also determines the interrupts
21440d553cfSPaul Beesleymasked while executing in a lower EL, therefore controls preemption of delegated
21540d553cfSPaul Beesleyexecution.
21640d553cfSPaul Beesley
21740d553cfSPaul Beesley.. __: `ehf-apis`_
21840d553cfSPaul Beesley
21940d553cfSPaul BeesleyThe platform expresses the chosen priority levels by declaring an array of
22040d553cfSPaul Beesleypriority level descriptors. Each entry in the array is of type
22140d553cfSPaul Beesley``ehf_pri_desc_t``, and declares a priority level, and shall be populated by the
22240d553cfSPaul Beesley``EHF_PRI_DESC()`` macro.
22340d553cfSPaul Beesley
22440d553cfSPaul BeesleyNote:
22540d553cfSPaul Beesley
22640d553cfSPaul Beesley   The macro ``EHF_PRI_DESC()`` installs the descriptors in the array at a
22740d553cfSPaul Beesley   computed index, and not necessarily where the macro is placed in the array.
22840d553cfSPaul Beesley   The size of the array might therefore be larger than what it appears to be.
22940d553cfSPaul Beesley   The ``ARRAY_SIZE()`` macro therefore should be used to determine the size of
23040d553cfSPaul Beesley   array.
23140d553cfSPaul Beesley
23240d553cfSPaul BeesleyFinally, this array of descriptors is exposed to |EHF| via the
23340d553cfSPaul Beesley``EHF_REGISTER_PRIORITIES()`` macro.
23440d553cfSPaul Beesley
23540d553cfSPaul BeesleyRefer to the `Interrupt handling example`_ for usage. See also: `Interrupt
23640d553cfSPaul BeesleyPrioritisation Considerations`_.
23740d553cfSPaul Beesley
23840d553cfSPaul BeesleyProgramming priority
23940d553cfSPaul Beesley~~~~~~~~~~~~~~~~~~~~
24040d553cfSPaul Beesley
24140d553cfSPaul BeesleyThe text in `Partitioning priority levels`_ only describes how the platform
24240d553cfSPaul Beesleyexpresses the required levels of priority. It however doesn't choose interrupts
24340d553cfSPaul Beesleynor program the required priority in GIC.
24440d553cfSPaul Beesley
24540d553cfSPaul BeesleyThe `Firmware Design guide`__ explains methods for configuring secure
24640d553cfSPaul Beesleyinterrupts. |EHF| requires the platform to enumerate interrupt properties (as
24740d553cfSPaul Beesleyopposed to just numbers) of Secure interrupts. The priority of secure interrupts
24840d553cfSPaul Beesleymust match that as determined in the `Partitioning priority levels`_ section above.
24940d553cfSPaul Beesley
25040d553cfSPaul Beesley.. __: firmware-design.rst#configuring-secure-interrupts
25140d553cfSPaul Beesley
25240d553cfSPaul BeesleySee `Limitations`_, and also refer to `Interrupt handling example`_ for
25340d553cfSPaul Beesleyillustration.
25440d553cfSPaul Beesley
25540d553cfSPaul BeesleyRegistering handler
25640d553cfSPaul Beesley-------------------
25740d553cfSPaul Beesley
25840d553cfSPaul BeesleyDispatchers register handlers for their priority levels through the following
25940d553cfSPaul BeesleyAPI:
26040d553cfSPaul Beesley
26140d553cfSPaul Beesley.. code:: c
26240d553cfSPaul Beesley
26340d553cfSPaul Beesley   int ehf_register_priority_handler(int pri, ehf_handler_t handler)
26440d553cfSPaul Beesley
26540d553cfSPaul BeesleyThe API takes two arguments:
26640d553cfSPaul Beesley
26740d553cfSPaul Beesley-  The priority level for which the handler is being registered;
26840d553cfSPaul Beesley
26940d553cfSPaul Beesley-  The handler to be registered. The handler must be aligned to 4 bytes.
27040d553cfSPaul Beesley
27140d553cfSPaul BeesleyIf a dispatcher owns more than one priority levels, it has to call the API for
27240d553cfSPaul Beesleyeach of them.
27340d553cfSPaul Beesley
27440d553cfSPaul BeesleyThe API will succeed, and return ``0``, only if:
27540d553cfSPaul Beesley
27640d553cfSPaul Beesley-  There exists a descriptor with the priority level requested.
27740d553cfSPaul Beesley
27840d553cfSPaul Beesley-  There are no handlers already registered by a previous call to the API.
27940d553cfSPaul Beesley
28040d553cfSPaul BeesleyOtherwise, the API returns ``-1``.
28140d553cfSPaul Beesley
28240d553cfSPaul BeesleyThe interrupt handler should have the following signature:
28340d553cfSPaul Beesley
28440d553cfSPaul Beesley.. code:: c
28540d553cfSPaul Beesley
28640d553cfSPaul Beesley   typedef int (*ehf_handler_t)(uint32_t intr_raw, uint32_t flags, void *handle,
28740d553cfSPaul Beesley                   void *cookie);
28840d553cfSPaul Beesley
28940d553cfSPaul BeesleyThe parameters are as obtained from the top-level `EL3 interrupt handler`__.
29040d553cfSPaul Beesley
29140d553cfSPaul Beesley.. __: interrupt-framework-design.rst#el3-runtime-firmware
29240d553cfSPaul Beesley
29340d553cfSPaul BeesleyThe `SDEI dispatcher`__, for example, expects the platform to allocate two
29440d553cfSPaul Beesleydifferent priority levels—``PLAT_SDEI_CRITICAL_PRI``, and
29540d553cfSPaul Beesley``PLAT_SDEI_NORMAL_PRI``—and registers the same handler to handle both levels.
29640d553cfSPaul Beesley
29740d553cfSPaul Beesley.. __: sdei.rst
29840d553cfSPaul Beesley
29940d553cfSPaul BeesleyInterrupt handling example
30040d553cfSPaul Beesley--------------------------
30140d553cfSPaul Beesley
30240d553cfSPaul BeesleyThe following annotated snippet demonstrates how a platform might choose to
30340d553cfSPaul Beesleyassign interrupts to fictitious dispatchers:
30440d553cfSPaul Beesley
30540d553cfSPaul Beesley.. code:: c
30640d553cfSPaul Beesley
30740d553cfSPaul Beesley   #include <common/interrupt_props.h>
30840d553cfSPaul Beesley   #include <drivers/arm/gic_common.h>
30940d553cfSPaul Beesley   #include <exception_mgmt.h>
31040d553cfSPaul Beesley
31140d553cfSPaul Beesley   ...
31240d553cfSPaul Beesley
31340d553cfSPaul Beesley   /*
31440d553cfSPaul Beesley    * This platform uses 2 bits for interrupt association. In total, 3 upper
31540d553cfSPaul Beesley    * bits are in use.
31640d553cfSPaul Beesley    *
31740d553cfSPaul Beesley    *  7 6 5   3      0
31840d553cfSPaul Beesley    * .-.-.-.----------.
31940d553cfSPaul Beesley    * |0|b|b|  ..0..   |
32040d553cfSPaul Beesley    * '-'-'-'----------'
32140d553cfSPaul Beesley    */
32240d553cfSPaul Beesley   #define PLAT_PRI_BITS        2
32340d553cfSPaul Beesley
32440d553cfSPaul Beesley   /* Priorities for individual dispatchers */
32540d553cfSPaul Beesley   #define DISP0_PRIO           0x00 /* Not used */
32640d553cfSPaul Beesley   #define DISP1_PRIO           0x20
32740d553cfSPaul Beesley   #define DISP2_PRIO           0x40
32840d553cfSPaul Beesley   #define DISP3_PRIO           0x60
32940d553cfSPaul Beesley
33040d553cfSPaul Beesley   /* Install priority level descriptors for each dispatcher */
33140d553cfSPaul Beesley   ehf_pri_desc_t plat_exceptions[] = {
33240d553cfSPaul Beesley        EHF_PRI_DESC(PLAT_PRI_BITS, DISP1_PRIO),
33340d553cfSPaul Beesley        EHF_PRI_DESC(PLAT_PRI_BITS, DISP2_PRIO),
33440d553cfSPaul Beesley        EHF_PRI_DESC(PLAT_PRI_BITS, DISP3_PRIO),
33540d553cfSPaul Beesley   };
33640d553cfSPaul Beesley
33740d553cfSPaul Beesley   /* Expose priority descriptors to Exception Handling Framework */
33840d553cfSPaul Beesley   EHF_REGISTER_PRIORITIES(plat_exceptions, ARRAY_SIZE(plat_exceptions),
33940d553cfSPaul Beesley        PLAT_PRI_BITS);
34040d553cfSPaul Beesley
34140d553cfSPaul Beesley   ...
34240d553cfSPaul Beesley
34340d553cfSPaul Beesley   /* List interrupt properties for GIC driver. All interrupts target EL3 */
34440d553cfSPaul Beesley   const interrupt_prop_t plat_interrupts[] = {
34540d553cfSPaul Beesley        /* Dispatcher 1 owns interrupts d1_0 and d1_1, so assigns priority DISP1_PRIO */
34640d553cfSPaul Beesley        INTR_PROP_DESC(d1_0, DISP1_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL),
34740d553cfSPaul Beesley        INTR_PROP_DESC(d1_1, DISP1_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL),
34840d553cfSPaul Beesley
34940d553cfSPaul Beesley        /* Dispatcher 2 owns interrupts d2_0 and d2_1, so assigns priority DISP2_PRIO */
35040d553cfSPaul Beesley        INTR_PROP_DESC(d2_0, DISP2_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL),
35140d553cfSPaul Beesley        INTR_PROP_DESC(d2_1, DISP2_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL),
35240d553cfSPaul Beesley
35340d553cfSPaul Beesley        /* Dispatcher 3 owns interrupts d3_0 and d3_1, so assigns priority DISP3_PRIO */
35440d553cfSPaul Beesley        INTR_PROP_DESC(d3_0, DISP3_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL),
35540d553cfSPaul Beesley        INTR_PROP_DESC(d3_1, DISP3_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL),
35640d553cfSPaul Beesley   };
35740d553cfSPaul Beesley
35840d553cfSPaul Beesley   ...
35940d553cfSPaul Beesley
36040d553cfSPaul Beesley   /* Dispatcher 1 registers its handler */
36140d553cfSPaul Beesley   ehf_register_priority_handler(DISP1_PRIO, disp1_handler);
36240d553cfSPaul Beesley
36340d553cfSPaul Beesley   /* Dispatcher 2 registers its handler */
36440d553cfSPaul Beesley   ehf_register_priority_handler(DISP2_PRIO, disp2_handler);
36540d553cfSPaul Beesley
36640d553cfSPaul Beesley   /* Dispatcher 3 registers its handler */
36740d553cfSPaul Beesley   ehf_register_priority_handler(DISP3_PRIO, disp3_handler);
36840d553cfSPaul Beesley
36940d553cfSPaul Beesley   ...
37040d553cfSPaul Beesley
37140d553cfSPaul BeesleySee also the `Build-time flow`_ and the `Run-time flow`_.
37240d553cfSPaul Beesley
37340d553cfSPaul BeesleyActivating and Deactivating priorities
37440d553cfSPaul Beesley--------------------------------------
37540d553cfSPaul Beesley
37640d553cfSPaul BeesleyA priority level is said to be *active* when an exception of that priority is
37740d553cfSPaul Beesleybeing handled: for interrupts, this is implied when the interrupt is
37840d553cfSPaul Beesleyacknowledged; for non-interrupt exceptions, such as SErrors or `SDEI explicit
37940d553cfSPaul Beesleydispatches`__, this has to be done via calling ``ehf_activate_priority()``. See
38040d553cfSPaul Beesley`Run-time flow`_.
38140d553cfSPaul Beesley
38240d553cfSPaul Beesley.. __: sdei.rst#explicit-dispatch-of-events
38340d553cfSPaul Beesley
38440d553cfSPaul BeesleyConversely, when the dispatcher has reached a logical resolution for the cause
38540d553cfSPaul Beesleyof the exception, the corresponding priority level ought to be deactivated. As
38640d553cfSPaul Beesleyabove, for interrupts, this is implied when the interrupt is EOId in the GIC;
38740d553cfSPaul Beesleyfor other exceptions, this has to be done via calling
38840d553cfSPaul Beesley``ehf_deactivate_priority()``.
38940d553cfSPaul Beesley
39040d553cfSPaul BeesleyThanks to `different provisions`__ for exception delegation, there are
39140d553cfSPaul Beesleypotentially more than one work flow for deactivation:
39240d553cfSPaul Beesley
39340d553cfSPaul Beesley.. __: `delegation-use-cases`_
39440d553cfSPaul Beesley
39540d553cfSPaul Beesley.. _deactivation workflows:
39640d553cfSPaul Beesley
39740d553cfSPaul Beesley-  The dispatcher has addressed the cause of the exception, and decided to take
39840d553cfSPaul Beesley   no further action. In this case, the dispatcher's handler deactivates the
39940d553cfSPaul Beesley   priority level before returning to the |EHF|. Runtime firmware, upon exit
40040d553cfSPaul Beesley   through an ``ERET``, resumes execution before the interrupt occurred.
40140d553cfSPaul Beesley
40240d553cfSPaul Beesley-  The dispatcher has to delegate the execution to lower ELs, and the cause of
40340d553cfSPaul Beesley   the exception can be considered resolved only when the lower EL returns
40440d553cfSPaul Beesley   signals complete (via an ``SMC``) at a future point in time. The following
40540d553cfSPaul Beesley   sequence ensues:
40640d553cfSPaul Beesley
40740d553cfSPaul Beesley   #. The dispatcher calls ``setjmp()`` to setup a jump point, and arranges to
40840d553cfSPaul Beesley      enter a lower EL upon the next ``ERET``.
40940d553cfSPaul Beesley
41040d553cfSPaul Beesley   #. Through the ensuing ``ERET`` from runtime firmware, execution is delegated
41140d553cfSPaul Beesley      to a lower EL.
41240d553cfSPaul Beesley
41340d553cfSPaul Beesley   #. The lower EL completes its execution, and signals completion via an
41440d553cfSPaul Beesley      ``SMC``.
41540d553cfSPaul Beesley
41640d553cfSPaul Beesley   #. The ``SMC`` is handled by the same dispatcher that handled the exception
41740d553cfSPaul Beesley      previously. Noticing the conclusion of exception handling, the dispatcher
41840d553cfSPaul Beesley      does ``longjmp()`` to resume beyond the previous jump point.
41940d553cfSPaul Beesley
42040d553cfSPaul BeesleyAs mentioned above, the |EHF| provides the following APIs for activating and
42140d553cfSPaul Beesleydeactivating interrupt:
42240d553cfSPaul Beesley
42340d553cfSPaul Beesley.. _ehf-apis:
42440d553cfSPaul Beesley
42540d553cfSPaul Beesley-  ``ehf_activate_priority()`` activates the supplied priority level, but only
42640d553cfSPaul Beesley   if the current active priority is higher than the given one; otherwise
42740d553cfSPaul Beesley   panics. Also, to prevent interruption by physical interrupts of lower
42840d553cfSPaul Beesley   priority, the |EHF| programs the *Priority Mask Register* corresponding to
42940d553cfSPaul Beesley   the PE to the priority being activated.  Dispatchers typically only need to
43040d553cfSPaul Beesley   call this when handling exceptions other than interrupts, and it needs to
43140d553cfSPaul Beesley   delegate execution to a lower EL at a desired priority level.
43240d553cfSPaul Beesley
43340d553cfSPaul Beesley-  ``ehf_deactivate_priority()`` deactivates a given priority, but only if the
43440d553cfSPaul Beesley   current active priority is equal to the given one; otherwise panics. |EHF|
43540d553cfSPaul Beesley   also restores the *Priority Mask Register* corresponding to the PE to the
43640d553cfSPaul Beesley   priority before the call to ``ehf_activate_priority()``. Dispatchers
43740d553cfSPaul Beesley   typically only need to call this after handling exceptions other than
43840d553cfSPaul Beesley   interrupts.
43940d553cfSPaul Beesley
44040d553cfSPaul BeesleyThe calling of APIs are subject to allowed `transitions`__. See also the
44140d553cfSPaul Beesley`Run-time flow`_.
44240d553cfSPaul Beesley
44340d553cfSPaul Beesley.. __: `Transition of priority levels`_
44440d553cfSPaul Beesley
44540d553cfSPaul BeesleyTransition of priority levels
44640d553cfSPaul Beesley-----------------------------
44740d553cfSPaul Beesley
44840d553cfSPaul BeesleyThe |EHF| APIs ``ehf_activate_priority()`` and ``ehf_deactivate_priority()`` can
44940d553cfSPaul Beesleybe called to transition the current priority level on a PE. A given sequence of
45040d553cfSPaul Beesleycalls to these APIs are subject to the following conditions:
45140d553cfSPaul Beesley
45240d553cfSPaul Beesley-  For activation, the |EHF| only allows for the priority to increase (i.e.
45340d553cfSPaul Beesley   numeric value decreases);
45440d553cfSPaul Beesley
45540d553cfSPaul Beesley-  For deactivation, the |EHF| only allows for the priority to decrease (i.e.
45640d553cfSPaul Beesley   numeric value increases). Additionally, the priority being deactivated is
45740d553cfSPaul Beesley   required to be the current priority.
45840d553cfSPaul Beesley
45940d553cfSPaul BeesleyIf these are violated, a panic will result.
46040d553cfSPaul Beesley
46140d553cfSPaul BeesleyEffect on SMC calls
46240d553cfSPaul Beesley-------------------
46340d553cfSPaul Beesley
46440d553cfSPaul BeesleyIn general, Secure execution is regarded as more important than Non-secure
46540d553cfSPaul Beesleyexecution. As discussed elsewhere in this document, EL3 execution, and any
46640d553cfSPaul Beesleydelegated execution thereafter, has the effect of raising GIC's priority
46740d553cfSPaul Beesleymask—either implicitly by acknowledging Secure interrupts, or when dispatchers
46840d553cfSPaul Beesleycall ``ehf_activate_priority()``. As a result, Non-secure interrupts cannot
46940d553cfSPaul Beesleypreempt any Secure execution.
47040d553cfSPaul Beesley
47140d553cfSPaul BeesleySMCs from Non-secure world are synchronous exceptions, and are mechanisms for
47240d553cfSPaul BeesleyNon-secure world to request Secure services. They're broadly classified as
47340d553cfSPaul Beesley*Fast* or *Yielding* (see `SMCCC`__).
47440d553cfSPaul Beesley
47540d553cfSPaul Beesley.. __: `http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html`
47640d553cfSPaul Beesley
47740d553cfSPaul Beesley-  *Fast* SMCs are atomic from the caller's point of view. I.e., they return
47840d553cfSPaul Beesley   to the caller only when the Secure world has finished serving the request.
47940d553cfSPaul Beesley   Any Non-secure interrupts that become pending meanwhile cannot preempt Secure
48040d553cfSPaul Beesley   execution.
48140d553cfSPaul Beesley
48240d553cfSPaul Beesley-  *Yielding* SMCs carry the semantics of a preemptible, lower-priority request.
48340d553cfSPaul Beesley   A pending Non-secure interrupt can preempt Secure execution handling a
48440d553cfSPaul Beesley   Yielding SMC. I.e., the caller might observe a Yielding SMC returning when
48540d553cfSPaul Beesley   either:
48640d553cfSPaul Beesley
48740d553cfSPaul Beesley   #. Secure world completes the request, and the caller would find ``SMC_OK``
48840d553cfSPaul Beesley      as the return code.
48940d553cfSPaul Beesley
49040d553cfSPaul Beesley   #. A Non-secure interrupt preempts Secure execution. Non-secure interrupt is
49140d553cfSPaul Beesley      handled, and Non-secure execution resumes after ``SMC`` instruction.
49240d553cfSPaul Beesley
49340d553cfSPaul Beesley   The dispatcher handling a Yielding SMC must provide a different return code
49440d553cfSPaul Beesley   to the Non-secure caller to distinguish the latter case. This return code,
49540d553cfSPaul Beesley   however, is not standardised (unlike ``SMC_UNKNOWN`` or ``SMC_OK``, for
49640d553cfSPaul Beesley   example), so will vary across dispatchers that handle the request.
49740d553cfSPaul Beesley
49840d553cfSPaul BeesleyFor the latter case above, dispatchers before |EHF| expect Non-secure interrupts
49940d553cfSPaul Beesleyto be taken to S-EL1 [#irq]_, so would get a chance to populate the designated
50040d553cfSPaul Beesleypreempted error code before yielding to Non-secure world.
50140d553cfSPaul Beesley
50240d553cfSPaul BeesleyThe introduction of |EHF| changes the behaviour as described in `Interrupt
50340d553cfSPaul Beesleyhandling`_.
50440d553cfSPaul Beesley
50540d553cfSPaul BeesleyWhen |EHF| is enabled, in order to allow Non-secure interrupts to preempt
50640d553cfSPaul BeesleyYielding SMC handling, the dispatcher must call ``ehf_allow_ns_preemption()``
50740d553cfSPaul BeesleyAPI. The API takes one argument, the error code to be returned to the Non-secure
50840d553cfSPaul Beesleyworld upon getting preempted.
50940d553cfSPaul Beesley
51040d553cfSPaul Beesley.. [#irq] In case of GICv2, Non-secure interrupts while in S-EL1 were signalled
51140d553cfSPaul Beesley          as IRQs, and in case of GICv3, FIQs.
51240d553cfSPaul Beesley
51340d553cfSPaul BeesleyBuild-time flow
51440d553cfSPaul Beesley---------------
51540d553cfSPaul Beesley
51640d553cfSPaul BeesleyPlease refer to the `figure`__ above.
51740d553cfSPaul Beesley
51840d553cfSPaul Beesley.. __: `ehf-figure`_
51940d553cfSPaul Beesley
52040d553cfSPaul BeesleyThe build-time flow involves the following steps:
52140d553cfSPaul Beesley
52240d553cfSPaul Beesley#. Platform assigns priorities by installing priority level descriptors for
52340d553cfSPaul Beesley   individual dispatchers, as described in `Partitioning priority levels`_.
52440d553cfSPaul Beesley
52540d553cfSPaul Beesley#. Platform provides interrupt properties to GIC driver, as described in
52640d553cfSPaul Beesley   `Programming priority`_.
52740d553cfSPaul Beesley
52840d553cfSPaul Beesley#. Dispatcher calling ``ehf_register_priority_handler()`` to register an
52940d553cfSPaul Beesley   interrupt handler.
53040d553cfSPaul Beesley
53140d553cfSPaul BeesleyAlso refer to the `Interrupt handling example`_.
53240d553cfSPaul Beesley
53340d553cfSPaul BeesleyRun-time flow
53440d553cfSPaul Beesley-------------
53540d553cfSPaul Beesley
53640d553cfSPaul Beesley.. _interrupt-flow:
53740d553cfSPaul Beesley
53840d553cfSPaul BeesleyThe following is an example flow for interrupts:
53940d553cfSPaul Beesley
54040d553cfSPaul Beesley#. The GIC driver, during initialization, iterates through the platform-supplied
54140d553cfSPaul Beesley   interrupt properties (see `Programming priority`_), and configures the
54240d553cfSPaul Beesley   interrupts. This programs the appropriate priority and group (Group 0) on
54340d553cfSPaul Beesley   interrupts belonging to different dispatchers.
54440d553cfSPaul Beesley
54540d553cfSPaul Beesley#. The |EHF|, during its initialisation, registers a top-level interrupt handler
54640d553cfSPaul Beesley   with the `Interrupt Management Framework`__ for EL3 interrupts. This also
54740d553cfSPaul Beesley   results in setting the routing bits in ``SCR_EL3``.
54840d553cfSPaul Beesley
54940d553cfSPaul Beesley   .. __: interrupt-framework-design.rst#el3-runtime-firmware
55040d553cfSPaul Beesley
55140d553cfSPaul Beesley#. When an interrupt belonging to a dispatcher fires, GIC raises an EL3/Group 0
55240d553cfSPaul Beesley   interrupt, and is taken to EL3.
55340d553cfSPaul Beesley
55440d553cfSPaul Beesley#. The top-level EL3 interrupt handler executes. The handler acknowledges the
55540d553cfSPaul Beesley   interrupt, reads its *Running Priority*, and from that, determines the
55640d553cfSPaul Beesley   dispatcher handler.
55740d553cfSPaul Beesley
55840d553cfSPaul Beesley#. The |EHF| programs the *Priority Mask Register* of the PE to the priority of
55940d553cfSPaul Beesley   the interrupt received.
56040d553cfSPaul Beesley
56140d553cfSPaul Beesley#. The |EHF| marks that priority level *active*, and jumps to the dispatcher
56240d553cfSPaul Beesley   handler.
56340d553cfSPaul Beesley
56440d553cfSPaul Beesley#. Once the dispatcher handler finishes its job, it has to immediately
56540d553cfSPaul Beesley   *deactivate* the priority level before returning to the |EHF|. See
56640d553cfSPaul Beesley   `deactivation workflows`_.
56740d553cfSPaul Beesley
56840d553cfSPaul Beesley.. _non-interrupt-flow:
56940d553cfSPaul Beesley
57040d553cfSPaul BeesleyThe following is an example flow for exceptions that targets EL3 other than
57140d553cfSPaul Beesleyinterrupt:
57240d553cfSPaul Beesley
57340d553cfSPaul Beesley#. The platform provides handlers for the specific kind of exception.
57440d553cfSPaul Beesley
57540d553cfSPaul Beesley#. The exception arrives, and the corresponding handler is executed.
57640d553cfSPaul Beesley
57740d553cfSPaul Beesley#. The handler calls ``ehf_activate_priority()`` to activate the required
57840d553cfSPaul Beesley   priority level. This also has the effect of raising GIC priority mask, thus
57940d553cfSPaul Beesley   preventing interrupts of lower priority from preempting the handling. The
58040d553cfSPaul Beesley   handler may choose to do the handling entirely in EL3 or delegate to a lower
58140d553cfSPaul Beesley   EL.
58240d553cfSPaul Beesley
58340d553cfSPaul Beesley#. Once exception handling concludes, the handler calls
58440d553cfSPaul Beesley   ``ehf_deactivate_priority()`` to deactivate the priority level activated
58540d553cfSPaul Beesley   earlier. This also has the effect of lowering GIC priority mask to what it
58640d553cfSPaul Beesley   was before.
58740d553cfSPaul Beesley
58840d553cfSPaul BeesleyInterrupt Prioritisation Considerations
58940d553cfSPaul Beesley---------------------------------------
59040d553cfSPaul Beesley
59140d553cfSPaul BeesleyThe GIC priority scheme, by design, prioritises Secure interrupts over Normal
59240d553cfSPaul Beesleyworld ones. The platform further assigns relative priorities amongst Secure
59340d553cfSPaul Beesleydispatchers through |EHF|.
59440d553cfSPaul Beesley
59540d553cfSPaul BeesleyAs mentioned in `Partitioning priority levels`_, interrupts targeting distinct
59640d553cfSPaul Beesleydispatchers fall in distinct priority levels. Because they're routed via the
59740d553cfSPaul BeesleyGIC, interrupt delivery to the PE is subject to GIC prioritisation rules. In
59840d553cfSPaul Beesleyparticular, when an interrupt is being handled by the PE (i.e., the interrupt is
59940d553cfSPaul Beesleyin *Active* state), only interrupts of higher priority are signalled to the PE,
60040d553cfSPaul Beesleyeven if interrupts of same or lower priority are pending. This has the side
60140d553cfSPaul Beesleyeffect of one dispatcher being starved of interrupts by virtue of another
60240d553cfSPaul Beesleydispatcher handling its (higher priority) interrupts.
60340d553cfSPaul Beesley
60440d553cfSPaul BeesleyThe |EHF| doesn't enforce a particular prioritisation policy, but the platform
60540d553cfSPaul Beesleyshould carefully consider the assignment of priorities to dispatchers integrated
60640d553cfSPaul Beesleyinto runtime firmware. The platform should sensibly delineate priority to
60740d553cfSPaul Beesleyvarious dispatchers according to their nature. In particular, dispatchers of
60840d553cfSPaul Beesleycritical nature (RAS, for example) should be assigned higher priority than
60940d553cfSPaul Beesleyothers (SDEI, for example); and within SDEI, Critical priority SDEI should be
61040d553cfSPaul Beesleyassigned higher priority than Normal ones.
61140d553cfSPaul Beesley
61240d553cfSPaul BeesleyLimitations
61340d553cfSPaul Beesley-----------
61440d553cfSPaul Beesley
61540d553cfSPaul BeesleyThe |EHF| has the following limitations:
61640d553cfSPaul Beesley
61740d553cfSPaul Beesley-  Although there could be up to 128 Secure dispatchers supported by the GIC
61840d553cfSPaul Beesley   priority scheme, the size of descriptor array exposed with
61940d553cfSPaul Beesley   ``EHF_REGISTER_PRIORITIES()`` macro is currently limited to 32. This serves most
62040d553cfSPaul Beesley   expected use cases. This may be expanded in the future, should use cases
62140d553cfSPaul Beesley   demand so.
62240d553cfSPaul Beesley
62340d553cfSPaul Beesley-  The platform must ensure that the priority assigned to the dispatcher in the
62440d553cfSPaul Beesley   exception descriptor and the programmed priority of interrupts handled by the
62540d553cfSPaul Beesley   dispatcher match. The |EHF| cannot verify that this has been followed.
62640d553cfSPaul Beesley
62740d553cfSPaul Beesley----
62840d553cfSPaul Beesley
62940d553cfSPaul Beesley*Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.*
63040d553cfSPaul Beesley
63140d553cfSPaul Beesley.. _Interrupt Framework Design: interrupt-framework-design.rst
63240d553cfSPaul Beesley.. _SDEI specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf
633