Merge pull request #172 from soby-mathew/sm/asm_assert

Introduce asm assert and optimize crash reporting
diff --git a/Makefile b/Makefile
index 39496fb..fef89c2 100644
--- a/Makefile
+++ b/Makefile
@@ -60,7 +60,9 @@
 # Determine the version of ARM GIC architecture to use for interrupt management
 # in EL3. The platform port can change this value if needed.
 ARM_GIC_ARCH		:=	2
-
+# Flag used to indicate if ASM_ASSERTION should be enabled for the build.
+# This defaults to being present in DEBUG builds only.
+ASM_ASSERTION		:=	${DEBUG}
 
 # Checkpatch ignores
 CHECK_IGNORE		=	--ignore COMPLEX_MACRO
@@ -90,8 +92,8 @@
 VERSION_STRING		:=	v${VERSION_MAJOR}.${VERSION_MINOR}(${BUILD_TYPE}):${BUILD_STRING}
 
 BL_COMMON_SOURCES	:=	common/bl_common.c			\
-				common/debug.c				\
 				common/tf_printf.c			\
+				common/aarch64/debug.S			\
 				lib/aarch64/cache_helpers.S		\
 				lib/aarch64/misc_helpers.S		\
 				lib/aarch64/xlat_helpers.c		\
@@ -207,6 +209,9 @@
 # Process ARM_GIC_ARCH flag
 $(eval $(call add_define,ARM_GIC_ARCH))
 
+# Process ASM_ASSERTION flag
+$(eval $(call assert_boolean,ASM_ASSERTION))
+$(eval $(call add_define,ASM_ASSERTION))
 
 ASFLAGS			+= 	-nostdinc -ffreestanding -Wa,--fatal-warnings	\
 				-Werror -Wmissing-include-dirs			\
diff --git a/bl31/aarch64/bl31_entrypoint.S b/bl31/aarch64/bl31_entrypoint.S
index 69d2243..fb8fd2c 100644
--- a/bl31/aarch64/bl31_entrypoint.S
+++ b/bl31/aarch64/bl31_entrypoint.S
@@ -82,13 +82,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
@@ -147,15 +156,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..e69878b 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,326 @@
 	 * 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", ""
+cpu_ectlr_reg:
+	.asciz	"cpuectlr_el1 =\t\t0x"
 
-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", ""
+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", ""
 
-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", ""
+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_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", ""
+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"
 
-	/* -----------------------------------------------------
-	 * Currently we are stack limited. Hence make sure that
-	 * we dont try to dump more than 20 registers using the
-	 * stack.
-	 * -----------------------------------------------------
+	/*
+	 * Helper function to print newline to console.
 	 */
+func print_newline
+	mov	x0, '\n'
+	b	plat_crash_console_putc
 
-#define REG_SIZE 0x8
+	/*
+	 * 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
 
-/* 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)
+	/*
+	 * 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
 
-	.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
+	/* ------------------------------------------------------
+	 * 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
-	bl	print_string_value
-	add	sp, sp, #CALLER_SAVED_REG_SIZE
+	str	x1, [x0]
 	.endm
 
-	.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
+	/* -----------------------------------------------------
+	 * 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
 
-	.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
 
-	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 */
+	/* -----------------------------------------------------
+	 * 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
 
-	adr	x0, el3_sys_regs
-	mov	x1, sp
-	bl	print_string_value
-	add	sp, sp, #EL3_SYS_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_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
+	/* ------------------------------------------------------------
+	 * 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]
 
-	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)]
+	/* 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
+
+	/* 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
 
+	/* 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)]
-
-	adr	x0, non_el3_sys_0_regs
-	mov	x1, sp
-	bl	print_string_value
-	add	sp, sp, #NON_EL3_SYS_0_REG_SIZE
-	.endm
+	/* Print the CPUECTLR_EL1 reg */
+	mrs	x0, midr_el1
+	lsr	x0, x0, #MIDR_PN_SHIFT
+	and	x0, x0, #MIDR_PN_MASK
+	cmp	x0, #MIDR_PN_A57
+	b.eq	1f
+	cmp	x0, #MIDR_PN_A53
+	b.ne	2f
+1:
+	adr	x4, cpu_ectlr_reg
+	bl	asm_print_str
+	mrs	x4, CPUECTLR_EL1
+	bl	asm_print_hex
+	bl	print_newline
+2:
 
-	.macro print_non_el3_sys_1_regs
-	sub	sp, sp, #NON_EL3_SYS_1_REG_SIZE
+	/* Print the gic registers */
+	plat_print_gic_regs
 
-	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
+	/* Print the interconnect registers */
+	plat_print_interconnect_regs
 
-	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
+	/* Done reporting */
+	b	crash_panic
 
-	/* ---------------------------------------------------
-	 * 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 0ab86ab..996dedc 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];
diff --git a/common/aarch64/debug.S b/common/aarch64/debug.S
new file mode 100644
index 0000000..b7d7ac2
--- /dev/null
+++ b/common/aarch64/debug.S
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 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 <asm_macros.S>
+
+	.globl	asm_print_str
+	.globl	asm_print_hex
+	.globl	asm_assert
+	.globl	do_panic
+
+/* Since the max decimal input number is 65536 */
+#define MAX_DEC_DIVISOR		10000
+/* The offset to add to get ascii for numerals '0 - 9' */
+#define ASCII_OFFSET_NUM	0x30
+
+#if ASM_ASSERTION
+.section .rodata.assert_str, "aS"
+assert_msg1:
+	.asciz "ASSERT: File "
+assert_msg2:
+	.asciz " Line "
+
+	/*
+	 * This macro is intended to be used to print the
+	 * line number in decimal. Used by asm_assert macro.
+	 * The max number expected is 65536.
+	 * In: x4 = the decimal to print.
+	 * Clobber: x30, x0, x1, x2, x5, x6
+	 */
+	.macro asm_print_line_dec
+	mov	x6, #10		/* Divide by 10 after every loop iteration */
+	mov	x5, #MAX_DEC_DIVISOR
+1:
+	udiv	x0, x4, x5		/* Get the quotient */
+	msub	x4, x0, x5, x4		/* Find the remainder */
+	add	x0, x0, #ASCII_OFFSET_NUM		/* Convert to ascii */
+	bl	plat_crash_console_putc
+	udiv	x5, x5, x6		/* Reduce divisor */
+	cbnz	x5, 1b
+	.endm
+
+
+/* ---------------------------------------------------------------------------
+ * Assertion support in assembly.
+ * The below function helps to support assertions in assembly where we do not
+ * have a C runtime stack. Arguments to the function are :
+ * x0 - File name
+ * x1 - Line no
+ * Clobber list : x30, x0, x1, x2, x3, x4, x5, x6.
+ * ---------------------------------------------------------------------------
+ */
+func asm_assert
+	mov	x5, x0
+	mov	x6, x1
+	/* Ensure the console is initialized */
+	bl	plat_crash_console_init
+	/* Check if the console is initialized */
+	cbz	x0, _assert_loop
+	/* The console is initialized */
+	adr	x4, assert_msg1
+	bl	asm_print_str
+	mov	x4, x5
+	bl	asm_print_str
+	adr	x4, assert_msg2
+	bl	asm_print_str
+	/* Check if line number higher than max permitted */
+	tst	x6, #~0xffff
+	b.ne	_assert_loop
+	mov	x4, x6
+	asm_print_line_dec
+_assert_loop:
+	b	_assert_loop
+#endif
+
+/*
+ * This function prints a string from address in x4.
+ * In: x4 = pointer to string.
+ * Clobber: x30, x0, x1, x2, x3
+ */
+func asm_print_str
+	mov	x3, x30
+1:
+	ldrb	w0, [x4], #0x1
+	cbz	x0, 2f
+	bl	plat_crash_console_putc
+	b	1b
+2:
+	ret	x3
+
+/*
+ * This function prints a hexadecimal number in x4.
+ * In: x4 = the hexadecimal to print.
+ * Clobber: x30, x0, x5, x1, x2, x3
+ */
+func asm_print_hex
+	mov	x3, x30
+	mov	x5, #64  /* No of bits to convert to ascii */
+1:
+	sub	x5, x5, #4
+	lsrv	x0, x4, x5
+	and	x0, x0, #0xf
+	cmp	x0, #0xA
+	b.lo	2f
+	/* Add by 0x27 in addition to ASCII_OFFSET_NUM
+	 * to get ascii for characters 'a - f'.
+	 */
+	add	x0, x0, #0x27
+2:
+	add	x0, x0, #ASCII_OFFSET_NUM
+	bl	plat_crash_console_putc
+	cbnz	x5, 1b
+	ret	x3
+
+	/***********************************************************
+	 * The common implementation of do_panic for all BL stages
+	 ***********************************************************/
+
+.section .rodata.panic_str, "aS"
+	panic_msg: .asciz "PANIC at PC : 0x"
+
+/* ---------------------------------------------------------------------------
+ * do_panic assumes that it is invoked from a C Runtime Environment ie a
+ * valid stack exists. This call will not return.
+ * Clobber list : if CRASH_REPORTING is not enabled then x30, x0 - x6
+ * ---------------------------------------------------------------------------
+ */
+
+/* This is for the non el3 BL stages to compile through */
+	.weak el3_panic
+
+func do_panic
+#if CRASH_REPORTING
+	str	x0, [sp, #-0x10]!
+	mrs	x0, currentel
+	ubfx	x0, x0, #2, #2
+	cmp	x0, #0x3
+	ldr	x0, [sp], #0x10
+	b.eq	el3_panic
+#endif
+
+panic_common:
+/*
+ * el3_panic will be redefined by the BL31
+ * crash reporting mechanism (if enabled)
+ */
+el3_panic:
+	mov	x6, x30
+	bl	plat_crash_console_init
+	/* Check if the console is initialized */
+	cbz	x0, _panic_loop
+	/* The console is initialized */
+	adr	x4, panic_msg
+	bl	asm_print_str
+	mov	x4, x6
+	/* The panic location is lr -4 */
+	sub	x4, x4, #4
+	bl	asm_print_hex
+_panic_loop:
+	b	_panic_loop
+
diff --git a/common/debug.c b/common/debug.c
deleted file mode 100644
index be54f5d..0000000
--- a/common/debug.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 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 <console.h>
-#include <debug.h>
-#include <stdarg.h>
-#include <stdio.h>
-
-/******************************************************************
-* This function is invoked from assembler error handling routines and
-* prints out the string and the value in 64 bit hex format. These
-* are passed to the function as input parameters.
-********************************************************************/
-void print_string_value(char *s, unsigned long *mem)
-{
-	unsigned char i, temp;
-	unsigned long val;
-
-	while (*s) {
-		i = 16;
-		while (*s)
-			console_putc(*s++);
-
-		s++;
-
-		console_putc('\t');
-		console_putc(':');
-		console_putc('0');
-		console_putc('x');
-
-		val = *mem++;
-
-		while (i--) {
-			temp = (val >> (i << 2)) & 0xf;
-			if (temp <  0xa)
-				console_putc('0' + temp);
-			else
-				console_putc('A' + (temp - 0xa));
-		}
-		console_putc('\n');
-	}
-}
-
-/***********************************************************
- * The common implementation of do_panic for all BL stages
- ***********************************************************/
-
-#if DEBUG
-void __dead2 do_panic(const char *file, int line)
-{
-		tf_printf("PANIC in file: %s line: %d\n", file, line);
-		while (1)
-			;
-}
-#else
-void __dead2 do_panic(void)
-{
-	unsigned long pc_reg;
-	__asm__ volatile("mov %0, x30\n"
-					: "=r" (pc_reg) : );
-
-	/* x30 reports the next eligible instruction whereas we want the
-	 * place where panic() is invoked. Hence decrement by 4.
-	 */
-	tf_printf("PANIC in PC location 0x%016X\n", pc_reg - 0x4);
-	while (1)
-		;
-
-}
-#endif
diff --git a/docs/porting-guide.md b/docs/porting-guide.md
index 2bd1b56..c711590 100644
--- a/docs/porting-guide.md
+++ b/docs/porting-guide.md
@@ -15,6 +15,7 @@
     *   Boot Loader stage 3-1 (BL3-1)
     *   PSCI implementation (in BL3-1)
     *   Interrupt Management framework (in BL3-1)
+    *   Crash Reporting mechanism (in BL3-1)
 4.  C Library
 5.  Storage abstraction layer
 
@@ -268,10 +269,18 @@
 *   **Macro : plat_print_gic_regs**
 
     This macro allows the crash reporting routine to print GIC registers
-    in case of an unhandled IRQ or FIQ in BL3-1. This aids in debugging and
+    in case of an unhandled exception in BL3-1. This aids in debugging and
     this macro can be defined to be empty in case GIC register reporting is
     not desired.
 
+*   **Macro : plat_print_interconnect_regs**
+
+    This macro allows the crash reporting routine to print interconnect registers
+    in case of an unhandled exception in BL3-1. This aids in debugging and
+    this macro can be defined to be empty in case interconnect register reporting
+    is not desired. In the ARM FVP port, the CCI snoop control registers are
+    reported.
+
 ### Other mandatory modifications
 
 The following mandatory modifications may be implemented in any file
@@ -1265,6 +1274,41 @@
 interrupt id from the relevant _Interrupt Group Register_ (`GICD_IGROUPRn`). It
 uses the group value to determine the type of interrupt.
 
+3.5  Crash Reporting mechanism (in BL3-1)
+----------------------------------------------
+BL3-1 implements a crash reporting mechanism which prints the various registers
+of the CPU to enable quick crash analysis and debugging. It requires that a console
+is designated as the crash console by the platform which will used to print the
+register dump.
+
+The following functions must be implemented by the platform if it wants crash reporting
+mechanism in BL3-1. The functions are implemented in assembly so that they can be
+invoked without a C Runtime stack.
+
+### Function : plat_crash_console_init
+
+    Argument : void
+    Return   : int
+
+This API is used by the crash reporting mechanism to intialize the crash console.
+It should only use the general purpose registers x0 to x2 to do the initiaization
+and returns 1 on success.
+
+The FVP port designates the PL011_UART0 as the crash console and calls the
+console_core_init() to initialize the console.
+
+### Function : plat_crash_console_putc
+
+    Argument : int
+    Return   : int
+
+This API is used by the crash reporting mechanism to print a character on the
+designated crash console. It should only use general purpose registers x1 and
+x2 to do its work. The parameter and the return value are in general purpose
+register x0.
+
+The FVP port designates the PL011_UART0 as the crash console and calls the
+console_core_putc() to print the character on the console.
 
 4.  C Library
 -------------
diff --git a/docs/user-guide.md b/docs/user-guide.md
index a4d7f46..41e7606 100644
--- a/docs/user-guide.md
+++ b/docs/user-guide.md
@@ -181,6 +181,11 @@
     BL3-1. This option defaults to the value of `DEBUG` - i.e. by default
     this is only enabled for a debug build of the firmware.
 
+*   `ASM_ASSERTION`: This flag determines whether the assertion checks within
+    assembly source files are enabled or not. This option defaults to the
+    value of `DEBUG` - i.e. by default this is only enabled for a debug
+    build of the firmware.
+
 ### Creating a Firmware Image Package
 
 FIPs are automatically created as part of the build instructions described in
diff --git a/drivers/arm/pl011/pl011_console.S b/drivers/arm/pl011/pl011_console.S
new file mode 100644
index 0000000..5ff1582
--- /dev/null
+++ b/drivers/arm/pl011/pl011_console.S
@@ -0,0 +1,178 @@
+/*
+ * 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 <asm_macros.S>
+#include <pl011.h>
+
+	.globl	console_init
+	.globl	console_putc
+	.globl	console_core_init
+	.globl	console_core_putc
+	.globl	console_getc
+
+	/*
+	 *  The console base is in the data section and not in .bss
+	 *  even though it is zero-init. In particular, this allows
+	 *  the console functions to start using this variable before
+	 *  the runtime memory is initialized for images which do not
+	 *  need to copy the .data section from ROM to RAM.
+	 */
+.section .data.console_base ; .align 3
+	console_base: .quad 0x0
+
+	/* -----------------------------------------------
+	 * int console_init(unsigned long base_addr,
+	 * unsigned int uart_clk, unsigned int baud_rate)
+	 * Function to initialize the console without a
+	 * C Runtime to print debug information. It saves
+	 * the console base to the data section.
+	 * In: x0 - console base address
+	 *     w1 - Uart clock in Hz
+	 *     w2 - Baud rate
+	 * out: return 1 on success.
+	 * Clobber list : x1 - x3
+	 * -----------------------------------------------
+	 */
+func console_init
+	adrp	x3, console_base
+	str	x0, [x3, :lo12:console_base]
+	b	console_core_init
+
+	/* -----------------------------------------------
+	 * int console_core_init(unsigned long base_addr,
+	 * unsigned int uart_clk, unsigned int baud_rate)
+	 * Function to initialize the console without a
+	 * C Runtime to print debug information. This
+	 * function will be accessed by console_init and
+	 * crash reporting.
+	 * In: x0 - console base address
+	 *     w1 - Uart clock in Hz
+	 *     w2 - Baud rate
+	 * Out: return 1 on success
+	 * Clobber list : x1, x2
+	 * -----------------------------------------------
+	 */
+func console_core_init
+	/* Check the input base address */
+	cbz	x0, init_fail
+	/* Check baud rate and uart clock for sanity */
+	cbz	w1, init_fail
+	cbz	w2, init_fail
+	/* Program the baudrate */
+	/* Divisor =  (Uart clock * 4) / baudrate */
+	lsl	w1, w1, #2
+	udiv	w2, w1, w2
+	/* IBRD = Divisor >> 6 */
+	lsr	w1, w2, #6
+	/* Write the IBRD */
+	str	w1, [x0, #UARTIBRD]
+	/* FBRD = Divisor & 0x3F */
+	and	w1, w2, #0x3f
+	/* Write the FBRD */
+	str	w1, [x0, #UARTFBRD]
+	mov	w1, #PL011_LINE_CONTROL
+	str	w1, [x0, #UARTLCR_H]
+	/* Clear any pending errors */
+	str	wzr, [x0, #UARTECR]
+	/* Enable tx, rx, and uart overall */
+	mov	w1, #(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN)
+	str	w1, [x0, #UARTCR]
+	mov	w0, #1
+init_fail:
+	ret
+
+	/* ---------------------------------------------
+	 * int console_putc(int c)
+	 * Function to output a character over the
+	 * console. It returns the character printed on
+	 * success or -1 on error.
+	 * In : x0 - character to be printed
+	 * Out : return -1 on error else return character.
+	 * Clobber list : x1, x2
+	 * ---------------------------------------------
+	 */
+func console_putc
+	adrp	x2, console_base
+	ldr	x1, [x2, :lo12:console_base]
+	b	console_core_putc
+
+	/* --------------------------------------------------------
+	 * int console_core_putc(int c, unsigned int base_addr)
+	 * Function to output a character over the console. It
+	 * returns the character printed on success or -1 on error.
+	 * In : w0 - character to be printed
+	 *      x1 - console base address
+	 * Out : return -1 on error else return character.
+	 * Clobber list : x2
+	 * --------------------------------------------------------
+	 */
+func console_core_putc
+	/* Check the input parameter */
+	cbz	x1, putc_error
+	/* Prepend '\r' to '\n' */
+	cmp	w0, #0xA
+	b.ne	2f
+1:
+	/* Check if the transmit FIFO is full */
+	ldr	w2, [x1, #UARTFR]
+	tbnz	w2, #PL011_UARTFR_TXFF_BIT, 1b
+	mov	w2, #0xD
+	str	w2, [x1, #UARTDR]
+2:
+	/* Check if the transmit FIFO is full */
+	ldr	w2, [x1, #UARTFR]
+	tbnz	w2, #PL011_UARTFR_TXFF_BIT, 2b
+	str	w0, [x1, #UARTDR]
+	ret
+putc_error:
+	mov	w0, #-1
+	ret
+
+	/* ---------------------------------------------
+	 * int console_getc(void)
+	 * Function to get a character from the console.
+	 * It returns the character grabbed on success
+	 * or -1 on error.
+	 * Clobber list : x0, x1
+	 * ---------------------------------------------
+	 */
+func console_getc
+	adrp	x0, console_base
+	ldr	x1, [x0, :lo12:console_base]
+	cbz	x1, getc_error
+1:
+	/* Check if the receive FIFO is empty */
+	ldr	w0, [x1, #UARTFR]
+	tbnz	w0, #PL011_UARTFR_RXFE_BIT, 1b
+	ldr	w0, [x1, #UARTDR]
+	ret
+getc_error:
+	mov	w0, #-1
+	ret
diff --git a/drivers/arm/pl011/pl011_console.c b/drivers/arm/pl011/pl011_console.c
deleted file mode 100644
index 81897ca..0000000
--- a/drivers/arm/pl011/pl011_console.c
+++ /dev/null
@@ -1,98 +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 <assert.h>
-#include <console.h>
-#include <pl011.h>
-
-static unsigned long uart_base;
-
-void console_init(unsigned long base_addr)
-{
-	/* TODO: assert() internally calls printf() and will result in
-	 * an infinite loop. This needs to be fixed with some kind of
-	 * exception  mechanism or early panic support. This also applies
-	 * to the other assert() calls below.
-	 */
-	assert(base_addr);
-
-	/* Initialise internal base address variable */
-	uart_base = base_addr;
-
-	/* Baud Rate */
-#if defined(PL011_INTEGER) && defined(PL011_FRACTIONAL)
-	pl011_write_ibrd(uart_base, PL011_INTEGER);
-	pl011_write_fbrd(uart_base, PL011_FRACTIONAL);
-#else
-	pl011_setbaudrate(uart_base, PL011_BAUDRATE);
-#endif
-
-	pl011_write_lcr_h(uart_base, PL011_LINE_CONTROL);
-
-	/* Clear any pending errors */
-	pl011_write_ecr(uart_base, 0);
-
-	/* Enable tx, rx, and uart overall */
-	pl011_write_cr(uart_base, PL011_UARTCR_RXE | PL011_UARTCR_TXE |
-			PL011_UARTCR_UARTEN);
-
-}
-
-#define WAIT_UNTIL_UART_FREE(base)				\
-	while ((pl011_read_fr(base) & PL011_UARTFR_TXFF))	\
-		continue
-
-int console_putc(int c)
-{
-	/* If the console has not been initialized then return an error
-	 * code. Asserting here would result in recursion and stack
-	 * exhaustion
-	 */
-	if (!uart_base)
-		return -1;
-
-	if (c == '\n') {
-		WAIT_UNTIL_UART_FREE(uart_base);
-		pl011_write_dr(uart_base, '\r');
-	}
-
-	WAIT_UNTIL_UART_FREE(uart_base);
-	pl011_write_dr(uart_base, c);
-	return c;
-}
-
-int console_getc(void)
-{
-	assert(uart_base);
-
-	while ((pl011_read_fr(uart_base) & PL011_UARTFR_RXFE) != 0)
-		;
-	return pl011_read_dr(uart_base);
-}
diff --git a/include/bl31/cpu_data.h b/include/bl31/cpu_data.h
index 5f45f14..ef0b68c 100644
--- a/include/bl31/cpu_data.h
+++ b/include/bl31/cpu_data.h
@@ -32,9 +32,14 @@
 #define __CPU_DATA_H__
 
 /* Offsets for the cpu_data structure */
-#define CPU_DATA_CRASH_STACK_OFFSET	0x10
+#define CPU_DATA_CRASH_BUF_OFFSET	0x10
+#if CRASH_REPORTING
+#define CPU_DATA_LOG2SIZE		7
+#else
 #define CPU_DATA_LOG2SIZE		6
-
+#endif
+/* need enough space in crash buffer to save 8 registers */
+#define CPU_DATA_CRASH_BUF_SIZE	64
 #ifndef __ASSEMBLY__
 
 #include <arch_helpers.h>
@@ -61,9 +66,21 @@
 
 typedef struct cpu_data {
 	void *cpu_context[2];
-	uint64_t crash_stack;
+#if CRASH_REPORTING
+	uint64_t crash_buf[CPU_DATA_CRASH_BUF_SIZE >> 3];
+#endif
 } __aligned(CACHE_WRITEBACK_GRANULE) cpu_data_t;
 
+#if CRASH_REPORTING
+/* verify assembler offsets match data structures */
+CASSERT(CPU_DATA_CRASH_BUF_OFFSET == __builtin_offsetof
+	(cpu_data_t, crash_buf),
+	assert_cpu_data_crash_stack_offset_mismatch);
+#endif
+
+CASSERT((1 << CPU_DATA_LOG2SIZE) == sizeof(cpu_data_t),
+	assert_cpu_data_log2size_mismatch);
+
 struct cpu_data *_cpu_data_by_index(uint32_t cpu_index);
 struct cpu_data *_cpu_data_by_mpidr(uint64_t mpidr);
 
diff --git a/include/common/asm_macros.S b/include/common/asm_macros.S
index 2bccf58..238fa82 100644
--- a/include/common/asm_macros.S
+++ b/include/common/asm_macros.S
@@ -162,3 +162,36 @@
 	.macro get_up_stack _name, _size
 	ldr x0, =(\_name + \_size)
 	.endm
+
+	/*
+	 * Helper macro to generate the best mov/movk combinations according
+	 * the value to be moved. The 16 bits from '_shift' are tested and
+	 * if not zero, they are moved into '_reg' without affecting
+	 * other bits.
+	 */
+	.macro _mov_imm16 _reg, _val, _shift
+		.if (\_val >> \_shift) & 0xffff
+			.if (\_val & (1 << \_shift - 1))
+				movk	\_reg, (\_val >> \_shift) & 0xffff, LSL \_shift
+			.else
+				mov	\_reg, \_val & (0xffff << \_shift)
+			.endif
+		.endif
+	.endm
+
+	/*
+	 * Helper macro to load arbitrary values into 32 or 64-bit registers
+	 * which generates the best mov/movk combinations. Many base addresses
+	 * are 64KB aligned the macro will eliminate updating bits 15:0 in
+	 * that case
+	 */
+	.macro mov_imm _reg, _val
+		.if (\_val) == 0
+			mov	\_reg, #0
+		.else
+			_mov_imm16	\_reg, (\_val), 0
+			_mov_imm16	\_reg, (\_val), 16
+			_mov_imm16	\_reg, (\_val), 32
+			_mov_imm16	\_reg, (\_val), 48
+		.endif
+	.endm
diff --git a/drivers/arm/pl011/pl011.c b/include/common/assert_macros.S
similarity index 76%
rename from drivers/arm/pl011/pl011.c
rename to include/common/assert_macros.S
index e296c23..45d699b 100644
--- a/drivers/arm/pl011/pl011.c
+++ b/include/common/assert_macros.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 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:
@@ -28,14 +28,19 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <assert.h>
-#include <pl011.h>
-
-void pl011_setbaudrate(unsigned long base_addr, unsigned int baudrate)
-{
-	unsigned int divisor;
-	assert(baudrate);
-	divisor = (PL011_CLK_IN_HZ * 4) / baudrate;
-	pl011_write_ibrd(base_addr, divisor >> 6);
-	pl011_write_fbrd(base_addr, divisor & 0x3F);
-}
+	/*
+	 * Assembler macro to enable asm_assert. Use this macro wherever
+	 * assert is required in assembly.
+	 */
+#define ASM_ASSERT(_cc) \
+.ifndef .L_assert_filename ;\
+	.pushsection .rodata.str1.1, "aS" ;\
+	.L_assert_filename: ;\
+			.string	__FILE__ ;\
+	.popsection ;\
+.endif ;\
+	b._cc	1f ;\
+	adr	x0, .L_assert_filename ;\
+	mov	x1, __LINE__ ;\
+	b	asm_assert ;\
+1:
diff --git a/include/common/debug.h b/include/common/debug.h
index c70109f..3f5655b 100644
--- a/include/common/debug.h
+++ b/include/common/debug.h
@@ -52,22 +52,9 @@
 
 #define ERROR(...)	tf_printf("ERROR: " __VA_ARGS__)
 
-
-/* For the moment this Panic function is very basic, Report an error and
- * spin. This can be expanded in the future to provide more information.
- */
-#if DEBUG
-void __dead2 do_panic(const char *file, int line);
-#define panic()	do_panic(__FILE__, __LINE__)
-
-#else
 void __dead2 do_panic(void);
 #define panic()	do_panic()
 
-#endif
-
-void print_string_value(char *s, unsigned long *mem);
 void tf_printf(const char *fmt, ...);
 
-
 #endif /* __DEBUG_H__ */
diff --git a/include/drivers/arm/cci400.h b/include/drivers/arm/cci400.h
index 7222391..6246e48 100644
--- a/include/drivers/arm/cci400.h
+++ b/include/drivers/arm/cci400.h
@@ -65,8 +65,11 @@
 /* Status register bit definitions */
 #define CHANGE_PENDING_BIT		(1 << 0)
 
+#ifndef __ASSEMBLY__
+
 /* Function declarations */
 void cci_enable_coherency(unsigned long mpidr);
 void cci_disable_coherency(unsigned long mpidr);
 
+#endif /* __ASSEMBLY__ */
 #endif /* __CCI_400_H__ */
diff --git a/include/drivers/arm/pl011.h b/include/drivers/arm/pl011.h
index 281330e..7c4df62 100644
--- a/include/drivers/arm/pl011.h
+++ b/include/drivers/arm/pl011.h
@@ -31,9 +31,6 @@
 #ifndef __PL011_H__
 #define __PL011_H__
 
-#include <mmio.h>
-
-
 /* PL011 Registers */
 #define UARTDR                    0x000
 #define UARTRSR                   0x004
@@ -68,6 +65,9 @@
 #define PL011_UARTFR_DSR          (1 << 1)	/* Data set ready */
 #define PL011_UARTFR_CTS          (1 << 0)	/* Clear to send */
 
+#define PL011_UARTFR_TXFF_BIT	5	/* Transmit FIFO full bit in UARTFR register */
+#define PL011_UARTFR_RXFE_BIT	4	/* Receive FIFO empty bit in UARTFR register */
+
 /* Control reg bits */
 #define PL011_UARTCR_CTSEN        (1 << 15)	/* CTS hardware flow control enable */
 #define PL011_UARTCR_RTSEN        (1 << 14)	/* RTS hardware flow control enable */
@@ -78,14 +78,6 @@
 #define PL011_UARTCR_LBE          (1 << 7)	/* Loopback enable */
 #define PL011_UARTCR_UARTEN       (1 << 0)	/* UART Enable */
 
-#if !defined(PL011_BAUDRATE)
-#define PL011_BAUDRATE  115200
-#endif
-
-#if !defined(PL011_CLK_IN_HZ)
-#define PL011_CLK_IN_HZ 24000000
-#endif
-
 #if !defined(PL011_LINE_CONTROL)
 /* FIFO Enabled / No Parity / 8 Data bit / One Stop Bit */
 #define PL011_LINE_CONTROL  (PL011_UARTLCR_H_FEN | PL011_UARTLCR_H_WLEN_8)
@@ -103,58 +95,4 @@
 #define PL011_UARTLCR_H_PEN       (1 << 1)	/* Parity Enable */
 #define PL011_UARTLCR_H_BRK       (1 << 0)	/* Send break */
 
-/*******************************************************************************
- * Pl011 CPU interface accessors for writing registers
- ******************************************************************************/
-
-static inline void pl011_write_ibrd(unsigned long base, unsigned int val)
-{
-	mmio_write_32(base + UARTIBRD, val);
-}
-
-static inline void pl011_write_fbrd(unsigned long base, unsigned int val)
-{
-	mmio_write_32(base + UARTFBRD, val);
-}
-
-static inline void pl011_write_lcr_h(unsigned long base, unsigned int val)
-{
-	mmio_write_32(base + UARTLCR_H, val);
-}
-
-static inline void pl011_write_ecr(unsigned long base, unsigned int val)
-{
-	mmio_write_32(base + UARTECR, val);
-}
-
-static inline void pl011_write_cr(unsigned long base, unsigned int val)
-{
-	mmio_write_32(base + UARTCR, val);
-}
-
-static inline void pl011_write_dr(unsigned long base, unsigned int val)
-{
-	mmio_write_32(base + UARTDR, val);
-}
-
-/*******************************************************************************
- * Pl011 CPU interface accessors for reading registers
- ******************************************************************************/
-
-static inline unsigned int pl011_read_fr(unsigned long base)
-{
-	return mmio_read_32(base + UARTFR);
-}
-
-static inline unsigned int pl011_read_dr(unsigned long base)
-{
-	return mmio_read_32(base + UARTDR);
-}
-
-/*******************************************************************************
- * Function prototypes
- ******************************************************************************/
-
-void pl011_setbaudrate(unsigned long base_addr, unsigned int baudrate);
-
 #endif	/* __PL011_H__ */
diff --git a/include/drivers/console.h b/include/drivers/console.h
index e285909..f144ab9 100644
--- a/include/drivers/console.h
+++ b/include/drivers/console.h
@@ -31,7 +31,8 @@
 #ifndef __CONSOLE_H__
 #define __CONSOLE_H__
 
-void console_init(unsigned long base_addr);
+int console_init(unsigned long base_addr,
+		unsigned int uart_clk, unsigned int baud_rate);
 int console_putc(int c);
 int console_getc(void);
 
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index 4b73a09..ab93123 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -72,6 +72,8 @@
 unsigned int platform_get_core_pos(unsigned long mpidr);
 unsigned long platform_get_stack(unsigned long mpidr);
 void plat_report_exception(unsigned long);
+void plat_crash_console_init(unsigned long base_addr);
+int plat_crash_console_putc(int c);
 
 /*******************************************************************************
  * Mandatory BL1 functions
diff --git a/lib/aarch64/misc_helpers.S b/lib/aarch64/misc_helpers.S
index 439ca28..f605bf4 100644
--- a/lib/aarch64/misc_helpers.S
+++ b/lib/aarch64/misc_helpers.S
@@ -30,6 +30,7 @@
 
 #include <arch.h>
 #include <asm_macros.S>
+#include <assert_macros.S>
 
 	.globl	get_afflvl_shift
 	.globl	mpidr_mask_lower_afflvls
@@ -46,7 +47,6 @@
 	.globl	enable_vfp
 #endif
 
-
 func get_afflvl_shift
 	cmp	x0, #3
 	cinc	x0, x0, eq
@@ -79,6 +79,10 @@
  * -----------------------------------------------------------------------
  */
 func zeromem16
+#if ASM_ASSERTION
+	tst	x0, #0xf
+	ASM_ASSERT(eq)
+#endif
 	add	x2, x0, x1
 /* zero 16 bytes at a time */
 z_loop16:
@@ -105,6 +109,11 @@
  * --------------------------------------------------------------------------
  */
 func memcpy16
+#if ASM_ASSERTION
+	orr	x3, x0, x1
+	tst	x3, #0xf
+	ASM_ASSERT(eq)
+#endif
 /* copy 16 bytes at a time */
 m_loop16:
 	cmp	x2, #16
@@ -145,7 +154,6 @@
 	mov	x1, #(SCTLR_M_BIT | SCTLR_C_BIT | SCTLR_I_BIT)
 	b	do_disable_mmu
 
-
 /* ---------------------------------------------------------------------------
  * Enable the use of VFP at EL3
  * ---------------------------------------------------------------------------
diff --git a/plat/common/aarch64/platform_helpers.S b/plat/common/aarch64/platform_helpers.S
index f6ac13e..5e2d1b1 100644
--- a/plat/common/aarch64/platform_helpers.S
+++ b/plat/common/aarch64/platform_helpers.S
@@ -37,6 +37,8 @@
 	.weak	platform_is_primary_cpu
 	.weak	platform_check_mpidr
 	.weak	plat_report_exception
+	.weak	plat_crash_console_init
+	.weak	plat_crash_console_putc
 
 	/* -----------------------------------------------------
 	 *  int platform_get_core_pos(int mpidr);
@@ -79,3 +81,20 @@
 	 */
 func plat_report_exception
 	ret
+
+	/* -----------------------------------------------------
+	 * Placeholder function which should be redefined by
+	 * each platform.
+	 * -----------------------------------------------------
+	 */
+func plat_crash_console_init
+	mov	x0, #0
+	ret
+
+	/* -----------------------------------------------------
+	 * Placeholder function which should be redefined by
+	 * each platform.
+	 * -----------------------------------------------------
+	 */
+func plat_crash_console_putc
+	ret
diff --git a/plat/fvp/aarch64/fvp_helpers.S b/plat/fvp/aarch64/fvp_helpers.S
index 3cd0b46..823588e 100644
--- a/plat/fvp/aarch64/fvp_helpers.S
+++ b/plat/fvp/aarch64/fvp_helpers.S
@@ -32,6 +32,7 @@
 #include <asm_macros.S>
 #include <bl_common.h>
 #include <gic_v2.h>
+#include <pl011.h>
 #include "../drivers/pwrc/fvp_pwrc.h"
 #include "../fvp_def.h"
 
@@ -39,6 +40,8 @@
 	.globl	plat_secondary_cold_boot_setup
 	.globl	platform_mem_init
 	.globl	plat_report_exception
+	.globl	plat_crash_console_init
+	.globl	plat_crash_console_putc
 
 	.macro	fvp_choose_gicmmap  param1, param2, x_tmp, w_tmp, res
 	ldr	\x_tmp, =VE_SYSREGS_BASE + V2M_SYS_ID
@@ -187,3 +190,30 @@
 	add	x1, x1, #V2M_SYS_LED
 	str	w0, [x1]
 	ret
+
+	/* Define a crash console for the plaform */
+#define FVP_CRASH_CONSOLE_BASE		PL011_UART0_BASE
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_init(void)
+	 * Function to initialize the crash console
+	 * without a C Runtime to print crash report.
+	 * Clobber list : x0, x1, x2
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_init
+	mov_imm	x0, FVP_CRASH_CONSOLE_BASE
+	mov_imm	x1, PL011_UART0_CLK_IN_HZ
+	mov_imm	x2, PL011_BAUDRATE
+	b	console_core_init
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_putc(void)
+	 * Function to print a character on the crash
+	 * console without a C Runtime.
+	 * Clobber list : x1, x2
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_putc
+	mov_imm	x1, FVP_CRASH_CONSOLE_BASE
+	b	console_core_putc
diff --git a/plat/fvp/bl1_fvp_setup.c b/plat/fvp/bl1_fvp_setup.c
index bfd0f55..b146fdb 100644
--- a/plat/fvp/bl1_fvp_setup.c
+++ b/plat/fvp/bl1_fvp_setup.c
@@ -73,7 +73,7 @@
 	const size_t bl1_size = BL1_RAM_LIMIT - BL1_RAM_BASE;
 
 	/* Initialize the console to provide early debug support */
-	console_init(PL011_UART0_BASE);
+	console_init(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, PL011_BAUDRATE);
 
 	/* Allow BL1 to see the whole Trusted RAM */
 	bl1_tzram_layout.total_base = TZRAM_BASE;
diff --git a/plat/fvp/bl2_fvp_setup.c b/plat/fvp/bl2_fvp_setup.c
index beba804..c0ad340 100644
--- a/plat/fvp/bl2_fvp_setup.c
+++ b/plat/fvp/bl2_fvp_setup.c
@@ -168,7 +168,7 @@
 void bl2_early_platform_setup(meminfo_t *mem_layout)
 {
 	/* Initialize the console to provide early debug support */
-	console_init(PL011_UART0_BASE);
+	console_init(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, PL011_BAUDRATE);
 
 	/* Setup the BL2 memory layout */
 	bl2_tzram_layout = *mem_layout;
diff --git a/plat/fvp/bl31_fvp_setup.c b/plat/fvp/bl31_fvp_setup.c
index 96f4772..ca72aa9 100644
--- a/plat/fvp/bl31_fvp_setup.c
+++ b/plat/fvp/bl31_fvp_setup.c
@@ -143,7 +143,7 @@
 				void *plat_params_from_bl2)
 {
 	/* Initialize the console to provide early debug support */
-	console_init(PL011_UART0_BASE);
+	console_init(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, PL011_BAUDRATE);
 
 	/* Initialize the platform config for future decision making */
 	fvp_config_setup();
diff --git a/plat/fvp/bl32_fvp_setup.c b/plat/fvp/bl32_fvp_setup.c
index 901c585..aa49ff3 100644
--- a/plat/fvp/bl32_fvp_setup.c
+++ b/plat/fvp/bl32_fvp_setup.c
@@ -72,7 +72,7 @@
 	 * Initialize a different console than already in use to display
 	 * messages from TSP
 	 */
-	console_init(PL011_UART1_BASE);
+	console_init(PL011_UART1_BASE, PL011_UART1_CLK_IN_HZ, PL011_BAUDRATE);
 
 	/* Initialize the platform config for future decision making */
 	fvp_config_setup();
diff --git a/plat/fvp/fvp_def.h b/plat/fvp/fvp_def.h
index 89c8b02..21edb3b 100644
--- a/plat/fvp/fvp_def.h
+++ b/plat/fvp/fvp_def.h
@@ -198,6 +198,13 @@
 #define PL011_UART2_BASE		0x1c0b0000
 #define PL011_UART3_BASE		0x1c0c0000
 
+#define PL011_BAUDRATE  115200
+
+#define PL011_UART0_CLK_IN_HZ 24000000
+#define PL011_UART1_CLK_IN_HZ 24000000
+#define PL011_UART2_CLK_IN_HZ 24000000
+#define PL011_UART3_CLK_IN_HZ 24000000
+
 /*******************************************************************************
  * TrustZone address space controller related constants
  ******************************************************************************/
diff --git a/plat/fvp/include/plat_macros.S b/plat/fvp/include/plat_macros.S
index 602eaf1..727b958 100644
--- a/plat/fvp/include/plat_macros.S
+++ b/plat/fvp/include/plat_macros.S
@@ -27,31 +27,79 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
-
+#include <cci400.h>
 #include <gic_v2.h>
 #include <plat_config.h>
+#include "platform_def.h"
 
 .section .rodata.gic_reg_name, "aS"
-gic_regs: .asciz "gic_iar", "gic_ctlr", ""
+gic_regs:
+	.asciz "gic_hppir", "gic_ahppir", "gic_ctlr", ""
+gicd_pend_reg:
+	.asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n"
+newline:
+	.asciz "\n"
+spacer:
+	.asciz ":\t\t0x"
 
-/* Currently we have only 2 GIC registers to report */
-#define GIC_REG_SIZE 				(2 * 8)
 	/* ---------------------------------------------
 	 * The below macro prints out relevant GIC
 	 * registers whenever an unhandled exception is
 	 * taken in BL31.
+	 * Clobbers: x0 - x10, x16, sp
 	 * ---------------------------------------------
 	 */
 	.macro plat_print_gic_regs
-	adr	x0, plat_config;
-	ldr	w0, [x0, #CONFIG_GICC_BASE_OFFSET]
-	/* gic base address is now in x0 */
-	ldr	w1, [x0, #GICC_IAR]
-	ldr	w2, [x0, #GICC_CTLR]
-	sub	sp, sp, #GIC_REG_SIZE
-	stp	x1, x2, [sp] /* we store the gic registers as 64 bit */
-	adr	x0, gic_regs
-	mov	x1, sp
-	bl	print_string_value
-	add	sp, sp, #GIC_REG_SIZE
+	adr	x0, plat_config
+	ldr	w16, [x0, #CONFIG_GICC_BASE_OFFSET]
+	cbz	x16, 1f
+	/* gic base address is now in x16 */
+	adr	x6, gic_regs	/* Load the gic reg list to x6 */
+	/* Load the gic regs to gp regs used by str_in_crash_buf_print */
+	ldr	w8, [x16, #GICC_HPPIR]
+	ldr	w9, [x16, #GICC_AHPPIR]
+	ldr	w10, [x16, #GICC_CTLR]
+	/* Store to the crash buf and print to cosole */
+	bl	str_in_crash_buf_print
+
+	/* Print the GICD_ISPENDR regs */
+	add	x7, x16, #GICD_ISPENDR
+	adr	x4, gicd_pend_reg
+	bl	asm_print_str
+2:
+	sub	x4, x7, x16
+	cmp	x4, #0x280
+	b.eq	1f
+	bl	asm_print_hex
+	adr	x4, spacer
+	bl	asm_print_str
+	ldr	x4, [x7], #8
+	bl	asm_print_hex
+	adr	x4, newline
+	bl	asm_print_str
+	b	2b
+1:
+	.endm
+
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+	.asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+	/* ------------------------------------------------
+	 * The below macro prints out relevant interconnect
+	 * registers whenever an unhandled exception is
+	 * taken in BL31.
+	 * Clobbers: x0 - x9, sp
+	 * ------------------------------------------------
+	 */
+	.macro plat_print_interconnect_regs
+	adr	x6, cci_iface_regs
+	/* Store in x7 the base address of the first interface */
+	mov_imm	x7, (CCI400_BASE + SLAVE_IFACE3_OFFSET)
+	ldr	w8, [x7, #SNOOP_CTRL_REG]
+	/* Store in x7 the base address of the second interface */
+	mov_imm	x7, (CCI400_BASE + SLAVE_IFACE4_OFFSET)
+	ldr	w9, [x7, #SNOOP_CTRL_REG]
+	/* Store to the crash buf and print to console */
+	bl	str_in_crash_buf_print
 	.endm
diff --git a/plat/fvp/platform.mk b/plat/fvp/platform.mk
index b22a339..f6275b7 100644
--- a/plat/fvp/platform.mk
+++ b/plat/fvp/platform.mk
@@ -45,8 +45,7 @@
 
 PLAT_INCLUDES		:=	-Iplat/fvp/include/
 
-PLAT_BL_COMMON_SOURCES	:=	drivers/arm/pl011/pl011.c			\
-				drivers/arm/pl011/pl011_console.c		\
+PLAT_BL_COMMON_SOURCES	:=	drivers/arm/pl011/pl011_console.S		\
 				drivers/io/io_fip.c				\
 				drivers/io/io_memmap.c				\
 				drivers/io/io_semihosting.c			\