Fix crash dump for lower EL

This patch provides a fix for incorrect crash dump data for
lower EL when TF-A is built with HANDLE_EA_EL3_FIRST=1 option
which enables routing of External Aborts and SErrors to EL3.

Change-Id: I9d5e6775e6aad21db5b78362da6c3a3d897df977
Signed-off-by: Alexei Fedorov <Alexei.Fedorov@arm.com>
This commit is contained in:
Alexei Fedorov 2020-03-03 13:31:58 +00:00
parent 03ea84c345
commit b4292bc65e
7 changed files with 269 additions and 99 deletions

View File

@ -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 @@ panic_msg:
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 @@ func report_unhandled_exception
b do_crash_reporting
endfunc report_unhandled_exception
/* -----------------------------------------------------
* This function allows to report a crash (if crash
* reporting is enabled) when an unhandled interrupt
@ -187,6 +191,112 @@ func report_unhandled_interrupt
b do_crash_reporting
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
@ -200,9 +310,7 @@ func el3_panic
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 @@ endfunc el3_panic
* 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 @@ func do_crash_reporting
/* 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 @@ func do_crash_reporting
/* 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 @@ func do_crash_reporting
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 @@ func do_crash_reporting
/* 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 @@ report_unhandled_interrupt:
endfunc report_unhandled_exception
#endif /* CRASH_REPORTING */
func crash_panic
no_ret plat_panic_handler
endfunc crash_panic

View File

@ -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 @@ endfunc asm_print_newline
/* 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:
/*

View File

@ -37,7 +37,7 @@ struct frame_record {
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";

View File

@ -1177,83 +1177,104 @@ The sample crash output is shown below.
::
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
-----------------------------

View File

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

View File

@ -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

View File

@ -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 @@ int plat_sdei_validate_entry_point(uintptr_t ep, unsigned int client_mode)
}
#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 @@ void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
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();
}