Document design of the Interrupt Mangement Framework
authorAchin Gupta <achin.gupta@arm.com>
Mon, 2 Jun 2014 21:27:36 +0000 (22:27 +0100)
committerDan Handley <dan.handley@arm.com>
Tue, 3 Jun 2014 17:42:14 +0000 (18:42 +0100)
This patch adds documentation that describes the design of the Interrupt
management framework in the ARM Trusted Firmware. The porting-guide.md has also
been updated to describe the interface that should be implemented by each
platform to support this framework.

Change-Id: I3eda48e5c9456e6a9516956bee16a29e366633b7
Co-Authored-By: Soby Mathew <soby.mathew@arm.com>
docs/diagrams/non-sec-int-handling.png [new file with mode: 0644]
docs/diagrams/sec-int-handling.png [new file with mode: 0644]
docs/firmware-design.md
docs/interrupt-framework-design.md [new file with mode: 0644]
docs/porting-guide.md

diff --git a/docs/diagrams/non-sec-int-handling.png b/docs/diagrams/non-sec-int-handling.png
new file mode 100644 (file)
index 0000000..1a5f629
Binary files /dev/null and b/docs/diagrams/non-sec-int-handling.png differ
diff --git a/docs/diagrams/sec-int-handling.png b/docs/diagrams/sec-int-handling.png
new file mode 100644 (file)
index 0000000..2ebbca4
Binary files /dev/null and b/docs/diagrams/sec-int-handling.png differ
index 43c43585d9f8bc7c596b7b38982bf797fc43c34a..b20f06b35a85e7b7f5c6f5a005a63b6ff191a7d3 100644 (file)
@@ -32,6 +32,10 @@ Trusted Firmware runtime services via the ARM SMC (Secure Monitor Call)
 instruction. The SMC instruction must be used as mandated by the [SMC Calling
 Convention PDD][SMCCC] [3].
 
+The ARM Trusted Firmware implements a framework for configuring and managing
+interrupts generated in either security state. The details of the interrupt
+management framework and its design can be found in [ARM Trusted
+Firmware Interrupt Management Design guide][INTRG] [4].
 
 2.  Cold boot
 -------------
@@ -1296,6 +1300,7 @@ kernel at boot time. These can be found in the `fdts` directory.
 
 3.  [SMC Calling Convention PDD (ARM DEN 0028A)][SMCCC].
 
+4.  [ARM Trusted Firmware Interrupt Management Design guide][INTRG].
 
 
 - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1306,4 +1311,5 @@ _Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved._
 [PSCI]:             http://infocenter.arm.com/help/topic/com.arm.doc.den0022b/index.html "Power State Coordination Interface PDD (ARM DEN 0022B.b)"
 [SMCCC]:            http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html "SMC Calling Convention PDD (ARM DEN 0028A)"
 [UUID]:             https://tools.ietf.org/rfc/rfc4122.txt "A Universally Unique IDentifier (UUID) URN Namespace"
-[User Guide]:       user-guide.md
+[User Guide]:       ./user-guide.md
+[INTRG]:            ./interrupt-framework-design.md
diff --git a/docs/interrupt-framework-design.md b/docs/interrupt-framework-design.md
new file mode 100644 (file)
index 0000000..f96f764
--- /dev/null
@@ -0,0 +1,848 @@
+ARM Trusted Firmware Interrupt Management Design guide
+======================================================
+
+Contents :
+
+1.  Introduction
+    *    Assumptions
+    *    Concepts
+         -    Interrupt Types
+         -    Routing Model
+         -    Valid Routing Models
+              +    Secure-EL1 Interrupts
+              +    Non-secure Interrupts
+         -    Mapping of Interrupt Type to Signal
+
+2.  Interrupt Management
+    *    Software Components
+    *    Interrupt Registration
+         -    EL3 Runtime Firmware
+         -    Secure Payload Dispatcher
+              +    Test Secure Payload Dispatcher behavior
+         -    Secure Payload
+              +    Secure Payload IHF design w.r.t Secure-EL1 interrupts
+              +    Secure Payload IHF design w.r.t Non-secure interrupts
+              +    Test Secure Payload behavior
+    *    Interrupt Handling
+         -    EL3 Runtime Firmware
+         -    Secure Payload Dispatcher
+              +    Interrupt Entry
+              +    Interrupt Exit
+              +    Test Secure Payload Dispatcher behavior
+         -    Secure Payload
+              +    Test Secure Payload behavior
+
+
+1.  Introduction
+----------------
+This document describes the design of the Interrupt management framework in ARM
+Trusted Firmware. This section briefly describes the requirements from this
+framework. It also briefly explains some concepts and assumptions. They will
+help in understanding the implementation of the framework explained in
+subsequent sections.
+
+This framework is responsible for managing interrupts routed to EL3. It also
+allows EL3 software to configure the interrupt routing behavior. Its main
+objective is to implement the following two requirements.
+
+1.  It should be possible to route interrupts meant to be handled by secure
+    software (Secure interrupts) to EL3, when execution is in non-secure state
+    (normal world). The framework should then take care of handing control of
+    the interrupt to either software in EL3 or Secure-EL1 depending upon the
+    software configuration and the GIC implementation. This requirement ensures
+    that secure interrupts are under the control of the secure software with
+    respect to their delivery and handling without the possibility of
+    intervention from non-secure software.
+
+2.  It should be possible to route interrupts meant to be handled by
+  non-secure software (Non-secure interrupts) to the last executed exception
+    level in the normal world when the execution is in secure world at
+    exception levels lower than EL3. This could be done with or without the
+    knowledge of software executing in Secure-EL1/Secure-EL0. The choice of
+    approach should be governed by the secure software. This requirement
+    ensures that non-secure software is able to execute in tandem with the
+    secure software without overriding it.
+
+### 1.1 Assumptions
+The framework makes the following assumptions to simplify its implementation.
+
+1.  All secure interrupts are handled in Secure-EL1. They can be delivered to
+    Secure-EL1 via EL3 but they cannot be handled in EL3. It will be possible
+    to extend the framework to handle secure interrupts in EL3 in the future.
+
+2.  Interrupt exceptions (`PSTATE.I` and `F` bits) are masked during execution
+    in EL3.
+
+### 1.2 Concepts
+
+#### 1.2.1 Interrupt types
+The framework categorises an interrupt to be one of the following depending upon
+the exception level(s) it is handled in.
+
+1.  Secure EL1 interrupt. This type of interrupt can be routed to EL3 or
+    Secure-EL1 depending upon the security state of the current execution
+    context. It is always handled in Secure-EL1.
+
+2.  Non-secure interrupt. This type of interrupt can be routed to EL3,
+    Secure-EL1, Non-secure EL1 or EL2 depending upon the security state of the
+    current execution context. It is always handled in either Non-secure EL1
+    or EL2.
+
+3.  EL3 interrupt. This type of interrupt can be routed to EL3 or Secure-EL1
+    depending upon the security state of the current execution context. It is
+    always handled in EL3.
+
+In the current implementation of the framework, all secure interrupts are
+treated as Secure EL1 interrupts. It will be possible for EL3 software to
+configure a secure interrupt as an EL3 interrupt in future implementations.  The
+following constants define the various interrupt types in the framework
+implementation.
+
+    #define INTR_TYPE_S_EL1      0
+    #define INTR_TYPE_EL3        1
+    #define INTR_TYPE_NS         2
+
+
+#### 1.2.2 Routing model
+A type of interrupt can be either generated as an FIQ or an IRQ. The target
+exception level of an interrupt type is configured through the FIQ and IRQ bits
+in the Secure Configuration Register at EL3 (`SCR_EL3.FIQ` and `SCR_EL3.IRQ`
+bits). When `SCR_EL3.FIQ`=1, FIQs are routed to EL3. Otherwise they are routed
+to the First Exception Level (FEL) capable of handling interrupts. When
+`SCR_EL3.IRQ`=1, IRQs are routed to EL3. Otherwise they are routed to the
+FEL. This register is configured independently by EL3 software for each security
+state prior to entry into a lower exception level in that security state.
+
+A routing model for a type of interrupt (generated as FIQ or IRQ) is defined as
+its target exception level for each security state. It is represented by a
+single bit for each security state. A value of `0` means that the interrupt
+should be routed to the FEL. A value of `1` means that the interrupt should be
+routed to EL3. A routing model is applicable only when execution is not in EL3.
+
+The default routing model for an interrupt type is to route it to the FEL in
+either security state.
+
+#### 1.2.3 Valid routing models
+The framework considers certain routing models for each type of interrupt to be
+incorrect as they conflict with the requirements mentioned in Section 1. The
+following sub-sections describe all the possible routing models and specify
+which ones are valid or invalid. Only the Secure-EL1 and Non-secure interrupt
+types are considered as EL3 interrupts are currently unsupported (See 1.1). The
+terminology used in the following sub-sections is explained below.
+
+1.  __CSS__. Current Security State. `0` when secure and `1` when non-secure
+
+2.  __TEL3__. Target Exception Level 3. `0` when targeted to the FEL. `1` when
+    targeted to EL3.
+
+
+##### 1.2.3.1 Secure-EL1 interrupts
+
+1.  __CSS=0, TEL3=0__. Interrupt is routed to the FEL when execution is in
+    secure state. This is a valid routing model as secure software is in
+    control of handling secure interrupts.
+
+2.  __CSS=0, TEL3=1__. Interrupt is routed to EL3 when execution is in secure
+    state. This is a valid routing model as secure software in EL3 can
+    handover the interrupt to Secure-EL1 for handling.
+
+3.  __CSS=1, TEL3=0__. Interrupt is routed to the FEL when execution is in
+    non-secure state. This is an invalid routing model as a secure interrupt
+    is not visible to the secure software which violates the motivation behind
+    the ARM Security Extensions.
+
+4.  __CSS=1, TEL3=1__. Interrupt is routed to EL3 when execution is in secure
+    state. This is a valid routing model as secure software in EL3 can
+    handover the interrupt to Secure-EL1 for handling.
+
+
+##### 1.2.3.2 Non-secure interrupts
+
+1.  __CSS=0, TEL3=0__. Interrupt is routed to the FEL when execution is in
+    secure state. This allows the secure software to trap non-secure
+    interrupts, perform its bookeeping and hand the interrupt to the
+    non-secure software through EL3. This is a valid routing model as secure
+    software is in control of how its execution is pre-empted by non-secure
+    interrupts.
+
+2.  __CSS=0, TEL3=1__. Interrupt is routed to EL3 when execution is in secure
+    state. This is a valid routing model as secure software in EL3 can save
+    the state of software in Secure-EL1/Secure-EL0 before handing the
+    interrupt to non-secure software. This model requires additional
+    coordination between Secure-EL1 and EL3 software to ensure that the
+    former's state is correctly saved by the latter.
+
+3.  __CSS=1, TEL3=0__. Interrupt is routed to FEL when execution is in
+    non-secure state. This is an valid routing model as a non-secure interrupt
+    is handled by non-secure software.
+
+4.   __CSS=1, TEL3=1__. Interrupt is routed to EL3 when execution is in
+    non-secure state. This is an invalid routing model as there is no valid
+    reason to route the interrupt to EL3 software and then hand it back to
+    non-secure software for handling.
+
+
+#### 1.2.4 Mapping of interrupt type to signal
+The framework is meant to work with any interrupt controller implemented by a
+platform. A interrupt controller could generate a type of interrupt as either an
+FIQ or IRQ signal to the CPU depending upon the current security state.The
+mapping between the type and signal is known only to the platform. The framework
+uses this information to determine whether the IRQ or the FIQ bit should be
+programmed in `SCR_EL3` while applying the routing model for a type of
+interrupt. The platform provides this information through the
+`plat_interrupt_type_to_line()` API (described in the [Porting
+Guide]). For example, on the FVP port when the platform uses an ARM GICv2
+interrupt controller, Secure-EL1 interrupts are signalled through the FIQ signal
+while Non-secure interrupts are signalled through the IRQ signal. This applies
+when execution is in either security state.
+
+
+2. Interrupt management
+-----------------------
+The following sections describe how interrupts are managed by the interrupt
+handling framework. This entails:
+
+1.  Providing an interface to allow registration of a handler and specification
+    of the routing model for a type of interrupt.
+
+2.  Implementing support to hand control of an interrupt type to its registered
+    handler when the interrupt is generated.
+
+Both aspects of interrupt management involve various components in the secure
+software stack spanning from EL3 to Secure-EL1. These components are described
+in the section 2.1. The framework stores information associated with each type
+of interrupt in the following data structure.
+
+```
+typedef struct intr_type_desc {
+        interrupt_type_handler_t handler;
+        uint32_t flags;
+        uint32_t scr_el3[2];
+} intr_type_desc_t;
+```
+
+The `flags` field stores the routing model for the interrupt type in
+bits[1:0]. Bit[0] stores the routing model when execution is in the secure
+state. Bit[1] stores the routing model when execution is in the non-secure
+state. As mentioned in Section 1.2.2, a value of `0` implies that the interrupt
+should be targeted to the FEL. A value of `1` implies that it should be targeted
+to EL3. The remaining bits are reserved and SBZ. The helper macro
+`set_interrupt_rm_flag()` should be used to set the bits in the `flags`
+parameter.
+
+The `scr_el3[2]` field also stores the routing model but as a mapping of the
+model in the `flags` field to the corresponding bit in the `SCR_EL3` for each
+security state.
+
+The framework also depends upon the platform port to configure the interrupt
+controller to distinguish between secure and non-secure interrupts. The platform
+is expected to be aware of the secure devices present in the system and their
+associated interrupt numbers. It should configure the interrupt controller to
+enable the secure interrupts, ensure that their priority is always higher than
+the non-secure interrupts and target them to the primary CPU. It should also
+export the interface described in the the [Porting Guide][PRTG] to enable
+handling of interrupts.
+
+In the remainder of this document, for the sake of simplicity it is assumed that
+the FIQ signal is used to generate Secure-EL1 interrupts and the IRQ signal is
+used to generate non-secure interrupts in either security state.
+
+### 2.1 Software components
+Roles and responsibilities for interrupt management are sub-divided between the
+following components of software running in EL3 and Secure-EL1. Each component is
+briefly described below.
+
+1.  EL3 Runtime Firmware. This component is common to all ports of the ARM
+    Trusted Firmware.
+
+2.  Secure Payload Dispatcher (SPD) service. This service interfaces with the
+    Secure Payload (SP) software which runs in exception levels lower than EL3
+    i.e. Secure-EL1/Secure-EL0. It is responsible for switching execution
+    between software running in secure and non-secure states at exception
+    levels lower than EL3. A switch is triggered by a Secure Monitor Call from
+    either state. It uses the APIs exported by the Context management library
+    to implement this functionality. Switching execution between the two
+    security states is a requirement for interrupt management as well. This
+    results in a significant dependency on the SPD service. ARM Trusted
+    firmware implements an example Test Secure Payload Dispatcher (TSPD)
+    service.
+
+    An SPD service plugs into the EL3 runtime firmware and could be common to
+    some ports of the ARM Trusted Firmware.
+
+3.  Secure Payload (SP). On a production system, the Secure Payload corresponds
+    to a Secure OS which runs in Secure-EL1/Secure-EL0. It interfaces with the
+    SPD service to manage communication with non-secure software. ARM Trusted
+    Firmware implements an example secure payload called Test Secure Payload
+    (TSP) which runs only in Secure-EL1.
+
+    A Secure payload implementation could be common to some ports of the ARM
+    Trusted Firmware just like the SPD service.
+
+
+### 2.2 Interrupt registration
+This section describes in detail the role of each software component (see 2.1)
+during the registration of a handler for an interrupt type.
+
+
+#### 2.2.1 EL3 runtime firmware
+This component declares the following prototype for a handler of an interrupt type.
+
+        typedef uint64_t (*interrupt_type_handler_t)(uint32_t id,
+                                            uint32_t flags,
+                                            void *handle,
+                                            void *cookie);
+
+The value of the `id` parameter depends upon the definition of the
+`IMF_READ_INTERRUPT_ID` build time flag. When the flag is defined, `id` contains
+the number of the highest priority pending interrupt of the type that this
+handler was registered for. When the flag is not defined `id` contains
+`INTR_ID_UNAVAILABLE`.
+
+The `flags` parameter contains miscellaneous information as follows.
+
+1.  Security state, bit[0]. This bit indicates the security state of the lower
+    exception level when the interrupt was generated. A value of `1` means
+    that it was in the non-secure state. A value of `0` indicates that it was
+    in the secure state. This bit can be used by the handler to ensure that
+    interrupt was generated and routed as per the routing model specified
+    during registration.
+
+2.  Reserved, bits[31:1]. The remaining bits are reserved for future use.
+
+The `handle` parameter points to the `cpu_context` structure of the current CPU
+for the security state specified in the `flags` parameter.
+
+Once the handler routine completes, execution will return to either the secure
+or non-secure state. The handler routine should return a pointer to
+`cpu_context` structure of the current CPU for the the target security state. It
+should treat all error conditions as critical errors and take appropriate action
+within its implementation e.g. use assertion failures.
+
+The runtime firmware provides the following API for registering a handler for a
+particular type of interrupt. A Secure Payload Dispatcher service should use
+this API to register a handler for Secure-EL1 and optionally for non-secure
+interrupts. This API also requires the caller to specify the routing model for
+the type of interrupt.
+
+    int32_t register_interrupt_type_handler(uint32_t type,
+                                       interrupt_type_handler handler,
+                                       uint64_t flags);
+
+
+The `type` parameter can be one of the three interrupt types listed above i.e.
+`INTR_TYPE_S_EL1`, `INTR_TYPE_NS` & `INTR_TYPE_EL3` (currently unimplemented).
+The `flags` parameter is as described in Section 2.
+
+The function will return `0` upon a successful registration. It will return
+`-EALREADY` in case a handler for the interrupt type has already been
+registered.  If the `type` is unrecognised or the `flags` or the `handler` are
+invalid it will return `-EINVAL`. It will return `-ENOTSUP` if the specified
+`type` is not supported by the framework i.e. `INTR_TYPE_EL3`.
+
+Interrupt routing is governed by the configuration of the `SCR_EL3.FIQ/IRQ` bits
+prior to entry into a lower exception level in either security state. The
+context management library maintains a copy of the `SCR_EL3` system register for
+each security state in the `cpu_context` structure of each CPU. It exports the
+following APIs to let EL3 Runtime Firmware program and retrieve the routing
+model for each security state for the current CPU. The value of `SCR_EL3` stored
+in the `cpu_context` is used by the `el3_exit()` function to program the
+`SCR_EL3` register prior to returning from the EL3 exception level.
+
+        uint32_t cm_get_scr_el3(uint32_t security_state);
+        void cm_write_scr_el3_bit(uint32_t security_state,
+                                  uint32_t bit_pos,
+                                  uint32_t value);
+
+`cm_get_scr_el3()` returns the value of the `SCR_EL3` register for the specified
+security state of the current CPU. `cm_write_scr_el3()` writes a `0` or `1` to
+the bit specified by `bit_pos`. `register_interrupt_type_handler()` invokes
+`set_routing_model()` API which programs the `SCR_EL3` according to the routing
+model using the `cm_get_scr_el3()` and `cm_write_scr_el3_bit()` APIs.
+
+It is worth noting that in the current implementation of the framework, the EL3
+runtime firmware is responsible for programming the routing model. The SPD is
+responsible for ensuring that the routing model has been adhered to upon
+receiving an interrupt.
+
+#### 2.2.2 Secure payload dispatcher
+A SPD service is responsible for determining and maintaining the interrupt
+routing model supported by itself and the Secure Payload. It is also responsible
+for ferrying interrupts between secure and non-secure software depending upon
+the routing model. It could determine the routing model at build time or at
+runtime. It must use this information to register a handler for each interrupt
+type using the `register_interrupt_type_handler()` API in EL3 runtime firmware.
+
+If the routing model is not known to the SPD service at build time, then it must
+be provided by the SP as the result of its initialisation. The SPD should
+program the routing model only after SP initialisation has completed e.g. in the
+SPD initialisation function pointed to by the `bl32_init` variable.
+
+The SPD should determine the mechanism to pass control to the Secure Payload
+after receiving an interrupt from the EL3 runtime firmware. This information
+could either be provided to the SPD service at build time or by the SP at
+runtime.
+
+#### 2.2.2.1 Test secure payload dispatcher behavior
+The TSPD only handles Secure-EL1 interrupts and is provided with the following
+routing model at build time.
+
+*   Secure-EL1 interrupts are routed to EL3 when execution is in non-secure
+    state and are routed to the FEL when execution is in the secure state
+    i.e __CSS=0, TEL3=0__ & __CSS=1, TEL3=1__ for Secure-EL1 interrupts
+
+*   The default routing model is used for non-secure interrupts i.e they are
+    routed to the FEL in either security state i.e __CSS=0, TEL3=0__ &
+    __CSS=1, TEL3=0__ for Non-secure interrupts
+
+It performs the following actions in the `tspd_init()` function to fulfill the
+requirements mentioned earlier.
+
+1.  It passes control to the Test Secure Payload to perform its
+    initialisation. The TSP provides the address of the vector table
+    `tsp_vectors` in the SP which also includes the handler for Secure-EL1
+    interrupts in the `fiq_entry` field. The TSPD passes control to the TSP at
+    this address when it receives a Secure-EL1 interrupt.
+
+    The handover agreement between the TSP and the TSPD requires that the TSPD
+    masks all interrupts (`PSTATE.DAIF` bits) when it calls
+    `tsp_fiq_entry()`. The TSP has to preserve the callee saved general
+    purpose, SP_EL1/Secure-EL0, LR, VFP and system registers. It can use
+    `x0-x18` to enable its C runtime.
+
+2.  The TSPD implements a handler function for Secure-EL1 interrupts. It
+    registers it with the EL3 runtime firmware using the
+    `register_interrupt_type_handler()` API as follows
+
+        /* Forward declaration */
+        interrupt_type_handler tspd_secure_el1_interrupt_handler;
+        int32_t rc, flags = 0;
+        set_interrupt_rm_flag(flags, NON_SECURE);
+        rc = register_interrupt_type_handler(INTR_TYPE_S_EL1,
+                                         tspd_secure_el1_interrupt_handler,
+                                         flags);
+        assert(rc == 0);
+
+#### 2.2.3 Secure payload
+A Secure Payload must implement an interrupt handling framework at Secure-EL1
+(Secure-EL1 IHF) to support its chosen interrupt routing model. Secure payload
+execution will alternate between the below cases.
+
+1.  In the code where IRQ, FIQ or both interrupts are enabled, if an interrupt
+    type is targeted to the FEL, then it will be routed to the Secure-EL1
+    exception vector table. This is defined as the asynchronous model of
+    handling interrupts. This mode applies to both Secure-EL1 and non-secure
+    interrupts.
+
+2.  In the code where both interrupts are disabled, if an interrupt type is
+    targeted to the FEL, then execution will eventually migrate to the
+    non-secure state. Any non-secure interrupts will be handled as described
+    in the routing model where __CSS=1 and TEL3=0__. Secure-EL1 interrupts
+    will be routed to EL3 (as per the routing model where __CSS=1 and
+    TEL3=1__) where the SPD service will hand them to the SP. This is defined
+    as the synchronous mode of handling interrupts.
+
+The interrupt handling framework implemented by the SP should support one or
+both these interrupt handling models depending upon the chosen routing model.
+
+The following list briefly describes how the choice of a valid routing model
+(See 1.2.3) effects the implementation of the Secure-EL1 IHF. If the choice of
+the interrupt routing model is not known to the SPD service at compile time,
+then the SP should pass this information to the SPD service at runtime during
+its initialisation phase.
+
+As mentioned earlier, it is assumed that the FIQ signal is used to generate
+Secure-EL1 interrupts and the IRQ signal is used to generate non-secure
+interrupts in either security state.
+
+##### 2.2.3.1 Secure payload IHF design w.r.t secure-EL1 interrupts
+1.  __CSS=0, TEL3=0__. If `PSTATE.F=0`, Secure-EL1 interrupts will be
+    trigerred at one of the Secure-EL1 FIQ exception vectors. The Secure-EL1
+    IHF should implement support for handling FIQ interrupts asynchronously.
+
+    If `PSTATE.F=1` then Secure-EL1 interrupts will be handled as per the
+    synchronous interrupt handling model. The SP could implement this scenario
+    by exporting a seperate entrypoint for Secure-EL1 interrupts to the SPD
+    service during the registration phase. The SPD service would also need to
+    know the state of the system, general purpose and the `PSTATE` registers
+    in which it should arrange to return execution to the SP. The SP should
+    provide this information in an implementation defined way during the
+    registration phase if it is not known to the SPD service at build time.
+
+2.  __CSS=1, TEL3=1__. Interrupts are routed to EL3 when execution is in
+    non-secure state. They should be handled through the synchronous interrupt
+    handling model as described in 1. above.
+
+3.  __CSS=0, TEL3=1__. Secure interrupts are routed to EL3 when execution is in
+    secure state. They will not be visible to the SP. The `PSTATE.F` bit in
+    Secure-EL1/Secure-EL0 will not mask FIQs. The EL3 runtime firmware will
+    call the handler registered by the SPD service for Secure-EL1
+    interrupts. Secure-EL1 IHF should then handle all Secure-EL1 interrupt
+    through the synchronous interrupt handling model described in 1. above.
+
+
+##### 2.2.3.2 Secure payload IHF design w.r.t non-secure interrupts
+1.  __CSS=0, TEL3=0__. If `PSTATE.I=0`, non-secure interrupts will be
+    trigerred at one of the Secure-EL1 IRQ exception vectors . The Secure-EL1
+    IHF should co-ordinate with the SPD service to transfer execution to the
+    non-secure state where the interrupt should be handled e.g the SP could
+    allocate a function identifier to issue a SMC64 or SMC32 to the SPD
+    service which indicates that the SP execution has been pre-empted by a
+    non-secure interrupt. If this function identifier is not known to the SPD
+    service at compile time then the SP could provide it during the
+    registration phase.
+
+    If `PSTATE.I=1` then the non-secure interrupt will pend until execution
+    resumes in the non-secure state.
+
+2.  __CSS=0, TEL3=1__.  Non-secure interrupts are routed to EL3. They will not
+    be visible to the SP. The `PSTATE.I` bit in Secure-EL1/Secure-EL0 will
+    have not effect. The SPD service should register a non-secure interrupt
+    handler which should save the SP state correctly and resume execution in
+    the non-secure state where the interrupt will be handled. The Secure-EL1
+    IHF does not need to take any action.
+
+3.  __CSS=1, TEL3=0__.  Non-secure interrupts are handled in the FEL in
+    non-secure state (EL1/EL2) and are not visible to the SP. This routing
+    model does not affect the SP behavior.
+
+
+A Secure Payload must also ensure that all Secure-EL1 interrupts are correctly
+configured at the interrupt controller by the platform port of the EL3 runtime
+firmware. It should configure any additional Secure-EL1 interrupts which the EL3
+runtime firmware is not aware of through its platform port.
+
+#### 2.2.3.3 Test secure payload behavior
+The routing model for Secure-EL1 and non-secure interrupts chosen by the TSP is
+described in Section 2.2.2. It is known to the TSPD service at build time.
+
+The TSP implements an entrypoint (`tsp_fiq_entry()`) for handling Secure-EL1
+interrupts taken in non-secure state and routed through the TSPD service
+(synchronous handling model). It passes the reference to this entrypoint via
+`tsp_vectors` to the TSPD service.
+
+The TSP also replaces the default exception vector table referenced through the
+`early_exceptions` variable, with a vector table capable of handling FIQ and IRQ
+exceptions taken at the same (Secure-EL1) exception level. This table is
+referenced through the `tsp_exceptions` variable and programmed into the
+VBAR_EL1. It caters for the asynchronous handling model.
+
+The TSP also programs the Secure Physical Timer in the ARM Generic Timer block
+to raise a periodic interrupt (every half a second) for the purpose of testing
+interrupt management across all the software components listed in 2.1
+
+
+### 2.3 Interrupt handling
+This section describes in detail the role of each software component (see
+Section 2.1) in handling an interrupt of a particular type.
+
+#### 2.3.1 EL3 runtime firmware
+The EL3 runtime firmware populates the IRQ and FIQ exception vectors referenced
+by the `runtime_exceptions` variable as follows.
+
+1.  IRQ and FIQ exceptions taken from the current exception level with
+    `SP_EL0` or `SP_EL3` are reported as irrecoverable error conditions. As
+    mentioned earlier, EL3 runtime firmware always executes with the
+    `PSTATE.I` and `PSTATE.F` bits set.
+
+2.  The following text describes how the IRQ and FIQ exceptions taken from a
+    lower exception level using AArch64 or AArch32 are handled.
+
+When an interrupt is generated, the vector for each interrupt type is
+responsible for:
+
+1.  Saving the entire general purpose register context (x0-x30) immediately
+    upon exception entry. The registers are saved in the per-cpu `cpu_context`
+    data structure referenced by the `SP_EL3`register.
+
+2.  Saving the `ELR_EL3`, `SP_EL0` and `SPSR_EL3` system registers in the
+    per-cpu `cpu_context` data structure referenced by the `SP_EL3` register.
+
+3.  Switching to the C runtime stack by restoring the `CTX_RUNTIME_SP` value
+    from the per-cpu `cpu_context` data structure in `SP_EL0` and
+    executing the `msr spsel, #0` instruction.
+
+4.  Determining the type of interrupt. Secure-EL1 interrupts will be signalled
+    at the FIQ vector. Non-secure interrupts will be signalled at the IRQ
+    vector. The platform should implement the following API to determine the
+    type of the pending interrupt.
+
+        uint32_t plat_ic_get_interrupt_type(void);
+
+    It should return either `INTR_TYPE_S_EL1` or `INTR_TYPE_NS`.
+
+5.  Determining the handler for the type of interrupt that has been generated.
+    The following API has been added for this purpose.
+
+        interrupt_type_handler get_interrupt_type_handler(uint32_t interrupt_type);
+
+    It returns the reference to the registered handler for this interrupt
+    type. The `handler` is retrieved from the `intr_type_desc_t` structure as
+    described in Section 2. `NULL` is returned if no handler has been
+    registered for this type of interrupt. This scenario is reported as an
+    irrecoverable error condition.
+
+6.  Calling the registered handler function for the interrupt type generated.
+    The firmware also determines the interrupt id if the IMF_READ_INTERRUPT_ID
+    build time flag is set. The id is set to `INTR_ID_UNAVAILABLE` if the flag
+    is not set. The id along with the current security state and a reference to
+    the `cpu_context_t` structure for the current security state are passed to
+    the handler function as its arguments.
+
+    The handler function returns a reference to the per-cpu `cpu_context_t`
+    structure for the target security state.
+
+7.  Calling `el3_exit()` to return from EL3 into a lower exception level in
+    the security state determined by the handler routine. The `el3_exit()`
+    function is responsible for restoring the register context from the
+    `cpu_context_t` data structure for the target security state.
+
+
+#### 2.3.2 Secure payload dispatcher
+
+##### 2.3.2.1 Interrupt entry
+The SPD service begins handling an interrupt when the EL3 runtime firmware calls
+the handler function for that type of interrupt. The SPD service is responsible
+for the following:
+
+1.  Validating the interrupt. This involves ensuring that the interrupt was
+    generating according to the interrupt routing model specified by the SPD
+    service during registration. It should use the interrupt id and the
+    security state of the exception level (passed in the `flags` parameter of
+    the handler) where the interrupt was taken from to determine this. If the
+    interrupt is not recognised then the handler should treat it as an
+    irrecoverable error condition.
+
+    A SPD service can register a handler for Secure-EL1 and/or Non-secure
+    interrupts. The following text describes further error scenarios keeping
+    this in mind:
+
+    1.  __SPD service has registered a handler for Non-secure interrupts__:
+        When an interrupt is received by the handler, it could check its id
+        to ensure it has been configured as a non-secure interrupt at the
+        interrupt controller. A secure interrupt should never be handed to
+        the non-secure interrupt handler. A non-secure interrupt should
+        never be routed to EL3 when execution is in non-secure state. The
+        handler could check the security state flag to ensure this.
+
+    2.  __SPD service has registered a handler for Secure-EL1 interrupts__:
+        When an interrupt is received by the handler, it could check its id
+        to ensure it has been configured as a secure interrupt at the
+        interrupt controller. A non-secure interrupt should never be handed
+        to the secure interrupt handler. If the routing model chosen is such
+        that Secure-EL1 interrupts are not routed to EL3 when execution is
+        in non-secure state, then a Secure-EL1 interrupt generated in the
+        secure state would be invalid. The handler could use the security
+        state flag to check this.
+
+    The SPD service should use the platform API:
+    `plat_ic_get_interrupt_type()` to determine the type of interrupt for the
+    specified id.
+
+2.  Determining whether the security state of the exception level for handling
+    the interrupt is the same as the security state of the exception level
+    where the interrupt was generated. This depends upon the routing model and
+    type of the interrupt. The SPD should use this information to determine if
+    a context switch is required. The following two cases would require a
+    context switch from secure to non-secure or vice-versa.
+
+    1.  A Secure-EL1 interrupt taken from the non-secure state should be
+        routed to the Secure Payload.
+
+    2.  A non-secure interrupt taken from the secure state should be routed
+        to the last known non-secure exception level.
+
+    The SPD service must save the system register context of the current
+    security state. It must then restore the system register context of the
+    target security state. It should use the `cm_set_next_eret_context()` API
+    to ensure that the next `cpu_context` to be restored is of the target
+    security state.
+
+    If the target state is secure then execution should be handed to the SP as
+    per the synchronous interrupt handling model it implements. A Secure-EL1
+    interrupt can be routed to EL3 while execution is in the SP. This implies
+    that SP execution can be preempted while handling an interrupt by a
+    another higher priority Secure-EL1 interrupt (or a EL3 interrupt in the
+    future). The SPD service should manage secure interrupt priorities before
+    handing control to the SP to prevent this type of preemption which can
+    leave the system in an inconsistent state.
+
+3.  Setting the return value of the handler to the per-cpu `cpu_context` if
+    the interrupt has been successfully validated and ready to be handled at a
+    lower exception level.
+
+The routing model allows non-secure interrupts to be taken to Secure-EL1 when in
+secure state. The SPD service and the SP should implement a mechanism for
+routing these interrupts to the last known exception level in the non-secure
+state. The former should save the SP context, restore the non-secure context and
+arrange for entry into the non-secure state so that the interrupt can be
+handled.
+
+##### 2.3.2.2 Interrupt exit
+When the Secure Payload has finished handling a Secure-EL1 interrupt, it could
+return control back to the SPD service through a SMC32 or SMC64. The SPD service
+should handle this secure monitor call so that execution resumes in the
+exception level and the security state from where the Secure-EL1 interrupt was
+originally taken.
+
+##### 2.3.2.1 Test secure payload dispatcher behavior
+The example TSPD service registers a handler for Secure-EL1 interrupts taken
+from the non-secure state. Its handler `tspd_secure_el1_interrupt_handler()`
+takes the following actions upon being invoked.
+
+1.  It uses the `id` parameter to query the interrupt controller to ensure
+    that the interrupt is a Secure-EL1 interrupt. It asserts if this is not
+    the case.
+
+2.  It uses the security state provided in the `flags` parameter to ensure
+    that the secure interrupt originated from the non-secure state. It asserts
+    if this is not the case.
+
+3.  It saves the system register context for the non-secure state by calling
+    `cm_el1_sysregs_context_save(NON_SECURE);`.
+
+4.  It sets the `ELR_EL3` system register to `tsp_fiq_entry` and sets the
+    `SPSR_EL3.DAIF` bits in the secure CPU context. It sets `x0` to
+    `TSP_HANDLE_FIQ_AND_RETURN`. If the TSP was in the middle of handling a
+    standard SMC, then the `ELR_EL3` and `SPSR_EL3` registers in the secure CPU
+    context are saved first.
+
+5.  It restores the system register context for the secure state by calling
+    `cm_el1_sysregs_context_restore(SECURE);`.
+
+6.  It ensures that the secure CPU context is used to program the next
+    exception return from EL3 by calling `cm_set_next_eret_context(SECURE);`.
+
+7.  It returns the per-cpu `cpu_context` to indicate that the interrupt can
+    now be handled by the SP. `x1` is written with the value of `elr_el3`
+    register for the non-secure state. This information is used by the SP for
+    debugging purposes.
+
+The figure below describes how the interrupt handling is implemented by the TSPD
+when a Secure-EL1 interrupt is generated when execution is in the non-secure
+state.
+
+![Image 1](diagrams/sec-int-handling.png?raw=true)
+
+The TSP issues an SMC with `TSP_HANDLED_S_EL1_FIQ` as the function identifier to
+signal completion of interrupt handling.
+
+The TSP issues an SMC with `TSP_PREEMPTED` as the function identifier to signal
+generation of a non-secure interrupt in Secure-EL1.
+
+The TSPD service takes the following actions in `tspd_smc_handler()` function
+upon receiving an SMC with `TSP_HANDLED_S_EL1_FIQ` and `TSP_PREEMPTED` as the
+function identifiers:
+
+1.  It ensures that the call originated from the secure state otherwise
+    execution returns to the non-secure state with `SMC_UNK` in `x0`.
+
+2.  If the function identifier is `TSP_HANDLED_S_EL1_FIQ`, it restores the
+    saved `ELR_EL3` and `SPSR_EL3` system registers back to the secure CPU
+    context (see step 4 above) in case the TSP had been preempted by a non
+    secure interrupt earlier.  It does not save the secure context since the
+    TSP is expected to preserve it (see Section 2.2.2.1)
+
+3.  If the function identifier is `TSP_PREEMPTED`, it saves the system
+    register context for the secure state by calling
+    `cm_el1_sysregs_context_save(SECURE)`.
+
+4.  It restores the system register context for the non-secure state by
+    calling `cm_el1_sysregs_context_restore(NON_SECURE)`. It sets `x0` to
+    `SMC_PREEMPTED` if the incoming function identifier is
+    `TSP_PREEMPTED`. The Normal World is expected to resume the TSP after the
+    non-secure interrupt handling by issuing an SMC with `TSP_FID_RESUME` as
+    the function identifier.
+
+5.  It ensures that the non-secure CPU context is used to program the next
+    exception return from EL3 by calling
+    `cm_set_next_eret_context(NON_SECURE)`.
+
+6.  `tspd_smc_handler()` returns a reference to the non-secure `cpu_context`
+    as the return value.
+
+As mentioned in 4. above, if a non-secure interrupt preempts the TSP execution
+then the non-secure software issues an SMC with `TSP_FID_RESUME` as the function
+identifier to resume TSP execution. The TSPD service takes the following actions
+in `tspd_smc_handler()` function upon receiving this SMC:
+
+1.  It ensures that the call originated from the non secure state. An
+    assertion is raised otherwise.
+
+2.  Checks whether the TSP needs a resume i.e check if it was preempted. It
+    then saves the system register context for the secure state by calling
+    `cm_el1_sysregs_context_save(NON_SECURE)`.
+
+3.  Restores the secure context by calling
+    `cm_el1_sysregs_context_restore(SECURE)`
+
+4.  It ensures that the secure CPU context is used to program the next
+    exception return from EL3 by calling `cm_set_next_eret_context(SECURE)`.
+
+5.  `tspd_smc_handler()` returns a reference to the secure `cpu_context` as the
+    return value.
+
+The figure below describes how the TSP/TSPD handle a non-secure interrupt when
+it is generated during execution in the TSP with `PSTATE.I` = 0.
+
+![Image 2](diagrams/non-sec-int-handling.png?raw=true)
+
+
+#### 2.3.3 Secure payload
+The SP should implement one or both of the synchronous and asynchronous
+interrupt handling models depending upon the interrupt routing model it has
+chosen (as described in 2.2.3).
+
+In the synchronous model, it should begin handling a Secure-EL1 interrupt after
+receiving control from the SPD service at an entrypoint agreed upon during build
+time or during the registration phase. Before handling the interrupt, the SP
+should save any Secure-EL1 system register context which is needed for resuming
+normal execution in the SP later e.g. `SPSR_EL1, `ELR_EL1`. After handling the
+interrupt, the SP could return control back to the exception level and security
+state where the interrupt was originally taken from. The SP should use an SMC32
+or SMC64 to ask the SPD service to do this.
+
+In the asynchronous model, the Secure Payload is responsible for handling
+non-secure and Secure-EL1 interrupts at the IRQ and FIQ vectors in its exception
+vector table when `PSTATE.I` and `PSTATE.F` bits are 0. As described earlier,
+when a non-secure interrupt is generated, the SP should coordinate with the SPD
+service to pass control back to the non-secure state in the last known exception
+level. This will allow the non-secure interrupt to be handled in the non-secure
+state.
+
+##### 2.3.3.1 Test secure payload behavior
+The TSPD hands control of a Secure-EL1 interrupt to the TSP at the
+`tsp_fiq_entry()`.  The TSP handles the interrupt while ensuring that the
+handover agreement described in Section 2.2.2.1 is maintained. It updates some
+statistics by calling `tsp_update_sync_fiq_stats()`. It then calls
+`tsp_fiq_handler()` which.
+
+1.  Checks whether the interrupt is the secure physical timer interrupt. It
+    uses the platform API `plat_ic_get_pending_interrupt_id()` to get the
+    interrupt number.
+
+2.   Handles the interrupt by acknowledging it using the
+    `plat_ic_acknowledge_interrupt()` platform API, calling
+    `tsp_generic_timer_handler()` to reprogram the secure physical generic
+    timer and calling the `plat_ic_end_of_interrupt()` platform API to signal
+    end of interrupt processing.
+
+The TSP passes control back to the TSPD by issuing an SMC64 with
+`TSP_HANDLED_S_EL1_FIQ` as the function identifier.
+
+The TSP handles interrupts under the asynchronous model as follows.
+
+1.  Secure-EL1 interrupts are handled by calling the `tsp_fiq_handler()`
+    function. The function has been described above.
+
+2.  Non-secure interrupts are handled by issuing an SMC64 with `TSP_PREEMPTED`
+    as the function identifier. Execution resumes at the instruction that
+    follows this SMC instruction when the TSPD hands control to the TSP in
+    response to an SMC with `TSP_FID_RESUME` as the function identifier from
+    the non-secure state (see section 2.3.2.1).
+
+- - - - - - - - - - - - - - - - - - - - - - - - - -
+
+_Copyright (c) 2014, ARM Limited and Contributors. All rights reserved._
+
+[Porting Guide]:             ./porting-guide.md
index 753b129485c7587786ebace4c66f1cc1bd5698fb..d97019063dd805349c212810a579253a1278b0d8 100644 (file)
@@ -14,6 +14,7 @@ Contents
     *   Boot Loader stage 2 (BL2)
     *   Boot Loader stage 3-1 (BL3-1)
     *   PSCI implementation (in BL3-1)
+    *   Interrupt Management framework (in BL3-1)
 4.  C Library
 5.  Storage abstraction layer
 
@@ -1135,6 +1136,135 @@ critical for the PSCI runtime service to function correctly. More details are
 provided in the description of the `plat_get_aff_count()` and
 `plat_get_aff_state()` functions above.
 
+3.4  Interrupt Management framework (in BL3-1)
+----------------------------------------------
+BL3-1 implements an Interrupt Management Framework (IMF) to manage interrupts
+generated in either security state and targeted to EL1 or EL2 in the non-secure
+state or EL3/S-EL1 in the secure state.  The design of this framework is
+described in the [IMF Design Guide]
+
+A platform should export the following APIs to support the IMF. The following
+text briefly describes each api and its implementation on the FVP port. The API
+implementation depends upon the type of interrupt controller present in the
+platform. The FVP implements an ARM Generic Interrupt Controller (ARM GIC) as
+per the version 2.0 of the [ARM GIC Architecture Specification]
+
+### Function : plat_interrupt_type_to_line() [mandatory]
+
+    Argument : uint32_t, uint32_t
+    Return   : uint32_t
+
+The ARM processor signals an interrupt exception either through the IRQ or FIQ
+interrupt line. The specific line that is signaled depends on how the interrupt
+controller (IC) reports different interrupt types from an execution context in
+either security state. The IMF uses this API to determine which interrupt line
+the platform IC uses to signal each type of interrupt supported by the framework
+from a given security state.
+
+The first parameter will be one of the `INTR_TYPE_*` values (see [IMF Design
+Guide]) indicating the target type of the interrupt, the second parameter is the
+security state of the originating execution context. The return result is the
+bit position in the `SCR_EL3` register of the respective interrupt trap: IRQ=1,
+FIQ=2.
+
+The FVP port configures the ARM GIC to signal S-EL1 interrupts as FIQs and
+Non-secure interrupts as IRQs from either security state.
+
+
+### Function : plat_ic_get_pending_interrupt_type() [mandatory]
+
+    Argument : void
+    Return   : uint32_t
+
+This API returns the type of the highest priority pending interrupt at the
+platform IC. The IMF uses the interrupt type to retrieve the corresponding
+handler function. `INTR_TYPE_INVAL` is returned when there is no interrupt
+pending. The valid interrupt types that can be returned are `INTR_TYPE_EL3`,
+`INTR_TYPE_S_EL1` and `INTR_TYPE_NS`.
+
+The FVP port reads the _Highest Priority Pending Interrupt Register_
+(`GICC_HPPIR`) to determine the id of the pending interrupt. The type of interrupt
+depends upon the id value as follows.
+
+1. id < 1022 is reported as a S-EL1 interrupt
+2. id = 1022 is reported as a Non-secure interrupt.
+3. id = 1023 is reported as an invalid interrupt type.
+
+
+### Function : plat_ic_get_pending_interrupt_id() [mandatory]
+
+    Argument : void
+    Return   : uint32_t
+
+This API returns the id of the highest priority pending interrupt at the
+platform IC. The IMF passes the id returned by this API to the registered
+handler for the pending interrupt if the `IMF_READ_INTERRUPT_ID` build time flag
+is set. INTR_ID_UNAVAILABLE is returned when there is no interrupt pending.
+
+The FVP port reads the _Highest Priority Pending Interrupt Register_
+(`GICC_HPPIR`) to determine the id of the pending interrupt. The id that is
+returned by API depends upon the value of the id read from the interrupt
+controller as follows.
+
+1. id < 1022. id is returned as is.
+2. id = 1022. The _Aliased Highest Priority Pending Interrupt Register_
+   (`GICC_AHPPIR`) is read to determine the id of the non-secure interrupt. This
+   id is returned by the API.
+3. id = 1023. `INTR_ID_UNAVAILABLE` is returned.
+
+
+### Function : plat_ic_acknowledge_interrupt() [mandatory]
+
+    Argument : void
+    Return   : uint32_t
+
+This API is used by the CPU to indicate to the platform IC that processing of
+the highest pending interrupt has begun. It should return the id of the
+interrupt which is being processed.
+
+The FVP port reads the _Interrupt Acknowledge Register_ (`GICC_IAR`). This
+changes the state of the highest priority pending interrupt from pending to
+active in the interrupt controller. It returns the value read from the
+`GICC_IAR`. This value is the id of the interrupt whose state has been changed.
+
+The TSP uses this API to start processing of the secure physical timer
+interrupt.
+
+
+### Function : plat_ic_end_of_interrupt() [mandatory]
+
+    Argument : uint32_t
+    Return   : void
+
+This API is used by the CPU to indicate to the platform IC that processing of
+the interrupt corresponding to the id (passed as the parameter) has
+finished. The id should be the same as the id returned by the
+`plat_ic_acknowledge_interrupt()` API.
+
+The FVP port writes the id to the _End of Interrupt Register_
+(`GICC_EOIR`). This deactivates the corresponding interrupt in the interrupt
+controller.
+
+The TSP uses this API to finish processing of the secure physical timer
+interrupt.
+
+
+### Function : plat_ic_get_interrupt_type() [mandatory]
+
+    Argument : uint32_t
+    Return   : uint32_t
+
+This API returns the type of the interrupt id passed as the parameter.
+`INTR_TYPE_INVAL` is returned if the id is invalid. If the id is valid, a valid
+interrupt type (one of `INTR_TYPE_EL3`, `INTR_TYPE_S_EL1` and `INTR_TYPE_NS`) is
+returned depending upon how the interrupt has been configured by the platform
+IC.
+
+The FVP port configures S-EL1 interrupts as Group0 interrupts and Non-secure
+interrupts as Group1 interrupts. It reads the group value corresponding to the
+interrupt id from the relevant _Interrupt Group Register_ (`GICD_IGROUPRn`). It
+uses the group value to determine the type of interrupt.
+
 
 4.  C Library
 -------------
@@ -1227,8 +1357,10 @@ amount of open resources per driver.
 _Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved._
 
 
-[User Guide]: user-guide.md
-[FreeBSD]:    http://www.freebsd.org
+[ARM GIC Architecture Specification]: http://arminfo.emea.arm.com/help/topic/com.arm.doc.ihi0048b/IHI0048B_gic_architecture_specification.pdf
+[IMF Design Guide]:                   interrupt-framework-design.md
+[User Guide]:                         user-guide.md
+[FreeBSD]:                            http://www.freebsd.org
 
 [plat/common/aarch64/platform_mp_stack.S]: ../plat/common/aarch64/platform_mp_stack.S
 [plat/common/aarch64/platform_up_stack.S]: ../plat/common/aarch64/platform_up_stack.S