RAS: Introduce handler for Double Faults

Double fault is when the PE receives another error whilst one is being
handled. To detect double fault condition, a per-CPU flag is introduced
to track the status of error handling. The flag is checked/modified
while temporarily masking external aborts on the PE.

This patch routes double faults to a separate platform-defined handler.

Change-Id: I70e9b7ba4c817273c55a0af978d9755ff32cc702
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
diff --git a/bl31/aarch64/ea_delegate.S b/bl31/aarch64/ea_delegate.S
index 9faa503..9d7c5e8 100644
--- a/bl31/aarch64/ea_delegate.S
+++ b/bl31/aarch64/ea_delegate.S
@@ -5,6 +5,7 @@
  */
 
 
+#include <assert_macros.S>
 #include <asm_macros.S>
 #include <assert_macros.S>
 #include <context.h>
@@ -179,6 +180,15 @@
  * x1: EA syndrome
  */
 func ea_proceed
+	/*
+	 * If the ESR loaded earlier is not zero, we were processing an EA
+	 * already, and this is a double fault.
+	 */
+	ldr	x5, [sp, #CTX_EL3STATE_OFFSET + CTX_ESR_EL3]
+	cbz	x5, 1f
+	no_ret	plat_handle_double_fault
+
+1:
 	/* Save EL3 state */
 	mrs	x2, spsr_el3
 	mrs	x3, elr_el3
@@ -216,7 +226,6 @@
 	mov	x28, sp
 #endif
 	bl	plat_ea_handler
-	mov	x30, x29
 
 #if ENABLE_ASSERTIONS
 	/*
@@ -232,7 +241,7 @@
 	/* Make SP point to context */
 	msr	spsel, #1
 
-	/* Restore EL3 state */
+	/* Restore EL3 state and ESR */
 	ldp	x1, x2, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
 	msr	spsr_el3, x1
 	msr	elr_el3, x2
@@ -242,5 +251,13 @@
 	msr	scr_el3, x3
 	msr	esr_el3, x4
 
-	ret
+#if ENABLE_ASSERTIONS
+	cmp	x4, xzr
+	ASM_ASSERT(ne)
+#endif
+
+	/* Clear ESR storage */
+	str	xzr, [sp, #CTX_EL3STATE_OFFSET + CTX_ESR_EL3]
+
+	ret	x29
 endfunc ea_proceed
diff --git a/plat/common/aarch64/platform_helpers.S b/plat/common/aarch64/platform_helpers.S
index 13dfac8..8a07f8f 100644
--- a/plat/common/aarch64/platform_helpers.S
+++ b/plat/common/aarch64/platform_helpers.S
@@ -21,6 +21,7 @@
 	.weak	bl32_plat_enable_mmu
 
 	.weak	plat_handle_uncontainable_ea
+	.weak	plat_handle_double_fault
 
 #if !ENABLE_PLAT_COMPAT
 	.globl	platform_get_core_pos
@@ -200,3 +201,14 @@
 func plat_handle_uncontainable_ea
 	b	report_unhandled_exception
 endfunc plat_handle_uncontainable_ea
+
+	/* -----------------------------------------------------
+	 * Platform handler for Double Fault.
+	 *
+	 * x0: EA reason
+	 * x1: EA syndrome
+	 * -----------------------------------------------------
+	 */
+func plat_handle_double_fault
+	b	report_unhandled_exception
+endfunc plat_handle_double_fault