From e09a04f0689fd29aa909cc49ee94fd129798f986 Mon Sep 17 00:00:00 2001 From: Andrew Boie Date: Thu, 20 Apr 2017 15:32:10 -0700 Subject: [PATCH] arm: fix exception handling For exceptions where we are just going to abort the current thread, we need to exit handler mode properly so that PendSV can run and perform a context switch. For ARM architecture this means that the fatal error handling code path can indeed return if we were 1) in handler mode and 2) only wish to abort the current thread. Fixes a very long-standing bug where a thread that generates an exception, and should only abort the thread, instead takes down the entire system. Issue: ZEP-2052 Change-Id: Ib356a34a6fda2e0f8aff39c4b3270efceb81e54d Signed-off-by: Andrew Boie --- arch/arm/core/fatal.c | 13 +++++++------ arch/arm/core/fault.c | 2 -- arch/arm/core/sys_fatal_error_handler.c | 5 +---- include/arch/arm/cortex_m/error.h | 5 ++--- kernel/compiler_stack_protect.c | 1 + 5 files changed, 11 insertions(+), 15 deletions(-) diff --git a/arch/arm/core/fatal.c b/arch/arm/core/fatal.c index ae3004e1d84..b3258148aa8 100644 --- a/arch/arm/core/fatal.c +++ b/arch/arm/core/fatal.c @@ -61,12 +61,16 @@ const NANO_ESF _default_esf = { * 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 _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. */ -FUNC_NORETURN void _NanoFatalErrorHandler(unsigned int reason, +void _NanoFatalErrorHandler(unsigned int reason, const NANO_ESF *pEsf) { switch (reason) { @@ -101,7 +105,4 @@ FUNC_NORETURN void _NanoFatalErrorHandler(unsigned int reason, */ _SysFatalErrorHandler(reason, pEsf); - - for (;;) - ; } diff --git a/arch/arm/core/fault.c b/arch/arm/core/fault.c index 6e363756ad2..0590a139d14 100644 --- a/arch/arm/core/fault.c +++ b/arch/arm/core/fault.c @@ -355,8 +355,6 @@ static void _FaultDump(const NANO_ESF *esf, int fault) * * @param esf ESF on the stack, either MSP or PSP depending at what processor * state the exception was taken. - * - * @return This function does not return. */ void _Fault(const NANO_ESF *esf) { diff --git a/arch/arm/core/sys_fatal_error_handler.c b/arch/arm/core/sys_fatal_error_handler.c index 7ca627cb4bb..eb2c8625094 100644 --- a/arch/arm/core/sys_fatal_error_handler.c +++ b/arch/arm/core/sys_fatal_error_handler.c @@ -38,7 +38,7 @@ * * @return N/A */ -FUNC_NORETURN void _SysFatalErrorHandler(unsigned int reason, +void _SysFatalErrorHandler(unsigned int reason, const NANO_ESF *pEsf) { ARG_UNUSED(reason); @@ -53,12 +53,9 @@ FUNC_NORETURN void _SysFatalErrorHandler(unsigned int reason, } printk("Fatal fault in thread %p! Aborting.\n", _current); k_thread_abort(_current); - #else for (;;) { k_cpu_idle(); } #endif - - CODE_UNREACHABLE; } diff --git a/include/arch/arm/cortex_m/error.h b/include/arch/arm/cortex_m/error.h index efe7fdc08db..4e43d319d90 100644 --- a/include/arch/arm/cortex_m/error.h +++ b/include/arch/arm/cortex_m/error.h @@ -21,9 +21,8 @@ extern "C" { #endif #ifndef _ASMLANGUAGE -extern FUNC_NORETURN void _NanoFatalErrorHandler(unsigned int, - const NANO_ESF*); -extern void _SysFatalErrorHandler(unsigned int, const NANO_ESF*); +extern void _NanoFatalErrorHandler(unsigned int reason, const NANO_ESF *esf); +extern void _SysFatalErrorHandler(unsigned int reason, const NANO_ESF *esf); #endif #define _NANO_ERR_HW_EXCEPTION (0) /* MPU/Bus/Usage fault */ diff --git a/kernel/compiler_stack_protect.c b/kernel/compiler_stack_protect.c index 3fc37c837d5..903d8940a8e 100644 --- a/kernel/compiler_stack_protect.c +++ b/kernel/compiler_stack_protect.c @@ -36,6 +36,7 @@ void FUNC_NORETURN _StackCheckHandler(void) */ _NanoFatalErrorHandler(_NANO_ERR_STACK_CHK_FAIL, &_default_esf); + CODE_UNREACHABLE; } /* Global variable */