diff options
-rw-r--r-- | common/panic_output.c | 26 | ||||
-rw-r--r-- | core/minute-ia/panic.c | 70 | ||||
-rw-r--r-- | core/nds32/panic.c | 18 | ||||
-rw-r--r-- | include/software_panic.h | 11 |
4 files changed, 96 insertions, 29 deletions
diff --git a/common/panic_output.c b/common/panic_output.c index 8d34adaa38..1d85e0a9d8 100644 --- a/common/panic_output.c +++ b/common/panic_output.c @@ -10,6 +10,7 @@ #include "host_command.h" #include "panic.h" #include "printf.h" +#include "software_panic.h" #include "system.h" #include "task.h" #include "timer.h" @@ -19,6 +20,31 @@ /* Panic data goes at the end of RAM. */ static struct panic_data * const pdata_ptr = PANIC_DATA_PTR; +/* Common SW Panic reasons strings */ +const char * const panic_sw_reasons[] = { +#ifdef CONFIG_SOFTWARE_PANIC + "PANIC_SW_DIV_ZERO", + "PANIC_SW_STACK_OVERFLOW", + "PANIC_SW_PD_CRASH", + "PANIC_SW_ASSERT", + "PANIC_SW_WATCHDOG", + "PANIC_SW_RNG", + "PANIC_SW_PMIC_FAULT", +#endif +}; + +/** + * Check an interrupt vector as being a valid software panic + * @param reason Reason for panic + * @return 0 if not a valid software panic reason, otherwise non-zero. + */ +int panic_sw_reason_is_valid(uint32_t reason) +{ + return (IS_ENABLED(CONFIG_SOFTWARE_PANIC) && + reason >= PANIC_SW_BASE && + (reason - PANIC_SW_BASE) < ARRAY_SIZE(panic_sw_reasons)); +} + /** * Add a character directly to the UART buffer. * diff --git a/core/minute-ia/panic.c b/core/minute-ia/panic.c index 0898e4e717..442a69464a 100644 --- a/core/minute-ia/panic.c +++ b/core/minute-ia/panic.c @@ -9,6 +9,7 @@ #include "host_command.h" #include "panic.h" #include "printf.h" +#include "software_panic.h" #include "system.h" #include "task.h" #include "timer.h" @@ -50,10 +51,17 @@ const static char *panic_reason[] = { */ void panic_data_print(const struct panic_data *pdata) { - if (pdata->x86.vector == ISH_WDT_VEC) + if (pdata->x86.vector == PANIC_SW_WATCHDOG) panic_printf("Reason: Watchdog Expiration\n"); else if (pdata->x86.vector <= 20) panic_printf("Reason: %s\n", panic_reason[pdata->x86.vector]); + else if (panic_sw_reason_is_valid(pdata->x86.vector)) { + panic_printf("Software panic reason %s\n", + panic_sw_reasons[pdata->x86.vector - + PANIC_SW_BASE]); + panic_printf("Software panic info 0x%x\n", + pdata->x86.error_code); + } else panic_printf("Interrupt vector number: 0x%08X (unknown)\n", pdata->x86.vector); @@ -81,7 +89,7 @@ void panic_data_print(const struct panic_data *pdata) * order pushed to the stack by hardware: see "Intel 64 and IA-32 * Architectures Software Developer's Manual", Volume 3A, Figure 6-4. */ -__attribute__ ((noreturn)) void __keep exception_panic( +__attribute__((noreturn)) void __keep exception_panic( uint32_t vector, uint32_t error_code, uint32_t eip, @@ -111,6 +119,13 @@ __attribute__ ((noreturn)) void __keep exception_panic( PANIC_DATA_PTR->x86.esi = esi; PANIC_DATA_PTR->x86.edi = edi; + /* + * Convert ISH_WDT_VEC to be a SW Watchdog. This is for + * code that is in system_common_pre_init + */ + if (vector == ISH_WDT_VEC) + vector = PANIC_SW_WATCHDOG; + /* Save stack data to global panic structure */ PANIC_DATA_PTR->x86.vector = vector; PANIC_DATA_PTR->x86.error_code = error_code; @@ -134,32 +149,63 @@ __attribute__ ((noreturn)) void __keep exception_panic( panic_printf("Resetting system...\n"); panic_printf("===========================\n"); - if (panic_once) { + /* + * Post increment panic_once to make sure we only go through + * once before we resort to a hard reset + */ + if (panic_once++) system_reset(SYSTEM_RESET_HARD); - } else if (vector == ISH_WDT_VEC) { - panic_once = 1; + else if (vector == PANIC_SW_WATCHDOG) system_reset(SYSTEM_RESET_AP_WATCHDOG); - } else { - panic_once = 1; + else if (panic_sw_reason_is_valid(vector)) + system_reset(SYSTEM_RESET_MANUALLY_TRIGGERED); + else system_reset(0); - } __builtin_unreachable(); } #ifdef CONFIG_SOFTWARE_PANIC -void software_panic(uint32_t reason, uint32_t info) +__attribute__((noreturn)) void software_panic(uint32_t reason, uint32_t info) { - /* TODO: store panic log */ - while (1) - continue; + uint16_t code_segment; + + /* Get the current code segment */ + __asm__ volatile ("movw %%cs, %0":"=m" (code_segment)); + + exception_panic(reason, + info, + (uint32_t)__builtin_return_address(0), + code_segment, + 0); + + __builtin_unreachable(); } void panic_set_reason(uint32_t reason, uint32_t info, uint8_t exception) { + /* Setup panic data structure */ + memset(PANIC_DATA_PTR, 0, sizeof(struct panic_data)); + PANIC_DATA_PTR->magic = PANIC_DATA_MAGIC; + PANIC_DATA_PTR->struct_size = sizeof(struct panic_data); + PANIC_DATA_PTR->struct_version = 2; + PANIC_DATA_PTR->arch = PANIC_ARCH_X86; + + /* Log panic cause */ + PANIC_DATA_PTR->x86.vector = reason; + PANIC_DATA_PTR->x86.error_code = info; + PANIC_DATA_PTR->x86.eflags = exception; } void panic_get_reason(uint32_t *reason, uint32_t *info, uint8_t *exception) { + if (PANIC_DATA_PTR->magic == PANIC_DATA_MAGIC && + PANIC_DATA_PTR->struct_version == 2) { + *reason = PANIC_DATA_PTR->x86.vector; + *info = PANIC_DATA_PTR->x86.error_code; + *exception = PANIC_DATA_PTR->x86.eflags; + } else { + *reason = *info = *exception = 0; + } } #endif diff --git a/core/nds32/panic.c b/core/nds32/panic.c index 3dabc1d2f0..9bc06fc409 100644 --- a/core/nds32/panic.c +++ b/core/nds32/panic.c @@ -8,6 +8,7 @@ #include "cpu.h" #include "panic.h" #include "printf.h" +#include "software_panic.h" #include "system.h" #include "task.h" #include "timer.h" @@ -78,18 +79,6 @@ static const char * const itype_exc_type[16] = { #endif /* CONFIG_DEBUG_EXCEPTIONS */ #ifdef CONFIG_SOFTWARE_PANIC -/* Software panic reasons */ -static const char * const panic_sw_reasons[8] = { - "PANIC_SW_DIV_ZERO", - "PANIC_SW_STACK_OVERFLOW", - "PANIC_SW_PD_CRASH", - "PANIC_SW_ASSERT", - "PANIC_SW_WATCHDOG", - NULL, - NULL, - NULL, -}; - void software_panic(uint32_t reason, uint32_t info) { asm volatile ("mov55 $r6, %0" : : "r"(reason)); @@ -163,10 +152,11 @@ static void print_panic_information(uint32_t *regs, uint32_t itype, #ifdef CONFIG_DEBUG_EXCEPTIONS panic_printf("SWID of ITYPE: %x\n", ((itype >> 16) & 0x7fff)); - if ((regs[SOFT_PANIC_GPR_REASON] & 0xfffffff0) == PANIC_SW_BASE) { + if (panic_sw_reason_is_valid(regs[SOFT_PANIC_GPR_REASON])) { #ifdef CONFIG_SOFTWARE_PANIC panic_printf("Software panic reason %s\n", - panic_sw_reasons[(regs[SOFT_PANIC_GPR_REASON] & 0x7)]); + panic_sw_reasons[(regs[SOFT_PANIC_GPR_REASON] - + PANIC_SW_BASE)]); panic_printf("Software panic info 0x%x\n", regs[SOFT_PANIC_GPR_INFO]); #endif diff --git a/include/software_panic.h b/include/software_panic.h index 99205f02c3..2702c6dc92 100644 --- a/include/software_panic.h +++ b/include/software_panic.h @@ -1,10 +1,10 @@ -/* Copyright (c) 2015 The Chromium OS Authors. All rights reserved. +/* Copyright 2019 The Chromium OS Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. - * - * Software panic constants. This file must be parsable by the assembler. */ +/* Software panic constants. This file must be parsable by the assembler. */ + #ifndef __CROS_EC_SOFTWARE_PANIC_H #define __CROS_EC_SOFTWARE_PANIC_H @@ -23,4 +23,9 @@ #define PANIC_SW_BAD_RNG (PANIC_SW_BASE + 5) #define PANIC_SW_PMIC_FAULT (PANIC_SW_BASE + 6) +#ifndef __ASSEMBLER__ +extern const char * const panic_sw_reasons[]; +extern int panic_sw_reason_is_valid(uint32_t vec); +#endif + #endif /* __CROS_EC_SOFTWARE_PANIC_H */ |