summaryrefslogtreecommitdiff
path: root/src/arch/arm/armv7/exception.c
diff options
context:
space:
mode:
authorJulius Werner <jwerner@chromium.org>2014-05-14 14:53:18 -0700
committerMarc Jones <marc.jones@se-eng.com>2015-01-03 00:26:18 +0100
commit989e12bb6387bd06037805dcefa249d998b55b74 (patch)
treeed3c6e76eac6026ca939df452622d27bc555d864 /src/arch/arm/armv7/exception.c
parent739e6a84aa9ccacf54db3da6c1e0777cb86ebea5 (diff)
downloadcoreboot-989e12bb6387bd06037805dcefa249d998b55b74.tar.xz
arm: Fix stored PC value when handling exceptions
ARM processors save the PC value in the Link Register when they handle and exception, but they store it with an added offset (depending on the exception type). In order to make crashes easier to read and correctly support more complicated handlers in libpayload, this patch adjusts the saved PC value on exception entry to correct for that offset. (Note: The value that we now store is what ARM calls the "preferred return address". For most exceptions this is the faulting instruction, but for software interrupts (SWI) it is the instruction after that. This is the way most programs like GDB expect the stored PC address to work, so let's leave it at that.) Numbers taken from the Architecture Reference Manual at the end of section B1.8.3. BRANCH=none BUG=chrome-os-partner:18390 TEST=Provoked a data abort and an undefined instruction in both coreboot and depthcharge, confirmed that the PC address was spot on. Original-Change-Id: Ia958a7edfcd4aa5e04c20148140a6148586935ba Original-Signed-off-by: Julius Werner <jwerner@chromium.org> Original-Reviewed-on: https://chromium-review.googlesource.com/199844 Original-Reviewed-by: Stefan Reinauer <reinauer@chromium.org> Original-Reviewed-by: Vincent Palatin <vpalatin@chromium.org> (cherry picked from commit 4a914d36bb181d090f75b1414158846d40dc9bac) Signed-off-by: Marc Jones <marc.jones@se-eng.com> Change-Id: Ib63ca973d5f037a879b4d4d258a4983160b67dd6 Reviewed-on: http://review.coreboot.org/7992 Tested-by: build bot (Jenkins) Reviewed-by: David Hendricks <dhendrix@chromium.org>
Diffstat (limited to 'src/arch/arm/armv7/exception.c')
-rw-r--r--src/arch/arm/armv7/exception.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/src/arch/arm/armv7/exception.c b/src/arch/arm/armv7/exception.c
index b02e5c1892..eedd47d1d5 100644
--- a/src/arch/arm/armv7/exception.c
+++ b/src/arch/arm/armv7/exception.c
@@ -81,6 +81,7 @@ static void print_regs(uint32_t *regs)
void exception_undefined_instruction(uint32_t *regs)
{
printk(BIOS_ERR, "exception _undefined_instruction\n");
+ regs[15] -= 2; /* CAREFUL: specific to thumb mode (otherwise 4)! */
print_regs(regs);
dump_stack(regs[13], 512);
die("exception");
@@ -97,6 +98,7 @@ void exception_software_interrupt(uint32_t *regs)
void exception_prefetch_abort(uint32_t *regs)
{
printk(BIOS_ERR, "exception _prefetch_abort\n");
+ regs[15] -= 4;
print_regs(regs);
dump_stack(regs[13], 512);
die("exception");
@@ -105,6 +107,7 @@ void exception_prefetch_abort(uint32_t *regs)
void exception_data_abort(uint32_t *regs)
{
printk(BIOS_ERR, "exception _data_abort\n");
+ regs[15] -= 8;
print_regs(regs);
dump_stack(regs[13], 512);
die("exception");
@@ -121,6 +124,7 @@ void exception_not_used(uint32_t *regs)
void exception_irq(uint32_t *regs)
{
printk(BIOS_ERR, "exception _irq\n");
+ regs[15] -= 4;
print_regs(regs);
dump_stack(regs[13], 512);
die("exception");
@@ -129,6 +133,7 @@ void exception_irq(uint32_t *regs)
void exception_fiq(uint32_t *regs)
{
printk(BIOS_ERR, "exception _fiq\n");
+ regs[15] -= 4;
print_regs(regs);
dump_stack(regs[13], 512);
die("exception");