Introduce interrupt handling framework in BL3-1

This patch adds a common handler for FIQ and IRQ exceptions in the
BL3-1 runtime exception vector table. This function determines the
interrupt type and calls its handler. A crash is reported if an
inconsistency in the interrupt management framework is detected. In
the event of a spurious interrupt, execution resumes from the
instruction where the interrupt was generated.

This patch also removes 'cm_macros.S' as its contents have been moved
to 'runtime_exceptions.S'

Change-Id: I3c85ecf8eaf43a3fac429b119ed0bd706d2e2093
diff --git a/bl31/aarch64/bl31_entrypoint.S b/bl31/aarch64/bl31_entrypoint.S
index f582e76..3c9042b 100644
--- a/bl31/aarch64/bl31_entrypoint.S
+++ b/bl31/aarch64/bl31_entrypoint.S
@@ -31,8 +31,6 @@
 #include <arch.h>
 #include <asm_macros.S>
 #include <bl_common.h>
-#include <cm_macros.S>
-
 
 	.globl	bl31_entrypoint
 
diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S
index b6dcccb..4789b33 100644
--- a/bl31/aarch64/runtime_exceptions.S
+++ b/bl31/aarch64/runtime_exceptions.S
@@ -30,14 +30,118 @@
 
 #include <arch.h>
 #include <asm_macros.S>
-#include <cm_macros.S>
 #include <context.h>
+#include <interrupt_mgmt.h>
 #include <platform.h>
 #include <runtime_svc.h>
 
 	.globl	runtime_exceptions
 	.globl	el3_exit
 
+	/* -----------------------------------------------------
+	 * Handle SMC exceptions seperately from other sync.
+	 * exceptions.
+	 * -----------------------------------------------------
+	 */
+	.macro	handle_sync_exception
+	str	x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
+	mrs	x30, esr_el3
+	ubfx	x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH
+
+	cmp	x30, #EC_AARCH32_SMC
+	b.eq	smc_handler32
+
+	cmp	x30, #EC_AARCH64_SMC
+	b.eq	smc_handler64
+
+	/* -----------------------------------------------------
+	 * The following code handles any synchronous exception
+	 * that is not an SMC.
+	 * -----------------------------------------------------
+	 */
+
+	bl	dump_state_and_die
+	.endm
+
+
+	/* -----------------------------------------------------
+	 * This macro handles FIQ or IRQ interrupts i.e. EL3,
+	 * S-EL1 and NS interrupts.
+	 * -----------------------------------------------------
+	 */
+	.macro	handle_interrupt_exception label
+	str	x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
+	bl	save_gp_registers
+
+	/* Switch to the runtime stack i.e. SP_EL0 */
+	ldr	x2, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP]
+	mov	x20, sp
+	msr	spsel, #0
+	mov	sp, x2
+
+	/*
+	 * Find out whether this is a valid interrupt type. If the
+	 * interrupt controller reports a spurious interrupt then
+	 * return to where we came from.
+	 */
+	bl	ic_get_pending_interrupt_type
+	cmp	x0, #INTR_TYPE_INVAL
+	b.eq	interrupt_exit_\label
+
+	/*
+	 * Get the registered handler for this interrupt type. A
+	 * NULL return value implies that an interrupt was generated
+	 * for which there is no handler registered or the interrupt
+	 * was routed incorrectly. This is a problem of the framework
+	 * so report it as an error.
+	 */
+	bl	get_interrupt_type_handler
+	cbz	x0, interrupt_error_\label
+	mov	x21, x0
+
+	mov	x0, #INTR_ID_UNAVAILABLE
+#if IMF_READ_INTERRUPT_ID
+	/*
+	 * Read the id of the highest priority pending interrupt. If
+	 * no interrupt is asserted then return to where we came from.
+	 */
+	bl	ic_get_pending_interrupt_id
+	cmp	x0, #INTR_ID_UNAVAILABLE
+	b.eq	interrupt_exit_\label
+#endif
+
+	/*
+	 * Save the EL3 system registers needed to return from
+	 * this exception.
+	 */
+	mrs	x3, spsr_el3
+	mrs	x4, elr_el3
+	stp	x3, x4, [x20, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
+
+	/* Set the current security state in the 'flags' parameter */
+	mrs	x2, scr_el3
+	ubfx	x1, x2, #0, #1
+
+	/* Restore the reference to the 'handle' i.e. SP_EL3 */
+	mov	x2, x20
+
+	/* Call the interrupt type handler */
+	blr	x21
+
+interrupt_exit_\label:
+	/* Return from exception, possibly in a different security state */
+	b	el3_exit
+
+	/*
+	 * This label signifies a problem with the interrupt management
+	 * framework where it is not safe to go back to the instruction
+	 * where the interrupt was generated.
+	 */
+interrupt_error_\label:
+	bl	dump_intr_state_and_die
+	.endm
+
+
 	.macro save_x18_to_x29_sp_el0
 	stp	x18, x19, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X18]
 	stp	x20, x21, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X20]
@@ -140,12 +244,12 @@
 	 * -----------------------------------------------------
 	 */
 irq_aarch64:
-	bl	dump_intr_state_and_die
+	handle_interrupt_exception irq_aarch64
 	check_vector_size irq_aarch64
 
 	.align	7
 fiq_aarch64:
-	bl	dump_intr_state_and_die
+	handle_interrupt_exception fiq_aarch64
 	check_vector_size fiq_aarch64
 
 	.align	7
@@ -177,12 +281,12 @@
 	 * -----------------------------------------------------
 	 */
 irq_aarch32:
-	bl	dump_intr_state_and_die
+	handle_interrupt_exception irq_aarch32
 	check_vector_size irq_aarch32
 
 	.align	7
 fiq_aarch32:
-	bl	dump_intr_state_and_die
+	handle_interrupt_exception fiq_aarch32
 	check_vector_size fiq_aarch32
 
 	.align	7
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index 93a60c7..8155f3d 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -51,3 +51,11 @@
 				services/std_svc/psci/psci_setup.c
 
 BL31_LINKERFILE		:=	bl31/bl31.ld.S
+
+# Flag used by the generic interrupt management framework to  determine if
+# upon the assertion of an interrupt, it should pass the interrupt id or not
+IMF_READ_INTERRUPT_ID	:=	0
+
+$(eval $(call assert_boolean,IMF_READ_INTERRUPT_ID))
+$(eval $(call add_define,IMF_READ_INTERRUPT_ID))
+
diff --git a/docs/user-guide.md b/docs/user-guide.md
index 201db38..a13d29b 100644
--- a/docs/user-guide.md
+++ b/docs/user-guide.md
@@ -161,6 +161,11 @@
     for implementing the platform GIC API. This API is used by the interrupt
     management framework. Default is 2 i.e. version 2.0
 
+*   `IMF_READ_INTERRUPT_ID`: Boolean flag used by the interrupt management
+    framework to enable passing of the interrupt id to its handler. The id is
+    read using a platform GIC API. `INTR_ID_UNAVAILABLE` is passed instead if
+    this option set to 0. Default is 0.
+
 ### Creating a Firmware Image Package
 
 FIPs are automatically created as part of the build instructions described in
diff --git a/include/bl31/cm_macros.S b/include/bl31/cm_macros.S
deleted file mode 100644
index f12f8c3..0000000
--- a/include/bl31/cm_macros.S
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include <arch.h>
-#include <context.h>
-
-	/* -----------------------------------------------------
-	 * Handle SMC exceptions seperately from other sync.
-	 * exceptions.
-	 * -----------------------------------------------------
-	 */
-	.macro	handle_sync_exception
-	str	x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
-	mrs	x30, esr_el3
-	ubfx	x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH
-
-	cmp	x30, #EC_AARCH32_SMC
-	b.eq	smc_handler32
-
-	cmp	x30, #EC_AARCH64_SMC
-	b.eq	smc_handler64
-
-	/* -----------------------------------------------------
-	 * The following code handles any synchronous exception
-	 * that is not an SMC.
-	 * -----------------------------------------------------
-	 */
-
-	bl	dump_state_and_die
-	.endm
-
diff --git a/services/std_svc/psci/psci_entry.S b/services/std_svc/psci/psci_entry.S
index 256c538..c243d27 100644
--- a/services/std_svc/psci/psci_entry.S
+++ b/services/std_svc/psci/psci_entry.S
@@ -30,7 +30,6 @@
 
 #include <arch.h>
 #include <asm_macros.S>
-#include <cm_macros.S>
 #include <psci.h>
 
 	.globl	psci_aff_on_finish_entry