summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaisuke Nojiri <dnojiri@google.com>2013-03-25 16:07:08 -0700
committerChromeBot <chrome-bot@google.com>2013-04-05 11:28:48 -0700
commit0d1c48ea7c4dd25a718f63ce3cbcee8ee0fa026a (patch)
tree2f74bd80036da903a8194bbef0f37ec65094bfa9
parenta3dcfd54ef29ac7cbd988ce94e96bcc6ba924ac6 (diff)
downloadchrome-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.c98
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)