arc: fix CONFIG_ARC_STACK_CHECKING

- There's no clear need to disable frame pointers if this feature is
used, remove this directive.
- The 'top' and 'base' terms are reversed. The 'base' is the high
address of the stack. The top is the lowest address, where we cannot
push further down. Fixup member and offset names to correspond to how
these terms are used in hardware documentation.
- Use correct pointers for stack top location
- Fatal exceptions now go through _NanoFatalErrorHandler to report the
faulting ip and thread.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2017-05-11 15:33:16 -07:00 committed by Anas Nashif
parent 41c68ece83
commit 9175d20ceb
11 changed files with 44 additions and 65 deletions

View file

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

View file

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

View file

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

View file

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

View file

@ -17,50 +17,7 @@
#include <kernel.h>
#include <kernel_structs.h>
#ifdef CONFIG_PRINTK
#include <misc/printk.h>
#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);
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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