1*40d553cfSPaul BeesleyException Handling Framework in Trusted Firmware-A 2*40d553cfSPaul Beesley================================================== 3*40d553cfSPaul Beesley 4*40d553cfSPaul Beesley 5*40d553cfSPaul Beesley 6*40d553cfSPaul Beesley 7*40d553cfSPaul Beesley.. contents:: 8*40d553cfSPaul Beesley :depth: 2 9*40d553cfSPaul Beesley 10*40d553cfSPaul Beesley.. |EHF| replace:: Exception Handling Framework 11*40d553cfSPaul Beesley.. |TF-A| replace:: Trusted Firmware-A 12*40d553cfSPaul Beesley 13*40d553cfSPaul BeesleyThis document describes various aspects of handling exceptions by Runtime 14*40d553cfSPaul BeesleyFirmware (BL31) that are targeted at EL3, other than SMCs. The |EHF| takes care 15*40d553cfSPaul Beesleyof the following exceptions when targeted at EL3: 16*40d553cfSPaul Beesley 17*40d553cfSPaul Beesley- Interrupts 18*40d553cfSPaul Beesley- Synchronous External Aborts 19*40d553cfSPaul Beesley- Asynchronous External Aborts 20*40d553cfSPaul Beesley 21*40d553cfSPaul Beesley|TF-A|'s handling of synchronous ``SMC`` exceptions raised from lower ELs is 22*40d553cfSPaul Beesleydescribed in the `Firmware Design document`__. However, the |EHF| changes the 23*40d553cfSPaul Beesleysemantics of `interrupt handling`__ and `synchronous exceptions`__ other than 24*40d553cfSPaul BeesleySMCs. 25*40d553cfSPaul Beesley 26*40d553cfSPaul Beesley.. __: firmware-design.rst#handling-an-smc 27*40d553cfSPaul Beesley.. __: `Interrupt handling`_ 28*40d553cfSPaul Beesley.. __: `Effect on SMC calls`_ 29*40d553cfSPaul Beesley 30*40d553cfSPaul BeesleyThe |EHF| is selected by setting the build option ``EL3_EXCEPTION_HANDLING`` to 31*40d553cfSPaul Beesley``1``, and is only available for AArch64 systems. 32*40d553cfSPaul Beesley 33*40d553cfSPaul BeesleyIntroduction 34*40d553cfSPaul Beesley------------ 35*40d553cfSPaul Beesley 36*40d553cfSPaul BeesleyThrough various control bits in the ``SCR_EL3`` register, the Arm architecture 37*40d553cfSPaul Beesleyallows for asynchronous exceptions to be routed to EL3. As described in the 38*40d553cfSPaul Beesley`Interrupt Framework Design`_ document, depending on the chosen interrupt 39*40d553cfSPaul Beesleyrouting model, TF-A appropriately sets the ``FIQ`` and ``IRQ`` bits of 40*40d553cfSPaul Beesley``SCR_EL3`` register to effect this routing. For most use cases, other than for 41*40d553cfSPaul Beesleythe purpose of facilitating context switch between Normal and Secure worlds, 42*40d553cfSPaul BeesleyFIQs and IRQs routed to EL3 are not required to be handled in EL3. 43*40d553cfSPaul Beesley 44*40d553cfSPaul BeesleyHowever, the evolving system and standards landscape demands that various 45*40d553cfSPaul Beesleyexceptions are targeted at and handled in EL3. For instance: 46*40d553cfSPaul Beesley 47*40d553cfSPaul Beesley- Starting with ARMv8.2 architecture extension, many RAS features have been 48*40d553cfSPaul Beesley introduced to the Arm architecture. With RAS features implemented, various 49*40d553cfSPaul Beesley components of the system may use one of the asynchronous exceptions to signal 50*40d553cfSPaul Beesley error conditions to PEs. These error conditions are of critical nature, and 51*40d553cfSPaul Beesley it's imperative that corrective or remedial actions are taken at the earliest 52*40d553cfSPaul Beesley opportunity. Therefore, a *Firmware-first Handling* approach is generally 53*40d553cfSPaul Beesley followed in response to RAS events in the system. 54*40d553cfSPaul Beesley 55*40d553cfSPaul Beesley- The Arm `SDEI specification`_ defines interfaces through which Normal world 56*40d553cfSPaul Beesley interacts with the Runtime Firmware in order to request notification of 57*40d553cfSPaul Beesley system events. The SDEI specification requires that these events are notified 58*40d553cfSPaul Beesley even when the Normal world executes with the exceptions masked. This too 59*40d553cfSPaul Beesley implies that firmware-first handling is required, where the events are first 60*40d553cfSPaul Beesley received by the EL3 firmware, and then dispatched to Normal world through 61*40d553cfSPaul Beesley purely software mechanism. 62*40d553cfSPaul Beesley 63*40d553cfSPaul BeesleyFor |TF-A|, firmware-first handling means that asynchronous exceptions are 64*40d553cfSPaul Beesleysuitably routed to EL3, and the Runtime Firmware (BL31) is extended to include 65*40d553cfSPaul Beesleysoftware components that are capable of handling those exceptions that target 66*40d553cfSPaul BeesleyEL3. These components—referred to as *dispatchers* [#spd]_ in general—may 67*40d553cfSPaul Beesleychoose to: 68*40d553cfSPaul Beesley 69*40d553cfSPaul Beesley.. _delegation-use-cases: 70*40d553cfSPaul Beesley 71*40d553cfSPaul Beesley- Receive and handle exceptions entirely in EL3, meaning the exceptions 72*40d553cfSPaul Beesley handling terminates in EL3. 73*40d553cfSPaul Beesley 74*40d553cfSPaul Beesley- Receive exceptions, but handle part of the exception in EL3, and delegate the 75*40d553cfSPaul Beesley rest of the handling to a dedicated software stack running at lower Secure 76*40d553cfSPaul Beesley ELs. In this scheme, the handling spans various secure ELs. 77*40d553cfSPaul Beesley 78*40d553cfSPaul Beesley- Receive exceptions, but handle part of the exception in EL3, and delegate 79*40d553cfSPaul Beesley processing of the error to dedicated software stack running at lower secure 80*40d553cfSPaul Beesley ELs (as above); additionally, the Normal world may also be required to 81*40d553cfSPaul Beesley participate in the handling, or be notified of such events (for example, as 82*40d553cfSPaul Beesley an SDEI event). In this scheme, exception handling potentially and maximally 83*40d553cfSPaul Beesley spans all ELs in both Secure and Normal worlds. 84*40d553cfSPaul Beesley 85*40d553cfSPaul BeesleyOn any given system, all of the above handling models may be employed 86*40d553cfSPaul Beesleyindependently depending on platform choice and the nature of the exception 87*40d553cfSPaul Beesleyreceived. 88*40d553cfSPaul Beesley 89*40d553cfSPaul Beesley.. [#spd] Not to be confused with `Secure Payload Dispatcher`__, which is an 90*40d553cfSPaul Beesley EL3 component that operates in EL3 on behalf of Secure OS. 91*40d553cfSPaul Beesley 92*40d553cfSPaul Beesley.. __: firmware-design.rst#secure-el1-payloads-and-dispatchers 93*40d553cfSPaul Beesley 94*40d553cfSPaul BeesleyThe role of Exception Handling Framework 95*40d553cfSPaul Beesley---------------------------------------- 96*40d553cfSPaul Beesley 97*40d553cfSPaul BeesleyCorollary to the use cases cited above, the primary role of the |EHF| is to 98*40d553cfSPaul Beesleyfacilitate firmware-first handling of exceptions on Arm systems. The |EHF| thus 99*40d553cfSPaul Beesleyenables multiple exception dispatchers in runtime firmware to co-exist, register 100*40d553cfSPaul Beesleyfor, and handle exceptions targeted at EL3. This section outlines the basics, 101*40d553cfSPaul Beesleyand the rest of this document expands the various aspects of the |EHF|. 102*40d553cfSPaul Beesley 103*40d553cfSPaul BeesleyIn order to arbitrate exception handling among dispatchers, the |EHF| operation 104*40d553cfSPaul Beesleyis based on a priority scheme. This priority scheme is closely tied to how the 105*40d553cfSPaul BeesleyArm GIC architecture defines it, although it's applied to non-interrupt 106*40d553cfSPaul Beesleyexceptions too (SErrors, for example). 107*40d553cfSPaul Beesley 108*40d553cfSPaul BeesleyThe platform is required to `partition`__ the Secure priority space into 109*40d553cfSPaul Beesleypriority levels as applicable for the Secure software stack. It then assigns the 110*40d553cfSPaul Beesleydispatchers to one or more priority levels. The dispatchers then register 111*40d553cfSPaul Beesleyhandlers for the priority levels at runtime. A dispatcher can register handlers 112*40d553cfSPaul Beesleyfor more than one priority level. 113*40d553cfSPaul Beesley 114*40d553cfSPaul Beesley.. __: `Partitioning priority levels`_ 115*40d553cfSPaul Beesley 116*40d553cfSPaul Beesley 117*40d553cfSPaul Beesley.. _ehf-figure: 118*40d553cfSPaul Beesley 119*40d553cfSPaul Beesley.. image:: ../draw.io/ehf.svg 120*40d553cfSPaul Beesley 121*40d553cfSPaul BeesleyA priority level is *active* when a handler at that priority level is currently 122*40d553cfSPaul Beesleyexecuting in EL3, or has delegated the execution to a lower EL. For interrupts, 123*40d553cfSPaul Beesleythis is implicit when an interrupt is targeted and acknowledged at EL3, and the 124*40d553cfSPaul Beesleypriority of the acknowledged interrupt is used to match its registered handler. 125*40d553cfSPaul BeesleyThe priority level is likewise implicitly deactivated when the interrupt 126*40d553cfSPaul Beesleyhandling concludes by EOIing the interrupt. 127*40d553cfSPaul Beesley 128*40d553cfSPaul BeesleyNon-interrupt exceptions (SErrors, for example) don't have a notion of priority. 129*40d553cfSPaul BeesleyIn order for the priority arbitration to work, the |EHF| provides APIs in order 130*40d553cfSPaul Beesleyfor these non-interrupt exceptions to assume a priority, and to interwork with 131*40d553cfSPaul Beesleyinterrupts. Dispatchers handling such exceptions must therefore explicitly 132*40d553cfSPaul Beesleyactivate and deactivate the respective priority level as and when they're 133*40d553cfSPaul Beesleyhandled or delegated. 134*40d553cfSPaul Beesley 135*40d553cfSPaul BeesleyBecause priority activation and deactivation for interrupt handling is implicit 136*40d553cfSPaul Beesleyand involves GIC priority masking, it's impossible for a lower priority 137*40d553cfSPaul Beesleyinterrupt to preempt a higher priority one. By extension, this means that a 138*40d553cfSPaul Beesleylower priority dispatcher cannot preempt a higher-priority one. Priority 139*40d553cfSPaul Beesleyactivation and deactivation for non-interrupt exceptions, however, has to be 140*40d553cfSPaul Beesleyexplicit. The |EHF| therefore disallows for lower priority level to be activated 141*40d553cfSPaul Beesleywhilst a higher priority level is active, and would result in a panic. 142*40d553cfSPaul BeesleyLikewise, a panic would result if it's attempted to deactivate a lower priority 143*40d553cfSPaul Beesleylevel when a higher priority level is active. 144*40d553cfSPaul Beesley 145*40d553cfSPaul BeesleyIn essence, priority level activation and deactivation conceptually works like a 146*40d553cfSPaul Beesleystack—priority levels stack up in strictly increasing fashion, and need to be 147*40d553cfSPaul Beesleyunstacked in strictly the reverse order. For interrupts, the GIC ensures this is 148*40d553cfSPaul Beesleythe case; for non-interrupts, the |EHF| monitors and asserts this. See 149*40d553cfSPaul Beesley`Transition of priority levels`_. 150*40d553cfSPaul Beesley 151*40d553cfSPaul BeesleyInterrupt handling 152*40d553cfSPaul Beesley------------------ 153*40d553cfSPaul Beesley 154*40d553cfSPaul BeesleyThe |EHF| is a client of *Interrupt Management Framework*, and registers the 155*40d553cfSPaul Beesleytop-level handler for interrupts that target EL3, as described in the `Interrupt 156*40d553cfSPaul BeesleyFramework Design`_ document. This has the following implications. 157*40d553cfSPaul Beesley 158*40d553cfSPaul Beesley- On GICv3 systems, when executing in S-EL1, pending Non-secure interrupts of 159*40d553cfSPaul Beesley sufficient priority are signalled as FIQs, and therefore will be routed to 160*40d553cfSPaul Beesley EL3. As a result, S-EL1 software cannot expect to handle Non-secure 161*40d553cfSPaul Beesley interrupts at S-EL1. Essentially, this deprecates the routing mode described 162*40d553cfSPaul Beesley as `CSS=0, TEL3=0`__. 163*40d553cfSPaul Beesley 164*40d553cfSPaul Beesley .. __: interrupt-framework-design.rst#el3-interrupts 165*40d553cfSPaul Beesley 166*40d553cfSPaul Beesley In order for S-EL1 software to handle Non-secure interrupts while having 167*40d553cfSPaul Beesley |EHF| enabled, the dispatcher must adopt a model where Non-secure interrupts 168*40d553cfSPaul Beesley are received at EL3, but are then `synchronously`__ handled over to S-EL1. 169*40d553cfSPaul Beesley 170*40d553cfSPaul Beesley .. __: interrupt-framework-design.rst#secure-payload 171*40d553cfSPaul Beesley 172*40d553cfSPaul Beesley- On GICv2 systems, it's required that the build option ``GICV2_G0_FOR_EL3`` is 173*40d553cfSPaul Beesley set to ``1`` so that *Group 0* interrupts target EL3. 174*40d553cfSPaul Beesley 175*40d553cfSPaul Beesley- While executing in Secure world, |EHF| sets GIC Priority Mask Register to the 176*40d553cfSPaul Beesley lowest Secure priority. This means that no Non-secure interrupts can preempt 177*40d553cfSPaul Beesley Secure execution. See `Effect on SMC calls`_ for more details. 178*40d553cfSPaul Beesley 179*40d553cfSPaul BeesleyAs mentioned above, with |EHF|, the platform is required to partition *Group 0* 180*40d553cfSPaul Beesleyinterrupts into distinct priority levels. A dispatcher that chooses to receive 181*40d553cfSPaul Beesleyinterrupts can then *own* one or more priority levels, and register interrupt 182*40d553cfSPaul Beesleyhandlers for them. A given priority level can be assigned to only one handler. A 183*40d553cfSPaul Beesleydispatcher may register more than one priority level. 184*40d553cfSPaul Beesley 185*40d553cfSPaul BeesleyDispatchers are assigned interrupt priority levels in two steps: 186*40d553cfSPaul Beesley 187*40d553cfSPaul BeesleyPartitioning priority levels 188*40d553cfSPaul Beesley~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 189*40d553cfSPaul Beesley 190*40d553cfSPaul BeesleyInterrupts are associated to dispatchers by way of grouping and assigning 191*40d553cfSPaul Beesleyinterrupts to a priority level. In other words, all interrupts that are to 192*40d553cfSPaul Beesleytarget a particular dispatcher should fall in a particular priority level. For 193*40d553cfSPaul Beesleypriority assignment: 194*40d553cfSPaul Beesley 195*40d553cfSPaul Beesley- Of the 8 bits of priority that Arm GIC architecture permits, bit 7 must be 0 196*40d553cfSPaul Beesley (secure space). 197*40d553cfSPaul Beesley 198*40d553cfSPaul Beesley- Depending on the number of dispatchers to support, the platform must choose 199*40d553cfSPaul Beesley to use the top *n* of the 7 remaining bits to identify and assign interrupts 200*40d553cfSPaul Beesley to individual dispatchers. Choosing *n* bits supports up to 2\ :sup:`n` 201*40d553cfSPaul Beesley distinct dispatchers. For example, by choosing 2 additional bits (i.e., bits 202*40d553cfSPaul Beesley 6 and 5), the platform can partition into 4 secure priority ranges: ``0x0``, 203*40d553cfSPaul Beesley ``0x20``, ``0x40``, and ``0x60``. See `Interrupt handling example`_. 204*40d553cfSPaul Beesley 205*40d553cfSPaul BeesleyNote: 206*40d553cfSPaul Beesley 207*40d553cfSPaul Beesley The Arm GIC architecture requires that a GIC implementation that supports two 208*40d553cfSPaul Beesley security states must implement at least 32 priority levels; i.e., at least 5 209*40d553cfSPaul Beesley upper bits of the 8 bits are writeable. In the scheme described above, when 210*40d553cfSPaul Beesley choosing *n* bits for priority range assignment, the platform must ensure 211*40d553cfSPaul Beesley that at least ``n+1`` top bits of GIC priority are writeable. 212*40d553cfSPaul Beesley 213*40d553cfSPaul BeesleyThe priority thus assigned to an interrupt is also used to determine the 214*40d553cfSPaul Beesleypriority of delegated execution in lower ELs. Delegated execution in lower EL is 215*40d553cfSPaul Beesleyassociated with a priority level chosen with ``ehf_activate_priority()`` API 216*40d553cfSPaul Beesley(described `later`__). The chosen priority level also determines the interrupts 217*40d553cfSPaul Beesleymasked while executing in a lower EL, therefore controls preemption of delegated 218*40d553cfSPaul Beesleyexecution. 219*40d553cfSPaul Beesley 220*40d553cfSPaul Beesley.. __: `ehf-apis`_ 221*40d553cfSPaul Beesley 222*40d553cfSPaul BeesleyThe platform expresses the chosen priority levels by declaring an array of 223*40d553cfSPaul Beesleypriority level descriptors. Each entry in the array is of type 224*40d553cfSPaul Beesley``ehf_pri_desc_t``, and declares a priority level, and shall be populated by the 225*40d553cfSPaul Beesley``EHF_PRI_DESC()`` macro. 226*40d553cfSPaul Beesley 227*40d553cfSPaul BeesleyNote: 228*40d553cfSPaul Beesley 229*40d553cfSPaul Beesley The macro ``EHF_PRI_DESC()`` installs the descriptors in the array at a 230*40d553cfSPaul Beesley computed index, and not necessarily where the macro is placed in the array. 231*40d553cfSPaul Beesley The size of the array might therefore be larger than what it appears to be. 232*40d553cfSPaul Beesley The ``ARRAY_SIZE()`` macro therefore should be used to determine the size of 233*40d553cfSPaul Beesley array. 234*40d553cfSPaul Beesley 235*40d553cfSPaul BeesleyFinally, this array of descriptors is exposed to |EHF| via the 236*40d553cfSPaul Beesley``EHF_REGISTER_PRIORITIES()`` macro. 237*40d553cfSPaul Beesley 238*40d553cfSPaul BeesleyRefer to the `Interrupt handling example`_ for usage. See also: `Interrupt 239*40d553cfSPaul BeesleyPrioritisation Considerations`_. 240*40d553cfSPaul Beesley 241*40d553cfSPaul BeesleyProgramming priority 242*40d553cfSPaul Beesley~~~~~~~~~~~~~~~~~~~~ 243*40d553cfSPaul Beesley 244*40d553cfSPaul BeesleyThe text in `Partitioning priority levels`_ only describes how the platform 245*40d553cfSPaul Beesleyexpresses the required levels of priority. It however doesn't choose interrupts 246*40d553cfSPaul Beesleynor program the required priority in GIC. 247*40d553cfSPaul Beesley 248*40d553cfSPaul BeesleyThe `Firmware Design guide`__ explains methods for configuring secure 249*40d553cfSPaul Beesleyinterrupts. |EHF| requires the platform to enumerate interrupt properties (as 250*40d553cfSPaul Beesleyopposed to just numbers) of Secure interrupts. The priority of secure interrupts 251*40d553cfSPaul Beesleymust match that as determined in the `Partitioning priority levels`_ section above. 252*40d553cfSPaul Beesley 253*40d553cfSPaul Beesley.. __: firmware-design.rst#configuring-secure-interrupts 254*40d553cfSPaul Beesley 255*40d553cfSPaul BeesleySee `Limitations`_, and also refer to `Interrupt handling example`_ for 256*40d553cfSPaul Beesleyillustration. 257*40d553cfSPaul Beesley 258*40d553cfSPaul BeesleyRegistering handler 259*40d553cfSPaul Beesley------------------- 260*40d553cfSPaul Beesley 261*40d553cfSPaul BeesleyDispatchers register handlers for their priority levels through the following 262*40d553cfSPaul BeesleyAPI: 263*40d553cfSPaul Beesley 264*40d553cfSPaul Beesley.. code:: c 265*40d553cfSPaul Beesley 266*40d553cfSPaul Beesley int ehf_register_priority_handler(int pri, ehf_handler_t handler) 267*40d553cfSPaul Beesley 268*40d553cfSPaul BeesleyThe API takes two arguments: 269*40d553cfSPaul Beesley 270*40d553cfSPaul Beesley- The priority level for which the handler is being registered; 271*40d553cfSPaul Beesley 272*40d553cfSPaul Beesley- The handler to be registered. The handler must be aligned to 4 bytes. 273*40d553cfSPaul Beesley 274*40d553cfSPaul BeesleyIf a dispatcher owns more than one priority levels, it has to call the API for 275*40d553cfSPaul Beesleyeach of them. 276*40d553cfSPaul Beesley 277*40d553cfSPaul BeesleyThe API will succeed, and return ``0``, only if: 278*40d553cfSPaul Beesley 279*40d553cfSPaul Beesley- There exists a descriptor with the priority level requested. 280*40d553cfSPaul Beesley 281*40d553cfSPaul Beesley- There are no handlers already registered by a previous call to the API. 282*40d553cfSPaul Beesley 283*40d553cfSPaul BeesleyOtherwise, the API returns ``-1``. 284*40d553cfSPaul Beesley 285*40d553cfSPaul BeesleyThe interrupt handler should have the following signature: 286*40d553cfSPaul Beesley 287*40d553cfSPaul Beesley.. code:: c 288*40d553cfSPaul Beesley 289*40d553cfSPaul Beesley typedef int (*ehf_handler_t)(uint32_t intr_raw, uint32_t flags, void *handle, 290*40d553cfSPaul Beesley void *cookie); 291*40d553cfSPaul Beesley 292*40d553cfSPaul BeesleyThe parameters are as obtained from the top-level `EL3 interrupt handler`__. 293*40d553cfSPaul Beesley 294*40d553cfSPaul Beesley.. __: interrupt-framework-design.rst#el3-runtime-firmware 295*40d553cfSPaul Beesley 296*40d553cfSPaul BeesleyThe `SDEI dispatcher`__, for example, expects the platform to allocate two 297*40d553cfSPaul Beesleydifferent priority levels—``PLAT_SDEI_CRITICAL_PRI``, and 298*40d553cfSPaul Beesley``PLAT_SDEI_NORMAL_PRI``—and registers the same handler to handle both levels. 299*40d553cfSPaul Beesley 300*40d553cfSPaul Beesley.. __: sdei.rst 301*40d553cfSPaul Beesley 302*40d553cfSPaul BeesleyInterrupt handling example 303*40d553cfSPaul Beesley-------------------------- 304*40d553cfSPaul Beesley 305*40d553cfSPaul BeesleyThe following annotated snippet demonstrates how a platform might choose to 306*40d553cfSPaul Beesleyassign interrupts to fictitious dispatchers: 307*40d553cfSPaul Beesley 308*40d553cfSPaul Beesley.. code:: c 309*40d553cfSPaul Beesley 310*40d553cfSPaul Beesley #include <common/interrupt_props.h> 311*40d553cfSPaul Beesley #include <drivers/arm/gic_common.h> 312*40d553cfSPaul Beesley #include <exception_mgmt.h> 313*40d553cfSPaul Beesley 314*40d553cfSPaul Beesley ... 315*40d553cfSPaul Beesley 316*40d553cfSPaul Beesley /* 317*40d553cfSPaul Beesley * This platform uses 2 bits for interrupt association. In total, 3 upper 318*40d553cfSPaul Beesley * bits are in use. 319*40d553cfSPaul Beesley * 320*40d553cfSPaul Beesley * 7 6 5 3 0 321*40d553cfSPaul Beesley * .-.-.-.----------. 322*40d553cfSPaul Beesley * |0|b|b| ..0.. | 323*40d553cfSPaul Beesley * '-'-'-'----------' 324*40d553cfSPaul Beesley */ 325*40d553cfSPaul Beesley #define PLAT_PRI_BITS 2 326*40d553cfSPaul Beesley 327*40d553cfSPaul Beesley /* Priorities for individual dispatchers */ 328*40d553cfSPaul Beesley #define DISP0_PRIO 0x00 /* Not used */ 329*40d553cfSPaul Beesley #define DISP1_PRIO 0x20 330*40d553cfSPaul Beesley #define DISP2_PRIO 0x40 331*40d553cfSPaul Beesley #define DISP3_PRIO 0x60 332*40d553cfSPaul Beesley 333*40d553cfSPaul Beesley /* Install priority level descriptors for each dispatcher */ 334*40d553cfSPaul Beesley ehf_pri_desc_t plat_exceptions[] = { 335*40d553cfSPaul Beesley EHF_PRI_DESC(PLAT_PRI_BITS, DISP1_PRIO), 336*40d553cfSPaul Beesley EHF_PRI_DESC(PLAT_PRI_BITS, DISP2_PRIO), 337*40d553cfSPaul Beesley EHF_PRI_DESC(PLAT_PRI_BITS, DISP3_PRIO), 338*40d553cfSPaul Beesley }; 339*40d553cfSPaul Beesley 340*40d553cfSPaul Beesley /* Expose priority descriptors to Exception Handling Framework */ 341*40d553cfSPaul Beesley EHF_REGISTER_PRIORITIES(plat_exceptions, ARRAY_SIZE(plat_exceptions), 342*40d553cfSPaul Beesley PLAT_PRI_BITS); 343*40d553cfSPaul Beesley 344*40d553cfSPaul Beesley ... 345*40d553cfSPaul Beesley 346*40d553cfSPaul Beesley /* List interrupt properties for GIC driver. All interrupts target EL3 */ 347*40d553cfSPaul Beesley const interrupt_prop_t plat_interrupts[] = { 348*40d553cfSPaul Beesley /* Dispatcher 1 owns interrupts d1_0 and d1_1, so assigns priority DISP1_PRIO */ 349*40d553cfSPaul Beesley INTR_PROP_DESC(d1_0, DISP1_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), 350*40d553cfSPaul Beesley INTR_PROP_DESC(d1_1, DISP1_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), 351*40d553cfSPaul Beesley 352*40d553cfSPaul Beesley /* Dispatcher 2 owns interrupts d2_0 and d2_1, so assigns priority DISP2_PRIO */ 353*40d553cfSPaul Beesley INTR_PROP_DESC(d2_0, DISP2_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), 354*40d553cfSPaul Beesley INTR_PROP_DESC(d2_1, DISP2_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), 355*40d553cfSPaul Beesley 356*40d553cfSPaul Beesley /* Dispatcher 3 owns interrupts d3_0 and d3_1, so assigns priority DISP3_PRIO */ 357*40d553cfSPaul Beesley INTR_PROP_DESC(d3_0, DISP3_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), 358*40d553cfSPaul Beesley INTR_PROP_DESC(d3_1, DISP3_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), 359*40d553cfSPaul Beesley }; 360*40d553cfSPaul Beesley 361*40d553cfSPaul Beesley ... 362*40d553cfSPaul Beesley 363*40d553cfSPaul Beesley /* Dispatcher 1 registers its handler */ 364*40d553cfSPaul Beesley ehf_register_priority_handler(DISP1_PRIO, disp1_handler); 365*40d553cfSPaul Beesley 366*40d553cfSPaul Beesley /* Dispatcher 2 registers its handler */ 367*40d553cfSPaul Beesley ehf_register_priority_handler(DISP2_PRIO, disp2_handler); 368*40d553cfSPaul Beesley 369*40d553cfSPaul Beesley /* Dispatcher 3 registers its handler */ 370*40d553cfSPaul Beesley ehf_register_priority_handler(DISP3_PRIO, disp3_handler); 371*40d553cfSPaul Beesley 372*40d553cfSPaul Beesley ... 373*40d553cfSPaul Beesley 374*40d553cfSPaul BeesleySee also the `Build-time flow`_ and the `Run-time flow`_. 375*40d553cfSPaul Beesley 376*40d553cfSPaul BeesleyActivating and Deactivating priorities 377*40d553cfSPaul Beesley-------------------------------------- 378*40d553cfSPaul Beesley 379*40d553cfSPaul BeesleyA priority level is said to be *active* when an exception of that priority is 380*40d553cfSPaul Beesleybeing handled: for interrupts, this is implied when the interrupt is 381*40d553cfSPaul Beesleyacknowledged; for non-interrupt exceptions, such as SErrors or `SDEI explicit 382*40d553cfSPaul Beesleydispatches`__, this has to be done via calling ``ehf_activate_priority()``. See 383*40d553cfSPaul Beesley`Run-time flow`_. 384*40d553cfSPaul Beesley 385*40d553cfSPaul Beesley.. __: sdei.rst#explicit-dispatch-of-events 386*40d553cfSPaul Beesley 387*40d553cfSPaul BeesleyConversely, when the dispatcher has reached a logical resolution for the cause 388*40d553cfSPaul Beesleyof the exception, the corresponding priority level ought to be deactivated. As 389*40d553cfSPaul Beesleyabove, for interrupts, this is implied when the interrupt is EOId in the GIC; 390*40d553cfSPaul Beesleyfor other exceptions, this has to be done via calling 391*40d553cfSPaul Beesley``ehf_deactivate_priority()``. 392*40d553cfSPaul Beesley 393*40d553cfSPaul BeesleyThanks to `different provisions`__ for exception delegation, there are 394*40d553cfSPaul Beesleypotentially more than one work flow for deactivation: 395*40d553cfSPaul Beesley 396*40d553cfSPaul Beesley.. __: `delegation-use-cases`_ 397*40d553cfSPaul Beesley 398*40d553cfSPaul Beesley.. _deactivation workflows: 399*40d553cfSPaul Beesley 400*40d553cfSPaul Beesley- The dispatcher has addressed the cause of the exception, and decided to take 401*40d553cfSPaul Beesley no further action. In this case, the dispatcher's handler deactivates the 402*40d553cfSPaul Beesley priority level before returning to the |EHF|. Runtime firmware, upon exit 403*40d553cfSPaul Beesley through an ``ERET``, resumes execution before the interrupt occurred. 404*40d553cfSPaul Beesley 405*40d553cfSPaul Beesley- The dispatcher has to delegate the execution to lower ELs, and the cause of 406*40d553cfSPaul Beesley the exception can be considered resolved only when the lower EL returns 407*40d553cfSPaul Beesley signals complete (via an ``SMC``) at a future point in time. The following 408*40d553cfSPaul Beesley sequence ensues: 409*40d553cfSPaul Beesley 410*40d553cfSPaul Beesley #. The dispatcher calls ``setjmp()`` to setup a jump point, and arranges to 411*40d553cfSPaul Beesley enter a lower EL upon the next ``ERET``. 412*40d553cfSPaul Beesley 413*40d553cfSPaul Beesley #. Through the ensuing ``ERET`` from runtime firmware, execution is delegated 414*40d553cfSPaul Beesley to a lower EL. 415*40d553cfSPaul Beesley 416*40d553cfSPaul Beesley #. The lower EL completes its execution, and signals completion via an 417*40d553cfSPaul Beesley ``SMC``. 418*40d553cfSPaul Beesley 419*40d553cfSPaul Beesley #. The ``SMC`` is handled by the same dispatcher that handled the exception 420*40d553cfSPaul Beesley previously. Noticing the conclusion of exception handling, the dispatcher 421*40d553cfSPaul Beesley does ``longjmp()`` to resume beyond the previous jump point. 422*40d553cfSPaul Beesley 423*40d553cfSPaul BeesleyAs mentioned above, the |EHF| provides the following APIs for activating and 424*40d553cfSPaul Beesleydeactivating interrupt: 425*40d553cfSPaul Beesley 426*40d553cfSPaul Beesley.. _ehf-apis: 427*40d553cfSPaul Beesley 428*40d553cfSPaul Beesley- ``ehf_activate_priority()`` activates the supplied priority level, but only 429*40d553cfSPaul Beesley if the current active priority is higher than the given one; otherwise 430*40d553cfSPaul Beesley panics. Also, to prevent interruption by physical interrupts of lower 431*40d553cfSPaul Beesley priority, the |EHF| programs the *Priority Mask Register* corresponding to 432*40d553cfSPaul Beesley the PE to the priority being activated. Dispatchers typically only need to 433*40d553cfSPaul Beesley call this when handling exceptions other than interrupts, and it needs to 434*40d553cfSPaul Beesley delegate execution to a lower EL at a desired priority level. 435*40d553cfSPaul Beesley 436*40d553cfSPaul Beesley- ``ehf_deactivate_priority()`` deactivates a given priority, but only if the 437*40d553cfSPaul Beesley current active priority is equal to the given one; otherwise panics. |EHF| 438*40d553cfSPaul Beesley also restores the *Priority Mask Register* corresponding to the PE to the 439*40d553cfSPaul Beesley priority before the call to ``ehf_activate_priority()``. Dispatchers 440*40d553cfSPaul Beesley typically only need to call this after handling exceptions other than 441*40d553cfSPaul Beesley interrupts. 442*40d553cfSPaul Beesley 443*40d553cfSPaul BeesleyThe calling of APIs are subject to allowed `transitions`__. See also the 444*40d553cfSPaul Beesley`Run-time flow`_. 445*40d553cfSPaul Beesley 446*40d553cfSPaul Beesley.. __: `Transition of priority levels`_ 447*40d553cfSPaul Beesley 448*40d553cfSPaul BeesleyTransition of priority levels 449*40d553cfSPaul Beesley----------------------------- 450*40d553cfSPaul Beesley 451*40d553cfSPaul BeesleyThe |EHF| APIs ``ehf_activate_priority()`` and ``ehf_deactivate_priority()`` can 452*40d553cfSPaul Beesleybe called to transition the current priority level on a PE. A given sequence of 453*40d553cfSPaul Beesleycalls to these APIs are subject to the following conditions: 454*40d553cfSPaul Beesley 455*40d553cfSPaul Beesley- For activation, the |EHF| only allows for the priority to increase (i.e. 456*40d553cfSPaul Beesley numeric value decreases); 457*40d553cfSPaul Beesley 458*40d553cfSPaul Beesley- For deactivation, the |EHF| only allows for the priority to decrease (i.e. 459*40d553cfSPaul Beesley numeric value increases). Additionally, the priority being deactivated is 460*40d553cfSPaul Beesley required to be the current priority. 461*40d553cfSPaul Beesley 462*40d553cfSPaul BeesleyIf these are violated, a panic will result. 463*40d553cfSPaul Beesley 464*40d553cfSPaul BeesleyEffect on SMC calls 465*40d553cfSPaul Beesley------------------- 466*40d553cfSPaul Beesley 467*40d553cfSPaul BeesleyIn general, Secure execution is regarded as more important than Non-secure 468*40d553cfSPaul Beesleyexecution. As discussed elsewhere in this document, EL3 execution, and any 469*40d553cfSPaul Beesleydelegated execution thereafter, has the effect of raising GIC's priority 470*40d553cfSPaul Beesleymask—either implicitly by acknowledging Secure interrupts, or when dispatchers 471*40d553cfSPaul Beesleycall ``ehf_activate_priority()``. As a result, Non-secure interrupts cannot 472*40d553cfSPaul Beesleypreempt any Secure execution. 473*40d553cfSPaul Beesley 474*40d553cfSPaul BeesleySMCs from Non-secure world are synchronous exceptions, and are mechanisms for 475*40d553cfSPaul BeesleyNon-secure world to request Secure services. They're broadly classified as 476*40d553cfSPaul Beesley*Fast* or *Yielding* (see `SMCCC`__). 477*40d553cfSPaul Beesley 478*40d553cfSPaul Beesley.. __: `http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html` 479*40d553cfSPaul Beesley 480*40d553cfSPaul Beesley- *Fast* SMCs are atomic from the caller's point of view. I.e., they return 481*40d553cfSPaul Beesley to the caller only when the Secure world has finished serving the request. 482*40d553cfSPaul Beesley Any Non-secure interrupts that become pending meanwhile cannot preempt Secure 483*40d553cfSPaul Beesley execution. 484*40d553cfSPaul Beesley 485*40d553cfSPaul Beesley- *Yielding* SMCs carry the semantics of a preemptible, lower-priority request. 486*40d553cfSPaul Beesley A pending Non-secure interrupt can preempt Secure execution handling a 487*40d553cfSPaul Beesley Yielding SMC. I.e., the caller might observe a Yielding SMC returning when 488*40d553cfSPaul Beesley either: 489*40d553cfSPaul Beesley 490*40d553cfSPaul Beesley #. Secure world completes the request, and the caller would find ``SMC_OK`` 491*40d553cfSPaul Beesley as the return code. 492*40d553cfSPaul Beesley 493*40d553cfSPaul Beesley #. A Non-secure interrupt preempts Secure execution. Non-secure interrupt is 494*40d553cfSPaul Beesley handled, and Non-secure execution resumes after ``SMC`` instruction. 495*40d553cfSPaul Beesley 496*40d553cfSPaul Beesley The dispatcher handling a Yielding SMC must provide a different return code 497*40d553cfSPaul Beesley to the Non-secure caller to distinguish the latter case. This return code, 498*40d553cfSPaul Beesley however, is not standardised (unlike ``SMC_UNKNOWN`` or ``SMC_OK``, for 499*40d553cfSPaul Beesley example), so will vary across dispatchers that handle the request. 500*40d553cfSPaul Beesley 501*40d553cfSPaul BeesleyFor the latter case above, dispatchers before |EHF| expect Non-secure interrupts 502*40d553cfSPaul Beesleyto be taken to S-EL1 [#irq]_, so would get a chance to populate the designated 503*40d553cfSPaul Beesleypreempted error code before yielding to Non-secure world. 504*40d553cfSPaul Beesley 505*40d553cfSPaul BeesleyThe introduction of |EHF| changes the behaviour as described in `Interrupt 506*40d553cfSPaul Beesleyhandling`_. 507*40d553cfSPaul Beesley 508*40d553cfSPaul BeesleyWhen |EHF| is enabled, in order to allow Non-secure interrupts to preempt 509*40d553cfSPaul BeesleyYielding SMC handling, the dispatcher must call ``ehf_allow_ns_preemption()`` 510*40d553cfSPaul BeesleyAPI. The API takes one argument, the error code to be returned to the Non-secure 511*40d553cfSPaul Beesleyworld upon getting preempted. 512*40d553cfSPaul Beesley 513*40d553cfSPaul Beesley.. [#irq] In case of GICv2, Non-secure interrupts while in S-EL1 were signalled 514*40d553cfSPaul Beesley as IRQs, and in case of GICv3, FIQs. 515*40d553cfSPaul Beesley 516*40d553cfSPaul BeesleyBuild-time flow 517*40d553cfSPaul Beesley--------------- 518*40d553cfSPaul Beesley 519*40d553cfSPaul BeesleyPlease refer to the `figure`__ above. 520*40d553cfSPaul Beesley 521*40d553cfSPaul Beesley.. __: `ehf-figure`_ 522*40d553cfSPaul Beesley 523*40d553cfSPaul BeesleyThe build-time flow involves the following steps: 524*40d553cfSPaul Beesley 525*40d553cfSPaul Beesley#. Platform assigns priorities by installing priority level descriptors for 526*40d553cfSPaul Beesley individual dispatchers, as described in `Partitioning priority levels`_. 527*40d553cfSPaul Beesley 528*40d553cfSPaul Beesley#. Platform provides interrupt properties to GIC driver, as described in 529*40d553cfSPaul Beesley `Programming priority`_. 530*40d553cfSPaul Beesley 531*40d553cfSPaul Beesley#. Dispatcher calling ``ehf_register_priority_handler()`` to register an 532*40d553cfSPaul Beesley interrupt handler. 533*40d553cfSPaul Beesley 534*40d553cfSPaul BeesleyAlso refer to the `Interrupt handling example`_. 535*40d553cfSPaul Beesley 536*40d553cfSPaul BeesleyRun-time flow 537*40d553cfSPaul Beesley------------- 538*40d553cfSPaul Beesley 539*40d553cfSPaul Beesley.. _interrupt-flow: 540*40d553cfSPaul Beesley 541*40d553cfSPaul BeesleyThe following is an example flow for interrupts: 542*40d553cfSPaul Beesley 543*40d553cfSPaul Beesley#. The GIC driver, during initialization, iterates through the platform-supplied 544*40d553cfSPaul Beesley interrupt properties (see `Programming priority`_), and configures the 545*40d553cfSPaul Beesley interrupts. This programs the appropriate priority and group (Group 0) on 546*40d553cfSPaul Beesley interrupts belonging to different dispatchers. 547*40d553cfSPaul Beesley 548*40d553cfSPaul Beesley#. The |EHF|, during its initialisation, registers a top-level interrupt handler 549*40d553cfSPaul Beesley with the `Interrupt Management Framework`__ for EL3 interrupts. This also 550*40d553cfSPaul Beesley results in setting the routing bits in ``SCR_EL3``. 551*40d553cfSPaul Beesley 552*40d553cfSPaul Beesley .. __: interrupt-framework-design.rst#el3-runtime-firmware 553*40d553cfSPaul Beesley 554*40d553cfSPaul Beesley#. When an interrupt belonging to a dispatcher fires, GIC raises an EL3/Group 0 555*40d553cfSPaul Beesley interrupt, and is taken to EL3. 556*40d553cfSPaul Beesley 557*40d553cfSPaul Beesley#. The top-level EL3 interrupt handler executes. The handler acknowledges the 558*40d553cfSPaul Beesley interrupt, reads its *Running Priority*, and from that, determines the 559*40d553cfSPaul Beesley dispatcher handler. 560*40d553cfSPaul Beesley 561*40d553cfSPaul Beesley#. The |EHF| programs the *Priority Mask Register* of the PE to the priority of 562*40d553cfSPaul Beesley the interrupt received. 563*40d553cfSPaul Beesley 564*40d553cfSPaul Beesley#. The |EHF| marks that priority level *active*, and jumps to the dispatcher 565*40d553cfSPaul Beesley handler. 566*40d553cfSPaul Beesley 567*40d553cfSPaul Beesley#. Once the dispatcher handler finishes its job, it has to immediately 568*40d553cfSPaul Beesley *deactivate* the priority level before returning to the |EHF|. See 569*40d553cfSPaul Beesley `deactivation workflows`_. 570*40d553cfSPaul Beesley 571*40d553cfSPaul Beesley.. _non-interrupt-flow: 572*40d553cfSPaul Beesley 573*40d553cfSPaul BeesleyThe following is an example flow for exceptions that targets EL3 other than 574*40d553cfSPaul Beesleyinterrupt: 575*40d553cfSPaul Beesley 576*40d553cfSPaul Beesley#. The platform provides handlers for the specific kind of exception. 577*40d553cfSPaul Beesley 578*40d553cfSPaul Beesley#. The exception arrives, and the corresponding handler is executed. 579*40d553cfSPaul Beesley 580*40d553cfSPaul Beesley#. The handler calls ``ehf_activate_priority()`` to activate the required 581*40d553cfSPaul Beesley priority level. This also has the effect of raising GIC priority mask, thus 582*40d553cfSPaul Beesley preventing interrupts of lower priority from preempting the handling. The 583*40d553cfSPaul Beesley handler may choose to do the handling entirely in EL3 or delegate to a lower 584*40d553cfSPaul Beesley EL. 585*40d553cfSPaul Beesley 586*40d553cfSPaul Beesley#. Once exception handling concludes, the handler calls 587*40d553cfSPaul Beesley ``ehf_deactivate_priority()`` to deactivate the priority level activated 588*40d553cfSPaul Beesley earlier. This also has the effect of lowering GIC priority mask to what it 589*40d553cfSPaul Beesley was before. 590*40d553cfSPaul Beesley 591*40d553cfSPaul BeesleyInterrupt Prioritisation Considerations 592*40d553cfSPaul Beesley--------------------------------------- 593*40d553cfSPaul Beesley 594*40d553cfSPaul BeesleyThe GIC priority scheme, by design, prioritises Secure interrupts over Normal 595*40d553cfSPaul Beesleyworld ones. The platform further assigns relative priorities amongst Secure 596*40d553cfSPaul Beesleydispatchers through |EHF|. 597*40d553cfSPaul Beesley 598*40d553cfSPaul BeesleyAs mentioned in `Partitioning priority levels`_, interrupts targeting distinct 599*40d553cfSPaul Beesleydispatchers fall in distinct priority levels. Because they're routed via the 600*40d553cfSPaul BeesleyGIC, interrupt delivery to the PE is subject to GIC prioritisation rules. In 601*40d553cfSPaul Beesleyparticular, when an interrupt is being handled by the PE (i.e., the interrupt is 602*40d553cfSPaul Beesleyin *Active* state), only interrupts of higher priority are signalled to the PE, 603*40d553cfSPaul Beesleyeven if interrupts of same or lower priority are pending. This has the side 604*40d553cfSPaul Beesleyeffect of one dispatcher being starved of interrupts by virtue of another 605*40d553cfSPaul Beesleydispatcher handling its (higher priority) interrupts. 606*40d553cfSPaul Beesley 607*40d553cfSPaul BeesleyThe |EHF| doesn't enforce a particular prioritisation policy, but the platform 608*40d553cfSPaul Beesleyshould carefully consider the assignment of priorities to dispatchers integrated 609*40d553cfSPaul Beesleyinto runtime firmware. The platform should sensibly delineate priority to 610*40d553cfSPaul Beesleyvarious dispatchers according to their nature. In particular, dispatchers of 611*40d553cfSPaul Beesleycritical nature (RAS, for example) should be assigned higher priority than 612*40d553cfSPaul Beesleyothers (SDEI, for example); and within SDEI, Critical priority SDEI should be 613*40d553cfSPaul Beesleyassigned higher priority than Normal ones. 614*40d553cfSPaul Beesley 615*40d553cfSPaul BeesleyLimitations 616*40d553cfSPaul Beesley----------- 617*40d553cfSPaul Beesley 618*40d553cfSPaul BeesleyThe |EHF| has the following limitations: 619*40d553cfSPaul Beesley 620*40d553cfSPaul Beesley- Although there could be up to 128 Secure dispatchers supported by the GIC 621*40d553cfSPaul Beesley priority scheme, the size of descriptor array exposed with 622*40d553cfSPaul Beesley ``EHF_REGISTER_PRIORITIES()`` macro is currently limited to 32. This serves most 623*40d553cfSPaul Beesley expected use cases. This may be expanded in the future, should use cases 624*40d553cfSPaul Beesley demand so. 625*40d553cfSPaul Beesley 626*40d553cfSPaul Beesley- The platform must ensure that the priority assigned to the dispatcher in the 627*40d553cfSPaul Beesley exception descriptor and the programmed priority of interrupts handled by the 628*40d553cfSPaul Beesley dispatcher match. The |EHF| cannot verify that this has been followed. 629*40d553cfSPaul Beesley 630*40d553cfSPaul Beesley---- 631*40d553cfSPaul Beesley 632*40d553cfSPaul Beesley*Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.* 633*40d553cfSPaul Beesley 634*40d553cfSPaul Beesley.. _Interrupt Framework Design: interrupt-framework-design.rst 635*40d553cfSPaul Beesley.. _SDEI specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf 636