Skip to content
Permalink
Browse files

kernel: consolidate error handling code

* z_NanoFatalErrorHandler() is now moved to common kernel code
  and renamed z_fatal_error(). Arches dump arch-specific info
  before calling.
* z_SysFatalErrorHandler() is now moved to common kernel code
  and renamed k_sys_fatal_error_handler(). It is now much simpler;
  the default policy is simply to lock interrupts and halt the system.
  If an implementation of this function returns, then the currently
  running thread is aborted.
* New arch-specific APIs introduced:
  - z_arch_system_halt() simply powers off or halts the system.
* We now have a standard set of fatal exception reason codes,
  namespaced under K_ERR_*
* CONFIG_SIMPLE_FATAL_ERROR_HANDLER deleted
* LOG_PANIC() calls moved to k_sys_fatal_error_handler()

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
  • Loading branch information...
andrewboie committed Jul 11, 2019
1 parent 81245a0 commit 71ce8ceb1843f94861c3feebb86761842ca1c531
Showing with 392 additions and 1,178 deletions.
  1. +0 −9 arch/Kconfig
  2. +0 −1 arch/arc/core/CMakeLists.txt
  3. +4 −60 arch/arc/core/fatal.c
  4. +5 −6 arch/arc/core/fault.c
  5. +0 −74 arch/arc/core/sys_fatal_error_handler.c
  6. +1 −1 arch/arc/include/kernel_arch_func.h
  7. +0 −1 arch/arm/core/CMakeLists.txt
  8. +5 −84 arch/arm/core/fatal.c
  9. +13 −14 arch/arm/core/fault.c
  10. +0 −73 arch/arm/core/sys_fatal_error_handler.c
  11. +2 −0 arch/arm/include/kernel_arch_func.h
  12. +10 −104 arch/nios2/core/fatal.c
  13. +2 −2 arch/nios2/core/irq_manage.c
  14. +3 −0 arch/nios2/include/kernel_arch_func.h
  15. +4 −108 arch/posix/core/fatal.c
  16. +5 −115 arch/riscv32/core/fatal.c
  17. +2 −3 arch/riscv32/core/irq_manage.c
  18. +2 −3 arch/riscv32/include/kernel_arch_func.h
  19. +0 −1 arch/x86/core/ia32.cmake
  20. +43 −105 arch/x86/core/ia32/fatal.c
  21. +6 −14 arch/x86/core/ia32/intstub.S
  22. +0 −83 arch/x86/core/ia32/sys_fatal_error_handler.c
  23. +1 −14 arch/x86_64/core/x86_64.c
  24. +14 −123 arch/xtensa/core/fatal.c
  25. +2 −2 arch/xtensa/core/xtensa-asm2.c
  26. +1 −0 arch/xtensa/include/kernel_arch_func.h
  27. +8 −7 doc/guides/porting/arch.rst
  28. +1 −14 include/arch/arc/v2/error.h
  29. +0 −11 include/arch/arm/cortex_m/error.h
  30. +0 −7 include/arch/nios2/arch.h
  31. +0 −14 include/arch/posix/arch.h
  32. +0 −13 include/arch/riscv32/exp.h
  33. +0 −31 include/arch/x86/ia32/arch.h
  34. +0 −12 include/arch/x86_64/arch.h
  35. +0 −13 include/arch/xtensa/arch.h
  36. +87 −0 include/fatal.h
  37. +5 −6 include/kernel.h
  38. +1 −0 include/kernel_includes.h
  39. +1 −0 kernel/CMakeLists.txt
  40. +1 −1 kernel/compiler_stack_protect.c
  41. +118 −0 kernel/fatal.c
  42. +5 −0 kernel/include/kernel_internal.h
  43. +1 −1 kernel/thread.c
  44. +2 −0 subsys/testsuite/ztest/include/ztest.h
  45. +1 −1 subsys/testsuite/ztest/include/ztest_test.h
  46. +5 −0 tests/arch/x86/static_idt/src/main.c
  47. +9 −36 tests/kernel/fatal/src/main.c
  48. +1 −1 tests/kernel/mem_protect/mem_protect/src/common.c
  49. +1 −1 tests/kernel/mem_protect/protection/src/main.c
  50. +5 −0 tests/kernel/mem_protect/stackprot/src/main.c
  51. +7 −7 tests/kernel/mem_protect/userspace/src/main.c
  52. +1 −1 tests/kernel/pipe/pipe/src/test_pipe.c
  53. +7 −1 tests/kernel/threads/dynamic_thread/src/main.c
@@ -241,15 +241,6 @@ config DYNAMIC_OBJECTS
API call, or when the number of references to that object drops to
zero.

config SIMPLE_FATAL_ERROR_HANDLER
bool "Simple system fatal error handler"
default y if !MULTITHREADING
help
Provides an implementation of _SysFatalErrorHandler() that hard hangs
instead of aborting the faulting thread, and does not print anything,
for footprint-concerned systems. Only enable this option if you do not
want debug capabilities in case of system fatal error.

if ARCH_HAS_NOCACHE_MEMORY_SUPPORT

config NOCACHE_MEMORY
@@ -14,7 +14,6 @@ zephyr_library_sources(
isr_wrapper.S
regular_irq.S
switch.S
sys_fatal_error_handler.c
prep_c.c
reset.S
vector_table.c
@@ -19,74 +19,18 @@
#include <sys/printk.h>
#include <logging/log_ctrl.h>

/**
*
* @brief Kernel fatal error handler
*
* This routine is called when fatal error conditions are detected by software
* and is responsible only for reporting the error. Once reported, it then
* invokes the user provided routine z_SysFatalErrorHandler() which is
* responsible for implementing the error handling policy.
*
* The caller is expected to always provide a usable ESF. In the event that the
* fatal error does not have a hardware generated ESF, the caller should either
* create its own or use a pointer to the global default ESF <_default_esf>.
*
* @return This function does not return.
*/
void z_NanoFatalErrorHandler(unsigned int reason, const NANO_ESF *pEsf)
void z_arc_fatal_error(unsigned int reason, const NANO_ESF *esf)
{
LOG_PANIC();

switch (reason) {
case _NANO_ERR_HW_EXCEPTION:
break;

#if defined(CONFIG_STACK_CANARIES) || defined(CONFIG_ARC_STACK_CHECKING) \
|| defined(CONFIG_STACK_SENTINEL) || defined(CONFIG_MPU_STACK_GUARD)
case _NANO_ERR_STACK_CHK_FAIL:
printk("***** Stack Check Fail! *****\n");
break;
#endif

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;
}

printk("Current thread ID = %p\n", k_current_get());

if (reason == _NANO_ERR_HW_EXCEPTION) {
if (reason == K_ERR_CPU_EXCEPTION) {
printk("Faulting instruction address = 0x%lx\n",
z_arc_v2_aux_reg_read(_ARC_V2_ERET));
}

/*
* Now that the error has been reported, call the user implemented
* policy
* to respond to the error. The decisions as to what responses are
* appropriate to the various errors are something the customer must
* decide.
*/

z_SysFatalErrorHandler(reason, pEsf);
z_fatal_error(reason, esf);
}

FUNC_NORETURN void z_arch_syscall_oops(void *ssf_ptr)
{
LOG_PANIC();
z_SysFatalErrorHandler(_NANO_ERR_KERNEL_OOPS, ssf_ptr);
z_arc_fatal_error(K_ERR_KERNEL_OOPS, ssf_ptr);
CODE_UNREACHABLE;
}
@@ -371,7 +371,7 @@ static void dump_exception_info(u32_t vector, u32_t cause, u32_t parameter)
*
* This routine is called when fatal error conditions are detected by hardware
* and is responsible only for reporting the error. Once reported, it then
* invokes the user provided routine z_SysFatalErrorHandler() which is
* invokes the user provided routine k_sys_fatal_error_handler() which is
* responsible for implementing the error handling policy.
*/
void _Fault(NANO_ESF *esf)
@@ -391,15 +391,14 @@ void _Fault(NANO_ESF *esf)
}
}
#endif
LOG_PANIC();

vector = Z_ARC_V2_ECR_VECTOR(ecr);
cause = Z_ARC_V2_ECR_CODE(ecr);
parameter = Z_ARC_V2_ECR_PARAMETER(ecr);

/* exception raised by kernel */
if (vector == ARC_EV_TRAP && parameter == _TRAP_S_CALL_RUNTIME_EXCEPT) {
z_NanoFatalErrorHandler(esf->r0, esf);
z_arc_fatal_error(esf->r0, esf);
return;
}

@@ -417,7 +416,7 @@ void _Fault(NANO_ESF *esf)
* parameter = 0x2 | [0x4 | 0x8 | 0x1]
*/
if (vector == ARC_EV_PROT_V && parameter & 0x2) {
z_NanoFatalErrorHandler(_NANO_ERR_STACK_CHK_FAIL, esf);
z_arc_fatal_error(K_ERR_STACK_CHK_FAIL, esf);
return;
}
#endif
@@ -426,10 +425,10 @@ void _Fault(NANO_ESF *esf)
if (vector == ARC_EV_PROT_V && ((parameter == 0x4) ||
(parameter == 0x24))) {
if (z_check_thread_stack_fail(exc_addr, arc_exc_saved_sp)) {
z_NanoFatalErrorHandler(_NANO_ERR_STACK_CHK_FAIL, esf);
z_arc_fatal_error(K_ERR_STACK_CHK_FAIL, esf);
return;
}
}
#endif
z_NanoFatalErrorHandler(_NANO_ERR_HW_EXCEPTION, esf);
z_arc_fatal_error(K_ERR_CPU_EXCEPTION, esf);
}

This file was deleted.

@@ -61,7 +61,7 @@ extern void z_arc_userspace_enter(k_thread_entry_t user_entry, void *p1,


extern void z_arch_switch(void *switch_to, void **switched_from);

extern void z_arc_fatal_error(unsigned int reason, const NANO_ESF *esf);
#endif /* _ASMLANGUAGE */

#ifdef __cplusplus
@@ -19,7 +19,6 @@ zephyr_library_sources(
cpu_idle.S
fault_s.S
fatal.c
sys_fatal_error_handler.c
thread_abort.c
)

@@ -20,102 +20,23 @@
#include <sys/printk.h>
#include <logging/log_ctrl.h>

/**
*
* @brief Kernel fatal error handler
*
* This routine is called when fatal error conditions are detected by software
* and is responsible only for reporting the error. Once reported, it then
* invokes the user provided routine z_SysFatalErrorHandler() which is
* responsible for implementing the error handling policy.
*
* The caller is expected to always provide a usable ESF. In the event that the
* fatal error does not have a hardware generated ESF, the caller should either
* create its own or use a pointer to the global default ESF <_default_esf>.
*
* Unlike other arches, this function may return if z_SysFatalErrorHandler
* determines that only the current thread should be aborted and the CPU
* was in handler mode. PendSV will be asserted in this case and the current
* thread taken off the run queue. Leaving the exception will immediately
* trigger a context switch.
*
* @param reason the reason that the handler was called
* @param pEsf pointer to the exception stack frame
*
* @return This function does not return.
*/
void z_NanoFatalErrorHandler(unsigned int reason,
const NANO_ESF *pEsf)
void z_arm_fatal_error(unsigned int reason, const NANO_ESF *esf)
{
#ifdef CONFIG_THREAD_NAME
const char *thread_name = k_thread_name_get(k_current_get());
#endif

LOG_PANIC();

switch (reason) {
case _NANO_ERR_HW_EXCEPTION:
printk("***** Hardware exception *****\n");
break;
#if defined(CONFIG_STACK_CANARIES) || defined(CONFIG_STACK_SENTINEL) || \
defined(CONFIG_HW_STACK_PROTECTION) || \
defined(CONFIG_USERSPACE)
case _NANO_ERR_STACK_CHK_FAIL:
printk("***** Stack Check Fail! *****\n");
break;
#endif /* CONFIG_STACK_CANARIES */

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;
}
printk("Current thread ID = %p"
#ifdef CONFIG_THREAD_NAME
" (%s)"
#endif
"\n"
"Faulting instruction address = 0x%x\n",
k_current_get(),
#ifdef CONFIG_THREAD_NAME
thread_name ? thread_name : "unknown",
#endif
pEsf->basic.pc);

/*
* Now that the error has been reported, call the user implemented
* policy
* to respond to the error. The decisions as to what responses are
* appropriate to the various errors are something the customer must
* decide.
*/

z_SysFatalErrorHandler(reason, pEsf);
printk("Faulting instruction address = 0x%x\n",
esf->basic.pc);
z_fatal_error(reason, esf);
}

void z_do_kernel_oops(const NANO_ESF *esf)
{
z_NanoFatalErrorHandler(esf->basic.r0, esf);
z_arm_fatal_error(esf->basic.r0, esf);
}

FUNC_NORETURN void z_arch_syscall_oops(void *ssf_ptr)
{
u32_t *ssf_contents = ssf_ptr;
NANO_ESF oops_esf = { 0 };

LOG_PANIC();

oops_esf.basic.pc = ssf_contents[3];

z_do_kernel_oops(&oops_esf);

0 comments on commit 71ce8ce

Please sign in to comment.
You can’t perform that action at this time.