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