diff --git a/arch/arc/core/fatal.c b/arch/arc/core/fatal.c index c0c76988fda..5204060a67a 100644 --- a/arch/arc/core/fatal.c +++ b/arch/arc/core/fatal.c @@ -16,13 +16,7 @@ #include #include #include - -#ifdef CONFIG_PRINTK #include -#define PR_EXC(...) printk(__VA_ARGS__) -#else -#define PR_EXC(...) -#endif /* CONFIG_PRINTK */ const NANO_ESF _default_esf = { 0xdeaddead, /* placeholder */ @@ -48,24 +42,32 @@ FUNC_NORETURN void _NanoFatalErrorHandler(unsigned int reason, { switch (reason) { case _NANO_ERR_INVALID_TASK_EXIT: - PR_EXC("***** Invalid Exit Software Error! *****\n"); + printk("***** Invalid Exit Software Error! *****\n"); break; #if defined(CONFIG_STACK_CANARIES) case _NANO_ERR_STACK_CHK_FAIL: - PR_EXC("***** Stack Check Fail! *****\n"); + printk("***** Stack Check Fail! *****\n"); break; #endif case _NANO_ERR_ALLOCATION_FAIL: - PR_EXC("**** Kernel Allocation Failure! ****\n"); + printk("**** Kernel Allocation Failure! ****\n"); + break; + + case _NANO_ERR_KERNEL_OOPS: + printk("***** Kernel OOPS! *****\n"); + break; + + case _NANO_ERR_KERNEL_PANIC: + printk("***** Kernel Panic! *****\n"); break; default: - PR_EXC("**** Unknown Fatal Error %d! ****\n", reason); + printk("**** Unknown Fatal Error %d! ****\n", reason); break; } - PR_EXC("Current thread ID = %p\n" + printk("Current thread ID = %p\n" "Faulting instruction address = 0x%lx\n", k_current_get(), _arc_v2_aux_reg_read(_ARC_V2_ERET)); diff --git a/arch/arc/core/sys_fatal_error_handler.c b/arch/arc/core/sys_fatal_error_handler.c index 6e446faba4e..35b768f2b18 100644 --- a/arch/arc/core/sys_fatal_error_handler.c +++ b/arch/arc/core/sys_fatal_error_handler.c @@ -40,23 +40,27 @@ FUNC_NORETURN void _SysFatalErrorHandler(unsigned int reason, const NANO_ESF *pEsf) { - ARG_UNUSED(reason); ARG_UNUSED(pEsf); #if !defined(CONFIG_SIMPLE_FATAL_ERROR_HANDLER) + if (reason == _NANO_ERR_KERNEL_PANIC) { + goto hang_system; + } if (k_is_in_isr() || _is_thread_essential()) { printk("Fatal fault in %s! Spinning...\n", k_is_in_isr() ? "ISR" : "essential thread"); - for (;;) - ; /* spin forever */ + goto hang_system; } printk("Fatal fault in thread %p! Aborting.\n", _current); k_thread_abort(_current); + +hang_system: #else + ARG_UNUSED(reason); +#endif + for (;;) { k_cpu_idle(); } -#endif - CODE_UNREACHABLE; } diff --git a/arch/arm/core/fatal.c b/arch/arm/core/fatal.c index b3258148aa8..b5617f0253f 100644 --- a/arch/arm/core/fatal.c +++ b/arch/arm/core/fatal.c @@ -17,13 +17,7 @@ #include #include - -#ifdef CONFIG_PRINTK #include -#define PR_EXC(...) printk(__VA_ARGS__) -#else -#define PR_EXC(...) -#endif /* CONFIG_PRINTK */ /* * Define a default ESF for use with _NanoFatalErrorHandler() in the event @@ -75,24 +69,32 @@ void _NanoFatalErrorHandler(unsigned int reason, { switch (reason) { case _NANO_ERR_INVALID_TASK_EXIT: - PR_EXC("***** Invalid Exit Software Error! *****\n"); + printk("***** Invalid Exit Software Error! *****\n"); break; #if defined(CONFIG_STACK_CANARIES) case _NANO_ERR_STACK_CHK_FAIL: - PR_EXC("***** Stack Check Fail! *****\n"); + printk("***** Stack Check Fail! *****\n"); break; #endif /* CONFIG_STACK_CANARIES */ case _NANO_ERR_ALLOCATION_FAIL: - PR_EXC("**** Kernel Allocation Failure! ****\n"); + printk("**** Kernel Allocation Failure! ****\n"); + break; + + case _NANO_ERR_KERNEL_OOPS: + printk("***** Kernel OOPS! *****\n"); + break; + + case _NANO_ERR_KERNEL_PANIC: + printk("***** Kernel Panic! *****\n"); break; default: - PR_EXC("**** Unknown Fatal Error %d! ****\n", reason); + printk("**** Unknown Fatal Error %d! ****\n", reason); break; } - PR_EXC("Current thread ID = %p\n" + printk("Current thread ID = %p\n" "Faulting instruction address = 0x%x\n", k_current_get(), pEsf->pc); diff --git a/arch/arm/core/sys_fatal_error_handler.c b/arch/arm/core/sys_fatal_error_handler.c index eb2c8625094..6684f76d15e 100644 --- a/arch/arm/core/sys_fatal_error_handler.c +++ b/arch/arm/core/sys_fatal_error_handler.c @@ -41,21 +41,28 @@ void _SysFatalErrorHandler(unsigned int reason, const NANO_ESF *pEsf) { - ARG_UNUSED(reason); ARG_UNUSED(pEsf); #if !defined(CONFIG_SIMPLE_FATAL_ERROR_HANDLER) + if (reason == _NANO_ERR_KERNEL_PANIC) { + goto hang_system; + } if (k_is_in_isr() || _is_thread_essential()) { printk("Fatal fault in %s! Spinning...\n", k_is_in_isr() ? "ISR" : "essential thread"); - for (;;) - ; /* spin forever */ + goto hang_system; } printk("Fatal fault in thread %p! Aborting.\n", _current); k_thread_abort(_current); + return; + +hang_system: #else + ARG_UNUSED(reason); +#endif + for (;;) { k_cpu_idle(); } -#endif + CODE_UNREACHABLE; } diff --git a/arch/nios2/core/fatal.c b/arch/nios2/core/fatal.c index 8ffa942dd46..51e8d4a42c9 100644 --- a/arch/nios2/core/fatal.c +++ b/arch/nios2/core/fatal.c @@ -65,6 +65,14 @@ FUNC_NORETURN void _NanoFatalErrorHandler(unsigned int reason, printk("**** Kernel Allocation Failure! ****\n"); break; + case _NANO_ERR_KERNEL_OOPS: + printk("***** Kernel OOPS! *****\n"); + break; + + case _NANO_ERR_KERNEL_PANIC: + printk("***** Kernel Panic! *****\n"); + break; + default: printk("**** Unknown Fatal Error %u! ****\n", reason); break; @@ -210,26 +218,30 @@ FUNC_NORETURN void _Fault(const NANO_ESF *esf) FUNC_NORETURN void _SysFatalErrorHandler(unsigned int reason, const NANO_ESF *pEsf) { - ARG_UNUSED(reason); ARG_UNUSED(pEsf); #if !defined(CONFIG_SIMPLE_FATAL_ERROR_HANDLER) + if (reason == _NANO_ERR_KERNEL_PANIC) { + goto hang_system; + } if (k_is_in_isr() || _is_thread_essential()) { printk("Fatal fault in %s! Spinning...\n", k_is_in_isr() ? "ISR" : "essential thread"); -#ifdef ALT_CPU_HAS_DEBUG_STUB - _nios2_break(); -#endif - for (;;) - ; /* spin forever */ + goto hang_system; } printk("Fatal fault in thread %p! Aborting.\n", _current); k_thread_abort(_current); + +hang_system: #else + ARG_UNUSED(reason); +#endif + +#ifdef ALT_CPU_HAS_DEBUG_STUB + _nios2_break(); +#endif for (;;) { k_cpu_idle(); } -#endif - CODE_UNREACHABLE; } diff --git a/arch/riscv32/core/fatal.c b/arch/riscv32/core/fatal.c index 1af24cbe084..42ecc4c4d11 100644 --- a/arch/riscv32/core/fatal.c +++ b/arch/riscv32/core/fatal.c @@ -7,13 +7,7 @@ #include #include #include - -#ifdef CONFIG_PRINTK #include -#define PRINTK(...) printk(__VA_ARGS__) -#else -#define PRINTK(...) -#endif const NANO_ESF _default_esf = { 0xdeadbaad, @@ -72,25 +66,33 @@ FUNC_NORETURN void _NanoFatalErrorHandler(unsigned int reason, break; case _NANO_ERR_INVALID_TASK_EXIT: - PRINTK("***** Invalid Exit Software Error! *****\n"); + printk("***** Invalid Exit Software Error! *****\n"); break; #if defined(CONFIG_STACK_CANARIES) case _NANO_ERR_STACK_CHK_FAIL: - PRINTK("***** Stack Check Fail! *****\n"); + printk("***** Stack Check Fail! *****\n"); break; #endif /* CONFIG_STACK_CANARIES */ case _NANO_ERR_ALLOCATION_FAIL: - PRINTK("**** Kernel Allocation Failure! ****\n"); + printk("**** Kernel Allocation Failure! ****\n"); + break; + + case _NANO_ERR_KERNEL_OOPS: + printk("***** Kernel OOPS! *****\n"); + break; + + case _NANO_ERR_KERNEL_PANIC: + printk("***** Kernel Panic! *****\n"); break; default: - PRINTK("**** Unknown Fatal Error %d! ****\n", reason); + printk("**** Unknown Fatal Error %d! ****\n", reason); break; } - PRINTK("Current thread ID = %p\n" + printk("Current thread ID = %p\n" "Faulting instruction address = 0x%x\n" " ra: 0x%x gp: 0x%x tp: 0x%x t0: 0x%x\n" " t1: 0x%x t2: 0x%x t3: 0x%x t4: 0x%x\n" @@ -134,27 +136,28 @@ FUNC_NORETURN void _NanoFatalErrorHandler(unsigned int reason, */ void _SysFatalErrorHandler(unsigned int reason, const NANO_ESF *esf) { - ARG_UNUSED(reason); ARG_UNUSED(esf); #if !defined(CONFIG_SIMPLE_FATAL_ERROR_HANDLER) - if (k_is_in_isr() || _is_thread_essential()) { - PRINTK("Fatal fault in %s! Spinning...\n", - k_is_in_isr() ? "ISR" : "essential thread"); - /* spin forever */ - for (;;) - __asm__ volatile("nop"); + if (reason == _NANO_ERR_KERNEL_PANIC) { + goto hang_system; } - PRINTK("Fatal fault in thread! Aborting.\n"); + if (k_is_in_isr() || _is_thread_essential()) { + printk("Fatal fault in %s! Spinning...\n", + k_is_in_isr() ? "ISR" : "essential thread"); + goto hang_system; + } + printk("Fatal fault in thread %p! Aborting.\n", _current); k_thread_abort(_current); +hang_system: #else + ARG_UNUSED(reason); +#endif + for (;;) { k_cpu_idle(); } - -#endif - CODE_UNREACHABLE; } @@ -190,7 +193,7 @@ FUNC_NORETURN void _Fault(const NANO_ESF *esf) mcause &= SOC_MCAUSE_EXP_MASK; - PRINTK("Exception cause %s (%d)\n", cause_str(mcause), (int)mcause); + printk("Exception cause %s (%d)\n", cause_str(mcause), (int)mcause); _NanoFatalErrorHandler(_NANO_ERR_CPU_EXCEPTION, esf); } diff --git a/arch/x86/core/fatal.c b/arch/x86/core/fatal.c index 6f66745b5ac..fcbe976989b 100644 --- a/arch/x86/core/fatal.c +++ b/arch/x86/core/fatal.c @@ -92,6 +92,13 @@ FUNC_NORETURN void _NanoFatalErrorHandler(unsigned int reason, break; #endif /* CONFIG_STACK_CANARIES */ + case _NANO_ERR_KERNEL_OOPS: + printk("***** Kernel OOPS! *****\n"); + break; + + case _NANO_ERR_KERNEL_PANIC: + printk("***** Kernel Panic! *****\n"); + break; case _NANO_ERR_ALLOCATION_FAIL: printk("**** Kernel Allocation Failure! ****\n"); diff --git a/arch/x86/core/sys_fatal_error_handler.c b/arch/x86/core/sys_fatal_error_handler.c index 180db9dce29..faf1ba54d3b 100644 --- a/arch/x86/core/sys_fatal_error_handler.c +++ b/arch/x86/core/sys_fatal_error_handler.c @@ -41,23 +41,27 @@ FUNC_NORETURN void _SysFatalErrorHandler(unsigned int reason, const NANO_ESF *pEsf) { - ARG_UNUSED(reason); ARG_UNUSED(pEsf); #if !defined(CONFIG_SIMPLE_FATAL_ERROR_HANDLER) + if (reason == _NANO_ERR_KERNEL_PANIC) { + goto hang_system; + } if (k_is_in_isr() || _is_thread_essential()) { printk("Fatal fault in %s! Spinning...\n", k_is_in_isr() ? "ISR" : "essential thread"); - for (;;) - ; /* spin forever */ + goto hang_system; } printk("Fatal fault in thread %p! Aborting.\n", _current); k_thread_abort(_current); + +hang_system: #else + ARG_UNUSED(reason); +#endif + for (;;) { k_cpu_idle(); } -#endif - CODE_UNREACHABLE; } diff --git a/arch/xtensa/core/fatal.c b/arch/xtensa/core/fatal.c index fa1e3f7e211..98fb3f4eef5 100644 --- a/arch/xtensa/core/fatal.c +++ b/arch/xtensa/core/fatal.c @@ -63,6 +63,15 @@ FUNC_NORETURN void _NanoFatalErrorHandler(unsigned int reason, case _NANO_ERR_ALLOCATION_FAIL: printk("**** Kernel Allocation Failure! ****\n"); break; + + case _NANO_ERR_KERNEL_OOPS: + printk("***** Kernel OOPS! *****\n"); + break; + + case _NANO_ERR_KERNEL_PANIC: + printk("***** Kernel Panic! *****\n"); + break; + default: printk("**** Unknown Fatal Error %d! ****\n", reason); break; @@ -215,28 +224,32 @@ extern FUNC_NORETURN void exit(int exit_code); FUNC_NORETURN void _SysFatalErrorHandler(unsigned int reason, const NANO_ESF *pEsf) { - ARG_UNUSED(reason); ARG_UNUSED(pEsf); #if !defined(CONFIG_SIMPLE_FATAL_ERROR_HANDLER) + if (reason == _NANO_ERR_KERNEL_PANIC) { + goto hang_system; + } if (k_is_in_isr() || _is_thread_essential()) { printk("Fatal fault in %s! Spinning...\n", k_is_in_isr() ? "ISR" : "essential thread"); -#ifdef XT_SIMULATOR - exit(255 - reason); -#else - for (;;) - ; /* spin forever */ -#endif + goto hang_system; } printk("Fatal fault in thread %p! Aborting.\n", _current); k_thread_abort(_current); + +hang_system: +#else + ARG_UNUSED(reason); +#endif + +#ifdef XT_SIMULATOR + exit(255 - reason); #else for (;;) { k_cpu_idle(); } #endif - CODE_UNREACHABLE; } diff --git a/include/arch/arc/v2/error.h b/include/arch/arc/v2/error.h index 727ea9354bd..37e41085b24 100644 --- a/include/arch/arc/v2/error.h +++ b/include/arch/arc/v2/error.h @@ -31,6 +31,8 @@ extern void _SysFatalErrorHandler(unsigned int cause, const NANO_ESF *esf); #define _NANO_ERR_INVALID_TASK_EXIT (1) /* Invalid task exit */ #define _NANO_ERR_STACK_CHK_FAIL (2) /* Stack corruption detected */ #define _NANO_ERR_ALLOCATION_FAIL (3) /* Kernel Allocation Failure */ +#define _NANO_ERR_KERNEL_OOPS (4) /* Kernel oops (fatal to thread) */ +#define _NANO_ERR_KERNEL_PANIC (5) /* Kernel panic (fatal to system) */ #ifdef __cplusplus } diff --git a/include/arch/arm/cortex_m/error.h b/include/arch/arm/cortex_m/error.h index 4e43d319d90..6d1e77f6009 100644 --- a/include/arch/arm/cortex_m/error.h +++ b/include/arch/arm/cortex_m/error.h @@ -29,6 +29,8 @@ extern void _SysFatalErrorHandler(unsigned int reason, const NANO_ESF *esf); #define _NANO_ERR_INVALID_TASK_EXIT (1) /* Invalid task exit */ #define _NANO_ERR_STACK_CHK_FAIL (2) /* Stack corruption detected */ #define _NANO_ERR_ALLOCATION_FAIL (3) /* Kernel Allocation Failure */ +#define _NANO_ERR_KERNEL_OOPS (4) /* Kernel oops (fatal to thread) */ +#define _NANO_ERR_KERNEL_PANIC (5) /* Kernel panic (fatal to system) */ #ifdef __cplusplus } diff --git a/include/arch/nios2/arch.h b/include/arch/nios2/arch.h index a616855895f..7704305ba4e 100644 --- a/include/arch/nios2/arch.h +++ b/include/arch/nios2/arch.h @@ -29,6 +29,8 @@ extern "C" { #define _NANO_ERR_STACK_CHK_FAIL (2) /* Stack corruption detected */ #define _NANO_ERR_ALLOCATION_FAIL (3) /* Kernel Allocation Failure */ #define _NANO_ERR_SPURIOUS_INT (4) /* Spurious interrupt */ +#define _NANO_ERR_KERNEL_OOPS (5) /* Kernel oops (fatal to thread) */ +#define _NANO_ERR_KERNEL_PANIC (6) /* Kernel panic (fatal to system) */ /* APIs need to support non-byte addressable architectures */ diff --git a/include/arch/riscv32/exp.h b/include/arch/riscv32/exp.h index 43248efef11..9da414263b3 100644 --- a/include/arch/riscv32/exp.h +++ b/include/arch/riscv32/exp.h @@ -73,6 +73,8 @@ extern void _SysFatalErrorHandler(unsigned int reason, #define _NANO_ERR_STACK_CHK_FAIL (2) /* Stack corruption detected */ #define _NANO_ERR_ALLOCATION_FAIL (3) /* Kernel Allocation Failure */ #define _NANO_ERR_SPURIOUS_INT (4) /* Spurious interrupt */ +#define _NANO_ERR_KERNEL_OOPS (5) /* Kernel oops (fatal to thread) */ +#define _NANO_ERR_KERNEL_PANIC (6) /* Kernel panic (fatal to system) */ #ifdef __cplusplus } diff --git a/include/arch/x86/arch.h b/include/arch/x86/arch.h index e21529b8143..9a2207ce05d 100644 --- a/include/arch/x86/arch.h +++ b/include/arch/x86/arch.h @@ -339,6 +339,10 @@ typedef struct nanoIsf { #define _NANO_ERR_ALLOCATION_FAIL (5) /** Unhandled exception */ #define _NANO_ERR_CPU_EXCEPTION (6) +/** Kernel oops (fatal to thread) */ +#define _NANO_ERR_KERNEL_OOPS (7) +/** Kernel panic (fatal to system) */ +#define _NANO_ERR_KERNEL_PANIC (8) #ifndef _ASMLANGUAGE diff --git a/include/arch/xtensa/arch.h b/include/arch/xtensa/arch.h index d65c4383b61..db0e9d0f00b 100644 --- a/include/arch/xtensa/arch.h +++ b/include/arch/xtensa/arch.h @@ -50,6 +50,8 @@ extern "C" { #define _NANO_ERR_STACK_CHK_FAIL (2) /* Stack corruption detected */ #define _NANO_ERR_ALLOCATION_FAIL (3) /* Kernel Allocation Failure */ #define _NANO_ERR_RESERVED_IRQ (4) /* Reserved interrupt */ +#define _NANO_ERR_KERNEL_OOPS (5) /* Kernel oops (fatal to thread) */ +#define _NANO_ERR_KERNEL_PANIC (6) /* Kernel panic (fatal to system) */ /* Xtensa GPRs are often designated by two different names */ #define sys_define_gpr_with_alias(name1, name2) union { u32_t name1, name2; } diff --git a/include/bluetooth/log.h b/include/bluetooth/log.h index e5c564b17c9..9a037e2feb0 100644 --- a/include/bluetooth/log.h +++ b/include/bluetooth/log.h @@ -85,7 +85,7 @@ static inline __printf_like(1, 2) void _bt_log_dummy(const char *fmt, ...) {}; #define BT_ASSERT(cond) if (!(cond)) { \ BT_ERR("assert: '" #cond "' failed"); \ - _SysFatalErrorHandler(0, NULL); \ + k_oops(); \ } #define BT_STACK(name, size) \ diff --git a/include/kernel.h b/include/kernel.h index 8d42c623924..30c1c8fcfb9 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -3554,6 +3554,51 @@ extern void _sys_power_save_idle_exit(s32_t ticks); #include +#ifdef _ARCH_EXCEPT +/* This archtecture has direct support for triggering a CPU exception */ +#define _k_except_reason(reason) _ARCH_EXCEPT(reason) +#else + +#include + +/* NOTE: This is the implementation for arches that do not implement + * _ARCH_EXCEPT() to generate a real CPU exception. + * + * We won't have a real exception frame to determine the PC value when + * the oops occurred, so print file and line number before we jump into + * the fatal error handler. + */ +#define _k_except_reason(reason) do { \ + printk("@ %s:%d:\n", __FILE__, __LINE__); \ + _NanoFatalErrorHandler(reason, &_default_esf); \ + CODE_UNREACHABLE; \ + } while (0) + +#endif /* _ARCH__EXCEPT */ + +/** + * @brief Fatally terminate a thread + * + * This should be called when a thread has encountered an unrecoverable + * runtime condition and needs to terminate. What this ultimately + * means is determined by the _fatal_error_handler() implementation, which + * will be called will reason code _NANO_ERR_KERNEL_OOPS. + * + * If this is called from ISR context, the default system fatal error handler + * will treat it as an unrecoverable system error, just like k_panic(). + */ +#define k_oops() _k_except_reason(_NANO_ERR_KERNEL_OOPS) + +/** + * @brief Fatally terminate the system + * + * This should be called when the Zephyr kernel has encountered an + * unrecoverable runtime condition and needs to terminate. What this ultimately + * means is determined by the _fatal_error_handler() implementation, which + * will be called will reason code _NANO_ERR_KERNEL_PANIC. + */ +#define k_panic() _k_except_reason(_NANO_ERR_KERNEL_PANIC) + /* * private APIs that are utilized by one or more public APIs */ diff --git a/kernel/compiler_stack_protect.c b/kernel/compiler_stack_protect.c index 903d8940a8e..a55632d1830 100644 --- a/kernel/compiler_stack_protect.c +++ b/kernel/compiler_stack_protect.c @@ -21,6 +21,7 @@ #include #include #include +#include /** * @@ -34,9 +35,7 @@ void FUNC_NORETURN _StackCheckHandler(void) { /* Stack canary error is a software fatal condition; treat it as such. */ - - _NanoFatalErrorHandler(_NANO_ERR_STACK_CHK_FAIL, &_default_esf); - CODE_UNREACHABLE; + _k_except_reason(_NANO_ERR_STACK_CHK_FAIL); } /* Global variable */ diff --git a/kernel/thread.c b/kernel/thread.c index 473ee9afa32..3c9c0d3c811 100644 --- a/kernel/thread.c +++ b/kernel/thread.c @@ -142,8 +142,7 @@ FUNC_NORETURN void _thread_entry(void (*entry)(void *, void *, void *), #ifdef CONFIG_MULTITHREADING if (_is_thread_essential()) { - _NanoFatalErrorHandler(_NANO_ERR_INVALID_TASK_EXIT, - &_default_esf); + _k_except_reason(_NANO_ERR_INVALID_TASK_EXIT); } k_thread_abort(_current);