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 10Software 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.. uml:: ../resources/diagrams/plantuml/sdei_general.puml 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 53Defining events 54--------------- 55 56A platform choosing to include the SDEI dispatcher must also define the events 57available on the platform, along with their attributes. 58 59The platform is expected to provide two arrays of event descriptors: one for 60private events, and another for shared events. The SDEI dispatcher provides 61``SDEI_PRIVATE_EVENT()`` and ``SDEI_SHARED_EVENT()`` macros to populate the 62event descriptors. Both macros take 3 arguments: 63 64- The event number: this must be a positive 32-bit integer. 65 66- For an event that has a backing interrupt, the interrupt number the event is 67 bound to: 68 69 - If it's not applicable to an event, this shall be left as ``0``. 70 71 - If the event is dynamic, this should be specified as ``SDEI_DYN_IRQ``. 72 73- A bit map of `Event flags`_. 74 75To define event 0, the macro ``SDEI_DEFINE_EVENT_0()`` should be used. This 76macro takes only one parameter: an SGI number to signal other PEs. 77 78To define an event that's meant to be explicitly dispatched (i.e., not as a 79result of receiving an SDEI interrupt), the macro ``SDEI_EXPLICIT_EVENT()`` 80should be used. It accepts two parameters: 81 82- The event number (as above); 83 84- Event priority: ``SDEI_MAPF_CRITICAL`` or ``SDEI_MAPF_NORMAL``, as described 85 below. 86 87Once the event descriptor arrays are defined, they should be exported to the 88SDEI dispatcher using the ``REGISTER_SDEI_MAP()`` macro, passing it the pointers 89to 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 91defined. 92 93Regarding event descriptors: 94 95- For Event 0: 96 97 - There must be exactly one descriptor in the private array, and none in the 98 shared array. 99 100 - The event should be defined using ``SDEI_DEFINE_EVENT_0()``. 101 102 - Must be bound to a Secure SGI on the platform. 103 104- Explicit events should only be used in the private array. 105 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`_. 109 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. 112 113- Both arrays must be sorted in the increasing order of event number. 114 115The SDEI specification doesn't have provisions for discovery of available events 116on the platform. The list of events made available to the client, along with 117their semantics, have to be communicated out of band; for example, through 118Device Trees or firmware configuration tables. 119 120See also `Event definition example`_. 121 122Event flags 123~~~~~~~~~~~ 124 125Event 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 127`Defining events`_). 128 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. 132 133- ``SDEI_MAPF_BOUND``: Marks the event as statically bound to an interrupt. 134 These events cannot be re-bound at runtime. 135 136- ``SDEI_MAPF_NORMAL``: Marks the event as having *Normal* priority. This is 137 the default priority. 138 139- ``SDEI_MAPF_CRITICAL``: Marks the event as having *Critical* priority. 140 141Event definition example 142------------------------ 143 144.. code:: c 145 146 static sdei_ev_map_t plat_private_sdei[] = { 147 /* Event 0 definition */ 148 SDEI_DEFINE_EVENT_0(8), 149 150 /* PPI */ 151 SDEI_PRIVATE_EVENT(8, 23, SDEI_MAPF_BOUND), 152 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) 156 157 /* Events for explicit dispatch */ 158 SDEI_EXPLICIT_EVENT(2000, SDEI_MAPF_NORMAL); 159 SDEI_EXPLICIT_EVENT(2000, SDEI_MAPF_CRITICAL); 160 }; 161 162 /* Shared event mappings */ 163 static sdei_ev_map_t plat_shared_sdei[] = { 164 SDEI_SHARED_EVENT(804, 0, SDEI_MAPF_DYNAMIC), 165 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) 169 }; 170 171 /* Export SDEI events */ 172 REGISTER_SDEI_MAP(plat_private_sdei, plat_shared_sdei); 173 174Configuration within Exception Handling Framework 175------------------------------------------------- 176 177The SDEI dispatcher functions alongside the Exception Handling Framework. This 178means that the platform must assign priorities to both Normal and Critical SDEI 179interrupts for the platform: 180 181- Install priority descriptors for Normal and Critical SDEI interrupts. 182 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. 186 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``. 190 191See also :ref:`porting_guide_sdei_requirements`. 192 193Determining client EL 194--------------------- 195 196The SDEI specification requires that the *physical* SDEI client executes in the 197highest Non-secure EL implemented on the system. This means that the dispatcher 198will only allow SDEI calls to be made from: 199 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. 203 204- Non-secure EL1, if EL2 is not implemented or disabled. 205 206See the function ``sdei_client_el()`` in ``sdei_private.h``. 207 208.. _explicit-dispatch-of-events: 209 210Explicit dispatch of events 211--------------------------- 212 213Typically, an SDEI event dispatch is caused by the PE receiving interrupts that 214are bound to an SDEI event. However, there are cases where the Secure world 215requires dispatch of an SDEI event as a direct or indirect result of a past 216activity, such as receiving a Secure interrupt or an exception. 217 218The SDEI dispatcher implementation provides ``sdei_dispatch_event()`` API for 219this purpose. The API has the following signature: 220 221.. code:: c 222 223 int sdei_dispatch_event(int ev_num); 224 225The parameter ``ev_num`` is the event number to dispatch. The API returns ``0`` 226on success, or ``-1`` on failure. 227 228The following figure depicts a scenario involving explicit dispatch of SDEI 229event. A commentary is provided below: 230 231.. uml:: ../resources/diagrams/plantuml/sdei_explicit_dispatch.puml 232 233As part of initialisation, the SDEI client registers a handler for a platform 234event [1], enables the event [3], and unmasks the current PE [5]. Note that, 235unlike in `general SDEI dispatch`_, this doesn't involve interrupt binding, as 236bound or dynamic events can't be explicitly dispatched (see the section below). 237 238At a later point in time, a critical event [#critical-event]_ is trapped into 239EL3 [7]. EL3 performs a first-level triage of the event, and a RAS component 240assumes further handling [8]. The dispatch completes, but intends to involve 241Non-secure world in further handling, and therefore decides to explicitly 242dispatch an event [10] (which the client had already registered for [1]). The 243rest of the sequence is similar to that in the `general SDEI dispatch`_: the 244requested event is dispatched to the client (assuming all the conditions are 245met), and when the handler completes, the preempted execution resumes. 246 247Conditions for event dispatch 248~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 249 250All of the following requirements must be met for the API to return ``0`` and 251event to be dispatched: 252 253- SDEI events must be unmasked on the PE. I.e. the client must have called 254 ``PE_UNMASK`` beforehand. 255 256- Event 0 can't be dispatched. 257 258- The event must be declared using the ``SDEI_EXPLICIT_EVENT()`` macro 259 described above. 260 261- The event must be private to the PE. 262 263- The event must have been registered for and enabled. 264 265- A dispatch for the same event must not be outstanding. I.e. it hasn't already 266 been dispatched and is yet to be completed. 267 268- The priority of the event (either Critical or Normal, as configured by the 269 platform at build-time) shouldn't cause priority inversion. This means: 270 271 - If it's of Normal priority, neither Normal nor Critical priority dispatch 272 must be outstanding on the PE. 273 274 - If it's of a Critical priority, no Critical priority dispatch must be 275 outstanding on the PE. 276 277Further, the caller should be aware of the following assumptions made by the 278dispatcher: 279 280- The caller of the API is a component running in EL3; for example, a RAS 281 driver. 282 283- The requested dispatch will be permitted by the Exception Handling Framework. 284 I.e. the caller must make sure that the requested dispatch has sufficient 285 priority so as not to cause priority level inversion within Exception 286 Handling Framework. 287 288- The caller must be prepared for the SDEI dispatcher to restore the Non-secure 289 context, and mark that the active context. 290 291- The call will block until the SDEI client completes the event (i.e. when the 292 client calls either ``SDEI_EVENT_COMPLETE`` or ``SDEI_COMPLETE_AND_RESUME``). 293 294- The caller must be prepared for this API to return failure and handle 295 accordingly. 296 297Porting requirements 298-------------------- 299 300The porting requirements of the SDEI dispatcher are outlined in the 301:ref:`Porting Guide <porting_guide_sdei_requirements>`. 302 303Note on writing SDEI event handlers 304----------------------------------- 305 306*This section pertains to SDEI event handlers in general, not just when using 307the TF-A SDEI dispatcher.* 308 309The SDEI specification requires that event handlers preserve the contents of all 310registers except ``x0`` to ``x17``. This has significance if event handler is 311written in C: compilers typically adjust the stack frame at the beginning and 312end of C functions. For example, AArch64 GCC typically produces the following 313function prologue and epilogue: 314 315:: 316 317 c_event_handler: 318 stp x29, x30, [sp,#-32]! 319 mov x29, sp 320 321 ... 322 323 bl ... 324 325 ... 326 327 ldp x29, x30, [sp],#32 328 ret 329 330The register ``x29`` is used as frame pointer in the prologue. Because neither a 331valid ``SDEI_EVENT_COMPLETE`` nor ``SDEI_EVENT_COMPLETE_AND_RESUME`` calls 332return to the handler, the epilogue never gets executed, and registers ``x29`` 333and ``x30`` (in the case above) are inadvertently corrupted. This violates the 334SDEI specification, and the normal execution thereafter will result in 335unexpected behaviour. 336 337To work this around, it's advised that the top-level event handlers are 338implemented in assembly, following a similar pattern as below: 339 340:: 341 342 asm_event_handler: 343 /* Save link register whilst maintaining stack alignment */ 344 stp xzr, x30, [sp, #-16]! 345 bl c_event_handler 346 347 /* Restore link register */ 348 ldp xzr, x30, [sp], #16 349 350 /* Complete call */ 351 ldr x0, =SDEI_EVENT_COMPLETE 352 smc #0 353 b . 354 355-------------- 356 357*Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved.* 358 359.. rubric:: Footnotes 360 361.. [#std-event] Except event 0, which is defined by the SDEI specification as a 362 standard event. 363 364.. [#critical-event] Examples of critical events are *SError*, *Synchronous 365 External Abort*, *Fault Handling interrupt* or *Error 366 Recovery interrupt* from one of RAS nodes in the system. 367 368.. _SDEI specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf 369.. _Software Delegated Exception Interface: `SDEI specification`_ 370