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