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