[coreboot-gerrit] New patch to review for coreboot: 8e8f573 arm: Fix stored PC value when handling exceptions

Marc Jones (marc.jones@se-eng.com) gerrit at coreboot.org
Wed Dec 31 06:34:47 CET 2014


Marc Jones (marc.jones at se-eng.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/7992

-gerrit

commit 8e8f573592078528a2bfe9872cebf52d5205acbe
Author: Julius Werner <jwerner at chromium.org>
Date:   Wed May 14 14:53:18 2014 -0700

    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 at chromium.org>
    Original-Reviewed-on: https://chromium-review.googlesource.com/199844
    Original-Reviewed-by: Stefan Reinauer <reinauer at chromium.org>
    Original-Reviewed-by: Vincent Palatin <vpalatin at chromium.org>
    (cherry picked from commit 4a914d36bb181d090f75b1414158846d40dc9bac)
    Signed-off-by: Marc Jones <marc.jones at se-eng.com>
    
    Change-Id: Ib63ca973d5f037a879b4d4d258a4983160b67dd6
---
 payloads/libpayload/arch/arm/exception_asm.S | 19 +++++++++++++++++++
 src/arch/arm/armv7/exception.c               |  5 +++++
 2 files changed, 24 insertions(+)

diff --git a/payloads/libpayload/arch/arm/exception_asm.S b/payloads/libpayload/arch/arm/exception_asm.S
index 974d172..7b722cb 100644
--- a/payloads/libpayload/arch/arm/exception_asm.S
+++ b/payloads/libpayload/arch/arm/exception_asm.S
@@ -45,25 +45,44 @@ exception_table:
 1:
 	mov	sp, $0
 	b	exception_common
+
+/* Undefined Instruction (CAREFUL: the PC offset is specific to thumb mode!) */
 2:
+	sub	lr, lr, $2
 	mov	sp, $1
 	b	exception_common
+
+/* Software Interrupt (no PC offset necessary) */
 3:
 	mov	sp, $2
 	b	exception_common
+
+/* Prefetch Abort */
 4:
+	sub	lr, lr, $4
 	mov	sp, $3
 	b	exception_common
+
+/* Data Abort */
 5:
+	sub	lr, lr, $8
 	mov	sp, $4
 	b	exception_common
+
+/* (not used) */
 6:
 	mov	sp, $5
 	b	exception_common
+
+/* Interrupt */
 7:
+	sub	lr, lr, $4
 	mov	sp, $6
 	b	exception_common
+
+/* Fast Interrupt */
 8:
+	sub	lr, lr, $4
 	mov	sp, $7
 	b	exception_common
 
diff --git a/src/arch/arm/armv7/exception.c b/src/arch/arm/armv7/exception.c
index b02e5c1..eedd47d 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");



More information about the coreboot-gerrit mailing list