From df02923944570d2f29d31075df07eb0d192d24cb Mon Sep 17 00:00:00 2001 From: Ioannis Glaropoulos Date: Mon, 7 Oct 2019 11:24:36 +0200 Subject: [PATCH] kernel: fatal: use nested exception info in z_fatal_error In z_fatal_error() we invoke the arch-specific API that evaluates whether we are in a nested exception. We then use the result to log a message that the error occurred in ISR. In non-test mode, we unconditionally panic, if an exception has occurred in an ISR and the fatal error handler has not returned (apart from the case of an error in stack sentinel check). Signed-off-by: Ioannis Glaropoulos --- include/kernel.h | 2 +- kernel/fatal.c | 45 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/include/kernel.h b/include/kernel.h index 407729b8c22..f8b841bf27e 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -4794,7 +4794,7 @@ static inline void k_cpu_atomic_idle(unsigned int key) extern void z_sys_power_save_idle_exit(s32_t ticks); #ifdef Z_ARCH_EXCEPT -/* This archtecture has direct support for triggering a CPU exception */ +/* This architecture has direct support for triggering a CPU exception */ #define z_except_reason(reason) Z_ARCH_EXCEPT(reason) #else diff --git a/kernel/fatal.c b/kernel/fatal.c index 4830eab3a28..65daa38d93c 100644 --- a/kernel/fatal.c +++ b/kernel/fatal.c @@ -5,7 +5,9 @@ */ #include + #include +#include #include #include #include @@ -93,11 +95,12 @@ void z_fatal_error(unsigned int reason, const z_arch_esf_t *esf) * an IRQ or exception was being handled, or thread context. * * See #17656 - * - * if (k_is_in_isr()) { - * LOG_ERR("Fault during interrupt handling\n"); - * } */ +#if defined(CONFIG_ARCH_HAS_NESTED_EXCEPTION_DETECTION) + if (z_arch_is_in_nested_exception(esf)) { + LOG_ERR("Fault during interrupt handling\n"); + } +#endif LOG_ERR("Current thread: %p (%s)", thread, log_strdup(thread_name_get(thread))); @@ -107,6 +110,13 @@ void z_fatal_error(unsigned int reason, const z_arch_esf_t *esf) /* If the system fatal error handler returns, then kill the faulting * thread; a policy decision was made not to hang the system. * + * Policy for fatal errors in ISRs: unconditionally panic. + * + * There is one exception to this policy: a stack sentinel + * check may be performed (on behalf of the current thread) + * during ISR exit, but in this case the thread should be + * aborted. + * * Note that k_thread_abort() returns on some architectures but * not others; e.g. on ARC, x86_64, Xtensa with ASM2, ARM */ @@ -114,8 +124,31 @@ void z_fatal_error(unsigned int reason, const z_arch_esf_t *esf) __ASSERT(reason != K_ERR_KERNEL_PANIC, "Attempted to recover from a kernel panic condition"); /* FIXME: #17656 */ - __ASSERT(!k_is_in_isr(), - "Attempted to recover from a fatal error in ISR"); +#if defined(CONFIG_ARCH_HAS_NESTED_EXCEPTION_DETECTION) + if (z_arch_is_in_nested_exception(esf)) { +#if defined(CONFIG_STACK_SENTINEL) + if (reason != K_ERR_STACK_CHK_FAIL) { + __ASSERT(0, + "Attempted to recover from a fatal error in ISR"); + } +#endif /* CONFIG_STACK_SENTINEL */ + } +#endif /* CONFIG_ARCH_HAS_NESTED_EXCEPTION_DETECTION */ + } else { + /* Test mode */ +#if defined(CONFIG_ARCH_HAS_NESTED_EXCEPTION_DETECTION) + if (z_arch_is_in_nested_exception(esf)) { + /* Abort the thread only on STACK Sentinel check fail. */ +#if defined(CONFIG_STACK_SENTINEL) + if (reason != K_ERR_STACK_CHK_FAIL) { + return; + } +#else + return; +#endif /* CONFIG_STACK_SENTINEL */ + } +#endif /*CONFIG_ARCH_HAS_NESTED_EXCEPTION_DETECTION */ } + k_thread_abort(thread); }