xref: /rk3399_ARM-atf/docs/components/sdei.rst (revision 40d553cfde38d4f68449c62967cd1ce0d6478750)
1*40d553cfSPaul BeesleySDEI: Software Delegated Exception Interface
2*40d553cfSPaul Beesley============================================
3*40d553cfSPaul Beesley
4*40d553cfSPaul Beesley.. contents::
5*40d553cfSPaul Beesley    :depth: 2
6*40d553cfSPaul Beesley
7*40d553cfSPaul BeesleyThis document provides an overview of the SDEI dispatcher implementation in
8*40d553cfSPaul BeesleyTrusted Firmware-A (TF-A).
9*40d553cfSPaul Beesley
10*40d553cfSPaul BeesleyIntroduction
11*40d553cfSPaul Beesley------------
12*40d553cfSPaul Beesley
13*40d553cfSPaul Beesley`Software Delegated Exception Interface`_ (SDEI) is an Arm specification for
14*40d553cfSPaul BeesleyNon-secure world to register handlers with firmware to receive notifications
15*40d553cfSPaul Beesleyabout system events. Firmware will first receive the system events by way of
16*40d553cfSPaul Beesleyasynchronous exceptions and, in response, arranges for the registered handler to
17*40d553cfSPaul Beesleyexecute in the Non-secure EL.
18*40d553cfSPaul Beesley
19*40d553cfSPaul BeesleyNormal world software that interacts with the SDEI dispatcher (makes SDEI
20*40d553cfSPaul Beesleyrequests and receives notifications) is referred to as the *SDEI Client*. A
21*40d553cfSPaul Beesleyclient receives the event notification at the registered handler even when it
22*40d553cfSPaul Beesleywas executing with exceptions masked. The list of SDEI events available to the
23*40d553cfSPaul Beesleyclient are specific to the platform [#std-event]_. See also `Determining client
24*40d553cfSPaul BeesleyEL`_.
25*40d553cfSPaul Beesley
26*40d553cfSPaul Beesley.. _general SDEI dispatch:
27*40d553cfSPaul Beesley
28*40d553cfSPaul BeesleyThe following figure depicts a general sequence involving SDEI client executing
29*40d553cfSPaul Beesleyat EL2 and an event dispatch resulting from the triggering of a bound interrupt.
30*40d553cfSPaul BeesleyA commentary is provided below:
31*40d553cfSPaul Beesley
32*40d553cfSPaul Beesley.. image:: ../plantuml/sdei_general.svg
33*40d553cfSPaul Beesley
34*40d553cfSPaul BeesleyAs part of initialisation, the SDEI client binds a Non-secure interrupt [1], and
35*40d553cfSPaul Beesleythe SDEI dispatcher returns a platform dynamic event number [2]. The client then
36*40d553cfSPaul Beesleyregisters a handler for that event [3], enables the event [5], and unmasks all
37*40d553cfSPaul Beesleyevents on the current PE [7]. This sequence is typical of an SDEI client, but it
38*40d553cfSPaul Beesleymay involve additional SDEI calls.
39*40d553cfSPaul Beesley
40*40d553cfSPaul BeesleyAt a later point in time, when the bound interrupt triggers [9], it's trapped to
41*40d553cfSPaul BeesleyEL3. The interrupt is handed over to the SDEI dispatcher, which then arranges to
42*40d553cfSPaul Beesleyexecute the registered handler [10]. The client terminates its execution with
43*40d553cfSPaul Beesley``SDEI_EVENT_COMPLETE`` [11], following which the dispatcher resumes the
44*40d553cfSPaul Beesleyoriginal EL2 execution [13]. Note that the SDEI interrupt remains active until
45*40d553cfSPaul Beesleythe client handler completes, at which point EL3 does EOI [12].
46*40d553cfSPaul Beesley
47*40d553cfSPaul BeesleyOther than events bound to interrupts (as depicted in the sequence above, SDEI
48*40d553cfSPaul Beesleyevents can be explicitly dispatched in response to other exceptions, for
49*40d553cfSPaul Beesleyexample, upon receiving an *SError* or *Synchronous External Abort*. See
50*40d553cfSPaul Beesley`Explicit dispatch of events`_.
51*40d553cfSPaul Beesley
52*40d553cfSPaul BeesleyThe remainder of this document only discusses the design and implementation of
53*40d553cfSPaul BeesleySDEI dispatcher in TF-A, and assumes that the reader is familiar with the SDEI
54*40d553cfSPaul Beesleyspecification, the interfaces, and their requirements.
55*40d553cfSPaul Beesley
56*40d553cfSPaul Beesley.. [#std-event] Except event 0, which is defined by the SDEI specification as a
57*40d553cfSPaul Beesley                standard event.
58*40d553cfSPaul Beesley
59*40d553cfSPaul BeesleyDefining events
60*40d553cfSPaul Beesley---------------
61*40d553cfSPaul Beesley
62*40d553cfSPaul BeesleyA platform choosing to include the SDEI dispatcher must also define the events
63*40d553cfSPaul Beesleyavailable on the platform, along with their attributes.
64*40d553cfSPaul Beesley
65*40d553cfSPaul BeesleyThe platform is expected to provide two arrays of event descriptors: one for
66*40d553cfSPaul Beesleyprivate events, and another for shared events. The SDEI dispatcher provides
67*40d553cfSPaul Beesley``SDEI_PRIVATE_EVENT()`` and ``SDEI_SHARED_EVENT()`` macros to populate the
68*40d553cfSPaul Beesleyevent descriptors. Both macros take 3 arguments:
69*40d553cfSPaul Beesley
70*40d553cfSPaul Beesley-  The event number: this must be a positive 32-bit integer.
71*40d553cfSPaul Beesley
72*40d553cfSPaul Beesley-  For an event that has a backing interrupt, the interrupt number the event is
73*40d553cfSPaul Beesley   bound to:
74*40d553cfSPaul Beesley
75*40d553cfSPaul Beesley   - If it's not applicable to an event, this shall be left as ``0``.
76*40d553cfSPaul Beesley
77*40d553cfSPaul Beesley   - If the event is dynamic, this should be specified as ``SDEI_DYN_IRQ``.
78*40d553cfSPaul Beesley
79*40d553cfSPaul Beesley-  A bit map of `Event flags`_.
80*40d553cfSPaul Beesley
81*40d553cfSPaul BeesleyTo define event 0, the macro ``SDEI_DEFINE_EVENT_0()`` should be used. This
82*40d553cfSPaul Beesleymacro takes only one parameter: an SGI number to signal other PEs.
83*40d553cfSPaul Beesley
84*40d553cfSPaul BeesleyTo define an event that's meant to be `explicitly dispatched`__ (i.e., not as a
85*40d553cfSPaul Beesleyresult of receiving an SDEI interrupt), the macro ``SDEI_EXPLICIT_EVENT()``
86*40d553cfSPaul Beesleyshould be used. It accepts two parameters:
87*40d553cfSPaul Beesley
88*40d553cfSPaul Beesley.. __: `Explicit dispatch of events`_
89*40d553cfSPaul Beesley
90*40d553cfSPaul Beesley-  The event number (as above);
91*40d553cfSPaul Beesley
92*40d553cfSPaul Beesley-  Event priority: ``SDEI_MAPF_CRITICAL`` or ``SDEI_MAPF_NORMAL``, as described
93*40d553cfSPaul Beesley   below.
94*40d553cfSPaul Beesley
95*40d553cfSPaul BeesleyOnce the event descriptor arrays are defined, they should be exported to the
96*40d553cfSPaul BeesleySDEI dispatcher using the ``REGISTER_SDEI_MAP()`` macro, passing it the pointers
97*40d553cfSPaul Beesleyto the private and shared event descriptor arrays, respectively. Note that the
98*40d553cfSPaul Beesley``REGISTER_SDEI_MAP()`` macro must be used in the same file where the arrays are
99*40d553cfSPaul Beesleydefined.
100*40d553cfSPaul Beesley
101*40d553cfSPaul BeesleyRegarding event descriptors:
102*40d553cfSPaul Beesley
103*40d553cfSPaul Beesley-  For Event 0:
104*40d553cfSPaul Beesley
105*40d553cfSPaul Beesley   - There must be exactly one descriptor in the private array, and none in the
106*40d553cfSPaul Beesley     shared array.
107*40d553cfSPaul Beesley
108*40d553cfSPaul Beesley   - The event should be defined using ``SDEI_DEFINE_EVENT_0()``.
109*40d553cfSPaul Beesley
110*40d553cfSPaul Beesley   - Must be bound to a Secure SGI on the platform.
111*40d553cfSPaul Beesley
112*40d553cfSPaul Beesley-  Explicit events should only be used in the private array.
113*40d553cfSPaul Beesley
114*40d553cfSPaul Beesley-  Statically bound shared and private interrupts must be bound to shared and
115*40d553cfSPaul Beesley   private interrupts on the platform, respectively. See the section on
116*40d553cfSPaul Beesley   `interrupt configuration`__.
117*40d553cfSPaul Beesley
118*40d553cfSPaul Beesley   .. __: `Configuration within Exception Handling Framework`_
119*40d553cfSPaul Beesley
120*40d553cfSPaul Beesley-  Both arrays should be one-dimensional. The ``REGISTER_SDEI_MAP()`` macro
121*40d553cfSPaul Beesley   takes care of replicating private events for each PE on the platform.
122*40d553cfSPaul Beesley
123*40d553cfSPaul Beesley-  Both arrays must be sorted in the increasing order of event number.
124*40d553cfSPaul Beesley
125*40d553cfSPaul BeesleyThe SDEI specification doesn't have provisions for discovery of available events
126*40d553cfSPaul Beesleyon the platform. The list of events made available to the client, along with
127*40d553cfSPaul Beesleytheir semantics, have to be communicated out of band; for example, through
128*40d553cfSPaul BeesleyDevice Trees or firmware configuration tables.
129*40d553cfSPaul Beesley
130*40d553cfSPaul BeesleySee also `Event definition example`_.
131*40d553cfSPaul Beesley
132*40d553cfSPaul BeesleyEvent flags
133*40d553cfSPaul Beesley~~~~~~~~~~~
134*40d553cfSPaul Beesley
135*40d553cfSPaul BeesleyEvent flags describe the properties of the event. They are bit maps that can be
136*40d553cfSPaul Beesley``OR``\ ed to form parameters to macros that `define events`__.
137*40d553cfSPaul Beesley
138*40d553cfSPaul Beesley.. __: `Defining events`_
139*40d553cfSPaul Beesley
140*40d553cfSPaul Beesley-  ``SDEI_MAPF_DYNAMIC``: Marks the event as dynamic. Dynamic events can be
141*40d553cfSPaul Beesley   bound to (or released from) any Non-secure interrupt at runtime via the
142*40d553cfSPaul Beesley   ``SDEI_INTERRUPT_BIND`` and ``SDEI_INTERRUPT_RELEASE`` calls.
143*40d553cfSPaul Beesley
144*40d553cfSPaul Beesley-  ``SDEI_MAPF_BOUND``: Marks the event as statically bound to an interrupt.
145*40d553cfSPaul Beesley   These events cannot be re-bound at runtime.
146*40d553cfSPaul Beesley
147*40d553cfSPaul Beesley-  ``SDEI_MAPF_NORMAL``: Marks the event as having *Normal* priority. This is
148*40d553cfSPaul Beesley   the default priority.
149*40d553cfSPaul Beesley
150*40d553cfSPaul Beesley-  ``SDEI_MAPF_CRITICAL``: Marks the event as having *Critical* priority.
151*40d553cfSPaul Beesley
152*40d553cfSPaul BeesleyEvent definition example
153*40d553cfSPaul Beesley------------------------
154*40d553cfSPaul Beesley
155*40d553cfSPaul Beesley.. code:: c
156*40d553cfSPaul Beesley
157*40d553cfSPaul Beesley   static sdei_ev_map_t plat_private_sdei[] = {
158*40d553cfSPaul Beesley        /* Event 0 definition */
159*40d553cfSPaul Beesley        SDEI_DEFINE_EVENT_0(8),
160*40d553cfSPaul Beesley
161*40d553cfSPaul Beesley        /* PPI */
162*40d553cfSPaul Beesley        SDEI_PRIVATE_EVENT(8, 23, SDEI_MAPF_BOUND),
163*40d553cfSPaul Beesley
164*40d553cfSPaul Beesley        /* Dynamic private events */
165*40d553cfSPaul Beesley        SDEI_PRIVATE_EVENT(100, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
166*40d553cfSPaul Beesley        SDEI_PRIVATE_EVENT(101, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC)
167*40d553cfSPaul Beesley
168*40d553cfSPaul Beesley        /* Events for explicit dispatch */
169*40d553cfSPaul Beesley        SDEI_EXPLICIT_EVENT(2000, SDEI_MAPF_NORMAL);
170*40d553cfSPaul Beesley        SDEI_EXPLICIT_EVENT(2000, SDEI_MAPF_CRITICAL);
171*40d553cfSPaul Beesley   };
172*40d553cfSPaul Beesley
173*40d553cfSPaul Beesley   /* Shared event mappings */
174*40d553cfSPaul Beesley   static sdei_ev_map_t plat_shared_sdei[] = {
175*40d553cfSPaul Beesley        SDEI_SHARED_EVENT(804, 0, SDEI_MAPF_DYNAMIC),
176*40d553cfSPaul Beesley
177*40d553cfSPaul Beesley        /* Dynamic shared events */
178*40d553cfSPaul Beesley        SDEI_SHARED_EVENT(3000, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
179*40d553cfSPaul Beesley        SDEI_SHARED_EVENT(3001, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC)
180*40d553cfSPaul Beesley   };
181*40d553cfSPaul Beesley
182*40d553cfSPaul Beesley   /* Export SDEI events */
183*40d553cfSPaul Beesley   REGISTER_SDEI_MAP(plat_private_sdei, plat_shared_sdei);
184*40d553cfSPaul Beesley
185*40d553cfSPaul BeesleyConfiguration within Exception Handling Framework
186*40d553cfSPaul Beesley-------------------------------------------------
187*40d553cfSPaul Beesley
188*40d553cfSPaul BeesleyThe SDEI dispatcher functions alongside the Exception Handling Framework. This
189*40d553cfSPaul Beesleymeans that the platform must assign priorities to both Normal and Critical SDEI
190*40d553cfSPaul Beesleyinterrupts for the platform:
191*40d553cfSPaul Beesley
192*40d553cfSPaul Beesley-  Install priority descriptors for Normal and Critical SDEI interrupts.
193*40d553cfSPaul Beesley
194*40d553cfSPaul Beesley-  For those interrupts that are statically bound (i.e. events defined as having
195*40d553cfSPaul Beesley   the ``SDEI_MAPF_BOUND`` property), enumerate their properties for the GIC
196*40d553cfSPaul Beesley   driver to configure interrupts accordingly.
197*40d553cfSPaul Beesley
198*40d553cfSPaul Beesley   The interrupts must be configured to target EL3. This means that they should
199*40d553cfSPaul Beesley   be configured as *Group 0*.  Additionally, on GICv2 systems, the build option
200*40d553cfSPaul Beesley   ``GICV2_G0_FOR_EL3`` must be set to ``1``.
201*40d553cfSPaul Beesley
202*40d553cfSPaul BeesleySee also `SDEI porting requirements`_.
203*40d553cfSPaul Beesley
204*40d553cfSPaul BeesleyDetermining client EL
205*40d553cfSPaul Beesley---------------------
206*40d553cfSPaul Beesley
207*40d553cfSPaul BeesleyThe SDEI specification requires that the *physical* SDEI client executes in the
208*40d553cfSPaul Beesleyhighest Non-secure EL implemented on the system. This means that the dispatcher
209*40d553cfSPaul Beesleywill only allow SDEI calls to be made from:
210*40d553cfSPaul Beesley
211*40d553cfSPaul Beesley-  EL2, if EL2 is implemented. The Hypervisor is expected to implement a
212*40d553cfSPaul Beesley   *virtual* SDEI dispatcher to support SDEI clients in Guest Operating Systems
213*40d553cfSPaul Beesley   executing in Non-secure EL1.
214*40d553cfSPaul Beesley
215*40d553cfSPaul Beesley-  Non-secure EL1, if EL2 is not implemented or disabled.
216*40d553cfSPaul Beesley
217*40d553cfSPaul BeesleySee the function ``sdei_client_el()`` in ``sdei_private.h``.
218*40d553cfSPaul Beesley
219*40d553cfSPaul BeesleyExplicit dispatch of events
220*40d553cfSPaul Beesley---------------------------
221*40d553cfSPaul Beesley
222*40d553cfSPaul BeesleyTypically, an SDEI event dispatch is caused by the PE receiving interrupts that
223*40d553cfSPaul Beesleyare bound to an SDEI event. However, there are cases where the Secure world
224*40d553cfSPaul Beesleyrequires dispatch of an SDEI event as a direct or indirect result of a past
225*40d553cfSPaul Beesleyactivity, such as receiving a Secure interrupt or an exception.
226*40d553cfSPaul Beesley
227*40d553cfSPaul BeesleyThe SDEI dispatcher implementation provides ``sdei_dispatch_event()`` API for
228*40d553cfSPaul Beesleythis purpose. The API has the following signature:
229*40d553cfSPaul Beesley
230*40d553cfSPaul Beesley::
231*40d553cfSPaul Beesley
232*40d553cfSPaul Beesley        int sdei_dispatch_event(int ev_num);
233*40d553cfSPaul Beesley
234*40d553cfSPaul BeesleyThe parameter ``ev_num`` is the event number to dispatch. The API returns ``0``
235*40d553cfSPaul Beesleyon success, or ``-1`` on failure.
236*40d553cfSPaul Beesley
237*40d553cfSPaul BeesleyThe following figure depicts a scenario involving explicit dispatch of SDEI
238*40d553cfSPaul Beesleyevent. A commentary is provided below:
239*40d553cfSPaul Beesley
240*40d553cfSPaul Beesley.. image:: ../plantuml/sdei_explicit_dispatch.svg
241*40d553cfSPaul Beesley
242*40d553cfSPaul BeesleyAs part of initialisation, the SDEI client registers a handler for a platform
243*40d553cfSPaul Beesleyevent [1], enables the event [3], and unmasks the current PE [5]. Note that,
244*40d553cfSPaul Beesleyunlike in `general SDEI dispatch`_, this doesn't involve interrupt binding, as
245*40d553cfSPaul Beesleybound or dynamic events can't be explicitly dispatched (see the section below).
246*40d553cfSPaul Beesley
247*40d553cfSPaul BeesleyAt a later point in time, a critical event [#critical-event]_ is trapped into
248*40d553cfSPaul BeesleyEL3 [7]. EL3 performs a first-level triage of the event, and a RAS component
249*40d553cfSPaul Beesleyassumes further handling [8]. The dispatch completes, but intends to involve
250*40d553cfSPaul BeesleyNon-secure world in further handling, and therefore decides to explicitly
251*40d553cfSPaul Beesleydispatch an event [10] (which the client had already registered for [1]). The
252*40d553cfSPaul Beesleyrest of the sequence is similar to that in the `general SDEI dispatch`_: the
253*40d553cfSPaul Beesleyrequested event is dispatched to the client (assuming all the conditions are
254*40d553cfSPaul Beesleymet), and when the handler completes, the preempted execution resumes.
255*40d553cfSPaul Beesley
256*40d553cfSPaul Beesley.. [#critical-event] Examples of critical event are *SError*, *Synchronous
257*40d553cfSPaul Beesley                     External Abort*, *Fault Handling interrupt*, or *Error
258*40d553cfSPaul Beesley                     Recovery interrupt* from one of RAS nodes in the system.
259*40d553cfSPaul Beesley
260*40d553cfSPaul BeesleyConditions for event dispatch
261*40d553cfSPaul Beesley~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
262*40d553cfSPaul Beesley
263*40d553cfSPaul BeesleyAll of the following requirements must be met for the API to return ``0`` and
264*40d553cfSPaul Beesleyevent to be dispatched:
265*40d553cfSPaul Beesley
266*40d553cfSPaul Beesley-  SDEI events must be unmasked on the PE. I.e. the client must have called
267*40d553cfSPaul Beesley   ``PE_UNMASK`` beforehand.
268*40d553cfSPaul Beesley
269*40d553cfSPaul Beesley-  Event 0 can't be dispatched.
270*40d553cfSPaul Beesley
271*40d553cfSPaul Beesley-  The event must be declared using the ``SDEI_EXPLICIT_EVENT()`` macro
272*40d553cfSPaul Beesley   described above.
273*40d553cfSPaul Beesley
274*40d553cfSPaul Beesley-  The event must be private to the PE.
275*40d553cfSPaul Beesley
276*40d553cfSPaul Beesley-  The event must have been registered for and enabled.
277*40d553cfSPaul Beesley
278*40d553cfSPaul Beesley-  A dispatch for the same event must not be outstanding. I.e. it hasn't already
279*40d553cfSPaul Beesley   been dispatched and is yet to be completed.
280*40d553cfSPaul Beesley
281*40d553cfSPaul Beesley-  The priority of the event (either Critical or Normal, as configured by the
282*40d553cfSPaul Beesley   platform at build-time) shouldn't cause priority inversion. This means:
283*40d553cfSPaul Beesley
284*40d553cfSPaul Beesley   -  If it's of Normal priority, neither Normal nor Critical priority dispatch
285*40d553cfSPaul Beesley      must be outstanding on the PE.
286*40d553cfSPaul Beesley
287*40d553cfSPaul Beesley   -  If it's of a Critical priority, no Critical priority dispatch must be
288*40d553cfSPaul Beesley      outstanding on the PE.
289*40d553cfSPaul Beesley
290*40d553cfSPaul BeesleyFurther, the caller should be aware of the following assumptions made by the
291*40d553cfSPaul Beesleydispatcher:
292*40d553cfSPaul Beesley
293*40d553cfSPaul Beesley-  The caller of the API is a component running in EL3; for example, a RAS
294*40d553cfSPaul Beesley   driver.
295*40d553cfSPaul Beesley
296*40d553cfSPaul Beesley-  The requested dispatch will be permitted by the Exception Handling Framework.
297*40d553cfSPaul Beesley   I.e. the caller must make sure that the requested dispatch has sufficient
298*40d553cfSPaul Beesley   priority so as not to cause priority level inversion within Exception
299*40d553cfSPaul Beesley   Handling Framework.
300*40d553cfSPaul Beesley
301*40d553cfSPaul Beesley-  The caller must be prepared for the SDEI dispatcher to restore the Non-secure
302*40d553cfSPaul Beesley   context, and mark that the active context.
303*40d553cfSPaul Beesley
304*40d553cfSPaul Beesley-  The call will block until the SDEI client completes the event (i.e. when the
305*40d553cfSPaul Beesley   client calls either ``SDEI_EVENT_COMPLETE`` or ``SDEI_COMPLETE_AND_RESUME``).
306*40d553cfSPaul Beesley
307*40d553cfSPaul Beesley-  The caller must be prepared for this API to return failure and handle
308*40d553cfSPaul Beesley   accordingly.
309*40d553cfSPaul Beesley
310*40d553cfSPaul BeesleyPorting requirements
311*40d553cfSPaul Beesley--------------------
312*40d553cfSPaul Beesley
313*40d553cfSPaul BeesleyThe porting requirements of the SDEI dispatcher are outlined in the `porting
314*40d553cfSPaul Beesleyguide`__.
315*40d553cfSPaul Beesley
316*40d553cfSPaul Beesley.. __: `SDEI porting requirements`_
317*40d553cfSPaul Beesley
318*40d553cfSPaul BeesleyNote on writing SDEI event handlers
319*40d553cfSPaul Beesley-----------------------------------
320*40d553cfSPaul Beesley
321*40d553cfSPaul Beesley*This section pertains to SDEI event handlers in general, not just when using
322*40d553cfSPaul Beesleythe TF-A SDEI dispatcher.*
323*40d553cfSPaul Beesley
324*40d553cfSPaul BeesleyThe SDEI specification requires that event handlers preserve the contents of all
325*40d553cfSPaul Beesleyregisters except ``x0`` to ``x17``. This has significance if event handler is
326*40d553cfSPaul Beesleywritten in C: compilers typically adjust the stack frame at the beginning and
327*40d553cfSPaul Beesleyend of C functions. For example, AArch64 GCC typically produces the following
328*40d553cfSPaul Beesleyfunction prologue and epilogue:
329*40d553cfSPaul Beesley
330*40d553cfSPaul Beesley::
331*40d553cfSPaul Beesley
332*40d553cfSPaul Beesley        c_event_handler:
333*40d553cfSPaul Beesley                stp     x29, x30, [sp,#-32]!
334*40d553cfSPaul Beesley                mov     x29, sp
335*40d553cfSPaul Beesley
336*40d553cfSPaul Beesley                ...
337*40d553cfSPaul Beesley
338*40d553cfSPaul Beesley                bl      ...
339*40d553cfSPaul Beesley
340*40d553cfSPaul Beesley                ...
341*40d553cfSPaul Beesley
342*40d553cfSPaul Beesley                ldp     x29, x30, [sp],#32
343*40d553cfSPaul Beesley                ret
344*40d553cfSPaul Beesley
345*40d553cfSPaul BeesleyThe register ``x29`` is used as frame pointer in the prologue. Because neither a
346*40d553cfSPaul Beesleyvalid ``SDEI_EVENT_COMPLETE`` nor ``SDEI_EVENT_COMPLETE_AND_RESUME`` calls
347*40d553cfSPaul Beesleyreturn to the handler, the epilogue never gets executed, and registers ``x29``
348*40d553cfSPaul Beesleyand ``x30`` (in the case above) are inadvertently corrupted. This violates the
349*40d553cfSPaul BeesleySDEI specification, and the normal execution thereafter will result in
350*40d553cfSPaul Beesleyunexpected behaviour.
351*40d553cfSPaul Beesley
352*40d553cfSPaul BeesleyTo work this around, it's advised that the top-level event handlers are
353*40d553cfSPaul Beesleyimplemented in assembly, following a similar pattern as below:
354*40d553cfSPaul Beesley
355*40d553cfSPaul Beesley::
356*40d553cfSPaul Beesley
357*40d553cfSPaul Beesley        asm_event_handler:
358*40d553cfSPaul Beesley                /* Save link register whilst maintaining stack alignment */
359*40d553cfSPaul Beesley                stp     xzr, x30, [sp, #-16]!
360*40d553cfSPaul Beesley                bl      c_event_handler
361*40d553cfSPaul Beesley
362*40d553cfSPaul Beesley                /* Restore link register */
363*40d553cfSPaul Beesley                ldp     xzr, x30, [sp], #16
364*40d553cfSPaul Beesley
365*40d553cfSPaul Beesley                /* Complete call */
366*40d553cfSPaul Beesley                ldr     x0, =SDEI_EVENT_COMPLETE
367*40d553cfSPaul Beesley                smc     #0
368*40d553cfSPaul Beesley                b       .
369*40d553cfSPaul Beesley
370*40d553cfSPaul Beesley----
371*40d553cfSPaul Beesley
372*40d553cfSPaul Beesley*Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.*
373*40d553cfSPaul Beesley
374*40d553cfSPaul Beesley.. _SDEI specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf
375*40d553cfSPaul Beesley.. _SDEI porting requirements: ../getting_started/porting-guide.rst#sdei-porting-requirements
376