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