summaryrefslogtreecommitdiff
path: root/core/nds32
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 /core/nds32
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>
Diffstat (limited to 'core/nds32')
-rw-r--r--core/nds32/config_core.h2
-rw-r--r--core/nds32/panic.c177
-rw-r--r--core/nds32/task.c19
3 files changed, 193 insertions, 5 deletions
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;
}