summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2012-08-31 13:10:16 -0700
committerCharlie Mooney <charliemooney@chromium.org>2012-09-17 17:01:05 -0700
commit833898a07c5da3145cd6c8157c1b7925c37cf5a6 (patch)
treee38139e4c86d37ed9986477014446d9b94542961
parent30f8374fa0a47c633ff6b149f425c865b910545c (diff)
downloadchrome-ec-833898a07c5da3145cd6c8157c1b7925c37cf5a6.tar.gz
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 <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/32051 Reviewed-on: https://gerrit.chromium.org/gerrit/32355 Reviewed-by: David Hendricks <dhendrix@chromium.org> Tested-by: David Hendricks <dhendrix@chromium.org> (cherry picked from commit 5f92fdc0b6ec36beeb5c1d447f052e5f77d29e39) Change-Id: Ibc3991c04797b88e453ef5bd25fa72751a056fac Signed-off-by: Charlie Mooney <charliemooney@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/33452 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--common/system_common.c24
-rw-r--r--core/cortex-m/panic.c61
-rw-r--r--include/panic.h51
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 <stdarg.h>
+/* 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 */