diff options
author | Sandrine Bailleux <sandrine.bailleux@arm.com> | 2019-01-28 07:40:15 +0000 |
---|---|---|
committer | TrustedFirmware Code Review <review@review.trustedfirmware.org> | 2019-01-28 07:40:15 +0000 |
commit | 6d7047dcb24325e0a782b47c0ad507b6a5b32746 (patch) | |
tree | 7e8496ca50786a6f38e42a9d00c944c73738f1b7 /tftf | |
parent | 09a00ef98c6108fec75dafcc7dbdddacb2ee2e91 (diff) | |
parent | a43b003acd6c8e8991a57e993f7bfcdfaa04f980 (diff) | |
download | tf-a-tests-6d7047dcb24325e0a782b47c0ad507b6a5b32746.tar.gz |
Merge changes from topic "sb/exception-dump"
* changes:
Dump some registers when hitting an unexpected exception
Improve readability of TFTF exceptions code
Diffstat (limited to 'tftf')
-rw-r--r-- | tftf/framework/aarch32/exception_report.c | 53 | ||||
-rw-r--r-- | tftf/framework/aarch32/exceptions.S | 24 | ||||
-rw-r--r-- | tftf/framework/aarch64/exception_report.c | 60 | ||||
-rw-r--r-- | tftf/framework/aarch64/exceptions.S | 105 | ||||
-rw-r--r-- | tftf/framework/framework.mk | 1 |
5 files changed, 173 insertions, 70 deletions
diff --git a/tftf/framework/aarch32/exception_report.c b/tftf/framework/aarch32/exception_report.c new file mode 100644 index 000000000..46665e3e9 --- /dev/null +++ b/tftf/framework/aarch32/exception_report.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> +#include <stdio.h> + +#include <arch_helpers.h> +#include <debug.h> +#include <platform.h> +#include <utils_def.h> + +/* We save r0-r12. */ +#define GPREGS_CNT 13 + +/* Set of registers saved by the crash_dump() assembly function. */ +struct cpu_context { + u_register_t regs[GPREGS_CNT]; + u_register_t lr; + u_register_t sp; +}; + +void __dead2 print_exception(const struct cpu_context *ctx) +{ + u_register_t mpid = read_mpidr(); + + /* + * The instruction barrier ensures we don't read stale values of system + * registers. + */ + isb(); + + printf("Unhandled exception on CPU%u.\n", platform_get_core_pos(mpid)); + + /* Dump some interesting system registers. */ + printf("System registers:\n"); + printf(" MPIDR=0x%lx\n", mpid); + printf(" HSR=0x%lx ELR=0x%lx SPSR=0x%lx\n", read_hsr(), + read_elr_hyp(), read_spsr()); + + /* Dump general-purpose registers. */ + printf("General-purpose registers:\n"); + for (int i = 0; i < GPREGS_CNT; ++i) { + printf(" r%u=0x%lx\n", i, ctx->regs[i]); + } + printf(" LR=0x%lx\n", ctx->lr); + printf(" SP=0x%lx\n", ctx->sp); + + while (1) + wfi(); +} diff --git a/tftf/framework/aarch32/exceptions.S b/tftf/framework/aarch32/exceptions.S index 1e6c574db..aaeb93c1a 100644 --- a/tftf/framework/aarch32/exceptions.S +++ b/tftf/framework/aarch32/exceptions.S @@ -12,13 +12,23 @@ vector_base tftf_vector b tftf_entrypoint - b . /* Undef */ - b . /* Syscall */ - b . /* Prefetch abort */ - b . /* Data abort */ - b . /* Hyp trap */ - b tftf_intr_handle/* IRQ */ - b . /* FIQ */ + b crash_dump /* Undef */ + b crash_dump /* Syscall */ + b crash_dump /* Prefetch abort */ + b crash_dump /* Data abort */ + b crash_dump /* Hyp trap */ + b tftf_intr_handle /* IRQ */ + b crash_dump /* FIQ */ + +func crash_dump + /* Save SP and general-purpose registers on the stack. */ + push {sp} + push {r0-r12, lr} + + /* Print the saved CPU context on the UART. */ + mov r0, sp + b print_exception +endfunc crash_dump /* ---------------------------------------------------------------------------- * The IRQ exception handler diff --git a/tftf/framework/aarch64/exception_report.c b/tftf/framework/aarch64/exception_report.c new file mode 100644 index 000000000..0add2764a --- /dev/null +++ b/tftf/framework/aarch64/exception_report.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> +#include <stdio.h> + +#include <arch_helpers.h> +#include <debug.h> +#include <platform.h> +#include <utils_def.h> + +/* We save x0-x30. */ +#define GPREGS_CNT 31 + +/* Set of registers saved by the crash_dump() assembly function. */ +struct cpu_context { + u_register_t regs[GPREGS_CNT]; + u_register_t sp; +}; + +/* + * Read the EL1 or EL2 version of a register, depending on the current exception + * level. + */ +#define read_sysreg(_name) \ + (IS_IN_EL2() ? read_##_name##_el2() : read_##_name##_el1()) + +void __dead2 print_exception(const struct cpu_context *ctx) +{ + u_register_t mpid = read_mpidr_el1(); + + /* + * The instruction barrier ensures we don't read stale values of system + * registers. + */ + isb(); + + printf("Unhandled exception on CPU%u.\n", platform_get_core_pos(mpid)); + + /* Dump some interesting system registers. */ + printf("System registers:\n"); + printf(" MPIDR=0x%lx\n", mpid); + printf(" ESR=0x%lx ELR=0x%lx FAR=0x%lx\n", read_sysreg(esr), + read_sysreg(elr), read_sysreg(far)); + printf(" SCTLR=0x%lx SPSR=0x%lx DAIF=0x%lx\n", + read_sysreg(sctlr), read_sysreg(spsr), read_daif()); + + /* Dump general-purpose registers. */ + printf("General-purpose registers:\n"); + for (int i = 0; i < GPREGS_CNT; ++i) { + printf(" x%u=0x%lx\n", i, ctx->regs[i]); + } + printf(" SP=0x%lx\n", ctx->sp); + + while (1) + wfi(); +} diff --git a/tftf/framework/aarch64/exceptions.S b/tftf/framework/aarch64/exceptions.S index 6014b12ed..677b30fe9 100644 --- a/tftf/framework/aarch64/exceptions.S +++ b/tftf/framework/aarch64/exceptions.S @@ -8,88 +8,54 @@ .globl tftf_vector +/* + * Exception vector code for unhandled exceptions. + * Print a crash dump on the UART and loops forever. + */ +.macro unhandled_exception name + vector_entry \name + b crash_dump + end_vector_entry \name +.endm + vector_base tftf_vector /* * Current EL with SP0 : 0x0 - 0x200. */ -vector_entry SynchronousExceptionSP0 - b SynchronousExceptionSP0 -end_vector_entry SynchronousExceptionSP0 - -vector_entry IrqSP0 - b IrqSP0 -end_vector_entry IrqSP0 - -vector_entry FiqSP0 - b FiqSP0 -end_vector_entry FiqSP0 - -vector_entry SErrorSP0 - b SErrorSP0 -end_vector_entry SErrorSP0 +unhandled_exception SynchronousExceptionSP0 +unhandled_exception IrqSP0 +unhandled_exception FiqSP0 +unhandled_exception SErrorSP0 /* * Current EL with SPx : 0x200 - 0x400. */ -vector_entry SynchronousExceptionSPx - b SynchronousExceptionSPx -end_vector_entry SynchronousExceptionSPx +unhandled_exception SynchronousExceptionSPx vector_entry IrqSPx b irq_vector_entry end_vector_entry IrqSPx -vector_entry FiqSPx - b FiqSPx -end_vector_entry FiqSPx - -vector_entry SErrorSPx - b SErrorSPx -end_vector_entry SErrorSPx +unhandled_exception FiqSPx +unhandled_exception SErrorSPx /* * Lower EL using AArch64 : 0x400 - 0x600. */ -vector_entry SynchronousExceptionA64 - b SynchronousExceptionA64 -end_vector_entry SynchronousExceptionA64 - -vector_entry IrqA64 - b IrqA64 -end_vector_entry IrqA64 - -vector_entry FiqA64 - b FiqA64 -end_vector_entry FiqA64 - -vector_entry SErrorA64 - b SErrorA64 -end_vector_entry SErrorA64 +unhandled_exception SynchronousExceptionA64 +unhandled_exception IrqA64 +unhandled_exception FiqA64 +unhandled_exception SErrorA64 /* * Lower EL using AArch32 : 0x600 - 0x800. */ -vector_entry SynchronousExceptionA32 - b SynchronousExceptionA32 -end_vector_entry SynchronousExceptionA32 +unhandled_exception SynchronousExceptionA32 +unhandled_exception IrqA32 +unhandled_exception FiqA32 +unhandled_exception SErrorA32 -vector_entry IrqA32 - b IrqA32 -end_vector_entry IrqA32 - -vector_entry FiqA32 - b FiqA32 -end_vector_entry FiqA32 - -vector_entry SErrorA32 - b SErrorA32 -end_vector_entry SErrorA32 - -/* - * Exceptions will always be from the same exception level so no need to save - * and restore SPSR. - */ .macro save_gp_regs stp x0, x1, [sp, #0x0] stp x2, x3, [sp, #0x10] @@ -106,13 +72,12 @@ end_vector_entry SErrorA32 stp x24, x25, [sp, #0xc0] stp x26, x27, [sp, #0xd0] stp x28, x29, [sp, #0xe0] - mrs x0, sp_el0 - stp x30, x0, [sp, #0xf0] + /* We push xzr simply to keep the stack 16-byte aligned. */ + stp x30, xzr, [sp, #0xf0] .endm .macro restore_gp_regs - ldp x30, x0, [sp, #0xf0] - msr sp_el0, x0 + ldp x30, xzr, [sp, #0xf0] ldp x28, x29, [sp, #0xe0] ldp x26, x27, [sp, #0xd0] ldp x24, x25, [sp, #0xc0] @@ -138,3 +103,17 @@ func irq_vector_entry add sp, sp, #0x100 eret endfunc irq_vector_entry + +func crash_dump + /* Save general-purpose registers on the stack. */ + sub sp, sp, #0x100 + save_gp_regs + + /* Save original stack pointer value on the stack. */ + add x1, sp, #0x100 + str x1, [sp, #0xf8] + + /* Print the saved CPU context on the UART. */ + mov x0, sp + b print_exception +endfunc crash_dump diff --git a/tftf/framework/framework.mk b/tftf/framework/framework.mk index 4e5dc2e65..36b29b23e 100644 --- a/tftf/framework/framework.mk +++ b/tftf/framework/framework.mk @@ -51,6 +51,7 @@ FRAMEWORK_SOURCES += $(addprefix tftf/, \ framework/${ARCH}/asm_debug.S \ framework/${ARCH}/entrypoint.S \ framework/${ARCH}/exceptions.S \ + framework/${ARCH}/exception_report.c \ framework/debug.c \ framework/main.c \ framework/nvm_results_helpers.c \ |