diff options
-rw-r--r-- | common/panic_output.c | 66 | ||||
-rw-r--r-- | core/cortex-m/config_core.h | 2 | ||||
-rw-r--r-- | core/cortex-m/panic.c | 22 | ||||
-rw-r--r-- | core/cortex-m/task.c | 35 | ||||
-rw-r--r-- | core/cortex-m/uldivmod.S | 4 | ||||
-rw-r--r-- | core/cortex-m0/config_core.h | 1 | ||||
-rw-r--r-- | core/cortex-m0/div.S | 4 | ||||
-rw-r--r-- | core/cortex-m0/panic.c | 22 | ||||
-rw-r--r-- | core/cortex-m0/task.c | 35 | ||||
-rw-r--r-- | core/cortex-m0/uldivmod.S | 4 | ||||
-rw-r--r-- | include/config.h | 6 | ||||
-rw-r--r-- | include/panic.h | 16 | ||||
-rw-r--r-- | include/software_panic.h | 23 |
13 files changed, 163 insertions, 77 deletions
diff --git a/common/panic_output.c b/common/panic_output.c index 4f0f22d00d..af98c5953d 100644 --- a/common/panic_output.c +++ b/common/panic_output.c @@ -6,6 +6,7 @@ #include "common.h" #include "console.h" #include "cpu.h" +#include "hooks.h" #include "host_command.h" #include "panic.h" #include "printf.h" @@ -82,8 +83,11 @@ void panic_reboot(void) void panic_assert_fail(const char *fname, int linenum) { panic_printf("\nASSERTION FAILURE at %s:%d\n", fname, linenum); - +#ifdef CONFIG_SOFTWARE_PANIC + software_panic(PANIC_SW_ASSERT, linenum); +#else panic_reboot(); +#endif } #else void panic_assert_fail(const char *msg, const char *func, const char *fname, @@ -91,8 +95,11 @@ void panic_assert_fail(const char *msg, const char *func, const char *fname, { panic_printf("\nASSERTION FAILURE '%s' in %s() at %s:%d\n", msg, func, fname, linenum); - +#ifdef CONFIG_SOFTWARE_PANIC + software_panic(PANIC_SW_ASSERT, linenum); +#else panic_reboot(); +#endif } #endif #endif @@ -108,6 +115,37 @@ struct panic_data *panic_get_data(void) return pdata_ptr->magic == PANIC_DATA_MAGIC ? pdata_ptr : NULL; } +#ifdef CONFIG_SOFTWARE_PANIC +static void panic_init(void) +{ + /* Log panic cause if watchdog caused reset */ + if (system_get_reset_flags() & RESET_FLAG_WATCHDOG) + panic_log_watchdog(); +} +DECLARE_HOOK(HOOK_INIT, panic_init, HOOK_PRIO_DEFAULT); +#endif + +#ifdef CONFIG_CMD_STACKOVERFLOW +static void stack_overflow_recurse(int n) +{ + ccprintf("+%d", n); + + /* + * Force task context switch, since that's where we do stack overflow + * checking. + */ + msleep(10); + + stack_overflow_recurse(n+1); + + /* + * Do work after the recursion, or else the compiler uses tail-chaining + * and we don't actually consume additional stack. + */ + ccprintf("-%d", n); +} +#endif /* CONFIG_CMD_STACKOVERFLOW */ + /*****************************************************************************/ /* Console commands */ @@ -116,14 +154,26 @@ static int command_crash(int argc, char **argv) if (argc < 2) return EC_ERROR_PARAM1; - if (!strcasecmp(argv[1], "divzero")) { - int a = 1, b = 0; + if (!strcasecmp(argv[1], "assert")) { + ASSERT(0); + } else if (!strcasecmp(argv[1], "divzero")) { + int zero = 0; cflush(); - ccprintf("%08x", a / b); + if (argc >= 3 && !strcasecmp(argv[2], "unsigned")) + ccprintf("%08x", (unsigned long)1 / zero); + else + ccprintf("%08x", (long)1 / zero); +#ifdef CONFIG_CMD_STACKOVERFLOW + } else if (!strcasecmp(argv[1], "stack")) { + stack_overflow_recurse(1); +#endif } else if (!strcasecmp(argv[1], "unaligned")) { cflush(); ccprintf("%08x", *(int *)0xcdef); + } else if (!strcasecmp(argv[1], "watchdog")) { + while (1) + ; } else { return EC_ERROR_PARAM1; } @@ -132,9 +182,9 @@ static int command_crash(int argc, char **argv) return EC_ERROR_UNKNOWN; } DECLARE_CONSOLE_COMMAND(crash, command_crash, - "[divzero | unaligned]", - "Crash the system (for testing)", - NULL); + "[assert | divzero | stack | unaligned | watchdog] [options]", + "Crash the system (for testing)", + NULL); static int command_panicinfo(int argc, char **argv) { diff --git a/core/cortex-m/config_core.h b/core/cortex-m/config_core.h index 7f3d253427..e72f4e58bb 100644 --- a/core/cortex-m/config_core.h +++ b/core/cortex-m/config_core.h @@ -10,4 +10,6 @@ #define BFD_ARCH arm #define BFD_FORMAT "elf32-littlearm" +#define CONFIG_SOFTWARE_PANIC + #endif /* __CONFIG_CORE_H */ diff --git a/core/cortex-m/panic.c b/core/cortex-m/panic.c index d63a5e3d9a..64fd5b8db1 100644 --- a/core/cortex-m/panic.c +++ b/core/cortex-m/panic.c @@ -373,6 +373,28 @@ void exception_panic(void) ); } +void software_panic(uint32_t panic_reason, uint32_t panic_info) +{ + __asm__("mov " STRINGIFY(SOFTWARE_PANIC_INFO_REG) ", %0\n" + "mov " STRINGIFY(SOFTWARE_PANIC_REASON_REG) ", %1\n" + "bl exception_panic\n" + : : "r"(panic_info), "r"(panic_reason)); +} + +void panic_log_watchdog(void) +{ + uint32_t *lregs = pdata_ptr->cm.regs; + + /* Watchdog reset, log panic cause */ + memset(pdata_ptr, 0, sizeof(*pdata_ptr)); + pdata_ptr->magic = PANIC_DATA_MAGIC; + pdata_ptr->struct_size = sizeof(*pdata_ptr); + pdata_ptr->struct_version = 2; + pdata_ptr->arch = PANIC_ARCH_CORTEX_M; + + lregs[3] = PANIC_SW_WATCHDOG; +} + void bus_fault_handler(void) { if (!bus_fault_ignored) diff --git a/core/cortex-m/task.c b/core/cortex-m/task.c index 69e93457cb..f7fda67374 100644 --- a/core/cortex-m/task.c +++ b/core/cortex-m/task.c @@ -10,6 +10,7 @@ #include "console.h" #include "cpu.h" #include "link_defs.h" +#include "panic.h" #include "task.h" #include "timer.h" #include "uart.h" @@ -225,7 +226,7 @@ void svc_handler(int desched, task_id_t resched) if (*current->stack != STACK_UNUSED_VALUE) { panic_printf("\n\nStack overflow in %s task!\n", task_names[current - tasks]); - panic_reboot(); + software_panic(PANIC_SW_STACK_OVERFLOW, current - tasks); } #endif @@ -590,38 +591,6 @@ DECLARE_CONSOLE_COMMAND(taskready, command_task_ready, NULL); #endif -#ifdef CONFIG_CMD_STACKOVERFLOW -static void stack_overflow_recurse(int n) -{ - ccprintf("+%d", n); - - /* - * Force task context switch, since that's where we do stack overflow - * checking. - */ - msleep(10); - - stack_overflow_recurse(n+1); - - /* - * Do work after the recursion, or else the compiler uses tail-chaining - * and we don't actually consume additional stack. - */ - ccprintf("-%d", n); -} - -static int command_stackoverflow(int argc, char **argv) -{ - ccprintf("Recursing 0,"); - stack_overflow_recurse(1); - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(stackoverflow, command_stackoverflow, - NULL, - "Recurse until stack overflow", - NULL); -#endif /* CONFIG_CMD_STACKOVERFLOW */ - void task_pre_init(void) { uint32_t *stack_next = (uint32_t *)task_stacks; diff --git a/core/cortex-m/uldivmod.S b/core/cortex-m/uldivmod.S index a14bdb203f..256023e9cc 100644 --- a/core/cortex-m/uldivmod.S +++ b/core/cortex-m/uldivmod.S @@ -16,6 +16,7 @@ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "software_panic.h" .syntax unified @@ -174,4 +175,5 @@ L_dont_sub4: pop {r4, r5, r6, r7, pc} __aeabi_ldiv0: - bl panic_reboot + ldr SOFTWARE_PANIC_REASON_REG, =PANIC_SW_DIV_ZERO + bl exception_panic diff --git a/core/cortex-m0/config_core.h b/core/cortex-m0/config_core.h index 11c209c66a..9c04d467e3 100644 --- a/core/cortex-m0/config_core.h +++ b/core/cortex-m0/config_core.h @@ -12,5 +12,6 @@ /* Emulate the CLZ instruction since the CPU core is lacking support */ #define CONFIG_SOFTWARE_CLZ +#define CONFIG_SOFTWARE_PANIC #endif /* __CONFIG_CORE_H */ diff --git a/core/cortex-m0/div.S b/core/cortex-m0/div.S index 833465a59e..898ecafe83 100644 --- a/core/cortex-m0/div.S +++ b/core/cortex-m0/div.S @@ -18,6 +18,7 @@ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "software_panic.h" .syntax unified @@ -161,4 +162,5 @@ L_dont_sub0: bx lr __aeabi_idiv0: - bl panic_reboot + ldr SOFTWARE_PANIC_REASON_REG, =PANIC_SW_DIV_ZERO + bl exception_panic diff --git a/core/cortex-m0/panic.c b/core/cortex-m0/panic.c index 7857fb55dd..2b17a1bd73 100644 --- a/core/cortex-m0/panic.c +++ b/core/cortex-m0/panic.c @@ -166,6 +166,28 @@ void exception_panic(void) ); } +void software_panic(uint32_t panic_reason, uint32_t panic_info) +{ + __asm__("mov " STRINGIFY(SOFTWARE_PANIC_INFO_REG) ", %0\n" + "mov " STRINGIFY(SOFTWARE_PANIC_REASON_REG) ", %1\n" + "bl exception_panic\n" + : : "r"(panic_info), "r"(panic_reason)); +} + +void panic_log_watchdog(void) +{ + uint32_t *lregs = pdata_ptr->cm.regs; + + /* Watchdog reset, log panic cause */ + memset(pdata_ptr, 0, sizeof(*pdata_ptr)); + pdata_ptr->magic = PANIC_DATA_MAGIC; + pdata_ptr->struct_size = sizeof(*pdata_ptr); + pdata_ptr->struct_version = 2; + pdata_ptr->arch = PANIC_ARCH_CORTEX_M; + + lregs[3] = PANIC_SW_WATCHDOG; +} + void bus_fault_handler(void) { if (!bus_fault_ignored) diff --git a/core/cortex-m0/task.c b/core/cortex-m0/task.c index e51621b41e..86fb7071d5 100644 --- a/core/cortex-m0/task.c +++ b/core/cortex-m0/task.c @@ -10,6 +10,7 @@ #include "console.h" #include "cpu.h" #include "link_defs.h" +#include "panic.h" #include "task.h" #include "timer.h" #include "uart.h" @@ -209,7 +210,7 @@ task_ *__svc_handler(int desched, task_id_t resched) if (*current->stack != STACK_UNUSED_VALUE) { panic_printf("\n\nStack overflow in %s task!\n", task_names[current - tasks]); - panic_reboot(); + software_panic(PANIC_SW_STACK_OVERFLOW, current - tasks); } #endif @@ -574,38 +575,6 @@ DECLARE_CONSOLE_COMMAND(taskready, command_task_ready, NULL); #endif -#ifdef CONFIG_CMD_STACKOVERFLOW -static void stack_overflow_recurse(int n) -{ - ccprintf("+%d", n); - - /* - * Force task context switch, since that's where we do stack overflow - * checking. - */ - msleep(10); - - stack_overflow_recurse(n+1); - - /* - * Do work after the recursion, or else the compiler uses tail-chaining - * and we don't actually consume additional stack. - */ - ccprintf("-%d", n); -} - -static int command_stackoverflow(int argc, char **argv) -{ - ccprintf("Recursing 0,"); - stack_overflow_recurse(1); - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(stackoverflow, command_stackoverflow, - NULL, - "Recurse until stack overflow", - NULL); -#endif /* CONFIG_CMD_STACKOVERFLOW */ - void task_pre_init(void) { uint32_t *stack_next = (uint32_t *)task_stacks; diff --git a/core/cortex-m0/uldivmod.S b/core/cortex-m0/uldivmod.S index b8855023ad..6909c6f242 100644 --- a/core/cortex-m0/uldivmod.S +++ b/core/cortex-m0/uldivmod.S @@ -16,6 +16,7 @@ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "software_panic.h" .syntax unified @@ -172,4 +173,5 @@ L_dont_sub4: pop {r4, r5, r6, r7, pc} __aeabi_ldiv0: - bl panic_reboot + ldr SOFTWARE_PANIC_REASON_REG, =DIV_ZERO_PANIC + bl exception_panic diff --git a/include/config.h b/include/config.h index 9fb9508644..5f30ba31f3 100644 --- a/include/config.h +++ b/include/config.h @@ -379,6 +379,12 @@ #define CONFIG_COMMON_PANIC_OUTPUT /* + * Store a panic log and halt the system for a software-related reasons, such as + * stack overflow or assertion failure. + */ +#undef CONFIG_SOFTWARE_PANIC + +/* * Provide the default GPIO abstraction layer. * You want this unless you are doing a really tiny firmware. */ diff --git a/include/panic.h b/include/panic.h index 74376554b6..1097029002 100644 --- a/include/panic.h +++ b/include/panic.h @@ -9,6 +9,8 @@ #ifndef __CROS_EC_PANIC_H #define __CROS_EC_PANIC_H +#include "software_panic.h" + #include <stdarg.h> /* ARM Cortex-Mx registers saved on panic */ @@ -120,6 +122,20 @@ void panic(const char *msg); */ void panic_reboot(void); +#ifdef CONFIG_SOFTWARE_PANIC +/** + * Store a panic log and halt the system for a software-related reason, such as + * stack overflow or assertion failure. + */ +void software_panic(uint32_t panic_reason, uint32_t panic_info); + +/** + * Log a watchdog panic in the panic log. Called on the subsequent reboot after + * the watchdog fires. + */ +void panic_log_watchdog(void); +#endif + /** * Enable/disable bus fault handler * diff --git a/include/software_panic.h b/include/software_panic.h new file mode 100644 index 0000000000..9dc6d5a394 --- /dev/null +++ b/include/software_panic.h @@ -0,0 +1,23 @@ +/* Copyright (c) 2015 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. + */ + +#ifndef __CROS_EC_SOFTWARE_PANIC_H +#define __CROS_EC_SOFTWARE_PANIC_H + +/* Holds software panic reason PANIC_SW_* */ +#define SOFTWARE_PANIC_REASON_REG r4 +#define SOFTWARE_PANIC_INFO_REG r5 + +#define PANIC_SW_BASE 0xDEAD6660 + +/* Software panic reasons */ +#define PANIC_SW_DIV_ZERO (PANIC_SW_BASE + 0) +#define PANIC_SW_STACK_OVERFLOW (PANIC_SW_BASE + 1) +#define PANIC_SW_ASSERT (PANIC_SW_BASE + 3) +#define PANIC_SW_WATCHDOG (PANIC_SW_BASE + 4) + +#endif /* __CROS_EC_SOFTWARE_PANIC_H */ |