Rework the crash reporting in BL3-1 to use less stack

This patch reworks the crash reporting mechanism to further
optimise the stack and code size. The reporting makes use
of assembly console functions to avoid calling C Runtime
to report the CPU state. The crash buffer requirement is
reduced to 64 bytes with this implementation. The crash
buffer is now part of per-cpu data which makes retrieving
the crash buffer trivial.

Also now panic() will use crash reporting if
invoked from BL3-1.

Fixes ARM-software/tf-issues#199

Change-Id: I79d27a4524583d723483165dc40801f45e627da5
diff --git a/bl31/aarch64/bl31_entrypoint.S b/bl31/aarch64/bl31_entrypoint.S
index 6e48e31..e2141f7 100644
--- a/bl31/aarch64/bl31_entrypoint.S
+++ b/bl31/aarch64/bl31_entrypoint.S
@@ -72,13 +72,22 @@
 	isb
 
 	/* ---------------------------------------------
-	 * Set the exception vector and zero tpidr_el3
-	 * until the crash reporting is set up
+	 * Initialise cpu_data early to enable crash
+	 * reporting to have access to crash stack.
+	 * Since crash reporting depends on cpu_data to
+	 * report the unhandled exception, not
+	 * doing so can lead to recursive exceptions due
+	 * to a NULL TPIDR_EL3
+	 * ---------------------------------------------
+	 */
+	bl	init_cpu_data_ptr
+
+	/* ---------------------------------------------
+	 * Set the exception vector.
 	 * ---------------------------------------------
 	 */
 	adr	x1, runtime_exceptions
 	msr	vbar_el3, x1
-	msr	tpidr_el3, xzr
 
 	/* ---------------------------------------------------------------------
 	 * The initial state of the Architectural feature trap register
@@ -137,15 +146,6 @@
 	bl	zeromem16
 
 	/* ---------------------------------------------
-	 * Initialise cpu_data and crash reporting
-	 * ---------------------------------------------
-	 */
-#if CRASH_REPORTING
-	bl	init_crash_reporting
-#endif
-	bl	init_cpu_data_ptr
-
-	/* ---------------------------------------------
 	 * Use SP_EL0 for the C runtime stack.
 	 * ---------------------------------------------
 	 */
diff --git a/bl31/aarch64/crash_reporting.S b/bl31/aarch64/crash_reporting.S
index 1118e96..4570514 100644
--- a/bl31/aarch64/crash_reporting.S
+++ b/bl31/aarch64/crash_reporting.S
@@ -34,11 +34,13 @@
 #include <plat_macros.S>
 #include <platform_def.h>
 
-	.globl	dump_state_and_die
-	.globl	dump_intr_state_and_die
-	.globl  init_crash_reporting
+	.globl	report_unhandled_exception
+	.globl	report_unhandled_interrupt
+	.globl	el3_panic
 
 #if CRASH_REPORTING
+#define REG_SIZE	0x8
+
 	/* ------------------------------------------------------
 	 * The below section deals with dumping the system state
 	 * when an unhandled exception is taken in EL3.
@@ -46,267 +48,304 @@
 	 * be dumped during a unhandled exception is given below.
 	 * ------------------------------------------------------
 	 */
-.section .rodata.dump_reg_name, "aS"
-caller_saved_regs:	.asciz	"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",\
-	 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16",\
-	 "x17", "x18", ""
+.section .rodata.crash_prints, "aS"
+print_spacer:
+	.asciz	" =\t\t0x"
 
-callee_saved_regs: .asciz	"x19", "x20", "x21", "x22", "x23", "x24",\
-	 "x25", "x26", "x27", "x28", "x29", "x30", ""
+gp_regs:
+	.asciz	"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",\
+		"x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",\
+		"x16", "x17", "x18", "x19", "x20", "x21", "x22",\
+		"x23", "x24", "x25", "x26", "x27", "x28", "x29", ""
+el3_sys_regs:
+	.asciz	"scr_el3", "sctlr_el3", "cptr_el3", "tcr_el3",\
+		"daif", "mair_el3", "spsr_el3", "elr_el3", "ttbr0_el3",\
+		"esr_el3", "far_el3", ""
 
-el3_sys_regs: .asciz	"scr_el3", "sctlr_el3", "cptr_el3", "tcr_el3",\
-	 "daif", "mair_el3", "spsr_el3", "elr_el3", "ttbr0_el3", "esr_el3",\
-	 "sp_el3", "far_el3", ""
+non_el3_sys_regs:
+	.asciz	"spsr_el1", "elr_el1", "spsr_abt", "spsr_und",\
+		"spsr_irq", "spsr_fiq", "sctlr_el1", "actlr_el1", "cpacr_el1",\
+		"csselr_el1", "sp_el1", "esr_el1", "ttbr0_el1", "ttbr1_el1",\
+		"mair_el1", "amair_el1", "tcr_el1", "tpidr_el1", "tpidr_el0",\
+		"tpidrro_el0", "dacr32_el2", "ifsr32_el2", "par_el1",\
+		"mpidr_el1", "afsr0_el1", "afsr1_el1", "contextidr_el1",\
+		"vbar_el1", "cntp_ctl_el0", "cntp_cval_el0", "cntv_ctl_el0",\
+		"cntv_cval_el0", "cntkctl_el1", "fpexc32_el2", "sp_el0", ""
 
-non_el3_sys_0_regs: .asciz "spsr_el1", "elr_el1", "spsr_abt", "spsr_und",\
-	"spsr_irq", "spsr_fiq", "sctlr_el1", "actlr_el1", "cpacr_el1",\
-	"csselr_el1", "sp_el1", "esr_el1", "ttbr0_el1", "ttbr1_el1",\
-	"mair_el1", "amair_el1", "tcr_el1", "tpidr_el1", ""
+panic_msg:
+	.asciz "PANIC in EL3 at x30 = 0x"
+excpt_msg:
+	.asciz "Unhandled Exception in EL3.\nx30 =\t\t0x"
+intr_excpt_msg:
+	.asciz "Unhandled Interrupt Exception in EL3.\nx30 =\t\t0x"
 
-non_el3_sys_1_regs: .asciz "tpidr_el0", "tpidrro_el0", "dacr32_el2",\
-	"ifsr32_el2", "par_el1", "far_el1", "afsr0_el1", "afsr1_el1",\
-	"contextidr_el1", "vbar_el1", "cntp_ctl_el0", "cntp_cval_el0",\
-	"cntv_ctl_el0", "cntv_cval_el0", "cntkctl_el1", "fpexc32_el2",\
-	"sp_el0", ""
+	/*
+	 * Helper function to print newline to console.
+	 */
+func print_newline
+	mov	x0, '\n'
+	b	plat_crash_console_putc
+
+	/*
+	 * Helper function to print from crash buf.
+	 * The print loop is controlled by the buf size and
+	 * ascii reg name list which is passed in x6. The
+	 * function returns the crash buf address in x0.
+	 * Clobbers : x0 - x7, sp
+	 */
+func size_controlled_print
+	/* Save the lr */
+	mov	sp, x30
+	/* load the crash buf address */
+	mrs	x7, tpidr_el3
+test_size_list:
+	/* Calculate x5 always as it will be clobbered by asm_print_hex */
+	mrs	x5, tpidr_el3
+	add	x5, x5, #CPU_DATA_CRASH_BUF_SIZE
+	/* Test whether we have reached end of crash buf */
+	cmp	x7, x5
+	b.eq	exit_size_print
+	ldrb	w4, [x6]
+	/* Test whether we are at end of list */
+	cbz	w4, exit_size_print
+	mov	x4, x6
+	/* asm_print_str updates x4 to point to next entry in list */
+	bl	asm_print_str
+	/* update x6 with the updated list pointer */
+	mov	x6, x4
+	adr	x4, print_spacer
+	bl	asm_print_str
+	ldr	x4, [x7], #REG_SIZE
+	bl	asm_print_hex
+	bl	print_newline
+	b	test_size_list
+exit_size_print:
+	mov	x30, sp
+	ret
+
+	/*
+	 * Helper function to store x8 - x15 registers to
+	 * the crash buf. The system registers values are
+	 * copied to x8 to x15 by the caller which are then
+	 * copied to the crash buf by this function.
+	 * x0 points to the crash buf. It then calls
+	 * size_controlled_print to print to console.
+	 * Clobbers : x0 - x7, sp
+	 */
+func str_in_crash_buf_print
+	/* restore the crash buf address in x0 */
+	mrs	x0, tpidr_el3
+	stp	x8, x9, [x0]
+	stp	x10, x11, [x0, #REG_SIZE * 2]
+	stp	x12, x13, [x0, #REG_SIZE * 4]
+	stp	x14, x15, [x0, #REG_SIZE * 6]
+	b	size_controlled_print
+
+	/* ------------------------------------------------------
+	 * This macro calculates the offset to crash buf from
+	 * cpu_data and stores it in tpidr_el3. It also saves x0
+	 * and x1 in the crash buf by using sp as a temporary
+	 * register.
+	 * ------------------------------------------------------
+	 */
+	.macro prepare_crash_buf_save_x0_x1
+	/* we can corrupt this reg to free up x0 */
+	mov	sp, x0
+	/* tpidr_el3 contains the address to cpu_data structure */
+	mrs	x0, tpidr_el3
+	/* Calculate the Crash buffer offset in cpu_data */
+	add	x0, x0, #CPU_DATA_CRASH_BUF_OFFSET
+	/* Store crash buffer address in tpidr_el3 */
+	msr	tpidr_el3, x0
+	str	x1, [x0, #REG_SIZE]
+	mov	x1, sp
+	str	x1, [x0]
+	.endm
 
 	/* -----------------------------------------------------
-	 * Currently we are stack limited. Hence make sure that
-	 * we dont try to dump more than 20 registers using the
-	 * stack.
+	 * This function allows to report a crash (if crash
+	 * reporting is enabled) when an unhandled exception
+	 * occurs. It prints the CPU state via the crash console
+	 * making use of the crash buf. This function will
+	 * not return.
 	 * -----------------------------------------------------
 	 */
+func report_unhandled_exception
+	prepare_crash_buf_save_x0_x1
+	adr	x0, excpt_msg
+	mov	sp, x0
+	/* This call will not return */
+	b	do_crash_reporting
 
-#define REG_SIZE 0x8
 
-/* The caller saved registers are X0 to X18 */
-#define CALLER_SAVED_REG_SIZE 		(20 * REG_SIZE)
-/* The caller saved registers are X19 to X30 */
-#define CALLEE_SAVED_REG_SIZE 		(12 * REG_SIZE)
-/* The EL3 sys regs*/
-#define EL3_SYS_REG_SIZE 			(12 * REG_SIZE)
-/* The non EL3 sys regs set-0 */
-#define NON_EL3_SYS_0_REG_SIZE 		(18 * REG_SIZE)
-/* The non EL3 sys regs set-1 */
-#define NON_EL3_SYS_1_REG_SIZE 		(18 * REG_SIZE)
+	/* -----------------------------------------------------
+	 * This function allows to report a crash (if crash
+	 * reporting is enabled) when an unhandled interrupt
+	 * occurs. It prints the CPU state via the crash console
+	 * making use of the crash buf. This function will
+	 * not return.
+	 * -----------------------------------------------------
+	 */
+func report_unhandled_interrupt
+	prepare_crash_buf_save_x0_x1
+	adr	x0, intr_excpt_msg
+	mov	sp, x0
+	/* This call will not return */
+	b	do_crash_reporting
 
-	.macro print_caller_saved_regs
-	sub	sp, sp, #CALLER_SAVED_REG_SIZE
-	stp	x0, x1, [sp]
-	stp	x2, x3, [sp, #(REG_SIZE * 2)]
-	stp	x4, x5, [sp, #(REG_SIZE * 4)]
-	stp	x6, x7, [sp, #(REG_SIZE * 6)]
-	stp	x8, x9, [sp, #(REG_SIZE * 8)]
-	stp	x10, x11, [sp, #(REG_SIZE * 10)]
-	stp	x12, x13, [sp, #(REG_SIZE * 12)]
-	stp	x14, x15, [sp, #(REG_SIZE * 14)]
-	stp	x16, x17, [sp, #(REG_SIZE * 16)]
-	stp	x18, xzr, [sp, #(REG_SIZE * 18)]
-	adr	x0, caller_saved_regs
-	mov	x1, sp
-	bl	print_string_value
-	add	sp, sp, #CALLER_SAVED_REG_SIZE
-	.endm
+	/* -----------------------------------------------------
+	 * This function allows to report a crash (if crash
+	 * reporting is enabled) when panic() is invoked from
+	 * C Runtime. It prints the CPU state via the crash
+	 * console making use of the crash buf. This function
+	 * will not return.
+	 * -----------------------------------------------------
+	 */
+func el3_panic
+	msr	spsel, #1
+	prepare_crash_buf_save_x0_x1
+	adr	x0, panic_msg
+	mov	sp, x0
+	/* This call will not return */
+	b	do_crash_reporting
 
-	.macro print_callee_saved_regs
-	sub	sp, sp, CALLEE_SAVED_REG_SIZE
-	stp	x19, x20, [sp]
-	stp	x21, x22, [sp, #(REG_SIZE * 2)]
-	stp	x23, x24, [sp, #(REG_SIZE * 4)]
-	stp	x25, x26, [sp, #(REG_SIZE * 6)]
-	stp	x27, x28, [sp, #(REG_SIZE * 8)]
-	stp	x29, x30, [sp, #(REG_SIZE * 10)]
-	adr	x0, callee_saved_regs
-	mov	x1, sp
-	bl	print_string_value
-	add	sp, sp, #CALLEE_SAVED_REG_SIZE
-	.endm
+	/* ------------------------------------------------------------
+	 * The common crash reporting functionality. It requires x0
+	 * and x1 has already been stored in crash buf, sp points to
+	 * crash message and tpidr_el3 contains the crash buf address.
+	 * The function does the following:
+	 *   - Retrieve the crash buffer from tpidr_el3
+	 *   - Store x2 to x6 in the crash buffer
+	 *   - Initialise the crash console.
+	 *   - Print the crash message by using the address in sp.
+	 *   - Print x30 value to the crash console.
+	 *   - Print x0 - x7 from the crash buf to the crash console.
+	 *   - Print x8 - x29 (in groups of 8 registers) using the
+	 *     crash buf to the crash console.
+	 *   - Print el3 sys regs (in groups of 8 registers) using the
+	 *     crash buf to the crash console.
+	 *   - Print non el3 sys regs (in groups of 8 registers) using
+	 *     the crash buf to the crash console.
+	 * ------------------------------------------------------------
+	 */
+func do_crash_reporting
+	/* Retrieve the crash buf from tpidr_el3 */
+	mrs	x0, tpidr_el3
+	/* Store x2 - x6, x30 in the crash buffer */
+	stp	x2, x3, [x0, #REG_SIZE * 2]
+	stp	x4, x5, [x0, #REG_SIZE * 4]
+	stp	x6, x30, [x0, #REG_SIZE * 6]
+	/* Initialize the crash console */
+	bl	plat_crash_console_init
+	/* Verify the console is initialized */
+	cbz	x0, crash_panic
+	/* Print the crash message. sp points to the crash message */
+	mov	x4, sp
+	bl	asm_print_str
+	/* load the crash buf address */
+	mrs	x0, tpidr_el3
+	/* report x30 first from the crash buf */
+	ldr	x4, [x0, #REG_SIZE * 7]
+	bl	asm_print_hex
+	bl	print_newline
+	/* Load the crash buf address */
+	mrs	x0, tpidr_el3
+	/* Now mov x7 into crash buf */
+	str	x7, [x0, #REG_SIZE * 7]
 
-	.macro print_el3_sys_regs
-	sub	sp, sp, #EL3_SYS_REG_SIZE
-	mrs	x9, scr_el3
-	mrs	x10, sctlr_el3
-	mrs	x11, cptr_el3
-	mrs	x12, tcr_el3
-	mrs	x13, daif
-	mrs	x14, mair_el3
-	mrs	x15, spsr_el3 /*save the elr and spsr regs seperately*/
-	mrs	x16, elr_el3
-	mrs	x17, ttbr0_el3
-	mrs	x8, esr_el3
-	mrs	x7, far_el3
+	/* Report x0 - x29 values stored in crash buf*/
+	/* Store the ascii list pointer in x6 */
+	adr	x6, gp_regs
+	/* Print x0 to x7 from the crash buf */
+	bl	size_controlled_print
+	/* Store x8 - x15 in crash buf and print */
+	bl	str_in_crash_buf_print
+	/* Load the crash buf address */
+	mrs	x0, tpidr_el3
+	/* Store the rest of gp regs and print */
+	stp	x16, x17, [x0]
+	stp	x18, x19, [x0, #REG_SIZE * 2]
+	stp	x20, x21, [x0, #REG_SIZE * 4]
+	stp	x22, x23, [x0, #REG_SIZE * 6]
+	bl	size_controlled_print
+	/* Load the crash buf address */
+	mrs	x0, tpidr_el3
+	stp	x24, x25, [x0]
+	stp	x26, x27, [x0, #REG_SIZE * 2]
+	stp	x28, x29, [x0, #REG_SIZE * 4]
+	bl	size_controlled_print
 
-	stp	x9, x10, [sp]
-	stp	x11, x12, [sp, #(REG_SIZE * 2)]
-	stp	x13, x14, [sp, #(REG_SIZE * 4)]
-	stp	x15, x16, [sp, #(REG_SIZE * 6)]
-	stp	x17, x8, [sp, #(REG_SIZE * 8)]
-	stp	x0, x7, [sp, #(REG_SIZE * 10)] /* sp_el3 is in x0 */
+	/* Print the el3 sys registers */
+	adr	x6, el3_sys_regs
+	mrs	x8, scr_el3
+	mrs	x9, sctlr_el3
+	mrs	x10, cptr_el3
+	mrs	x11, tcr_el3
+	mrs	x12, daif
+	mrs	x13, mair_el3
+	mrs	x14, spsr_el3
+	mrs	x15, elr_el3
+	bl	str_in_crash_buf_print
+	mrs	x8, ttbr0_el3
+	mrs	x9, esr_el3
+	mrs	x10, far_el3
+	bl	str_in_crash_buf_print
 
-	adr	x0, el3_sys_regs
-	mov	x1, sp
-	bl	print_string_value
-	add	sp, sp, #EL3_SYS_REG_SIZE
-	.endm
-
-	.macro print_non_el3_sys_0_regs
-	sub	sp, sp, #NON_EL3_SYS_0_REG_SIZE
-	mrs	x9, spsr_el1
-	mrs	x10, elr_el1
-	mrs	x11, spsr_abt
-	mrs	x12, spsr_und
-	mrs	x13, spsr_irq
-	mrs	x14, spsr_fiq
-	mrs	x15, sctlr_el1
-	mrs	x16, actlr_el1
-	mrs	x17, cpacr_el1
-	mrs	x8, csselr_el1
-
-	stp	x9, x10, [sp]
-	stp	x11, x12, [sp, #(REG_SIZE * 2)]
-	stp	x13, x14, [sp, #(REG_SIZE * 4)]
-	stp	x15, x16, [sp, #(REG_SIZE * 6)]
-	stp	x17, x8, [sp, #(REG_SIZE * 8)]
-
+	/* Print the non el3 sys registers */
+	adr	x6, non_el3_sys_regs
+	mrs	x8, spsr_el1
+	mrs	x9, elr_el1
+	mrs	x10, spsr_abt
+	mrs	x11, spsr_und
+	mrs	x12, spsr_irq
+	mrs	x13, spsr_fiq
+	mrs	x14, sctlr_el1
+	mrs	x15, actlr_el1
+	bl	str_in_crash_buf_print
+	mrs	x8, cpacr_el1
+	mrs	x9, csselr_el1
 	mrs	x10, sp_el1
 	mrs	x11, esr_el1
 	mrs	x12, ttbr0_el1
 	mrs	x13, ttbr1_el1
 	mrs	x14, mair_el1
 	mrs	x15, amair_el1
-	mrs	x16, tcr_el1
-	mrs	x17, tpidr_el1
+	bl	str_in_crash_buf_print
+	mrs	x8, tcr_el1
+	mrs	x9, tpidr_el1
+	mrs	x10, tpidr_el0
+	mrs	x11, tpidrro_el0
+	mrs	x12, dacr32_el2
+	mrs	x13, ifsr32_el2
+	mrs	x14, par_el1
+	mrs	x15, mpidr_el1
+	bl	str_in_crash_buf_print
+	mrs	x8, afsr0_el1
+	mrs	x9, afsr1_el1
+	mrs	x10, contextidr_el1
+	mrs	x11, vbar_el1
+	mrs	x12, cntp_ctl_el0
+	mrs	x13, cntp_cval_el0
+	mrs	x14, cntv_ctl_el0
+	mrs	x15, cntv_cval_el0
+	bl	str_in_crash_buf_print
+	mrs	x8, cntkctl_el1
+	mrs	x9, fpexc32_el2
+	mrs	x10, sp_el0
+	bl	str_in_crash_buf_print
 
-	stp	x10, x11, [sp, #(REG_SIZE * 10)]
-	stp	x12, x13, [sp, #(REG_SIZE * 12)]
-	stp	x14, x15, [sp, #(REG_SIZE * 14)]
-	stp	x16, x17, [sp, #(REG_SIZE * 16)]
+	/* Print the gic registers */
+	plat_print_gic_regs
 
-	adr	x0, non_el3_sys_0_regs
-	mov	x1, sp
-	bl	print_string_value
-	add	sp, sp, #NON_EL3_SYS_0_REG_SIZE
-	.endm
+	/* Done reporting */
+	b	crash_panic
 
-	.macro print_non_el3_sys_1_regs
-	sub	sp, sp, #NON_EL3_SYS_1_REG_SIZE
-
-	mrs	x9, tpidr_el0
-	mrs	x10, tpidrro_el0
-	mrs	x11, dacr32_el2
-	mrs	x12, ifsr32_el2
-	mrs	x13, par_el1
-	mrs	x14, far_el1
-	mrs	x15, afsr0_el1
-	mrs	x16, afsr1_el1
-	mrs	x17, contextidr_el1
-	mrs	x8, vbar_el1
-
-	stp	x9, x10, [sp]
-	stp	x11, x12, [sp, #(REG_SIZE * 2)]
-	stp	x13, x14, [sp, #(REG_SIZE * 4)]
-	stp	x15, x16, [sp, #(REG_SIZE * 6)]
-	stp	x17, x8, [sp, #(REG_SIZE * 8)]
-
-	mrs	x10, cntp_ctl_el0
-	mrs	x11, cntp_cval_el0
-	mrs	x12, cntv_ctl_el0
-	mrs	x13, cntv_cval_el0
-	mrs	x14, cntkctl_el1
-	mrs	x15, fpexc32_el2
-	mrs	x8, sp_el0
-
-	stp	x10, x11, [sp, #(REG_SIZE *10)]
-	stp	x12, x13, [sp, #(REG_SIZE * 12)]
-	stp	x14, x15, [sp, #(REG_SIZE * 14)]
-	stp	x8, xzr, [sp, #(REG_SIZE * 16)]
-
-	adr	x0, non_el3_sys_1_regs
-	mov	x1, sp
-	bl	print_string_value
-	add	sp, sp, #NON_EL3_SYS_1_REG_SIZE
-	.endm
-
-	.macro init_crash_stack
-	msr	cntfrq_el0, x0 /* we can corrupt this reg to free up x0 */
-	mrs	x0, tpidr_el3
-
-	/* Check if tpidr is initialized */
-	cbz	x0, infinite_loop
-
-	ldr	x0, [x0, #CPU_DATA_CRASH_STACK_OFFSET]
-	/* store the x30 and sp to stack */
-	str	x30, [x0, #-(REG_SIZE)]!
-	mov	x30, sp
-	str	x30, [x0, #-(REG_SIZE)]!
-	mov	sp, x0
-	mrs	x0, cntfrq_el0
-	.endm
-
-	/* ---------------------------------------------------
-	 * The below function initializes the crash dump stack ,
-	 * and prints the system state. This function
-	 * will not return.
-	 * ---------------------------------------------------
-	 */
-func dump_state_and_die
-	init_crash_stack
-	print_caller_saved_regs
-	b	print_state
-
-func dump_intr_state_and_die
-	init_crash_stack
-	print_caller_saved_regs
-	plat_print_gic_regs /* fall through to print_state */
-
-print_state:
-	/* copy the original x30 from stack */
-	ldr	x30, [sp, #REG_SIZE]
-	print_callee_saved_regs
-	/* copy the original SP_EL3 from stack to x0 and rewind stack */
-	ldr x0, [sp], #(REG_SIZE * 2)
-	print_el3_sys_regs
-	print_non_el3_sys_0_regs
-	print_non_el3_sys_1_regs
-
-#else	/* CRASH_REPORING */
-
-func dump_state_and_die
-dump_intr_state_and_die:
-
+#else	/* CRASH_REPORTING */
+func report_unhandled_exception
+report_unhandled_interrupt:
+	b	crash_panic
 #endif	/* CRASH_REPORING */
 
-infinite_loop:
-	b	infinite_loop
 
-
-#define PCPU_CRASH_STACK_SIZE	0x140
-
-	/* -----------------------------------------------------
-	 * Per-cpu crash stacks in normal memory.
-	 * -----------------------------------------------------
-	 */
-declare_stack pcpu_crash_stack, tzfw_normal_stacks, \
-		PCPU_CRASH_STACK_SIZE, PLATFORM_CORE_COUNT
-
-	/* -----------------------------------------------------
-	 * Provides each CPU with a small stacks for reporting
-	 * unhandled exceptions, and stores the stack address
-	 * in cpu_data
-	 *
-	 * This can be called without a runtime stack
-	 * clobbers: x0 - x4
-	 * -----------------------------------------------------
-	 */
-func init_crash_reporting
-	mov	x4, x30
-	mov	x2, #0
-	adr	x3, pcpu_crash_stack
-init_crash_loop:
-	mov	x0, x2
-	bl	_cpu_data_by_index
-	add	x3, x3, #PCPU_CRASH_STACK_SIZE
-	str	x3, [x0, #CPU_DATA_CRASH_STACK_OFFSET]
-	add	x2, x2, #1
-	cmp	x2, #PLATFORM_CORE_COUNT
-	b.lo	init_crash_loop
-	ret	x4
+func crash_panic
+	b	crash_panic
diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S
index a11cd71..2d56ea3 100644
--- a/bl31/aarch64/runtime_exceptions.S
+++ b/bl31/aarch64/runtime_exceptions.S
@@ -60,7 +60,7 @@
 	 * -----------------------------------------------------
 	 */
 
-	bl	dump_state_and_die
+	bl	report_unhandled_exception
 	.endm
 
 
@@ -142,7 +142,7 @@
 	 * where the interrupt was generated.
 	 */
 interrupt_error_\label:
-	bl	dump_intr_state_and_die
+	bl	report_unhandled_interrupt
 	.endm
 
 
@@ -158,7 +158,6 @@
 	.endm
 
 	.section	.vectors, "ax"; .align 11
-
 	.align	7
 runtime_exceptions:
 	/* -----------------------------------------------------
@@ -170,7 +169,7 @@
 	 * We don't expect any synchronous exceptions from EL3
 	 * -----------------------------------------------------
 	 */
-	bl	dump_state_and_die
+	bl	report_unhandled_exception
 	check_vector_size sync_exception_sp_el0
 
 	.align	7
@@ -180,17 +179,17 @@
 	 * -----------------------------------------------------
 	 */
 irq_sp_el0:
-	bl	dump_intr_state_and_die
+	bl	report_unhandled_interrupt
 	check_vector_size irq_sp_el0
 
 	.align	7
 fiq_sp_el0:
-	bl	dump_intr_state_and_die
+	bl	report_unhandled_interrupt
 	check_vector_size fiq_sp_el0
 
 	.align	7
 serror_sp_el0:
-	bl	dump_state_and_die
+	bl	report_unhandled_exception
 	check_vector_size serror_sp_el0
 
 	/* -----------------------------------------------------
@@ -206,22 +205,22 @@
 	 * There is a high probability that SP_EL3 is corrupted.
 	 * -----------------------------------------------------
 	 */
-	bl	dump_state_and_die
+	bl	report_unhandled_exception
 	check_vector_size sync_exception_sp_elx
 
 	.align	7
 irq_sp_elx:
-	bl	dump_intr_state_and_die
+	bl	report_unhandled_interrupt
 	check_vector_size irq_sp_elx
 
 	.align	7
 fiq_sp_elx:
-	bl	dump_intr_state_and_die
+	bl	report_unhandled_interrupt
 	check_vector_size fiq_sp_elx
 
 	.align	7
 serror_sp_elx:
-	bl	dump_state_and_die
+	bl	report_unhandled_exception
 	check_vector_size serror_sp_elx
 
 	/* -----------------------------------------------------
@@ -258,7 +257,7 @@
 
 	.align	7
 serror_aarch64:
-	bl	dump_state_and_die
+	bl	report_unhandled_exception
 	check_vector_size serror_aarch64
 
 	/* -----------------------------------------------------
@@ -295,7 +294,7 @@
 
 	.align	7
 serror_aarch32:
-	bl	dump_state_and_die
+	bl	report_unhandled_exception
 	check_vector_size serror_aarch32
 
 	.align	7
@@ -473,7 +472,7 @@
 
 rt_svc_fw_critical_error:
 	msr	spsel, #1 /* Switch to SP_ELx */
-	bl	dump_state_and_die
+	bl	report_unhandled_exception
 
 	/* -----------------------------------------------------
 	 * The following functions are used to saved and restore
diff --git a/bl31/cpu_data_array.c b/bl31/cpu_data_array.c
index b0042a1..4cba118 100644
--- a/bl31/cpu_data_array.c
+++ b/bl31/cpu_data_array.c
@@ -32,13 +32,5 @@
 #include <cpu_data.h>
 #include <platform_def.h>
 
-/* verify assembler offsets match data structures */
-CASSERT(CPU_DATA_CRASH_STACK_OFFSET == __builtin_offsetof
-	(cpu_data_t, crash_stack),
-	assert_cpu_data_crash_stack_offset_mismatch);
-
-CASSERT((1 << CPU_DATA_LOG2SIZE) == sizeof(cpu_data_t),
-	assert_cpu_data_log2size_mismatch);
-
 /* The per_cpu_ptr_cache_t space allocation */
 cpu_data_t percpu_data[PLATFORM_CORE_COUNT];