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:
parent
4a693c3c38
commit
b829bc78c1
|
@ -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.
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue