mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-29 18:11:05 +00:00
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:
committed by
ChromeBot
parent
a3dcfd54ef
commit
0d1c48ea7c
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user