arch: arc: refactor the arc stack check support

* the original stack check codes have no consideration
  for userspace case. This will wrong cause possible stack
  check exception.
* this commit refactors the arc stack check support to
  support the usperspace.

* this commit fixes #7885. All the failed tests in #7885
  are run again to verify this commit. The test results are ok

Signed-off-by: Wayne Ren <wei.ren@synopsys.com>
This commit is contained in:
Wayne Ren 2018-06-01 14:00:22 +08:00 committed by Anas Nashif
parent 4a693c3c38
commit b829bc78c1
10 changed files with 106 additions and 35 deletions

View file

@ -243,11 +243,7 @@ _firq_reschedule:
st_s r2, [r1, _kernel_offset_to_current]
#ifdef CONFIG_ARC_STACK_CHECKING
/* 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]
_load_stack_check_regs
#endif
/*
* _load_callee_saved_regs expects incoming thread in r2.

View file

@ -30,7 +30,12 @@ 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_base);
GEN_OFFSET_SYM(_thread_arch_t, k_stack_base);
GEN_OFFSET_SYM(_thread_arch_t, k_stack_top);
#ifdef CONFIG_USERSPACE
GEN_OFFSET_SYM(_thread_arch_t, u_stack_base);
GEN_OFFSET_SYM(_thread_arch_t, u_stack_top);
#endif
#endif
/* ARCv2-specific IRQ stack frame structure member offsets */

View file

@ -143,11 +143,7 @@ _rirq_common_interrupt_swap:
/* r2 contains pointer to new thread */
#ifdef CONFIG_ARC_STACK_CHECKING
/* 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]
_load_stack_check_regs
#endif
/*
* _load_callee_saved_regs expects incoming thread in r2.

View file

@ -104,11 +104,7 @@ SECTION_FUNC(TEXT, __swap)
/* entering here, r2 contains the new current thread */
#ifdef CONFIG_ARC_STACK_CHECKING
/* 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]
_load_stack_check_regs
#endif
/* XXX - can be moved to delay slot of _CAUSE_RIRQ ? */
st_s r2, [r1, _kernel_offset_to_current]

View file

@ -132,7 +132,24 @@ void _new_thread(struct k_thread *thread, k_thread_stack_t *stack,
#ifdef CONFIG_ARC_STACK_CHECKING
pInitCtx->status32 = _ARC_V2_STATUS32_SC |
_ARC_V2_STATUS32_E(_ARC_V2_DEF_IRQ_LEVEL);
thread->arch.stack_base = (u32_t) stackEnd;
#ifdef CONFIG_USERSPACE
if (options & K_USER) {
thread->arch.u_stack_top = (u32_t)pStackMem;
thread->arch.u_stack_base = (u32_t)stackEnd;
thread->arch.k_stack_top =
(u32_t)(stackEnd + STACK_GUARD_SIZE);
thread->arch.k_stack_base = (u32_t)
(stackEnd + STACK_GUARD_SIZE + CONFIG_PRIVILEGED_STACK_SIZE);
} else {
thread->arch.k_stack_top = (u32_t)pStackMem;
thread->arch.k_stack_base = (u32_t)stackEnd;
thread->arch.u_stack_top = 0;
thread->arch.u_stack_base = 0;
}
#else
thread->arch.k_stack_top = (u32_t) pStackMem;
thread->arch.k_stack_base = (u32_t) stackEnd;
#endif
#else
pInitCtx->status32 = _ARC_V2_STATUS32_E(_ARC_V2_DEF_IRQ_LEVEL);
#endif
@ -149,18 +166,9 @@ void _new_thread(struct k_thread *thread, k_thread_stack_t *stack,
if (options & K_USER) {
thread->arch.priv_stack_start =
(u32_t) (stackEnd + STACK_GUARD_SIZE);
(u32_t)(stackEnd + STACK_GUARD_SIZE);
thread->arch.priv_stack_size =
(u32_t)CONFIG_PRIVILEGED_STACK_SIZE;
#ifdef CONFIG_ARC_STACK_CHECKING
/*
* for user thread, set the correct stack base, it covers both user stack
* part and privileged stack part. One case can not be detected:
* the overflow from privilege stack to user stack.
*/
thread->arch.stack_base = (u32_t) stackEnd + STACK_GUARD_SIZE +
CONFIG_PRIVILEGED_STACK_SIZE;
#endif
} else {
thread->arch.priv_stack_start = 0;
thread->arch.priv_stack_size = 0;
@ -213,11 +221,20 @@ FUNC_NORETURN void _arch_user_mode_enter(k_thread_entry_t user_entry,
_current->stack_info.size -= CONFIG_PRIVILEGED_STACK_SIZE;
_current->arch.priv_stack_start =
(u32_t) (_current->stack_info.start +
_current->stack_info.size + STACK_GUARD_SIZE);
(u32_t)(_current->stack_info.start +
_current->stack_info.size + STACK_GUARD_SIZE);
_current->arch.priv_stack_size =
(u32_t)CONFIG_PRIVILEGED_STACK_SIZE;
#ifdef CONFIG_ARC_STACK_CHECKING
_current->arch.k_stack_top = _current->arch.priv_stack_start;
_current->arch.k_stack_base = _current->arch.priv_stack_start +
_current->arch.priv_stack_size;
_current->arch.u_stack_top = _current->stack_info.start;
_current->arch.u_stack_base = _current->stack_info.start +
_current->stack_info.size;
#endif
/* possible optimizaiton: no need to load mem domain anymore */
/* need to lock cpu here ? */
configure_mpu_thread(_current);

View file

@ -10,6 +10,7 @@
#include <kernel_structs.h>
#include <arch/cpu.h>
#include <syscall.h>
#include <swap_macros.h>
.macro clear_scratch_regs
mov r1, 0
@ -84,6 +85,12 @@ SECTION_FUNC(TEXT, _arc_userspace_enter)
/*
* In ARCv2, the U bit can only be set through exception return
*/
#ifdef CONFIG_ARC_STACK_CHECKING
/* disable stack checking during swap */
lr blink, [_ARC_V2_STATUS32]
bclr blink, blink, _ARC_V2_STATUS32_SC_BIT
kflag blink
#endif
/* the end of user stack in r5 */
add r5, r4, r5
/* start of privilege stack */
@ -107,6 +114,17 @@ _clear_user_stack:
cmp r4, r5
jlt _clear_user_stack
#ifdef CONFIG_ARC_STACK_CHECKING
mov r1, _kernel
ld_s r2, [r1, _kernel_offset_to_current]
_load_stack_check_regs
lr r0, [_ARC_V2_STATUS32]
bset r0, r0, _ARC_V2_STATUS32_SC_BIT
kflag r0
#endif
_arc_go_to_user_space:
lr r0, [_ARC_V2_STATUS32]
bset r0, r0, _ARC_V2_STATUS32_U_BIT

View file

@ -61,7 +61,12 @@ struct _thread_arch {
/* High address of stack region, stack grows downward from this
* location. Usesd for hardware stack checking
*/
u32_t stack_base;
u32_t k_stack_base;
u32_t k_stack_top;
#ifdef CONFIG_USERSPACE
u32_t u_stack_base;
u32_t u_stack_top ;
#endif
#endif
#ifdef CONFIG_USERSPACE

View file

@ -26,15 +26,21 @@
#define _thread_offset_to_return_value \
(___thread_t_arch_OFFSET + ___thread_arch_t_return_value_OFFSET)
#define _thread_offset_to_stack_base \
(___thread_t_arch_OFFSET + ___thread_arch_t_stack_base_OFFSET)
#define _thread_offset_to_k_stack_base \
(___thread_t_arch_OFFSET + ___thread_arch_t_k_stack_base_OFFSET)
#define _thread_offset_to_k_stack_top \
(___thread_t_arch_OFFSET + ___thread_arch_t_k_stack_top_OFFSET)
#define _thread_offset_to_u_stack_base \
(___thread_t_arch_OFFSET + ___thread_arch_t_u_stack_base_OFFSET)
#define _thread_offset_to_u_stack_top \
(___thread_t_arch_OFFSET + ___thread_arch_t_u_stack_top_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 */
#endif /* _offsets_short_arch__h_ */

View file

@ -242,6 +242,32 @@ extern "C" {
.endm
.macro _load_stack_check_regs
#ifdef CONFIG_ARC_HAS_SECURE
ld r3, [r2, _thread_offset_to_k_stack_base]
sr r3, [_ARC_V2_S_KSTACK_BASE]
ld r3, [r2, _thread_offset_to_k_stack_top]
sr r3, [_ARC_V2_S_KSTACK_TOP]
#ifdef CONFIG_USERSPACE
ld r3, [r2, _thread_offset_to_u_stack_base]
sr r3, [_ARC_V2_S_USTACK_BASE]
ld r3, [r2, _thread_offset_to_u_stack_top]
sr r3, [_ARC_V2_S_USTACK_TOP]
#endif
#else /* CONFIG_ARC_HAS_SECURE */
ld r3, [r2, _thread_offset_to_k_stack_base]
sr r3, [_ARC_V2_KSTACK_BASE]
ld r3, [r2, _thread_offset_to_k_stack_top]
sr r3, [_ARC_V2_KSTACK_TOP]
#ifdef CONFIG_USERSPACE
ld r3, [r2, _thread_offset_to_u_stack_base]
sr r3, [_ARC_V2_USTACK_BASE]
ld r3, [r2, _thread_offset_to_u_stack_top]
sr r3, [_ARC_V2_USTACK_TOP]
#endif
#endif /* CONFIG_ARC_HAS_SECURE */
.endm
#endif /* _ASMLANGUAGE */
#ifdef __cplusplus

View file

@ -76,8 +76,14 @@ extern "C" {
#define _ARC_V2_IRQ_PRIO_PEND 0x200
#define _ARC_V2_AUX_IRQ_HINT 0x201
#define _ARC_V2_IRQ_PRIORITY 0x206
#define _ARC_V2_USTACK_TOP 0x260
#define _ARC_V2_USTACK_BASE 0x261
#define _ARC_V2_S_USTACK_TOP 0x262
#define _ARC_V2_S_USTACK_BASE 0x263
#define _ARC_V2_KSTACK_TOP 0x264
#define _ARC_V2_KSTACK_BASE 0x265
#define _ARC_V2_S_KSTACK_TOP 0x266
#define _ARC_V2_S_KSTACK_BASE 0x267
#define _ARC_V2_JLI_BASE 0x290
#define _ARC_V2_LDI_BASE 0x291
#define _ARC_V2_EI_BASE 0x292