blob: 2a777b385b0561cfa0e8fcfb8f41532fe972ddb2 [file] [log] [blame]
Paul Beesleyea225122019-02-11 17:54:45 +00001SDEI: Software Delegated Exception Interface
2============================================
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +01003
Dan Handley610e7e12018-03-01 18:44:00 +00004This document provides an overview of the SDEI dispatcher implementation in
5Trusted Firmware-A (TF-A).
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +01006
7Introduction
8------------
9
Dan Handley610e7e12018-03-01 18:44:00 +000010`Software Delegated Exception Interface`_ (SDEI) is an Arm specification for
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +010011Non-secure world to register handlers with firmware to receive notifications
12about system events. Firmware will first receive the system events by way of
13asynchronous exceptions and, in response, arranges for the registered handler to
14execute in the Non-secure EL.
15
16Normal world software that interacts with the SDEI dispatcher (makes SDEI
17requests and receives notifications) is referred to as the *SDEI Client*. A
18client receives the event notification at the registered handler even when it
19was executing with exceptions masked. The list of SDEI events available to the
20client are specific to the platform [#std-event]_. See also `Determining client
21EL`_.
22
23.. _general SDEI dispatch:
24
25The following figure depicts a general sequence involving SDEI client executing
26at EL2 and an event dispatch resulting from the triggering of a bound interrupt.
27A commentary is provided below:
28
Paul Beesley8c178b52019-07-12 11:56:58 +010029.. uml:: ../resources/diagrams/plantuml/sdei_general.puml
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +010030
31As part of initialisation, the SDEI client binds a Non-secure interrupt [1], and
32the SDEI dispatcher returns a platform dynamic event number [2]. The client then
33registers a handler for that event [3], enables the event [5], and unmasks all
34events on the current PE [7]. This sequence is typical of an SDEI client, but it
35may involve additional SDEI calls.
36
37At a later point in time, when the bound interrupt triggers [9], it's trapped to
38EL3. The interrupt is handed over to the SDEI dispatcher, which then arranges to
39execute the registered handler [10]. The client terminates its execution with
40``SDEI_EVENT_COMPLETE`` [11], following which the dispatcher resumes the
41original EL2 execution [13]. Note that the SDEI interrupt remains active until
42the client handler completes, at which point EL3 does EOI [12].
43
John Tsichritzise14a9bb2019-05-28 12:45:06 +010044Other than events bound to interrupts, as depicted in the sequence above, SDEI
Jeenu Viswambharan34392302018-01-17 12:30:11 +000045events can be explicitly dispatched in response to other exceptions, for
46example, upon receiving an *SError* or *Synchronous External Abort*. See
47`Explicit dispatch of events`_.
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +010048
49The remainder of this document only discusses the design and implementation of
Dan Handley610e7e12018-03-01 18:44:00 +000050SDEI dispatcher in TF-A, and assumes that the reader is familiar with the SDEI
51specification, the interfaces, and their requirements.
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +010052
53.. [#std-event] Except event 0, which is defined by the SDEI specification as a
54 standard event.
55
56Defining events
57---------------
58
59A platform choosing to include the SDEI dispatcher must also define the events
60available on the platform, along with their attributes.
61
62The platform is expected to provide two arrays of event descriptors: one for
63private events, and another for shared events. The SDEI dispatcher provides
64``SDEI_PRIVATE_EVENT()`` and ``SDEI_SHARED_EVENT()`` macros to populate the
65event descriptors. Both macros take 3 arguments:
66
67- The event number: this must be a positive 32-bit integer.
68
Jeenu Viswambharan34392302018-01-17 12:30:11 +000069- For an event that has a backing interrupt, the interrupt number the event is
70 bound to:
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +010071
72 - If it's not applicable to an event, this shall be left as ``0``.
73
74 - If the event is dynamic, this should be specified as ``SDEI_DYN_IRQ``.
75
76- A bit map of `Event flags`_.
77
78To define event 0, the macro ``SDEI_DEFINE_EVENT_0()`` should be used. This
79macro takes only one parameter: an SGI number to signal other PEs.
80
Jeenu Viswambharan34392302018-01-17 12:30:11 +000081To define an event that's meant to be `explicitly dispatched`__ (i.e., not as a
82result of receiving an SDEI interrupt), the macro ``SDEI_EXPLICIT_EVENT()``
83should be used. It accepts two parameters:
84
85.. __: `Explicit dispatch of events`_
86
87- The event number (as above);
88
89- Event priority: ``SDEI_MAPF_CRITICAL`` or ``SDEI_MAPF_NORMAL``, as described
90 below.
91
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +010092Once the event descriptor arrays are defined, they should be exported to the
93SDEI dispatcher using the ``REGISTER_SDEI_MAP()`` macro, passing it the pointers
94to the private and shared event descriptor arrays, respectively. Note that the
95``REGISTER_SDEI_MAP()`` macro must be used in the same file where the arrays are
96defined.
97
98Regarding event descriptors:
99
100- For Event 0:
101
102 - There must be exactly one descriptor in the private array, and none in the
103 shared array.
104
105 - The event should be defined using ``SDEI_DEFINE_EVENT_0()``.
106
107 - Must be bound to a Secure SGI on the platform.
108
Jeenu Viswambharan34392302018-01-17 12:30:11 +0000109- Explicit events should only be used in the private array.
110
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +0100111- Statically bound shared and private interrupts must be bound to shared and
112 private interrupts on the platform, respectively. See the section on
113 `interrupt configuration`__.
114
115 .. __: `Configuration within Exception Handling Framework`_
116
117- Both arrays should be one-dimensional. The ``REGISTER_SDEI_MAP()`` macro
118 takes care of replicating private events for each PE on the platform.
119
120- Both arrays must be sorted in the increasing order of event number.
121
122The SDEI specification doesn't have provisions for discovery of available events
123on the platform. The list of events made available to the client, along with
124their semantics, have to be communicated out of band; for example, through
125Device Trees or firmware configuration tables.
126
127See also `Event definition example`_.
128
129Event flags
130~~~~~~~~~~~
131
132Event flags describe the properties of the event. They are bit maps that can be
133``OR``\ ed to form parameters to macros that `define events`__.
134
135.. __: `Defining events`_
136
137- ``SDEI_MAPF_DYNAMIC``: Marks the event as dynamic. Dynamic events can be
Antonio Nino Diaz56b68ad2019-02-28 13:35:21 +0000138 bound to (or released from) any Non-secure interrupt at runtime via the
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +0100139 ``SDEI_INTERRUPT_BIND`` and ``SDEI_INTERRUPT_RELEASE`` calls.
140
141- ``SDEI_MAPF_BOUND``: Marks the event as statically bound to an interrupt.
142 These events cannot be re-bound at runtime.
143
Jeenu Viswambharan34392302018-01-17 12:30:11 +0000144- ``SDEI_MAPF_NORMAL``: Marks the event as having *Normal* priority. This is
145 the default priority.
146
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +0100147- ``SDEI_MAPF_CRITICAL``: Marks the event as having *Critical* priority.
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +0100148
149Event definition example
150------------------------
151
152.. code:: c
153
154 static sdei_ev_map_t plat_private_sdei[] = {
155 /* Event 0 definition */
156 SDEI_DEFINE_EVENT_0(8),
157
158 /* PPI */
159 SDEI_PRIVATE_EVENT(8, 23, SDEI_MAPF_BOUND),
160
161 /* Dynamic private events */
162 SDEI_PRIVATE_EVENT(100, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
163 SDEI_PRIVATE_EVENT(101, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC)
Jeenu Viswambharan34392302018-01-17 12:30:11 +0000164
165 /* Events for explicit dispatch */
166 SDEI_EXPLICIT_EVENT(2000, SDEI_MAPF_NORMAL);
167 SDEI_EXPLICIT_EVENT(2000, SDEI_MAPF_CRITICAL);
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +0100168 };
169
170 /* Shared event mappings */
171 static sdei_ev_map_t plat_shared_sdei[] = {
172 SDEI_SHARED_EVENT(804, 0, SDEI_MAPF_DYNAMIC),
173
174 /* Dynamic shared events */
175 SDEI_SHARED_EVENT(3000, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
176 SDEI_SHARED_EVENT(3001, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC)
177 };
178
179 /* Export SDEI events */
180 REGISTER_SDEI_MAP(plat_private_sdei, plat_shared_sdei);
181
182Configuration within Exception Handling Framework
183-------------------------------------------------
184
185The SDEI dispatcher functions alongside the Exception Handling Framework. This
186means that the platform must assign priorities to both Normal and Critical SDEI
187interrupts for the platform:
188
189- Install priority descriptors for Normal and Critical SDEI interrupts.
190
191- For those interrupts that are statically bound (i.e. events defined as having
192 the ``SDEI_MAPF_BOUND`` property), enumerate their properties for the GIC
193 driver to configure interrupts accordingly.
194
195 The interrupts must be configured to target EL3. This means that they should
196 be configured as *Group 0*. Additionally, on GICv2 systems, the build option
197 ``GICV2_G0_FOR_EL3`` must be set to ``1``.
198
199See also `SDEI porting requirements`_.
200
201Determining client EL
202---------------------
203
204The SDEI specification requires that the *physical* SDEI client executes in the
205highest Non-secure EL implemented on the system. This means that the dispatcher
206will only allow SDEI calls to be made from:
207
208- EL2, if EL2 is implemented. The Hypervisor is expected to implement a
209 *virtual* SDEI dispatcher to support SDEI clients in Guest Operating Systems
210 executing in Non-secure EL1.
211
212- Non-secure EL1, if EL2 is not implemented or disabled.
213
214See the function ``sdei_client_el()`` in ``sdei_private.h``.
215
216Explicit dispatch of events
217---------------------------
218
219Typically, an SDEI event dispatch is caused by the PE receiving interrupts that
220are bound to an SDEI event. However, there are cases where the Secure world
221requires dispatch of an SDEI event as a direct or indirect result of a past
Antonio Nino Diaz56b68ad2019-02-28 13:35:21 +0000222activity, such as receiving a Secure interrupt or an exception.
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +0100223
224The SDEI dispatcher implementation provides ``sdei_dispatch_event()`` API for
225this purpose. The API has the following signature:
226
Paul Beesley493e3492019-03-13 15:11:04 +0000227.. code:: c
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +0100228
Jeenu Viswambharan8b7e6bc2018-02-16 12:07:48 +0000229 int sdei_dispatch_event(int ev_num);
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +0100230
Jeenu Viswambharan8b7e6bc2018-02-16 12:07:48 +0000231The parameter ``ev_num`` is the event number to dispatch. The API returns ``0``
232on success, or ``-1`` on failure.
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +0100233
234The following figure depicts a scenario involving explicit dispatch of SDEI
235event. A commentary is provided below:
236
Paul Beesley8c178b52019-07-12 11:56:58 +0100237.. uml:: ../resources/diagrams/plantuml/sdei_explicit_dispatch.puml
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +0100238
239As part of initialisation, the SDEI client registers a handler for a platform
240event [1], enables the event [3], and unmasks the current PE [5]. Note that,
241unlike in `general SDEI dispatch`_, this doesn't involve interrupt binding, as
242bound or dynamic events can't be explicitly dispatched (see the section below).
243
244At a later point in time, a critical event [#critical-event]_ is trapped into
Jeenu Viswambharan8b7e6bc2018-02-16 12:07:48 +0000245EL3 [7]. EL3 performs a first-level triage of the event, and a RAS component
246assumes further handling [8]. The dispatch completes, but intends to involve
247Non-secure world in further handling, and therefore decides to explicitly
248dispatch an event [10] (which the client had already registered for [1]). The
249rest of the sequence is similar to that in the `general SDEI dispatch`_: the
250requested event is dispatched to the client (assuming all the conditions are
251met), and when the handler completes, the preempted execution resumes.
Jeenu Viswambharan9a62fd12017-11-16 12:34:15 +0000252
253.. [#critical-event] Examples of critical event are *SError*, *Synchronous
254 External Abort*, *Fault Handling interrupt*, or *Error
255 Recovery interrupt* from one of RAS nodes in the system.
256
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +0100257Conditions for event dispatch
258~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
259
260All of the following requirements must be met for the API to return ``0`` and
261event to be dispatched:
262
263- SDEI events must be unmasked on the PE. I.e. the client must have called
264 ``PE_UNMASK`` beforehand.
265
266- Event 0 can't be dispatched.
267
Jeenu Viswambharan34392302018-01-17 12:30:11 +0000268- The event must be declared using the ``SDEI_EXPLICIT_EVENT()`` macro
269 described above.
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +0100270
271- The event must be private to the PE.
272
273- The event must have been registered for and enabled.
274
275- A dispatch for the same event must not be outstanding. I.e. it hasn't already
276 been dispatched and is yet to be completed.
277
278- The priority of the event (either Critical or Normal, as configured by the
279 platform at build-time) shouldn't cause priority inversion. This means:
280
281 - If it's of Normal priority, neither Normal nor Critical priority dispatch
282 must be outstanding on the PE.
283
284 - If it's of a Critical priority, no Critical priority dispatch must be
285 outstanding on the PE.
286
287Further, the caller should be aware of the following assumptions made by the
288dispatcher:
289
Jeenu Viswambharan8b7e6bc2018-02-16 12:07:48 +0000290- The caller of the API is a component running in EL3; for example, a RAS
291 driver.
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +0100292
293- The requested dispatch will be permitted by the Exception Handling Framework.
294 I.e. the caller must make sure that the requested dispatch has sufficient
295 priority so as not to cause priority level inversion within Exception
296 Handling Framework.
297
Jeenu Viswambharan8b7e6bc2018-02-16 12:07:48 +0000298- The caller must be prepared for the SDEI dispatcher to restore the Non-secure
299 context, and mark that the active context.
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +0100300
Jeenu Viswambharan8b7e6bc2018-02-16 12:07:48 +0000301- The call will block until the SDEI client completes the event (i.e. when the
302 client calls either ``SDEI_EVENT_COMPLETE`` or ``SDEI_COMPLETE_AND_RESUME``).
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +0100303
Jeenu Viswambharan8b7e6bc2018-02-16 12:07:48 +0000304- The caller must be prepared for this API to return failure and handle
305 accordingly.
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +0100306
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +0100307Porting requirements
308--------------------
309
310The porting requirements of the SDEI dispatcher are outlined in the `porting
311guide`__.
312
313.. __: `SDEI porting requirements`_
314
315Note on writing SDEI event handlers
316-----------------------------------
317
318*This section pertains to SDEI event handlers in general, not just when using
Dan Handley610e7e12018-03-01 18:44:00 +0000319the TF-A SDEI dispatcher.*
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +0100320
321The SDEI specification requires that event handlers preserve the contents of all
322registers except ``x0`` to ``x17``. This has significance if event handler is
323written in C: compilers typically adjust the stack frame at the beginning and
324end of C functions. For example, AArch64 GCC typically produces the following
325function prologue and epilogue:
326
327::
328
329 c_event_handler:
330 stp x29, x30, [sp,#-32]!
331 mov x29, sp
332
333 ...
334
335 bl ...
336
337 ...
338
339 ldp x29, x30, [sp],#32
340 ret
341
342The register ``x29`` is used as frame pointer in the prologue. Because neither a
343valid ``SDEI_EVENT_COMPLETE`` nor ``SDEI_EVENT_COMPLETE_AND_RESUME`` calls
344return to the handler, the epilogue never gets executed, and registers ``x29``
345and ``x30`` (in the case above) are inadvertently corrupted. This violates the
346SDEI specification, and the normal execution thereafter will result in
347unexpected behaviour.
348
349To work this around, it's advised that the top-level event handlers are
350implemented in assembly, following a similar pattern as below:
351
352::
353
354 asm_event_handler:
355 /* Save link register whilst maintaining stack alignment */
356 stp xzr, x30, [sp, #-16]!
357 bl c_event_handler
358
359 /* Restore link register */
360 ldp xzr, x30, [sp], #16
361
362 /* Complete call */
363 ldr x0, =SDEI_EVENT_COMPLETE
364 smc #0
365 b .
366
367----
368
Dan Handley610e7e12018-03-01 18:44:00 +0000369*Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.*
Jeenu Viswambharandb5e12e2017-10-18 14:35:20 +0100370
371.. _SDEI specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf
Paul Beesleyea225122019-02-11 17:54:45 +0000372.. _SDEI porting requirements: ../getting_started/porting-guide.rst#sdei-porting-requirements
John Tsichritzise14a9bb2019-05-28 12:45:06 +0100373.. _Software Delegated Exception Interface: `SDEI specification`_