summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/panic_output.c26
-rw-r--r--core/minute-ia/panic.c70
-rw-r--r--core/nds32/panic.c18
-rw-r--r--include/software_panic.h11
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 */