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