1SDEI: Software Delegated Exception Interface 2============================================ 3 4This document provides an overview of the SDEI dispatcher implementation in 5Trusted Firmware-A (TF-A). 6 7Introduction 8------------ 9 10`Software Delegated Exception Interface`_ (SDEI) is an Arm specification for 11Non-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 29.. image:: ../plantuml/sdei_general.svg 30 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 44Other than events bound to interrupts (as depicted in the sequence above, SDEI 45events 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`_. 48 49The remainder of this document only discusses the design and implementation of 50SDEI dispatcher in TF-A, and assumes that the reader is familiar with the SDEI 51specification, the interfaces, and their requirements. 52 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 69- For an event that has a backing interrupt, the interrupt number the event is 70 bound to: 71 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 81To 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 92Once 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 109- Explicit events should only be used in the private array. 110 111- 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 138 bound to (or released from) any Non-secure interrupt at runtime via the 139 ``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 144- ``SDEI_MAPF_NORMAL``: Marks the event as having *Normal* priority. This is 145 the default priority. 146 147- ``SDEI_MAPF_CRITICAL``: Marks the event as having *Critical* priority. 148 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) 164 165 /* Events for explicit dispatch */ 166 SDEI_EXPLICIT_EVENT(2000, SDEI_MAPF_NORMAL); 167 SDEI_EXPLICIT_EVENT(2000, SDEI_MAPF_CRITICAL); 168 }; 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 222activity, such as receiving a Secure interrupt or an exception. 223 224The SDEI dispatcher implementation provides ``sdei_dispatch_event()`` API for 225this purpose. The API has the following signature: 226 227.. code:: c 228 229 int sdei_dispatch_event(int ev_num); 230 231The parameter ``ev_num`` is the event number to dispatch. The API returns ``0`` 232on success, or ``-1`` on failure. 233 234The following figure depicts a scenario involving explicit dispatch of SDEI 235event. A commentary is provided below: 236 237.. image:: ../plantuml/sdei_explicit_dispatch.svg 238 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 245EL3 [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. 252 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 257Conditions 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 268- The event must be declared using the ``SDEI_EXPLICIT_EVENT()`` macro 269 described above. 270 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 290- The caller of the API is a component running in EL3; for example, a RAS 291 driver. 292 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 298- The caller must be prepared for the SDEI dispatcher to restore the Non-secure 299 context, and mark that the active context. 300 301- 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``). 303 304- The caller must be prepared for this API to return failure and handle 305 accordingly. 306 307Porting 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 319the TF-A SDEI dispatcher.* 320 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 369*Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.* 370 371.. _SDEI specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf 372.. _SDEI porting requirements: ../getting_started/porting-guide.rst#sdei-porting-requirements 373