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