diff options
-rw-r--r-- | chip/ish/config_chip.h | 5 | ||||
-rw-r--r-- | common/panic_output.c | 1 | ||||
-rw-r--r-- | core/minute-ia/panic.c | 108 | ||||
-rw-r--r-- | include/config.h | 24 | ||||
-rw-r--r-- | include/panic.h | 9 |
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 */ |