diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 6367102e3ec..44404b1a53c 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -111,6 +111,7 @@ config FIRQ_STACK_SIZE config ARC_STACK_CHECKING bool "Enable Stack Checking" depends on CPU_ARCV2 + select THREAD_STACK_INFO default n help ARCV2 has a special feature allowing to check stack overflows. This diff --git a/arch/arc/Makefile b/arch/arc/Makefile index 1bd121b4201..58ac46b0da0 100644 --- a/arch/arc/Makefile +++ b/arch/arc/Makefile @@ -5,7 +5,6 @@ cflags-y += $(call cc-option,-ffunction-sections,) $(call cc-option,-fdata-secti # See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63691 cflags-y += $(call cc-option,-fno-delete-null-pointer-checks) -cflags-$(CONFIG_ARC_STACK_CHECKING) = $(call cc-option,-fomit-frame-pointer) cflags-$(CONFIG_LTO) = $(call cc-option,-flto,) include $(srctree)/arch/$(ARCH)/soc/$(SOC_PATH)/Makefile diff --git a/arch/arc/core/fast_irq.S b/arch/arc/core/fast_irq.S index e5acb6f43fc..5d1f1be28b0 100644 --- a/arch/arc/core/fast_irq.S +++ b/arch/arc/core/fast_irq.S @@ -227,11 +227,11 @@ _firq_reschedule: st_s r2, [r1, _kernel_offset_to_current] #ifdef CONFIG_ARC_STACK_CHECKING - /* Use stack top and down registers from restored context */ - add r3, r2, _K_THREAD_NO_FLOAT_SIZEOF - sr r3, [_ARC_V2_KSTACK_TOP] - ld_s r3, [r2, _thread_offset_to_stack_top] + /* Use stack top and base registers from restored context */ + ld r3, [r2, _thread_offset_to_stack_base] sr r3, [_ARC_V2_KSTACK_BASE] + ld r3, [r2, _thread_offset_to_stack_top] + sr r3, [_ARC_V2_KSTACK_TOP] #endif /* * _load_callee_saved_regs expects incoming thread in r2. diff --git a/arch/arc/core/fatal.c b/arch/arc/core/fatal.c index 5204060a67a..bc961534005 100644 --- a/arch/arc/core/fatal.c +++ b/arch/arc/core/fatal.c @@ -41,11 +41,14 @@ FUNC_NORETURN void _NanoFatalErrorHandler(unsigned int reason, const NANO_ESF *pEsf) { switch (reason) { + case _NANO_ERR_HW_EXCEPTION: + break; + case _NANO_ERR_INVALID_TASK_EXIT: printk("***** Invalid Exit Software Error! *****\n"); break; -#if defined(CONFIG_STACK_CANARIES) +#if defined(CONFIG_STACK_CANARIES) || defined(CONFIG_ARC_STACK_CHECKING) case _NANO_ERR_STACK_CHK_FAIL: printk("***** Stack Check Fail! *****\n"); break; diff --git a/arch/arc/core/fault.c b/arch/arc/core/fault.c index 82ccc5c3da2..f76eeda19ad 100644 --- a/arch/arc/core/fault.c +++ b/arch/arc/core/fault.c @@ -17,50 +17,7 @@ #include #include - -#ifdef CONFIG_PRINTK #include -#define PR_EXC(...) printk(__VA_ARGS__) -#else -#define PR_EXC(...) -#endif /* CONFIG_PRINTK */ - -#if (CONFIG_FAULT_DUMP > 0) -#define FAULT_DUMP(esf, fault) _FaultDump(esf, fault) -#else -#define FAULT_DUMP(esf, fault) \ - do { \ - (void) esf; \ - (void) fault; \ - } while ((0)) -#endif - -#if (CONFIG_FAULT_DUMP > 0) -/* - * @brief Dump information regarding fault (FAULT_DUMP > 0) - * - * Dump information regarding the fault when CONFIG_FAULT_DUMP is set to 1 - * (short form). - * - * @return N/A - */ -void _FaultDump(const NANO_ESF *esf, int fault) -{ - ARG_UNUSED(esf); - ARG_UNUSED(fault); - -#ifdef CONFIG_PRINTK - u32_t exc_addr = _arc_v2_aux_reg_read(_ARC_V2_EFA); - u32_t ecr = _arc_v2_aux_reg_read(_ARC_V2_ECR); - - PR_EXC("Exception vector: 0x%x, cause code: 0x%x, parameter 0x%x\n", - _ARC_V2_ECR_VECTOR(ecr), - _ARC_V2_ECR_CODE(ecr), - _ARC_V2_ECR_PARAMETER(ecr)); - PR_EXC("Address 0x%x\n", exc_addr); -#endif -} -#endif /* CONFIG_FAULT_DUMP */ /* * @brief Fault handler @@ -74,9 +31,24 @@ void _FaultDump(const NANO_ESF *esf, int fault) */ void _Fault(void) { + u32_t vector, code, parameter; + u32_t exc_addr = _arc_v2_aux_reg_read(_ARC_V2_EFA); u32_t ecr = _arc_v2_aux_reg_read(_ARC_V2_ECR); - FAULT_DUMP(&_default_esf, ecr); + vector = _ARC_V2_ECR_VECTOR(ecr); + code = _ARC_V2_ECR_CODE(ecr); + parameter = _ARC_V2_ECR_PARAMETER(ecr); - _SysFatalErrorHandler(_NANO_ERR_HW_EXCEPTION, &_default_esf); + printk("Exception vector: 0x%x, cause code: 0x%x, parameter 0x%x\n", + vector, code, parameter); + printk("Address 0x%x\n", exc_addr); +#ifdef CONFIG_ARC_STACK_CHECKING + /* Vector 6 = EV_ProV. Regardless of code, parameter 2 means stack + * check violation + */ + if (vector == 6 && parameter == 2) { + _NanoFatalErrorHandler(_NANO_ERR_STACK_CHK_FAIL, &_default_esf); + } +#endif + _NanoFatalErrorHandler(_NANO_ERR_HW_EXCEPTION, &_default_esf); } diff --git a/arch/arc/core/offsets/offsets.c b/arch/arc/core/offsets/offsets.c index 1a463e4ffa2..09419c7fed4 100644 --- a/arch/arc/core/offsets/offsets.c +++ b/arch/arc/core/offsets/offsets.c @@ -30,7 +30,7 @@ GEN_OFFSET_SYM(_thread_arch_t, intlock_key); GEN_OFFSET_SYM(_thread_arch_t, relinquish_cause); GEN_OFFSET_SYM(_thread_arch_t, return_value); #ifdef CONFIG_ARC_STACK_CHECKING -GEN_OFFSET_SYM(_thread_arch_t, stack_top); +GEN_OFFSET_SYM(_thread_arch_t, stack_base); #endif /* ARCv2-specific IRQ stack frame structure member offsets */ diff --git a/arch/arc/core/regular_irq.S b/arch/arc/core/regular_irq.S index 8f4a5d615f1..d69f6b343f6 100644 --- a/arch/arc/core/regular_irq.S +++ b/arch/arc/core/regular_irq.S @@ -158,11 +158,11 @@ _rirq_common_interrupt_swap: /* r2 contains pointer to new thread */ #ifdef CONFIG_ARC_STACK_CHECKING - /* Use stack top and down registers from restored context */ - add r3, r2, _K_THREAD_NO_FLOAT_SIZEOF - sr r3, [_ARC_V2_KSTACK_TOP] - ld_s r3, [r2, _thread_offset_to_stack_top] + /* Use stack top and base registers from restored context */ + ld r3, [r2, _thread_offset_to_stack_base] sr r3, [_ARC_V2_KSTACK_BASE] + ld r3, [r2, _thread_offset_to_stack_top] + sr r3, [_ARC_V2_KSTACK_TOP] #endif /* * _load_callee_saved_regs expects incoming thread in r2. diff --git a/arch/arc/core/swap.S b/arch/arc/core/swap.S index ca775406710..02747019c45 100644 --- a/arch/arc/core/swap.S +++ b/arch/arc/core/swap.S @@ -99,11 +99,11 @@ SECTION_FUNC(TEXT, __swap) /* entering here, r2 contains the new current thread */ #ifdef CONFIG_ARC_STACK_CHECKING - /* Use stack top and down registers from restored context */ - add r3, r2, _K_THREAD_NO_FLOAT_SIZEOF - sr r3, [_ARC_V2_KSTACK_TOP] - ld_s r3, [r2, _thread_offset_to_stack_top] + /* Use stack top and base registers from restored context */ + ld r3, [r2, _thread_offset_to_stack_base] sr r3, [_ARC_V2_KSTACK_BASE] + ld r3, [r2, _thread_offset_to_stack_top] + sr r3, [_ARC_V2_KSTACK_TOP] #endif /* XXX - can be moved to delay slot of _CAUSE_RIRQ ? */ st_s r2, [r1, _kernel_offset_to_current] diff --git a/arch/arc/core/thread.c b/arch/arc/core/thread.c index 1c50755d4b1..5b25b79a039 100644 --- a/arch/arc/core/thread.c +++ b/arch/arc/core/thread.c @@ -84,7 +84,7 @@ void _new_thread(struct k_thread *thread, char *pStackMem, size_t stackSize, */ #ifdef CONFIG_ARC_STACK_CHECKING pInitCtx->status32 = _ARC_V2_STATUS32_SC | _ARC_V2_STATUS32_E(_ARC_V2_DEF_IRQ_LEVEL); - thread->arch.stack_top = (u32_t) stackEnd; + thread->arch.stack_base = (u32_t) stackEnd; #else pInitCtx->status32 = _ARC_V2_STATUS32_E(_ARC_V2_DEF_IRQ_LEVEL); #endif diff --git a/arch/arc/include/kernel_arch_thread.h b/arch/arc/include/kernel_arch_thread.h index a74c2a4e6d4..f349cbceace 100644 --- a/arch/arc/include/kernel_arch_thread.h +++ b/arch/arc/include/kernel_arch_thread.h @@ -58,8 +58,10 @@ struct _thread_arch { unsigned int return_value; #ifdef CONFIG_ARC_STACK_CHECKING - /* top of stack for hardware stack checking */ - u32_t stack_top; + /* High address of stack region, stack grows downward from this + * location. Usesd for hardware stack checking + */ + u32_t stack_base; #endif }; diff --git a/arch/arc/include/offsets_short_arch.h b/arch/arc/include/offsets_short_arch.h index eccf45ece8c..b8f78d8ccc8 100644 --- a/arch/arc/include/offsets_short_arch.h +++ b/arch/arc/include/offsets_short_arch.h @@ -26,12 +26,14 @@ #define _thread_offset_to_return_value \ (___thread_t_arch_OFFSET + ___thread_arch_t_return_value_OFFSET) -#define _thread_offset_to_stack_top \ - (___thread_t_arch_OFFSET + ___thread_arch_t_stack_top_OFFSET) +#define _thread_offset_to_stack_base \ + (___thread_t_arch_OFFSET + ___thread_arch_t_stack_base_OFFSET) #define _thread_offset_to_sp \ (___thread_t_callee_saved_OFFSET + ___callee_saved_t_sp_OFFSET) +#define _thread_offset_to_stack_top \ + (___thread_t_stack_info_OFFSET + ___thread_stack_info_t_start_OFFSET) /* end - threads */