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))
+