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