diff options
author | Daisuke Nojiri <dnojiri@google.com> | 2013-03-25 16:07:08 -0700 |
---|---|---|
committer | ChromeBot <chrome-bot@google.com> | 2013-04-05 11:28:48 -0700 |
commit | 0d1c48ea7c4dd25a718f63ce3cbcee8ee0fa026a (patch) | |
tree | 2f74bd80036da903a8194bbef0f37ec65094bfa9 | |
parent | a3dcfd54ef29ac7cbd988ce94e96bcc6ba924ac6 (diff) | |
download | chrome-ec-0d1c48ea7c4dd25a718f63ce3cbcee8ee0fa026a.tar.gz |
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>
-rw-r--r-- | core/cortex-m/panic.c | 98 |
1 files changed, 93 insertions, 5 deletions
diff --git a/core/cortex-m/panic.c b/core/cortex-m/panic.c index 91ea733f04..1b28aa00bf 100644 --- a/core/cortex-m/panic.c +++ b/core/cortex-m/panic.c @@ -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) |