Dumping stack contents on crash.

> crash divzero

=== EXCEPTION: 06 ====== xPSR: 01000200 ===========
r0 :00000000 r1 :0000db92 r2 :4000c018 r3 :200029c8
r4 :00000001 r5 :00000000 r6 :200056e4 r7 :00000000
r8 :00000000 r9 :200056f2 r10:00000000 r11:00000000
r12:00000000 sp :20002958 lr :00000355 pc :00000360
Divide by 0
mmfs = 2000000, shcsr = 70008, hfsr = 0, dfsr = 0

=========== Process Stack Contents ===========
200029c4: 200029c8 0000033d 00000002 0000d1b8
200029d4: 000095ef 200056e4 200056ea 00000000
200029e4: 00000000 00000000 00000000 00000000
200029f4: 00000000 00000000 00000000 00000000

Rebooting...

BUG=chrome-os-partner:16901
TEST=build link
BRANCH=none

Change-Id: I040a9cadf443bfdb3781ffc25a3376bf4aea30ef
Signed-off-by: Daisuke Nojiri <dnojiri@google.com>
Reviewed-on: https://gerrit.chromium.org/gerrit/46455
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
This commit is contained in:
Daisuke Nojiri
2013-03-25 16:07:08 -07:00
committed by ChromeBot
parent a3dcfd54ef
commit 0d1c48ea7c

View File

@@ -119,6 +119,17 @@ static void print_reg(int regnum, const uint32_t *regs, int index)
panic_puts((regnum & 3) == 3 ? "\n" : " ");
}
/*
* Returns non-zero if the exception frame was created on the main stack, or
* zero if it's on the process stack.
*
* See B1.5.8 "Exception return behavior" of ARM DDI 0403D for details.
*/
static int is_exception_in_handler_context(const uint32_t exc_return)
{
return (exc_return & 0xf) == 1 || (exc_return & 0xf) == 9;
}
#ifdef CONFIG_PANIC_HELP
/* Names for each of the bits in the mmfs register, starting at bit 0 */
static const char * const mmfs_name[32] = {
@@ -226,7 +237,51 @@ static void show_fault(uint32_t mmfs, uint32_t hfsr, uint32_t dfsr)
}
}
/**
/*
* Returns the size of the exception frame.
*
* See B1.5.7 "Stack alignment on exception entry" of ARM DDI 0403D for details.
* In short, the exception frame size can be either 0x20, 0x24, 0x68, or 0x6c
* depending on FPU context and padding for 8-byte alignment.
*/
static uint32_t get_exception_frame_size(const struct panic_data *pdata)
{
uint32_t frame_size = 0;
/* base exception frame */
frame_size += 8 * sizeof(uint32_t);
/* CPU uses xPSR[9] to indicate whether it padded the stack for
* alignment or not. */
if (pdata->frame[7] & (1 << 9))
frame_size += sizeof(uint32_t);
#ifdef CONFIG_FPU
/* CPU uses EXC_RETURN[4] to indicate whether it stored extended
* frame for FPU or not. */
if (!(pdata->regs[2] & (1 << 4)))
frame_size += 18 * sizeof(uint32_t);
#endif
return frame_size;
}
/*
* Returns the position of the process stack before the exception frame.
* It computes the size of the exception frame and adds it to psp.
* If the exception happened in the exception context, it returns psp as is.
*/
static uint32_t get_process_stack_position(const struct panic_data *pdata)
{
uint32_t psp = pdata->regs[0];
if (!is_exception_in_handler_context(pdata->regs[2]))
psp += get_exception_frame_size(pdata);
return psp;
}
/*
* Show extra information that might be useful to understand a panic()
*
* We show fault register information, including the fault address registers
@@ -243,6 +298,30 @@ static void panic_show_extra(const struct panic_data *pdata)
panic_printf("shcsr = %x, ", pdata->shcsr);
panic_printf("hfsr = %x, ", pdata->hfsr);
panic_printf("dfsr = %x\n", pdata->dfsr);
panic_printf("exc_return = %x\n", pdata->regs[2]);
}
/*
* Prints process stack contents stored above the exception frame.
*/
static void panic_show_process_stack(const struct panic_data *pdata)
{
panic_printf("\n=========== Process Stack Contents ===========");
if (pdata->flags & PANIC_DATA_FLAG_FRAME_VALID) {
uint32_t psp = get_process_stack_position(pdata);
int i;
for (i = 0; i < 16; i++) {
if (psp + sizeof(uint32_t) >
CONFIG_RAM_BASE + CONFIG_RAM_SIZE)
break;
if (i % 4 == 0)
panic_printf("\n%08x:", psp);
panic_printf(" %08x", *(uint32_t *)psp);
psp += sizeof(uint32_t);
}
} else {
panic_printf("\nBad psp");
}
}
#endif /* CONFIG_PANIC_HELP */
@@ -268,7 +347,7 @@ static void panic_print(const struct panic_data *pdata)
sregs = pdata->frame;
panic_printf("\n=== EXCEPTION: %02x ====== xPSR: %08x ===========\n",
lregs[1] & 7, sregs ? sregs[7] : -1);
lregs[1] & 0xff, sregs ? sregs[7] : -1);
for (i = 0; i < 4; i++)
print_reg(i, sregs, i);
for (i = 4; i < 10; i++)
@@ -298,11 +377,12 @@ void report_panic(void)
pdata->reserved = 0;
/* If stack is valid, save exception frame */
if (psp >= CONFIG_RAM_BASE &&
psp <= CONFIG_RAM_BASE + CONFIG_RAM_SIZE + 8 * sizeof(uint32_t)) {
if (!is_exception_in_handler_context(pdata->regs[2]) &&
(psp & 3) == 0 &&
psp >= CONFIG_RAM_BASE &&
psp <= CONFIG_RAM_BASE + CONFIG_RAM_SIZE - 8 * sizeof(uint32_t)) {
const uint32_t *sregs = (const uint32_t *)psp;
int i;
for (i = 0; i < 8; i++)
pdata->frame[i] = sregs[i];
pdata->flags |= PANIC_DATA_FLAG_FRAME_VALID;
@@ -317,6 +397,11 @@ void report_panic(void)
pdata->dfsr = CPU_NVIC_DFSR;
panic_print(pdata);
#ifdef CONFIG_PANIC_HELP
panic_show_process_stack(pdata);
/* TODO: Dump main stack contents as well if the exception happened
* in a handler's context. */
#endif
panic_reboot();
}
@@ -339,6 +424,9 @@ void exception_panic(void)
* compute [pregs] below if the asm blocks are separate, but if
* they are merged it uses two temporary registers and two
* immediate values.
*
* TODO: Save sp somewhere so that we can access exception frame
* when exception happens in handler's context.
*/
"mov sp, %[pstack]\n" : :
[pstack] "r" (pstack_addr)