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 <Ioannis.Glaropoulos@nordicsemi.no>
This commit is contained in:
Ioannis Glaropoulos 2019-10-07 11:24:36 +02:00 committed by Andrew Boie
commit df02923944
2 changed files with 40 additions and 7 deletions

View file

@ -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

View file

@ -5,7 +5,9 @@
*/
#include <kernel.h>
#include <kernel_internal.h>
#include <kernel_structs.h>
#include <sys/__assert.h>
#include <arch/cpu.h>
#include <logging/log_ctrl.h>
@ -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(),
#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);
}