summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Rosenthal <jrosenth@chromium.org>2019-05-02 09:58:48 -0600
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-05-01 21:28:35 +0000
commita1f6a6816f2a7f1394626e9c11cd9b29b6405c18 (patch)
treedcd3e044784cec84bbbfa591b5edb518f2934d53
parentbf211080d8e13f5b31fa51dac98397a42d81fcd5 (diff)
downloadchrome-ec-a1f6a6816f2a7f1394626e9c11cd9b29b6405c18.tar.gz
ish: preserve panic data across reset
This commit stores panic data across reset by storing panic data in the last 256 bytes of AON memory (before AON ROM). > crash divzero ========== PANIC ========== Reason: Divide By Zero Error Code = 0xFF00B60C EIP = 0xFF010008 CS = 0x00010202 EFLAGS = 0x00103085 EAX = 0x00000001 EBX = 0xFF01B118 ECX = 0x00000000 EDX = 0x00000000 ESI = 0x00000000 EDI = 0xFF017E0E Resetting system... =========================== ... ISH reset ... > panicinfo Saved panic data: (NEW) Reason: Divide By Zero Error Code = 0xFF00B60C EIP = 0xFF010008 CS = 0x00010202 EFLAGS = 0x00103085 EAX = 0x00000001 EBX = 0xFF01B118 ECX = 0x00000000 EDX = 0x00000000 ESI = 0x00000000 EDI = 0xFF017E0E BUG=b:129425206 BRANCH=none TEST=see console output above (on arcada_ish) Change-Id: I5c9e458b53076eafe7fa50ba851f2c6e863f2247 Signed-off-by: Jack Rosenthal <jrosenth@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1593418 Reviewed-by: Jett Rink <jettrink@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4469247 Commit-Queue: Rob Barnes <robbarnes@google.com> Reviewed-by: Boris Mittelberg <bmbm@google.com> Tested-by: Rob Barnes <robbarnes@google.com>
-rw-r--r--chip/ish/config_chip.h5
-rw-r--r--common/panic_output.c1
-rw-r--r--core/minute-ia/panic.c108
-rw-r--r--include/config.h24
-rw-r--r--include/panic.h9
5 files changed, 134 insertions, 13 deletions
diff --git a/chip/ish/config_chip.h b/chip/ish/config_chip.h
index 273bcd0788..63f3affa1f 100644
--- a/chip/ish/config_chip.h
+++ b/chip/ish/config_chip.h
@@ -40,6 +40,11 @@
#define CONFIG_RAM_SIZE CONFIG_ISH_SRAM_SIZE
#define CONFIG_RAM_BASE CONFIG_ISH_SRAM_BASE_START
+/* Store persistent panic data in AON memory */
+#define CONFIG_PANIC_DATA_SIZE 0xFF
+#define CONFIG_PANIC_DATA_BASE (CONFIG_AON_ROM_BASE \
+ - CONFIG_PANIC_DATA_SIZE)
+
/* System stack size */
#define CONFIG_STACK_SIZE 1024
diff --git a/common/panic_output.c b/common/panic_output.c
index 06b2b7e51e..e9f8f696b3 100644
--- a/common/panic_output.c
+++ b/common/panic_output.c
@@ -114,6 +114,7 @@ void panic(const char *msg)
struct panic_data *panic_get_data(void)
{
+ BUILD_ASSERT(sizeof(struct panic_data) <= CONFIG_PANIC_DATA_SIZE);
return pdata_ptr->magic == PANIC_DATA_MAGIC ? pdata_ptr : NULL;
}
diff --git a/core/minute-ia/panic.c b/core/minute-ia/panic.c
index c8cbe9d14c..7e1be1b76b 100644
--- a/core/minute-ia/panic.c
+++ b/core/minute-ia/panic.c
@@ -13,20 +13,62 @@
#include "task.h"
#include "timer.h"
#include "util.h"
-#include "watchdog.h"
/* Whether bus fault is ignored */
static int bus_fault_ignored;
/*
- * Print panic data
+ * This array maps an interrupt vector number to the corresponding
+ * exception name. See see "Intel 64 and IA-32 Architectures Software
+ * Developer's Manual", Volume 3A, Section 6.15.
*/
-void panic_data_print(const struct panic_data *pdata)
-{
-}
+const static char *panic_reason[] = {
+ "Divide By Zero",
+ "Debug Exception",
+ "NMI Interrupt",
+ "Breakpoint Exception",
+ "Overflow Exception",
+ "BOUND Range Exceeded Exception",
+ "Invalid Opcode Exception",
+ "Device Not Available Exception",
+ "Double Fault Exception",
+ "Coprocessor Segment Overrun",
+ "Invalid TSS Exception",
+ "Segment Not Present",
+ "Stack Fault Exception",
+ "General Protection Fault",
+ "Page Fault",
+ "Reserved",
+ "Math Fault",
+ "Alignment Check Exception",
+ "Machine Check Exception",
+ "SIMD Floating Point Exception",
+ "Virtualization Exception",
+};
-void __keep report_panic(void)
+/*
+ * Print panic data. This may be called either from the report_panic
+ * procedure (below) while handling a panic, or from the panicinfo
+ * console command.
+ */
+void panic_data_print(const struct panic_data *pdata)
{
+ if (pdata->x86.vector <= 20)
+ panic_printf("Reason: %s\n", panic_reason[pdata->x86.vector]);
+ else
+ panic_printf("Interrupt vector number: 0x%08X (unknown)\n",
+ pdata->x86.vector);
+ panic_printf("\n");
+ panic_printf("Error Code = 0x%08X\n", pdata->x86.error_code);
+ panic_printf("EIP = 0x%08X\n", pdata->x86.eip);
+ panic_printf("CS = 0x%08X\n", pdata->x86.cs);
+ panic_printf("EFLAGS = 0x%08X\n", pdata->x86.eflags);
+ panic_printf("EAX = 0x%08X\n", pdata->x86.eax);
+ panic_printf("EBX = 0x%08X\n", pdata->x86.ebx);
+ panic_printf("ECX = 0x%08X\n", pdata->x86.ecx);
+ panic_printf("EDX = 0x%08X\n", pdata->x86.edx);
+ panic_printf("ESI = 0x%08X\n", pdata->x86.esi);
+ panic_printf("EDI = 0x%08X\n", pdata->x86.edi);
}
/**
@@ -37,6 +79,60 @@ void __keep report_panic(void)
void __keep exception_panic(void);
void exception_panic(void)
{
+ /*
+ * If a panic were to occur during the reset procedure, we want
+ * to make sure that this panic will certainly cause a hard
+ * reset, rather than aontaskfw reset. Track if paniced once
+ * already.
+ */
+ static int panic_once;
+
+ register uint32_t eax asm("eax");
+ register uint32_t ebx asm("ebx");
+ register uint32_t ecx asm("ecx");
+ register uint32_t edx asm("edx");
+ register uint32_t esi asm("esi");
+ register uint32_t edi asm("edi");
+
+ /* Save registers to global panic structure */
+ PANIC_DATA_PTR->x86.eax = eax;
+ PANIC_DATA_PTR->x86.ebx = ebx;
+ PANIC_DATA_PTR->x86.ecx = ecx;
+ PANIC_DATA_PTR->x86.edx = edx;
+ PANIC_DATA_PTR->x86.esi = esi;
+ PANIC_DATA_PTR->x86.edi = edi;
+
+ /* Save stack data to global panic structure */
+ PANIC_DATA_PTR->x86.vector = vector;
+ PANIC_DATA_PTR->x86.error_code = error_code;
+ PANIC_DATA_PTR->x86.eip = eip;
+ PANIC_DATA_PTR->x86.cs = cs;
+ PANIC_DATA_PTR->x86.eflags = eflags;
+
+ /* Initialize panic data */
+ PANIC_DATA_PTR->arch = PANIC_ARCH_X86;
+ PANIC_DATA_PTR->struct_version = 2;
+ PANIC_DATA_PTR->magic = PANIC_DATA_MAGIC;
+
+ /* Display the panic and reset */
+ if (panic_once)
+ panic_printf("\nWhile resetting from a panic, another panic"
+ " occurred!");
+
+ panic_printf("\n========== PANIC ==========\n");
+ panic_data_print(PANIC_DATA_PTR);
+ panic_printf("\n");
+ panic_printf("Resetting system...\n");
+ panic_printf("===========================\n");
+
+ if (panic_once) {
+ system_reset(SYSTEM_RESET_HARD);
+ } else {
+ panic_once = 1;
+ system_reset(0);
+ }
+
+ __builtin_unreachable();
}
#ifdef CONFIG_SOFTWARE_PANIC
diff --git a/include/config.h b/include/config.h
index 7467a0fe9e..f153145e30 100644
--- a/include/config.h
+++ b/include/config.h
@@ -2520,6 +2520,13 @@
/* Support One Time Protection structure */
#undef CONFIG_OTP
+/*
+ * Address to store persistent panic data at. By default, this will be
+ * at the end of RAM, and have a size of sizeof(struct panic_data)
+ */
+#undef CONFIG_PANIC_DATA_BASE
+#undef CONFIG_PANIC_DATA_SIZE
+
/* Support PECI interface to x86 processor */
#undef CONFIG_PECI
@@ -3903,6 +3910,23 @@
/******************************************************************************/
/*
+ * Store panic data at end of memory by default, unless otherwise
+ * configured. This is safe because we don't context switch away from
+ * the panic handler before rebooting, and stacks and data start at
+ * the beginning of RAM.
+ */
+#ifndef CONFIG_PANIC_DATA_SIZE
+#define CONFIG_PANIC_DATA_SIZE sizeof(struct panic_data)
+#endif
+
+#ifndef CONFIG_PANIC_DATA_BASE
+#define CONFIG_PANIC_DATA_BASE (CONFIG_RAM_BASE \
+ + CONFIG_RAM_SIZE \
+ - CONFIG_PANIC_DATA_SIZE)
+#endif
+
+/******************************************************************************/
+/*
* Set minimum shared memory size, unless it is defined in board file.
*/
#ifndef CONFIG_SHAREDMEM_MINIMUM_SIZE
diff --git a/include/panic.h b/include/panic.h
index ffee055183..00a64b854d 100644
--- a/include/panic.h
+++ b/include/panic.h
@@ -68,13 +68,8 @@ enum panic_arch {
PANIC_ARCH_NDS32_N8 = 2, /* NDS32 N8 architecture */
};
-/*
- * 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
- * start at the beginning of RAM.
- */
-#define PANIC_DATA_PTR ((struct panic_data *)\
- (CONFIG_RAM_BASE + CONFIG_RAM_SIZE - sizeof(struct panic_data)))
+/* Use PANIC_DATA_PTR to refer to the persistent storage location */
+#define PANIC_DATA_PTR ((struct panic_data *)CONFIG_PANIC_DATA_BASE)
/* Flags for panic_data.flags */
/* panic_data.frame is valid */