1 SDEI: Software Delegated Exception Interface
2 ============================================
4 This document provides an overview of the SDEI dispatcher implementation in
5 Trusted Firmware-A (TF-A).
10 Software Delegated Exception Interface (|SDEI|) is an Arm specification for
11 Non-secure world to register handlers with firmware to receive notifications
12 about system events. Firmware will first receive the system events by way of
13 asynchronous exceptions and, in response, arranges for the registered handler to
14 execute in the Non-secure EL.
16 Normal world software that interacts with the SDEI dispatcher (makes SDEI
17 requests and receives notifications) is referred to as the *SDEI Client*. A
18 client receives the event notification at the registered handler even when it
19 was executing with exceptions masked. The list of SDEI events available to the
20 client are specific to the platform [#std-event]_. See also `Determining client
23 .. _general SDEI dispatch:
25 The following figure depicts a general sequence involving SDEI client executing
26 at EL2 and an event dispatch resulting from the triggering of a bound interrupt.
27 A commentary is provided below:
29 .. uml:: ../resources/diagrams/plantuml/sdei_general.puml
31 As part of initialisation, the SDEI client binds a Non-secure interrupt [1], and
32 the SDEI dispatcher returns a platform dynamic event number [2]. The client then
33 registers a handler for that event [3], enables the event [5], and unmasks all
34 events on the current PE [7]. This sequence is typical of an SDEI client, but it
35 may involve additional SDEI calls.
37 At a later point in time, when the bound interrupt triggers [9], it's trapped to
38 EL3. The interrupt is handed over to the SDEI dispatcher, which then arranges to
39 execute the registered handler [10]. The client terminates its execution with
40 ``SDEI_EVENT_COMPLETE`` [11], following which the dispatcher resumes the
41 original EL2 execution [13]. Note that the SDEI interrupt remains active until
42 the client handler completes, at which point EL3 does EOI [12].
44 Other than events bound to interrupts, as depicted in the sequence above, SDEI
45 events can be explicitly dispatched in response to other exceptions, for
46 example, upon receiving an *SError* or *Synchronous External Abort*. See
47 `Explicit dispatch of events`_.
49 The remainder of this document only discusses the design and implementation of
50 SDEI dispatcher in TF-A, and assumes that the reader is familiar with the SDEI
51 specification, the interfaces, and their requirements.
56 A platform choosing to include the SDEI dispatcher must also define the events
57 available on the platform, along with their attributes.
59 The platform is expected to provide two arrays of event descriptors: one for
60 private events, and another for shared events. The SDEI dispatcher provides
61 ``SDEI_PRIVATE_EVENT()`` and ``SDEI_SHARED_EVENT()`` macros to populate the
62 event descriptors. Both macros take 3 arguments:
64 - The event number: this must be a positive 32-bit integer.
66 - For an event that has a backing interrupt, the interrupt number the event is
69 - If it's not applicable to an event, this shall be left as ``0``.
71 - If the event is dynamic, this should be specified as ``SDEI_DYN_IRQ``.
73 - A bit map of `Event flags`_.
75 To define event 0, the macro ``SDEI_DEFINE_EVENT_0()`` should be used. This
76 macro takes only one parameter: an SGI number to signal other PEs.
78 To define an event that's meant to be explicitly dispatched (i.e., not as a
79 result of receiving an SDEI interrupt), the macro ``SDEI_EXPLICIT_EVENT()``
80 should be used. It accepts two parameters:
82 - The event number (as above);
84 - Event priority: ``SDEI_MAPF_CRITICAL`` or ``SDEI_MAPF_NORMAL``, as described
87 Once the event descriptor arrays are defined, they should be exported to the
88 SDEI dispatcher using the ``REGISTER_SDEI_MAP()`` macro, passing it the pointers
89 to the private and shared event descriptor arrays, respectively. Note that the
90 ``REGISTER_SDEI_MAP()`` macro must be used in the same file where the arrays are
93 Regarding event descriptors:
97 - There must be exactly one descriptor in the private array, and none in the
100 - The event should be defined using ``SDEI_DEFINE_EVENT_0()``.
102 - Must be bound to a Secure SGI on the platform.
104 - Explicit events should only be used in the private array.
106 - Statically bound shared and private interrupts must be bound to shared and
107 private interrupts on the platform, respectively. See the section on
108 `Configuration within Exception Handling Framework`_.
110 - Both arrays should be one-dimensional. The ``REGISTER_SDEI_MAP()`` macro
111 takes care of replicating private events for each PE on the platform.
113 - Both arrays must be sorted in the increasing order of event number.
115 The SDEI specification doesn't have provisions for discovery of available events
116 on the platform. The list of events made available to the client, along with
117 their semantics, have to be communicated out of band; for example, through
118 Device Trees or firmware configuration tables.
120 See also `Event definition example`_.
125 Event flags describe the properties of the event. They are bit maps that can be
126 ``OR``\ ed to form parameters to macros that define events (see
129 - ``SDEI_MAPF_DYNAMIC``: Marks the event as dynamic. Dynamic events can be
130 bound to (or released from) any Non-secure interrupt at runtime via the
131 ``SDEI_INTERRUPT_BIND`` and ``SDEI_INTERRUPT_RELEASE`` calls.
133 - ``SDEI_MAPF_BOUND``: Marks the event as statically bound to an interrupt.
134 These events cannot be re-bound at runtime.
136 - ``SDEI_MAPF_NORMAL``: Marks the event as having *Normal* priority. This is
137 the default priority.
139 - ``SDEI_MAPF_CRITICAL``: Marks the event as having *Critical* priority.
141 Event definition example
142 ------------------------
146 static sdei_ev_map_t plat_private_sdei[] = {
147 /* Event 0 definition */
148 SDEI_DEFINE_EVENT_0(8),
151 SDEI_PRIVATE_EVENT(8, 23, SDEI_MAPF_BOUND),
153 /* Dynamic private events */
154 SDEI_PRIVATE_EVENT(100, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
155 SDEI_PRIVATE_EVENT(101, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC)
157 /* Events for explicit dispatch */
158 SDEI_EXPLICIT_EVENT(2000, SDEI_MAPF_NORMAL);
159 SDEI_EXPLICIT_EVENT(2000, SDEI_MAPF_CRITICAL);
162 /* Shared event mappings */
163 static sdei_ev_map_t plat_shared_sdei[] = {
164 SDEI_SHARED_EVENT(804, 0, SDEI_MAPF_DYNAMIC),
166 /* Dynamic shared events */
167 SDEI_SHARED_EVENT(3000, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
168 SDEI_SHARED_EVENT(3001, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC)
171 /* Export SDEI events */
172 REGISTER_SDEI_MAP(plat_private_sdei, plat_shared_sdei);
174 Configuration within Exception Handling Framework
175 -------------------------------------------------
177 The SDEI dispatcher functions alongside the Exception Handling Framework. This
178 means that the platform must assign priorities to both Normal and Critical SDEI
179 interrupts for the platform:
181 - Install priority descriptors for Normal and Critical SDEI interrupts.
183 - For those interrupts that are statically bound (i.e. events defined as having
184 the ``SDEI_MAPF_BOUND`` property), enumerate their properties for the GIC
185 driver to configure interrupts accordingly.
187 The interrupts must be configured to target EL3. This means that they should
188 be configured as *Group 0*. Additionally, on GICv2 systems, the build option
189 ``GICV2_G0_FOR_EL3`` must be set to ``1``.
191 See also :ref:`porting_guide_sdei_requirements`.
193 Determining client EL
194 ---------------------
196 The SDEI specification requires that the *physical* SDEI client executes in the
197 highest Non-secure EL implemented on the system. This means that the dispatcher
198 will only allow SDEI calls to be made from:
200 - EL2, if EL2 is implemented. The Hypervisor is expected to implement a
201 *virtual* SDEI dispatcher to support SDEI clients in Guest Operating Systems
202 executing in Non-secure EL1.
204 - Non-secure EL1, if EL2 is not implemented or disabled.
206 See the function ``sdei_client_el()`` in ``sdei_private.h``.
208 Explicit dispatch of events
209 ---------------------------
211 Typically, an SDEI event dispatch is caused by the PE receiving interrupts that
212 are bound to an SDEI event. However, there are cases where the Secure world
213 requires dispatch of an SDEI event as a direct or indirect result of a past
214 activity, such as receiving a Secure interrupt or an exception.
216 The SDEI dispatcher implementation provides ``sdei_dispatch_event()`` API for
217 this purpose. The API has the following signature:
221 int sdei_dispatch_event(int ev_num);
223 The parameter ``ev_num`` is the event number to dispatch. The API returns ``0``
224 on success, or ``-1`` on failure.
226 The following figure depicts a scenario involving explicit dispatch of SDEI
227 event. A commentary is provided below:
229 .. uml:: ../resources/diagrams/plantuml/sdei_explicit_dispatch.puml
231 As part of initialisation, the SDEI client registers a handler for a platform
232 event [1], enables the event [3], and unmasks the current PE [5]. Note that,
233 unlike in `general SDEI dispatch`_, this doesn't involve interrupt binding, as
234 bound or dynamic events can't be explicitly dispatched (see the section below).
236 At a later point in time, a critical event [#critical-event]_ is trapped into
237 EL3 [7]. EL3 performs a first-level triage of the event, and a RAS component
238 assumes further handling [8]. The dispatch completes, but intends to involve
239 Non-secure world in further handling, and therefore decides to explicitly
240 dispatch an event [10] (which the client had already registered for [1]). The
241 rest of the sequence is similar to that in the `general SDEI dispatch`_: the
242 requested event is dispatched to the client (assuming all the conditions are
243 met), and when the handler completes, the preempted execution resumes.
245 Conditions for event dispatch
246 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
248 All of the following requirements must be met for the API to return ``0`` and
249 event to be dispatched:
251 - SDEI events must be unmasked on the PE. I.e. the client must have called
252 ``PE_UNMASK`` beforehand.
254 - Event 0 can't be dispatched.
256 - The event must be declared using the ``SDEI_EXPLICIT_EVENT()`` macro
259 - The event must be private to the PE.
261 - The event must have been registered for and enabled.
263 - A dispatch for the same event must not be outstanding. I.e. it hasn't already
264 been dispatched and is yet to be completed.
266 - The priority of the event (either Critical or Normal, as configured by the
267 platform at build-time) shouldn't cause priority inversion. This means:
269 - If it's of Normal priority, neither Normal nor Critical priority dispatch
270 must be outstanding on the PE.
272 - If it's of a Critical priority, no Critical priority dispatch must be
273 outstanding on the PE.
275 Further, the caller should be aware of the following assumptions made by the
278 - The caller of the API is a component running in EL3; for example, a RAS
281 - The requested dispatch will be permitted by the Exception Handling Framework.
282 I.e. the caller must make sure that the requested dispatch has sufficient
283 priority so as not to cause priority level inversion within Exception
286 - The caller must be prepared for the SDEI dispatcher to restore the Non-secure
287 context, and mark that the active context.
289 - The call will block until the SDEI client completes the event (i.e. when the
290 client calls either ``SDEI_EVENT_COMPLETE`` or ``SDEI_COMPLETE_AND_RESUME``).
292 - The caller must be prepared for this API to return failure and handle
298 The porting requirements of the SDEI dispatcher are outlined in the
299 :ref:`Porting Guide <porting_guide_sdei_requirements>`.
301 Note on writing SDEI event handlers
302 -----------------------------------
304 *This section pertains to SDEI event handlers in general, not just when using
305 the TF-A SDEI dispatcher.*
307 The SDEI specification requires that event handlers preserve the contents of all
308 registers except ``x0`` to ``x17``. This has significance if event handler is
309 written in C: compilers typically adjust the stack frame at the beginning and
310 end of C functions. For example, AArch64 GCC typically produces the following
311 function prologue and epilogue:
316 stp x29, x30, [sp,#-32]!
325 ldp x29, x30, [sp],#32
328 The register ``x29`` is used as frame pointer in the prologue. Because neither a
329 valid ``SDEI_EVENT_COMPLETE`` nor ``SDEI_EVENT_COMPLETE_AND_RESUME`` calls
330 return to the handler, the epilogue never gets executed, and registers ``x29``
331 and ``x30`` (in the case above) are inadvertently corrupted. This violates the
332 SDEI specification, and the normal execution thereafter will result in
333 unexpected behaviour.
335 To work this around, it's advised that the top-level event handlers are
336 implemented in assembly, following a similar pattern as below:
341 /* Save link register whilst maintaining stack alignment */
342 stp xzr, x30, [sp, #-16]!
345 /* Restore link register */
346 ldp xzr, x30, [sp], #16
349 ldr x0, =SDEI_EVENT_COMPLETE
355 *Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved.*
357 .. rubric:: Footnotes
359 .. [#std-event] Except event 0, which is defined by the SDEI specification as a
362 .. [#critical-event] Examples of critical events are *SError*, *Synchronous
363 External Abort*, *Fault Handling interrupt* or *Error
364 Recovery interrupt* from one of RAS nodes in the system.
366 .. _SDEI specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf
367 .. _Software Delegated Exception Interface: `SDEI specification`_