From 833898a07c5da3145cd6c8157c1b7925c37cf5a6 Mon Sep 17 00:00:00 2001 From: Randall Spangler Date: Fri, 31 Aug 2012 13:10:16 -0700 Subject: Save panic data across reboots, and add panicinfo command Jump data now precedes the panic data, if any, in memory. BUG=chrome-os-partner:7466 BRANCH=all TEST=manual 1. boot system 2. sysjump rw --> display should stay on and keyboard should still work (this verifies jump data is properly read across sysjump still) 3. crash unaligned --> system should reboot 4. panicinfo --> should print the same crash dump as before, with (NEW) 5. panicinfo --> ditto, without (NEW) 6. sysjump rw 7. panicinfo --> ditto, without (NEW) Original-Change-Id: I88285724e82a15553ab25877e3d8ec4c74a4dd5a Signed-off-by: Randall Spangler Reviewed-on: https://gerrit.chromium.org/gerrit/32051 Reviewed-on: https://gerrit.chromium.org/gerrit/32355 Reviewed-by: David Hendricks Tested-by: David Hendricks (cherry picked from commit 5f92fdc0b6ec36beeb5c1d447f052e5f77d29e39) Change-Id: Ibc3991c04797b88e453ef5bd25fa72751a056fac Signed-off-by: Charlie Mooney Reviewed-on: https://gerrit.chromium.org/gerrit/33452 Reviewed-by: Randall Spangler --- common/system_common.c | 24 +++++++++++++++----- core/cortex-m/panic.c | 61 ++++++++++++++++++++++---------------------------- include/panic.h | 51 ++++++++++++++++++++++++++++++++++++++--- 3 files changed, 94 insertions(+), 42 deletions(-) diff --git a/common/system_common.c b/common/system_common.c index b4c68ecc10..5014d8579f 100644 --- a/common/system_common.c +++ b/common/system_common.c @@ -15,6 +15,7 @@ #include "hooks.h" #include "host_command.h" #include "lpc.h" +#include "panic.h" #include "system.h" #include "task.h" #include "uart.h" @@ -60,10 +61,8 @@ struct jump_data { * data from the previous image. */ }; -/* Jump data goes at the end of RAM */ -static struct jump_data * const jdata = - (struct jump_data *)(CONFIG_RAM_BASE + CONFIG_RAM_SIZE - - sizeof(struct jump_data)); +/* Jump data (at end of RAM, or preceding panic data) */ +static struct jump_data *jdata; /* * Reset flag descriptions. Must be in same order as bits of RESET_FLAG_ @@ -165,7 +164,7 @@ int system_add_jump_tag(uint16_t tag, int version, int size, const void *data) struct jump_tag *t; /* Only allowed during a sysjump */ - if (jdata->magic != JUMP_DATA_MAGIC) + if (!jdata || jdata->magic != JUMP_DATA_MAGIC) return EC_ERROR_UNKNOWN; /* Make room for the new tag */ @@ -188,6 +187,9 @@ const uint8_t *system_get_jump_tag(uint16_t tag, int *version, int *size) const struct jump_tag *t; int used = 0; + if (!jdata) + return NULL; + /* Search through tag data for a match */ while (used < jdata->jump_tag_total) { /* Check the next tag */ @@ -456,6 +458,18 @@ const char *system_get_build_info(void) int system_common_pre_init(void) { + uint32_t addr; + + /* + * Put the jump data before the panic data, or at the end of RAM if + * panic data is not present. + */ + addr = (uint32_t)panic_get_data(); + if (!addr) + addr = CONFIG_RAM_BASE + CONFIG_RAM_SIZE; + + jdata = (struct jump_data *)(addr - sizeof(struct jump_data)); + /* * Check jump data if this is a jump between images. Jumps all show up * as an unknown reset reason, because we jumped directly from one diff --git a/core/cortex-m/panic.c b/core/cortex-m/panic.c index fabd452052..b86295d49d 100644 --- a/core/cortex-m/panic.c +++ b/core/cortex-m/panic.c @@ -19,38 +19,6 @@ /* Whether bus fault is ignored */ static int bus_fault_ignored; -/* Data saved across reboots */ -struct panic_data { - uint8_t arch; /* Architecture (PANIC_ARCH_*) */ - uint8_t struct_version; /* Structure version (currently 1) */ - uint8_t flags; /* Flags (PANIC_DATA_FLAG_*) */ - uint8_t reserved; /* Reserved; set 0 */ - - uint32_t regs[11]; /* psp, ipsr, lr, r4-r11 */ - uint32_t frame[8]; /* r0-r3, r12, lr, pc, xPSR */ - - uint32_t mmfs; - uint32_t bfar; - uint32_t mfar; - uint32_t shcsr; - uint32_t hfsr; - uint32_t dfsr; - - /* - * These fields go at the END of the struct so we can find it at the - * end of memory. - */ - uint32_t struct_size; /* Size of this struct */ - uint32_t magic; /* PANIC_SAVE_MAGIC if valid */ -}; - -#define PANIC_DATA_MAGIC 0x21636e50 /* "Pnc!" */ - -#define PANIC_ARCH_CORTEX_M 1 - -/* Flags for panic_data.flags */ -#define PANIC_DATA_FLAG_FRAME_VALID (1 << 0) /* panic_data.frame is valid */ - /* * Panic data goes at the end of RAM. This is safe because we don't context * switch away from the panic handler before rebooting, and stacks and data @@ -59,6 +27,7 @@ struct panic_data { static struct panic_data * const pdata_ptr = (struct panic_data *)(CONFIG_RAM_BASE + CONFIG_RAM_SIZE - sizeof(struct panic_data)); + /* Preceded by stack, rounded down to nearest 64-bit-aligned boundary */ static const uint32_t pstack_addr = (CONFIG_RAM_BASE + CONFIG_RAM_SIZE - sizeof(struct panic_data)) & ~7; @@ -303,7 +272,7 @@ static void panic_show_extra(const struct panic_data *pdata) panic_printf("mmfs = %x, ", pdata->mmfs); panic_printf("shcsr = %x, ", pdata->shcsr); panic_printf("hfsr = %x, ", pdata->hfsr); - panic_printf("dfsr = %x", pdata->dfsr); + panic_printf("dfsr = %x\n", pdata->dfsr); } #endif /* CONFIG_PANIC_HELP */ @@ -457,7 +426,10 @@ void panic(const char *msg) panic_reboot(); } - +struct panic_data *panic_get_data(void) +{ + return pdata_ptr->magic == PANIC_DATA_MAGIC ? pdata_ptr : NULL; +} /*****************************************************************************/ /* Console commands */ @@ -486,3 +458,24 @@ DECLARE_CONSOLE_COMMAND(crash, command_crash, "[divzero | unaligned]", "Crash the system (for testing)", NULL); + +static int command_panicinfo(int argc, char **argv) +{ + if (pdata_ptr->magic == PANIC_DATA_MAGIC) { + ccprintf("Saved panic data:%s\n", + (pdata_ptr->flags & PANIC_DATA_FLAG_OLD_CONSOLE ? + "" : " (NEW)")); + + panic_print(pdata_ptr); + + /* Data has now been printed */ + pdata_ptr->flags |= PANIC_DATA_FLAG_OLD_CONSOLE; + } else { + ccprintf("No saved panic data available.\n"); + } + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(panicinfo, command_panicinfo, + NULL, + "Print info from a previous panic", + NULL); diff --git a/include/panic.h b/include/panic.h index ecf6eb0232..bb3e853bd2 100644 --- a/include/panic.h +++ b/include/panic.h @@ -6,9 +6,47 @@ * device, which is currently the UART. */ -#ifndef __PANIC_H +#ifndef __CROS_EC_PANIC_H +#define __CROS_EC_PANIC_H + #include +/* Data saved across reboots */ +struct panic_data { + uint8_t arch; /* Architecture (PANIC_ARCH_*) */ + uint8_t struct_version; /* Structure version (currently 1) */ + uint8_t flags; /* Flags (PANIC_DATA_FLAG_*) */ + uint8_t reserved; /* Reserved; set 0 */ + + uint32_t regs[11]; /* psp, ipsr, lr, r4-r11 */ + uint32_t frame[8]; /* r0-r3, r12, lr, pc, xPSR */ + + uint32_t mmfs; + uint32_t bfar; + uint32_t mfar; + uint32_t shcsr; + uint32_t hfsr; + uint32_t dfsr; + + /* + * These fields go at the END of the struct so we can find it at the + * end of memory. + */ + uint32_t struct_size; /* Size of this struct */ + uint32_t magic; /* PANIC_SAVE_MAGIC if valid */ +}; + +#define PANIC_DATA_MAGIC 0x21636e50 /* "Pnc!" */ +#define PANIC_ARCH_CORTEX_M 1 /* Cortex-M architecture */ + +/* Flags for panic_data.flags */ +/* panic_data.frame is valid */ +#define PANIC_DATA_FLAG_FRAME_VALID (1 << 0) +/* Already printed at console */ +#define PANIC_DATA_FLAG_OLD_CONSOLE (1 << 1) +/* Already returned via host command */ +#define PANIC_DATA_FLAG_OLD_HOSTCMD (1 << 2) + /** * Write a character to the panic reporting device * @@ -56,7 +94,6 @@ void panic_vprintf(const char *format, va_list args); */ void panic_printf(const char *format, ...); - /** * Report an assertion failure and reset * @@ -82,4 +119,12 @@ void panic(const char *msg); */ void ignore_bus_fault(int ignored); -#endif +/** + * Return a pointer to the saved data from a previous panic. + * + * @param pointer to the panic data, or NULL if none available (for example, + * the last reboot was not caused by a panic). + */ +struct panic_data *panic_get_data(void); + +#endif /* __CROS_EC_PANIC_H */ -- cgit v1.2.1