Merge "Fix crash dump for lower EL" into integration
diff --git a/bl31/aarch64/crash_reporting.S b/bl31/aarch64/crash_reporting.S
index 97db2a1..d56b513 100644
--- a/bl31/aarch64/crash_reporting.S
+++ b/bl31/aarch64/crash_reporting.S
@@ -16,6 +16,7 @@
 	.globl	report_unhandled_exception
 	.globl	report_unhandled_interrupt
 	.globl	el3_panic
+	.globl	elx_panic
 
 #if CRASH_REPORTING
 
@@ -59,7 +60,11 @@
 excpt_msg:
 	.asciz "Unhandled Exception in EL3.\nx30"
 intr_excpt_msg:
-	.asciz "Unhandled Interrupt Exception in EL3.\nx30"
+	.ascii "Unhandled Interrupt Exception in EL3.\n"
+x30_msg:
+	.asciz "x30"
+excpt_msg_el:
+	.asciz "Unhandled Exception from EL"
 
 	/*
 	 * Helper function to print from crash buf.
@@ -170,7 +175,6 @@
 	b	do_crash_reporting
 endfunc report_unhandled_exception
 
-
 	/* -----------------------------------------------------
 	 * This function allows to report a crash (if crash
 	 * reporting is enabled) when an unhandled interrupt
@@ -188,6 +192,112 @@
 endfunc report_unhandled_interrupt
 
 	/* -----------------------------------------------------
+	 * This function allows to report a crash from the lower
+	 * exception level (if crash reporting is enabled) when
+	 * panic() is invoked from C Runtime.
+	 * It prints the CPU state via the crash console making
+	 * use of 'cpu_context' structure where general purpose
+	 * registers are saved and the crash buf.
+	 * This function will not return.
+	 *
+ 	 * x0: Exception level
+	 * -----------------------------------------------------
+	 */
+func elx_panic
+	msr	spsel, #MODE_SP_ELX
+	mov	x8, x0
+
+	/* Print the crash message */
+	adr	x4, excpt_msg_el
+	bl	asm_print_str
+
+	/* Print exception level */
+	add	x0, x8, #'0'
+	bl	plat_crash_console_putc
+	bl	asm_print_newline
+
+	/* Report x0 - x29 values stored in 'gpregs_ctx' structure */
+	/* Store the ascii list pointer in x6 */
+	adr	x6, gp_regs
+	add	x7, sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0
+
+print_next:
+	ldrb	w4, [x6]
+	/* Test whether we are at end of list */
+	cbz	w4, print_x30
+	mov	x4, x6
+	/* asm_print_str updates x4 to point to next entry in list */
+	bl	asm_print_str
+	/* x0 = number of symbols printed + 1 */
+	sub	x0, x4, x6
+	/* Update x6 with the updated list pointer */
+	mov	x6, x4
+	bl	print_alignment
+	ldr	x4, [x7], #REGSZ
+	bl	asm_print_hex
+	bl	asm_print_newline
+	b	print_next
+
+print_x30:
+	adr	x4, x30_msg
+	bl	asm_print_str
+
+	/* Print spaces to align "x30" string */
+	mov	x0, #4
+	bl	print_alignment
+
+	/* Report x30 */
+	ldr	x4, [x7]
+
+	/* ----------------------------------------------------------------
+	 * Different virtual address space size can be defined for each EL.
+	 * Ensure that we use the proper one by reading the corresponding
+	 * TCR_ELx register.
+	 * ----------------------------------------------------------------
+	 */
+	cmp	x8, #MODE_EL2
+	b.lt	from_el1	/* EL1 */
+	mrs	x2, sctlr_el2
+	mrs	x1, tcr_el2
+
+	/* ----------------------------------------------------------------
+	 * Check if pointer authentication is enabled at the specified EL.
+	 * If it isn't, we can then skip stripping a PAC code.
+	 * ----------------------------------------------------------------
+	 */
+test_pauth:
+	tst	x2, #(SCTLR_EnIA_BIT | SCTLR_EnIB_BIT)
+	b.eq	no_pauth
+
+	/* Demangle address */
+	and	x1, x1, #0x3F	/* T0SZ = TCR_ELx[5:0] */
+	sub	x1, x1, #64
+	neg	x1, x1		/* bottom_pac_bit = 64 - T0SZ */
+	mov	x2, #-1
+	lsl	x2, x2, x1
+	bic	x4, x4, x2
+
+no_pauth:
+	bl	asm_print_hex
+	bl	asm_print_newline
+
+	/* 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
+
+	/* Print the rest of crash dump */
+	b	print_el3_sys_regs
+
+from_el1:
+	mrs	x2, sctlr_el1
+	mrs	x1, tcr_el1
+	b	test_pauth
+endfunc	elx_panic
+
+	/* -----------------------------------------------------
 	 * 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
@@ -200,9 +310,7 @@
 	prepare_crash_buf_save_x0_x1
 	adr	x0, panic_msg
 	mov	sp, x0
-	/* This call will not return */
-	b	do_crash_reporting
-endfunc el3_panic
+	/* Fall through to 'do_crash_reporting' */
 
 	/* ------------------------------------------------------------
 	 * The common crash reporting functionality. It requires x0
@@ -223,7 +331,7 @@
 	 *     the crash buf to the crash console.
 	 * ------------------------------------------------------------
 	 */
-func do_crash_reporting
+do_crash_reporting:
 	/* Retrieve the crash buf from tpidr_el3 */
 	mrs	x0, tpidr_el3
 	/* Store x2 - x6, x30 in the crash buffer */
@@ -240,9 +348,9 @@
 	/* Print spaces to align "x30" string */
 	mov	x0, #4
 	bl	print_alignment
-	/* load the crash buf address */
+	/* Load the crash buf address */
 	mrs	x0, tpidr_el3
-	/* report x30 first from the crash buf */
+	/* Report x30 first from the crash buf */
 	ldr	x4, [x0, #REGSZ * 7]
 
 #if ENABLE_PAUTH
@@ -256,7 +364,7 @@
 	/* Now mov x7 into crash buf */
 	str	x7, [x0, #REGSZ * 7]
 
-	/* Report x0 - x29 values stored in crash buf*/
+	/* 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 */
@@ -279,6 +387,7 @@
 	bl	size_controlled_print
 
 	/* Print the el3 sys registers */
+print_el3_sys_regs:
 	adr	x6, el3_sys_regs
 	mrs	x8, scr_el3
 	mrs	x9, sctlr_el3
@@ -354,7 +463,7 @@
 
 	/* Done reporting */
 	no_ret	plat_panic_handler
-endfunc do_crash_reporting
+endfunc el3_panic
 
 #else	/* CRASH_REPORTING */
 func report_unhandled_exception
@@ -363,7 +472,6 @@
 endfunc report_unhandled_exception
 #endif	/* CRASH_REPORTING */
 
-
 func crash_panic
 	no_ret	plat_panic_handler
 endfunc crash_panic
diff --git a/common/aarch64/debug.S b/common/aarch64/debug.S
index e6e3298..7db2439 100644
--- a/common/aarch64/debug.S
+++ b/common/aarch64/debug.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -156,16 +156,32 @@
 
 /* This is for the non el3 BL stages to compile through */
 	.weak el3_panic
+	.weak elx_panic
 
 func do_panic
 #if CRASH_REPORTING
 	str	x0, [sp, #-0x10]!
 	mrs	x0, currentel
-	ubfx	x0, x0, #2, #2
-	cmp	x0, #0x3
+	ubfx	x0, x0, #MODE_EL_SHIFT, #MODE_EL_WIDTH
+	cmp	x0, #MODE_EL3
+#if !HANDLE_EA_EL3_FIRST
 	ldr	x0, [sp], #0x10
 	b.eq	el3_panic
-#endif
+#else
+	b.ne	to_panic_common
+
+	/* Check EL the exception taken from */
+	mrs	x0, spsr_el3
+	ubfx	x0, x0, #SPSR_EL_SHIFT, #SPSR_EL_WIDTH
+	cmp	x0, #MODE_EL3
+	b.ne	elx_panic
+	ldr	x0, [sp], #0x10
+	b	el3_panic
+
+to_panic_common:
+	ldr	x0, [sp], #0x10
+#endif /* HANDLE_EA_EL3_FIRST */
+#endif /* CRASH_REPORTING */
 
 panic_common:
 /*
diff --git a/common/backtrace/backtrace.c b/common/backtrace/backtrace.c
index 907117f..ef57500 100644
--- a/common/backtrace/backtrace.c
+++ b/common/backtrace/backtrace.c
@@ -37,7 +37,7 @@
 	uintptr_t return_addr;
 };
 
-static const char *get_el_str(unsigned int el)
+const char *get_el_str(unsigned int el)
 {
 	if (el == 3U) {
 		return "EL3";
diff --git a/docs/design/firmware-design.rst b/docs/design/firmware-design.rst
index d0d6ef6..8297dc7 100644
--- a/docs/design/firmware-design.rst
+++ b/docs/design/firmware-design.rst
@@ -1177,83 +1177,104 @@
 
 ::
 
-    x0  :0x000000004F00007C
-    x1  :0x0000000007FFFFFF
-    x2  :0x0000000004014D50
-    x3  :0x0000000000000000
-    x4  :0x0000000088007998
-    x5  :0x00000000001343AC
-    x6  :0x0000000000000016
-    x7  :0x00000000000B8A38
-    x8  :0x00000000001343AC
-    x9  :0x00000000000101A8
-    x10 :0x0000000000000002
-    x11 :0x000000000000011C
-    x12 :0x00000000FEFDC644
-    x13 :0x00000000FED93FFC
-    x14 :0x0000000000247950
-    x15 :0x00000000000007A2
-    x16 :0x00000000000007A4
-    x17 :0x0000000000247950
-    x18 :0x0000000000000000
-    x19 :0x00000000FFFFFFFF
-    x20 :0x0000000004014D50
-    x21 :0x000000000400A38C
-    x22 :0x0000000000247950
-    x23 :0x0000000000000010
-    x24 :0x0000000000000024
-    x25 :0x00000000FEFDC868
-    x26 :0x00000000FEFDC86A
-    x27 :0x00000000019EDEDC
-    x28 :0x000000000A7CFDAA
-    x29 :0x0000000004010780
-    x30 :0x000000000400F004
-    scr_el3 :0x0000000000000D3D
-    sctlr_el3   :0x0000000000C8181F
-    cptr_el3    :0x0000000000000000
-    tcr_el3 :0x0000000080803520
-    daif    :0x00000000000003C0
-    mair_el3    :0x00000000000004FF
-    spsr_el3    :0x00000000800003CC
-    elr_el3 :0x000000000400C0CC
-    ttbr0_el3   :0x00000000040172A0
-    esr_el3 :0x0000000096000210
-    sp_el3  :0x0000000004014D50
-    far_el3 :0x000000004F00007C
-    spsr_el1    :0x0000000000000000
-    elr_el1 :0x0000000000000000
-    spsr_abt    :0x0000000000000000
-    spsr_und    :0x0000000000000000
-    spsr_irq    :0x0000000000000000
-    spsr_fiq    :0x0000000000000000
-    sctlr_el1   :0x0000000030C81807
-    actlr_el1   :0x0000000000000000
-    cpacr_el1   :0x0000000000300000
-    csselr_el1  :0x0000000000000002
-    sp_el1  :0x0000000004028800
-    esr_el1 :0x0000000000000000
-    ttbr0_el1   :0x000000000402C200
-    ttbr1_el1   :0x0000000000000000
-    mair_el1    :0x00000000000004FF
-    amair_el1   :0x0000000000000000
-    tcr_el1 :0x0000000000003520
-    tpidr_el1   :0x0000000000000000
-    tpidr_el0   :0x0000000000000000
-    tpidrro_el0 :0x0000000000000000
-    dacr32_el2  :0x0000000000000000
-    ifsr32_el2  :0x0000000000000000
-    par_el1 :0x0000000000000000
-    far_el1 :0x0000000000000000
-    afsr0_el1   :0x0000000000000000
-    afsr1_el1   :0x0000000000000000
-    contextidr_el1  :0x0000000000000000
-    vbar_el1    :0x0000000004027000
-    cntp_ctl_el0    :0x0000000000000000
-    cntp_cval_el0   :0x0000000000000000
-    cntv_ctl_el0    :0x0000000000000000
-    cntv_cval_el0   :0x0000000000000000
-    cntkctl_el1 :0x0000000000000000
-    sp_el0  :0x0000000004010780
+    x0             = 0x000000002a4a0000
+    x1             = 0x0000000000000001
+    x2             = 0x0000000000000002
+    x3             = 0x0000000000000003
+    x4             = 0x0000000000000004
+    x5             = 0x0000000000000005
+    x6             = 0x0000000000000006
+    x7             = 0x0000000000000007
+    x8             = 0x0000000000000008
+    x9             = 0x0000000000000009
+    x10            = 0x0000000000000010
+    x11            = 0x0000000000000011
+    x12            = 0x0000000000000012
+    x13            = 0x0000000000000013
+    x14            = 0x0000000000000014
+    x15            = 0x0000000000000015
+    x16            = 0x0000000000000016
+    x17            = 0x0000000000000017
+    x18            = 0x0000000000000018
+    x19            = 0x0000000000000019
+    x20            = 0x0000000000000020
+    x21            = 0x0000000000000021
+    x22            = 0x0000000000000022
+    x23            = 0x0000000000000023
+    x24            = 0x0000000000000024
+    x25            = 0x0000000000000025
+    x26            = 0x0000000000000026
+    x27            = 0x0000000000000027
+    x28            = 0x0000000000000028
+    x29            = 0x0000000000000029
+    x30            = 0x0000000088000b78
+    scr_el3        = 0x000000000003073d
+    sctlr_el3      = 0x00000000b0cd183f
+    cptr_el3       = 0x0000000000000000
+    tcr_el3        = 0x000000008080351c
+    daif           = 0x00000000000002c0
+    mair_el3       = 0x00000000004404ff
+    spsr_el3       = 0x0000000060000349
+    elr_el3        = 0x0000000088000114
+    ttbr0_el3      = 0x0000000004018201
+    esr_el3        = 0x00000000be000000
+    far_el3        = 0x0000000000000000
+    spsr_el1       = 0x0000000000000000
+    elr_el1        = 0x0000000000000000
+    spsr_abt       = 0x0000000000000000
+    spsr_und       = 0x0000000000000000
+    spsr_irq       = 0x0000000000000000
+    spsr_fiq       = 0x0000000000000000
+    sctlr_el1      = 0x0000000030d00800
+    actlr_el1      = 0x0000000000000000
+    cpacr_el1      = 0x0000000000000000
+    csselr_el1     = 0x0000000000000000
+    sp_el1         = 0x0000000000000000
+    esr_el1        = 0x0000000000000000
+    ttbr0_el1      = 0x0000000000000000
+    ttbr1_el1      = 0x0000000000000000
+    mair_el1       = 0x0000000000000000
+    amair_el1      = 0x0000000000000000
+    tcr_el1        = 0x0000000000000000
+    tpidr_el1      = 0x0000000000000000
+    tpidr_el0      = 0x0000000000000000
+    tpidrro_el0    = 0x0000000000000000
+    par_el1        = 0x0000000000000000
+    mpidr_el1      = 0x0000000080000000
+    afsr0_el1      = 0x0000000000000000
+    afsr1_el1      = 0x0000000000000000
+    contextidr_el1 = 0x0000000000000000
+    vbar_el1       = 0x0000000000000000
+    cntp_ctl_el0   = 0x0000000000000000
+    cntp_cval_el0  = 0x0000000000000000
+    cntv_ctl_el0   = 0x0000000000000000
+    cntv_cval_el0  = 0x0000000000000000
+    cntkctl_el1    = 0x0000000000000000
+    sp_el0         = 0x0000000004014940
+    isr_el1        = 0x0000000000000000
+    dacr32_el2     = 0x0000000000000000
+    ifsr32_el2     = 0x0000000000000000
+    icc_hppir0_el1 = 0x00000000000003ff
+    icc_hppir1_el1 = 0x00000000000003ff
+    icc_ctlr_el3   = 0x0000000000080400
+    gicd_ispendr regs (Offsets 0x200-0x278)
+    Offset		    Value
+    0x200:	     0x0000000000000000
+    0x208:	     0x0000000000000000
+    0x210:	     0x0000000000000000
+    0x218:	     0x0000000000000000
+    0x220:	     0x0000000000000000
+    0x228:	     0x0000000000000000
+    0x230:	     0x0000000000000000
+    0x238:	     0x0000000000000000
+    0x240:	     0x0000000000000000
+    0x248:	     0x0000000000000000
+    0x250:	     0x0000000000000000
+    0x258:	     0x0000000000000000
+    0x260:	     0x0000000000000000
+    0x268:	     0x0000000000000000
+    0x270:	     0x0000000000000000
+    0x278:	     0x0000000000000000
 
 Guidelines for Reset Handlers
 -----------------------------
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index b0c2650..2b2c116 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -452,6 +452,9 @@
 #define SPSR_M_AARCH64		U(0x0)
 #define SPSR_M_AARCH32		U(0x1)
 
+#define SPSR_EL_SHIFT		U(2)
+#define SPSR_EL_WIDTH		U(2)
+
 #define SPSR_SSBS_BIT_AARCH64	BIT_64(12)
 #define SPSR_SSBS_BIT_AARCH32	BIT_64(23)
 
@@ -557,6 +560,7 @@
 
 #define MODE_EL_SHIFT		U(0x2)
 #define MODE_EL_MASK		U(0x3)
+#define MODE_EL_WIDTH		U(0x2)
 #define MODE_EL3		U(0x3)
 #define MODE_EL2		U(0x2)
 #define MODE_EL1		U(0x1)
diff --git a/include/common/debug.h b/include/common/debug.h
index 245e698..9aef15b 100644
--- a/include/common/debug.h
+++ b/include/common/debug.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -91,6 +91,7 @@
 
 #if ENABLE_BACKTRACE
 void backtrace(const char *cookie);
+const char *get_el_str(unsigned int el);
 #else
 #define backtrace(x)
 #endif
diff --git a/plat/common/aarch64/plat_common.c b/plat/common/aarch64/plat_common.c
index f8d3129..63871d9 100644
--- a/plat/common/aarch64/plat_common.c
+++ b/plat/common/aarch64/plat_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -64,6 +64,18 @@
 }
 #endif
 
+#if !ENABLE_BACKTRACE
+static const char *get_el_str(unsigned int el)
+{
+	if (el == MODE_EL3) {
+		return "EL3";
+	} else if (el == MODE_EL2) {
+		return "EL2";
+	}
+	return "S-EL1";
+}
+#endif /* !ENABLE_BACKTRACE */
+
 /* RAS functions common to AArch64 ARM platforms */
 void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
 		void *handle, uint64_t flags)
@@ -74,9 +86,17 @@
 	if (handled != 0)
 		return;
 #endif
+	unsigned int level = (unsigned int)GET_EL(read_spsr_el3());
 
-	ERROR("Unhandled External Abort received on 0x%lx at EL3!\n",
-			read_mpidr_el1());
-	ERROR(" exception reason=%u syndrome=0x%llx\n", ea_reason, syndrome);
+	ERROR("Unhandled External Abort received on 0x%lx from %s\n",
+		read_mpidr_el1(), get_el_str(level));
+	ERROR("exception reason=%u syndrome=0x%llx\n", ea_reason, syndrome);
+#if HANDLE_EA_EL3_FIRST
+	/* Skip backtrace for lower EL */
+	if (level != MODE_EL3) {
+		(void)console_flush();
+		do_panic();
+	}
+#endif
 	panic();
 }