summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDino Li <dino.li@ite.com.tw>2015-10-07 14:49:40 +0800
committerchrome-bot <chrome-bot@chromium.org>2015-10-07 17:51:36 -0700
commit4bb7c3e2f1c6dc5fcd529c5ca62804c6e271d3ff (patch)
treeb1873e3b6c7ecf315faf565978adf0d8c22f355d
parentf769f9837ccda37eb9b34750bd317148f6d747e3 (diff)
downloadchrome-ec-4bb7c3e2f1c6dc5fcd529c5ca62804c6e271d3ff.tar.gz
nds32: fix panic
Support saving panic data for nds32 core. Signed-off-by: Dino Li <dino.li@ite.com.tw> BRANCH=none BUG=none TEST=1. console commands 'crash' and 'panicinfo'. 2. ectool command 'panicinfo' crash assert ASSERTION FAILURE '0' in command_crash() at common/panic_output.c:162 === EXCEP: ITYPE=1 === R0 00000000 R1 000000a2 R2 00000060 R3 00000000 R4 00080c40 R5 00000000 R6 dead6663 R7 000000a2 R8 00000002 R9 00000000 R10 00081960 R15 00000000 FP 00000000 GP 000818d8 LP 0000079a SP 00080c60 IPC 000007a2 IPSW 70009 SWID of ITYPE: 0 Software panic reason PANIC_SW_ASSERT Software panic info 0xa2 Rebooting... panicinfo Saved panic data: (NEW) === EXCEP: ITYPE=1 === R0 00000000 R1 000000a2 R2 00000060 R3 00000000 R4 00080c40 R5 00000000 R6 dead6663 R7 000000a2 R8 00000002 R9 00000000 R10 00081960 R15 00000000 FP 00000000 GP 000818d8 LP 0000079a SP 00080c60 IPC 000007a2 IPSW 70009 SWID of ITYPE: 0 Software panic reason PANIC_SW_ASSERT Software panic info 0xa2 > crash divzero === EXCEP: ITYPE=10003 === R0 00000000 R1 00f02705 R2 00000060 R3 00081a09 R4 00000000 R5 00000000 R6 00000001 R7 00080cc0 R8 00000002 R9 00000000 R10 00081961 R15 00000000 FP 00000000 GP 000818d8 LP 00009bce SP 00080c90 IPC 00009bee IPSW 70009 SWID of ITYPE: 1 Exception type: General exception [Arithmetic] Exception is caused by a data memory access Rebooting... panicinfo Saved panic data: (NEW) === EXCEP: ITYPE=10003 === R0 00000000 R1 00f02705 R2 00000060 R3 00081a09 R4 00000000 R5 00000000 R6 00000001 R7 00080cc0 R8 00000002 R9 00000000 R10 00081961 R15 00000000 FP 00000000 GP 000818d8 LP 00009bce SP 00080c90 IPC 00009bee IPSW 70009 SWID of ITYPE: 1 Exception type: General exception [Arithmetic] Exception is caused by a data memory access > crash stack +1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+16+17 Stack overflow in CONSOLE task! === EXCEP: ITYPE=8 === R0 00000002 R1 00000002 R2 00000060 R3 00080458 R4 0000ebdd R5 00000000 R6 dead6661 R7 00000002 R8 00000bc8 R9 00000002 R10 00000000 R15 00000000 FP 00000000 GP 000818d8 LP 0000079a SP 00080448 IPC 00000a92 IPSW 70009 SWID of ITYPE: 0 Software panic reason PANIC_SW_STACK_OVERFLOW Software panic info 0x2 Rebooting... panicinfo Saved panic data: (NEW) === EXCEP: ITYPE=8 === R0 00000002 R1 00000002 R2 00000060 R3 00080458 R4 0000ebdd R5 00000000 R6 dead6661 R7 00000002 R8 00000bc8 R9 00000002 R10 00000000 R15 00000000 FP 00000000 GP 000818d8 LP 0000079a SP 00080448 IPC 00000a92 IPSW 70009 SWID of ITYPE: 0 Software panic reason PANIC_SW_STACK_OVERFLOW Software panic info 0x2 > crash watchdog Pre-watchdog warning! IPC: 00009c6c panicinfo Saved panic data: (NEW) === EXCEP: ITYPE=0 === R0 00000000 R1 00000000 R2 00000000 R3 00000000 R4 00000000 R5 00000000 R6 dead6664 R7 00000000 R8 00000000 R9 00000000 R10 00000000 R15 00000000 FP 00000000 GP 00000000 LP 00000000 SP 00000000 IPC 00009c6c IPSW 00000 SWID of ITYPE: 0 Software panic reason PANIC_SW_WATCHDOG Software panic info 0x0 > Change-Id: I3d491ecd0789335db4633f9bf2ca09cf85503ed9 Reviewed-on: https://chromium-review.googlesource.com/303286 Commit-Ready: Dino Li <dino.li@ite.com.tw> Tested-by: Dino Li <dino.li@ite.com.tw> Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--chip/it83xx/watchdog.c6
-rw-r--r--core/nds32/config_core.h2
-rw-r--r--core/nds32/panic.c177
-rw-r--r--core/nds32/task.c19
-rw-r--r--include/panic.h16
-rw-r--r--util/ectool.c92
6 files changed, 277 insertions, 35 deletions
diff --git a/chip/it83xx/watchdog.c b/chip/it83xx/watchdog.c
index e6941b1de5..6c15afc60a 100644
--- a/chip/it83xx/watchdog.c
+++ b/chip/it83xx/watchdog.c
@@ -14,6 +14,9 @@
#include "task.h"
#include "watchdog.h"
+/* Panic data goes at the end of RAM. */
+static struct panic_data * const pdata_ptr = PANIC_DATA_PTR;
+
/*
* We use WDT_EXT_TIMER to trigger an interrupt just before the watchdog timer
* will fire so that we can capture important state information before
@@ -25,6 +28,9 @@
void watchdog_warning_irq(void)
{
+#ifdef CONFIG_SOFTWARE_PANIC
+ pdata_ptr->nds_n8.ipc = get_ipc();
+#endif
/* clear interrupt status */
task_clear_pending_irq(et_ctrl_regs[WDT_EXT_TIMER].irq);
diff --git a/core/nds32/config_core.h b/core/nds32/config_core.h
index 0bf6595611..fae914f7eb 100644
--- a/core/nds32/config_core.h
+++ b/core/nds32/config_core.h
@@ -10,6 +10,8 @@
#define BFD_ARCH nds32
#define BFD_FORMAT "elf32-nds32le"
+#define CONFIG_SOFTWARE_PANIC
+
/*
* The Andestar v3m architecture has no CLZ instruction (contrary to v3),
* so let's use the software implementation.
diff --git a/core/nds32/panic.c b/core/nds32/panic.c
index 79cd065321..e1bd4e5c29 100644
--- a/core/nds32/panic.c
+++ b/core/nds32/panic.c
@@ -13,7 +13,134 @@
#include "timer.h"
#include "util.h"
-void report_panic(uint32_t *regs, uint32_t itype)
+/* General purpose register (r6) for saving software panic reason */
+#define SOFT_PANIC_GPR_REASON 6
+/* General purpose register (r7) for saving software panic information */
+#define SOFT_PANIC_GPR_INFO 7
+
+/* Panic data goes at the end of RAM. */
+static struct panic_data * const pdata_ptr = PANIC_DATA_PTR;
+
+#ifdef CONFIG_DEBUG_EXCEPTIONS
+/**
+ * bit[4] @ ITYPE, Indicates if an exception is caused by an instruction fetch
+ * or a data memory access for the following exceptions:
+ * -TLB fill
+ * -TLB VLPT miss
+ * -TLB read protection
+ * -TLB write protection
+ * -TLB non-executable page
+ * -TLB page modified
+ * -TLB Access bit
+ * -PTE not present (all)
+ * -Reserved PTE Attribute
+ * -Alignment check
+ * -Branch target alignment
+ * -Machine error
+ * -Precise bus error
+ * -Imprecise bus error
+ * -Nonexistent local memory address
+ * -MPZIU Control
+ * -Cache locking error
+ * -TLB locking error
+ * -TLB multiple hit
+ * -Parity/ECC error
+ * All other exceptions not in the abovetable should have the INST field of
+ * the ITYPE register set to 0.
+ */
+static const char * const itype_inst[2] = {
+ "a data memory access",
+ "an instruction fetch access",
+};
+
+/**
+ * bit[3-0] @ ITYPE, general exception type information.
+ */
+static const char * const itype_exc_type[16] = {
+ "Alignment check",
+ "Reserved instruction",
+ "Trap",
+ "Arithmetic",
+ "Precise bus error",
+ "Imprecise bus error",
+ "Coprocessor",
+ "Privileged instruction",
+
+ "Reserved value",
+ "Nonexistent local memory address",
+ "MPZIU Control",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+};
+#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));
+ asm volatile ("mov55 $r7, %0" : : "r"(info));
+ if (in_interrupt_context())
+ asm("j excep_handler");
+ else
+ asm("trap 0");
+}
+
+void panic_set_reason(uint32_t reason, uint32_t info, uint8_t exception)
+{
+ uint32_t *regs = pdata_ptr->nds_n8.regs;
+ uint32_t warning_ipc;
+
+ /* Setup panic data structure */
+ if (reason != PANIC_SW_WATCHDOG) {
+ memset(pdata_ptr, 0, sizeof(*pdata_ptr));
+ } else {
+ warning_ipc = pdata_ptr->nds_n8.ipc;
+ memset(pdata_ptr, 0, sizeof(*pdata_ptr));
+ pdata_ptr->nds_n8.ipc = warning_ipc;
+ }
+ pdata_ptr->magic = PANIC_DATA_MAGIC;
+ pdata_ptr->struct_size = sizeof(*pdata_ptr);
+ pdata_ptr->struct_version = 2;
+ pdata_ptr->arch = PANIC_ARCH_NDS32_N8;
+
+ /* Log panic cause */
+ pdata_ptr->nds_n8.itype = exception;
+ regs[SOFT_PANIC_GPR_REASON] = reason;
+ regs[SOFT_PANIC_GPR_INFO] = info;
+}
+
+void panic_get_reason(uint32_t *reason, uint32_t *info, uint8_t *exception)
+{
+ uint32_t *regs = pdata_ptr->nds_n8.regs;
+
+ if (pdata_ptr->magic == PANIC_DATA_MAGIC &&
+ pdata_ptr->struct_version == 2) {
+ *exception = pdata_ptr->nds_n8.itype;
+ *reason = regs[SOFT_PANIC_GPR_REASON];
+ *info = regs[SOFT_PANIC_GPR_INFO];
+ } else {
+ *exception = *reason = *info = 0;
+ }
+}
+#endif /* CONFIG_SOFTWARE_PANIC */
+
+static void print_panic_information(uint32_t *regs, uint32_t itype,
+ uint32_t ipc, uint32_t ipsw)
{
panic_printf("=== EXCEP: ITYPE=%x ===\n", itype);
panic_printf("R0 %08x R1 %08x R2 %08x R3 %08x\n",
@@ -24,8 +151,8 @@ void report_panic(uint32_t *regs, uint32_t itype)
regs[8], regs[9], regs[10], regs[11]);
panic_printf("FP %08x GP %08x LP %08x SP %08x\n",
regs[12], regs[13], regs[14], regs[15]);
- panic_printf("IPC %08x IPSW %05x\n", regs[16], regs[17]);
- if ((regs[17] & PSW_INTL_MASK) == (2 << PSW_INTL_SHIFT)) {
+ panic_printf("IPC %08x IPSW %05x\n", ipc, ipsw);
+ if ((ipsw & PSW_INTL_MASK) == (2 << PSW_INTL_SHIFT)) {
/* 2nd level exception */
uint32_t oipc;
@@ -33,9 +160,53 @@ void report_panic(uint32_t *regs, uint32_t itype)
panic_printf("OIPC %08x\n", oipc);
}
+#ifdef CONFIG_DEBUG_EXCEPTIONS
+ panic_printf("SWID of ITYPE: %x\n", ((itype >> 16) & 0x7fff));
+ if ((regs[SOFT_PANIC_GPR_REASON] & 0xfffffff0) == PANIC_SW_BASE) {
+#ifdef CONFIG_SOFTWARE_PANIC
+ panic_printf("Software panic reason %s\n",
+ panic_sw_reasons[(regs[SOFT_PANIC_GPR_REASON] & 0x7)]);
+ panic_printf("Software panic info 0x%x\n",
+ regs[SOFT_PANIC_GPR_INFO]);
+#endif
+ } else {
+ panic_printf("Exception type: General exception [%s]\n",
+ itype_exc_type[(itype & 0xf)]);
+ panic_printf("Exception is caused by %s\n",
+ itype_inst[(itype & (1 << 4))]);
+ }
+#endif
+}
+
+void report_panic(uint32_t *regs, uint32_t itype)
+{
+ int i;
+ struct panic_data *pdata = pdata_ptr;
+
+ pdata->magic = PANIC_DATA_MAGIC;
+ pdata->struct_size = sizeof(*pdata);
+ pdata->struct_version = 2;
+ pdata->arch = PANIC_ARCH_NDS32_N8;
+ pdata->flags = 0;
+ pdata->reserved = 0;
+
+ pdata->nds_n8.itype = itype;
+ for (i = 0; i < 16; i++)
+ pdata->nds_n8.regs[i] = regs[i];
+ pdata->nds_n8.ipc = regs[16];
+ pdata->nds_n8.ipsw = regs[17];
+
+ print_panic_information(regs, itype, regs[16], regs[17]);
panic_reboot();
}
void panic_data_print(const struct panic_data *pdata)
{
+ uint32_t itype, *regs, ipc, ipsw;
+ itype = pdata->nds_n8.itype;
+ regs = (uint32_t *)pdata->nds_n8.regs;
+ ipc = pdata->nds_n8.ipc;
+ ipsw = pdata->nds_n8.ipsw;
+
+ print_panic_information(regs, itype, ipc, ipsw);
}
diff --git a/core/nds32/task.c b/core/nds32/task.c
index df7743ed82..7edad8b6e4 100644
--- a/core/nds32/task.c
+++ b/core/nds32/task.c
@@ -304,12 +304,27 @@ task_ *next_sched_task(void)
#ifdef CONFIG_TASK_PROFILING
if (current_task != new_task) {
- current_task->runtime +=
- (exc_start_time - exc_end_time - exc_sub_time);
+ if ((current_task - tasks) < TASK_ID_COUNT) {
+ current_task->runtime +=
+ (exc_start_time - exc_end_time - exc_sub_time);
+ }
task_will_switch = 1;
}
#endif
+#ifdef CONFIG_DEBUG_STACK_OVERFLOW
+ if (*current_task->stack != STACK_UNUSED_VALUE) {
+ int i = task_get_current();
+ if (i < TASK_ID_COUNT) {
+ panic_printf("\n\nStack overflow in %s task!\n",
+ task_names[i]);
+#ifdef CONFIG_SOFTWARE_PANIC
+ software_panic(PANIC_SW_STACK_OVERFLOW, i);
+#endif
+ }
+ }
+#endif
+
return new_task;
}
diff --git a/include/panic.h b/include/panic.h
index ea7a40f7b0..a4fbf24b92 100644
--- a/include/panic.h
+++ b/include/panic.h
@@ -29,6 +29,14 @@ struct cortex_panic_data {
uint32_t dfsr;
};
+/* NDS32 N8 registers saved on panic */
+struct nds32_n8_panic_data {
+ uint32_t itype;
+ uint32_t regs[16]; /* r0-r10, r15, fp, gp, lp, sp */
+ uint32_t ipc;
+ uint32_t ipsw;
+};
+
/* Data saved across reboots */
struct panic_data {
uint8_t arch; /* Architecture (PANIC_ARCH_*) */
@@ -38,7 +46,8 @@ struct panic_data {
/* core specific panic data */
union {
- struct cortex_panic_data cm; /* Cortex-Mx registers */
+ struct cortex_panic_data cm; /* Cortex-Mx registers */
+ struct nds32_n8_panic_data nds_n8; /* NDS32 N8 registers */
};
/*
@@ -50,7 +59,10 @@ struct panic_data {
};
#define PANIC_DATA_MAGIC 0x21636e50 /* "Pnc!" */
-#define PANIC_ARCH_CORTEX_M 1 /* Cortex-M architecture */
+enum panic_arch {
+ PANIC_ARCH_CORTEX_M = 1, /* Cortex-M architecture */
+ PANIC_ARCH_NDS32_N8 = 2, /* NDS32 N8 architecture */
+};
/*
* Panic data goes at the end of RAM. This is safe because we don't context
diff --git a/util/ectool.c b/util/ectool.c
index 722ba32cb5..1c409846e0 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -4204,10 +4204,8 @@ static void print_panic_reg(int regnum, const uint32_t *regs, int index)
printf((regnum & 3) == 3 ? "\n" : " ");
}
-
-int cmd_panic_info(int argc, char *argv[])
+int cmd_panic_info_cm(int argc, char *argv[])
{
- int rv;
struct panic_data *pdata = (struct panic_data *)ec_inbuf;
const uint32_t *lregs = pdata->cm.regs;
const uint32_t *sregs = NULL;
@@ -4219,31 +4217,6 @@ int cmd_panic_info(int argc, char *argv[])
int i;
const char *panic_origins[3] = {"", "PROCESS", "HANDLER"};
- rv = ec_command(EC_CMD_GET_PANIC_INFO, 0, NULL, 0,
- ec_inbuf, ec_max_insize);
- if (rv < 0)
- return rv;
-
- if (rv == 0) {
- printf("No panic data.\n");
- return 0;
- }
-
- /*
- * We only understand panic data with version <= 2. Warn the user
- * of higher versions.
- */
- if (pdata->struct_version > 2)
- fprintf(stderr,
- "Unknown panic data version (%d). "
- "Following data may be incorrect!\n",
- pdata->struct_version);
-
- if (pdata->arch != PANIC_ARCH_CORTEX_M)
- fprintf(stderr, "Unknown architecture (%d). "
- "CPU specific data will be incorrect!\n",
- pdata->arch);
-
printf("Saved panic data:%s\n",
(pdata->flags & PANIC_DATA_FLAG_OLD_HOSTCMD ? "" : " (NEW)"));
@@ -4277,6 +4250,69 @@ int cmd_panic_info(int argc, char *argv[])
return 0;
}
+int cmd_panic_info_nds32(int argc, char *argv[])
+{
+ struct panic_data *pdata = (struct panic_data *)ec_inbuf;
+ const uint32_t *regs = pdata->nds_n8.regs;
+ uint32_t itype = pdata->nds_n8.itype;
+ uint32_t ipc = pdata->nds_n8.ipc;
+ uint32_t ipsw = pdata->nds_n8.ipsw;
+
+ printf("Saved panic data:%s\n",
+ (pdata->flags & PANIC_DATA_FLAG_OLD_HOSTCMD ? "" : " (NEW)"));
+
+ printf("=== EXCEP: ITYPE=%x ===\n", itype);
+ printf("R0 %08x R1 %08x R2 %08x R3 %08x\n",
+ regs[0], regs[1], regs[2], regs[3]);
+ printf("R4 %08x R5 %08x R6 %08x R7 %08x\n",
+ regs[4], regs[5], regs[6], regs[7]);
+ printf("R8 %08x R9 %08x R10 %08x R15 %08x\n",
+ regs[8], regs[9], regs[10], regs[11]);
+ printf("FP %08x GP %08x LP %08x SP %08x\n",
+ regs[12], regs[13], regs[14], regs[15]);
+ printf("IPC %08x IPSW %05x\n", ipc, ipsw);
+ printf("SWID of ITYPE: %x\n", ((itype >> 16) & 0x7fff));
+
+ return 0;
+}
+
+int cmd_panic_info(int argc, char *argv[])
+{
+ int rv;
+ struct panic_data *pdata = (struct panic_data *)ec_inbuf;
+
+ rv = ec_command(EC_CMD_GET_PANIC_INFO, 0, NULL, 0,
+ ec_inbuf, ec_max_insize);
+ if (rv < 0)
+ return rv;
+
+ if (rv == 0) {
+ printf("No panic data.\n");
+ return 0;
+ }
+
+ /*
+ * We only understand panic data with version <= 2. Warn the user
+ * of higher versions.
+ */
+ if (pdata->struct_version > 2)
+ fprintf(stderr,
+ "Unknown panic data version (%d). "
+ "Following data may be incorrect!\n",
+ pdata->struct_version);
+
+ switch (pdata->arch) {
+ case PANIC_ARCH_CORTEX_M:
+ return cmd_panic_info_cm(argc, argv);
+ case PANIC_ARCH_NDS32_N8:
+ return cmd_panic_info_nds32(argc, argv);
+ default:
+ fprintf(stderr, "Unknown architecture (%d).\n", pdata->arch);
+ break;
+ }
+ return -1;
+}
+
int cmd_power_info(int argc, char *argv[])
{