Merge pull request #1256 from jeenu-arm/tsp-ehf

TSP changes for EHF
diff --git a/Makefile b/Makefile
index 73566c0..83b8808 100644
--- a/Makefile
+++ b/Makefile
@@ -482,6 +482,7 @@
 $(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,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 940bc24..0eb7f54 100644
--- a/docs/interrupt-framework-design.rst
+++ b/docs/interrupt-framework-design.rst
@@ -135,7 +135,7 @@
    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 @@
    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 @@
 #. 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 @@
 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 @@
 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 @@
 
 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 @@
 
 --------------
 
-*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 ed5ba18..8cf15b8 100644
--- a/docs/user-guide.rst
+++ b/docs/user-guide.rst
@@ -617,6 +617,9 @@
    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 @@
 
 --------------
 
-*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 cccad3a..d41edd0 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 223e418..0747e15 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 @@
 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 2ba9f84..c564f8b 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 <bl_common.h>
 #include <context_mgmt.h>
 #include <debug.h>
+#include <ehf.h>
 #include <errno.h>
 #include <platform.h>
 #include <runtime_svc.h>
@@ -540,6 +541,18 @@
 				 */
 				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 @@
 		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.