diff --git a/Makefile b/Makefile index 73566c039..83b8808d1 100644 --- a/Makefile +++ b/Makefile @@ -482,6 +482,7 @@ $(eval $(call assert_boolean,CTX_INCLUDE_AARCH32_REGS)) $(eval $(call assert_boolean,CTX_INCLUDE_FPREGS)) $(eval $(call assert_boolean,DEBUG)) $(eval $(call assert_boolean,DISABLE_PEDANTIC)) +$(eval $(call assert_boolean,EL3_EXCEPTION_HANDLING)) $(eval $(call assert_boolean,ENABLE_AMU)) $(eval $(call assert_boolean,ENABLE_ASSERTIONS)) $(eval $(call assert_boolean,ENABLE_PLAT_COMPAT)) @@ -525,6 +526,7 @@ $(eval $(call add_define,ARM_GIC_ARCH)) $(eval $(call add_define,COLD_BOOT_SINGLE_CPU)) $(eval $(call add_define,CTX_INCLUDE_AARCH32_REGS)) $(eval $(call add_define,CTX_INCLUDE_FPREGS)) +$(eval $(call add_define,EL3_EXCEPTION_HANDLING)) $(eval $(call add_define,ENABLE_AMU)) $(eval $(call add_define,ENABLE_ASSERTIONS)) $(eval $(call add_define,ENABLE_PLAT_COMPAT)) diff --git a/docs/interrupt-framework-design.rst b/docs/interrupt-framework-design.rst index 940bc24f0..0eb7f54f2 100644 --- a/docs/interrupt-framework-design.rst +++ b/docs/interrupt-framework-design.rst @@ -135,7 +135,7 @@ Non-secure interrupts former's state is correctly saved by the latter. #. **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 + non-secure state. This is a valid routing model as a non-secure interrupt is handled by non-secure software. #. **CSS=1, TEL3=1**. Interrupt is routed to EL3 when execution is in @@ -151,6 +151,10 @@ EL3 interrupts in Secure-EL1/Secure-EL0 is in control of how its execution is preempted by EL3 interrupt and can handover the interrupt to EL3 for handling. + However, when ``EL3_EXCEPTION_HANDLING`` is ``1``, this routing model is + invalid as EL3 interrupts are unconditionally routed to EL3, and EL3 + interrupts will always preempt Secure EL1/EL0 execution. + #. **CSS=0, TEL3=1**. Interrupt is routed to EL3 when execution is in Secure-EL1/Secure-EL0. This is a valid routing model as secure software in EL3 can handle the interrupt. @@ -212,17 +216,14 @@ The framework makes the following assumptions to simplify its implementation. #. Interrupt exceptions (``PSTATE.I`` and ``F`` bits) are masked during execution in EL3. -#. .. rubric:: Interrupt management - :name: interrupt-management +#. Interrupt management: the following sections describe how interrupts are + managed by the interrupt handling framework. This entails: - The following sections describe how interrupts are managed by the interrupt - handling framework. This entails: + #. Providing an interface to allow registration of a handler and + specification of the routing model for a type of interrupt. -#. Providing an interface to allow registration of a handler and specification - of the routing model for a type of interrupt. - -#. Implementing support to hand control of an interrupt type to its registered - handler when the interrupt is generated. + #. 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 @@ -415,6 +416,9 @@ runtime. Test secure payload dispatcher behavior ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +**Note:** where this document discusses ``TSP_NS_INTR_ASYNC_PREEMPT`` as being +``1``, the same results also apply when ``EL3_EXCEPTION_HANDLING`` is ``1``. + The TSPD only handles Secure-EL1 interrupts and is provided with the following routing model at build time. @@ -678,14 +682,14 @@ the handler function for that type of interrupt. The SPD service is responsible for the following: #. Validating the interrupt. This involves ensuring that the interrupt was - generating according to the interrupt routing model specified by the SPD + generated according to the interrupt routing model specified by the SPD service during registration. It should use 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 + An SPD service can register a handler for Secure-EL1 and/or Non-secure interrupts. A non-secure interrupt should never be routed to EL3 from from non-secure state. Also if a routing model is chosen where Secure-EL1 interrupts are routed to S-EL1 when execution is in Secure state, then a @@ -809,9 +813,10 @@ Test secure payload dispatcher non-secure interrupt handling The TSP in Secure-EL1 can be preempted by a non-secure interrupt during ``yielding`` SMC processing or by a higher priority EL3 interrupt during -Secure-EL1 interrupt processing. Currently only non-secure interrupts can -cause preemption of TSP since there are no EL3 interrupts in the -system. +Secure-EL1 interrupt processing. When ``EL3_EXCEPTION_HANDLING`` is ``0``, only +non-secure interrupts can cause preemption of TSP since there are no EL3 +interrupts in the system. With ``EL3_EXCEPTION_HANDLING=1`` however, any EL3 +interrupt may preempt Secure execution. It should be noted that while TSP is preempted, the TSPD only allows entry into the TSP either for Secure-EL1 interrupt handling or for resuming the preempted @@ -994,7 +999,7 @@ TSP by returning ``SMC_UNK`` error. -------------- -*Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.* +*Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.* .. _Porting Guide: ./porting-guide.rst .. _SMC calling convention: http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html diff --git a/docs/user-guide.rst b/docs/user-guide.rst index ed5ba1842..8cf15b8ea 100644 --- a/docs/user-guide.rst +++ b/docs/user-guide.rst @@ -617,6 +617,9 @@ Common build options interrupts to TSP allowing it to save its context and hand over synchronously to EL3 via an SMC. + Note: when ``EL3_EXCEPTION_HANDLING`` is ``1``, ``TSP_NS_INTR_ASYNC_PREEMPT`` + must also be set to ``1``. + - ``USE_COHERENT_MEM``: This flag determines whether to include the coherent memory region in the BL memory map or not (see "Use of Coherent memory in Trusted Firmware" section in `Firmware Design`_). It can take the value 1 @@ -1867,7 +1870,7 @@ wakeup interrupt from RTC. -------------- -*Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.* +*Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.* .. _Linaro: `Linaro Release Notes`_ .. _Linaro Release: `Linaro Release Notes`_ diff --git a/include/bl31/interrupt_mgmt.h b/include/bl31/interrupt_mgmt.h index cccad3add..d41edd099 100644 --- a/include/bl31/interrupt_mgmt.h +++ b/include/bl31/interrupt_mgmt.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -80,9 +80,19 @@ ((x) == INTR_NS_VALID_RM1 ? 0 :\ -EINVAL)) +#if EL3_EXCEPTION_HANDLING +/* + * With EL3 exception handling, EL3 interrupts are always routed to EL3 from + * both Secure and Non-secure, and therefore INTR_EL3_VALID_RM1 is the only + * valid routing model. + */ +#define validate_el3_interrupt_rm(x) ((x) == INTR_EL3_VALID_RM1 ? 0 : \ + -EINVAL) +#else #define validate_el3_interrupt_rm(x) ((x) == INTR_EL3_VALID_RM0 ? 0 : \ ((x) == INTR_EL3_VALID_RM1 ? 0 :\ -EINVAL)) +#endif /******************************************************************************* * Macros to set the 'flags' parameter passed to an interrupt type handler. Only diff --git a/services/spd/tspd/tspd.mk b/services/spd/tspd/tspd.mk index 223e418e2..0747e15f6 100644 --- a/services/spd/tspd/tspd.mk +++ b/services/spd/tspd/tspd.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -43,5 +43,11 @@ $(warning "TSPD_ROUTE_IRQ_TO_EL3 is deprecated. Please use the new build flag TS TSP_NS_INTR_ASYNC_PREEMPT := ${TSPD_ROUTE_IRQ_TO_EL3} endif +ifeq ($(EL3_EXCEPTION_HANDLING),1) +ifeq ($(TSP_NS_INTR_ASYNC_PREEMPT),0) +$(error When EL3_EXCEPTION_HANDLING=1, TSP_NS_INTR_ASYNC_PREEMPT must also be 1) +endif +endif + $(eval $(call assert_boolean,TSP_NS_INTR_ASYNC_PREEMPT)) $(eval $(call add_define,TSP_NS_INTR_ASYNC_PREEMPT)) diff --git a/services/spd/tspd/tspd_main.c b/services/spd/tspd/tspd_main.c index 2ba9f84c0..c564f8b86 100644 --- a/services/spd/tspd/tspd_main.c +++ b/services/spd/tspd/tspd_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -540,6 +541,18 @@ uint64_t tspd_smc_handler(uint32_t smc_fid, */ enable_intr_rm_local(INTR_TYPE_NS, SECURE); #endif + +#if EL3_EXCEPTION_HANDLING + /* + * With EL3 exception handling, while an SMC is + * being processed, Non-secure interrupts can't + * preempt Secure execution. However, for + * yielding SMCs, we want preemption to happen; + * so explicitly allow NS preemption in this + * case. + */ + ehf_allow_ns_preemption(); +#endif } cm_el1_sysregs_context_restore(SECURE); @@ -646,7 +659,13 @@ uint64_t tspd_smc_handler(uint32_t smc_fid, enable_intr_rm_local(INTR_TYPE_NS, SECURE); #endif - +#if EL3_EXCEPTION_HANDLING + /* + * Allow the resumed yielding SMC processing to be preempted by + * Non-secure interrupts. + */ + ehf_allow_ns_preemption(); +#endif /* We just need to return to the preempted point in * TSP and the execution will resume as normal.