arc: fix the bug where regular irq comes out in user mode
if USERSPACE is configured, it needs to record the user/kernel mode of interrupted thread, because the switch of aux_sec_k_sp/aux_user_sp depends on the aux_irq_act's U bit. Signed-off-by: Watson Zeng <zhiwei@synopsys.com>
This commit is contained in:
parent
991b0db47e
commit
ffd8a91f55
|
@ -222,11 +222,36 @@ _firq_reschedule:
|
|||
* registers from the interrupted thread.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
/* when USERSPACE is configured, here need to consider the case where firq comes
|
||||
* out in user mode, according to ARCv2 ISA and nsim, the following micro ops
|
||||
* will be executed:
|
||||
* sp<-reg bank1'sp
|
||||
* switch between sp and _ARC_V2_USER_SP
|
||||
* then:
|
||||
* sp is the sp of kernel stack of interrupted thread
|
||||
* _ARC_V2_USER_SP is reg bank1'sp
|
||||
* the sp of user stack of interrupted thread is reg bank0'sp
|
||||
* if firq comes out in kernel mode, the following micro ops will be executed:
|
||||
* sp<-reg bank'sp
|
||||
* so, sw needs to do necessary handling to set up the correct sp
|
||||
*/
|
||||
lr r0, [_ARC_V2_AUX_IRQ_ACT]
|
||||
bbit0 r0, 31, _firq_from_kernel
|
||||
aex sp, [_ARC_V2_USER_SP]
|
||||
lr r0, [_ARC_V2_STATUS32]
|
||||
and r0, r0, ~_ARC_V2_STATUS32_RB(7)
|
||||
kflag r0
|
||||
aex sp, [_ARC_V2_USER_SP]
|
||||
b _firq_create_irq_stack_frame
|
||||
_firq_from_kernel:
|
||||
#endif
|
||||
/* chose register bank #0 */
|
||||
lr r0, [_ARC_V2_STATUS32]
|
||||
and r0, r0, ~_ARC_V2_STATUS32_RB(7)
|
||||
kflag r0
|
||||
|
||||
_firq_create_irq_stack_frame:
|
||||
/* we're back on the outgoing thread's stack */
|
||||
_create_irq_stack_frame
|
||||
|
||||
|
@ -241,6 +266,24 @@ _firq_reschedule:
|
|||
st ilink, [sp, ___isf_t_pc_OFFSET] /* ilink into pc */
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
/*
|
||||
* when USERSPACE is enabled, according to ARCv2 ISA, SP will be switched
|
||||
* if interrupt comes out in user mode, and will be recorded in bit 31
|
||||
* (U bit) of IRQ_ACT. when interrupt exits, SP will be switched back
|
||||
* according to U bit.
|
||||
*
|
||||
* need to remember the user/kernel status of interrupted thread, will be
|
||||
* restored when thread switched back
|
||||
*
|
||||
*/
|
||||
lr r4, [_ARC_V2_AUX_IRQ_ACT]
|
||||
and r3, r4, 0x80000000
|
||||
push_s r3
|
||||
|
||||
bclr r4, r4, 31
|
||||
sr r4, [_ARC_V2_AUX_IRQ_ACT]
|
||||
#endif
|
||||
mov_s r1, _kernel
|
||||
ld_s r2, [r1, _kernel_offset_to_current]
|
||||
|
||||
|
@ -323,6 +366,15 @@ _firq_return_from_coop:
|
|||
_firq_return_from_rirq:
|
||||
_firq_return_from_firq:
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
/*
|
||||
* need to recover the user/kernel status of interrupted thread
|
||||
*/
|
||||
pop_s r3
|
||||
lr r2, [_ARC_V2_AUX_IRQ_ACT]
|
||||
or r2, r2, r3
|
||||
sr r2, [_ARC_V2_AUX_IRQ_ACT]
|
||||
#endif
|
||||
_pop_irq_stack_frame
|
||||
|
||||
ld ilink, [sp, -4] /* status32 into ilink */
|
||||
|
|
|
@ -152,6 +152,24 @@ SECTION_FUNC(TEXT, _rirq_exit)
|
|||
.balign 4
|
||||
_rirq_reschedule:
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
/*
|
||||
* when USERSPACE is enabled, according to ARCv2 ISA, SP will be switched
|
||||
* if interrupt comes out in user mode, and will be recorded in bit 31
|
||||
* (U bit) of IRQ_ACT. when interrupt exits, SP will be switched back
|
||||
* according to U bit.
|
||||
*
|
||||
* need to remember the user/kernel status of interrupted thread, will be
|
||||
* restored when thread switched back
|
||||
*
|
||||
*/
|
||||
lr r4, [_ARC_V2_AUX_IRQ_ACT]
|
||||
and r3, r4, 0x80000000
|
||||
push_s r3
|
||||
|
||||
bclr r4, r4, 31
|
||||
sr r4, [_ARC_V2_AUX_IRQ_ACT]
|
||||
#endif
|
||||
/* _save_callee_saved_regs expects outgoing thread in r2 */
|
||||
_save_callee_saved_regs
|
||||
|
||||
|
@ -181,21 +199,6 @@ _rirq_common_interrupt_swap:
|
|||
pop_s r2
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
/*
|
||||
* when USERSPACE is enabled, according to ARCv2 ISA, SP will be switched
|
||||
* if interrupt comes out in user mode, and will be recorded in bit 31
|
||||
* (U bit) of IRQ_ACT. when interrupt exits, SP will be switched back
|
||||
* according to U bit.
|
||||
*
|
||||
* For the case that context switches in interrupt, the target sp must be
|
||||
* thread's kernel stack, no need to do hardware sp switch. so, U bit should
|
||||
* be cleared.
|
||||
*/
|
||||
lr r0, [_ARC_V2_AUX_IRQ_ACT]
|
||||
bclr r0, r0, 31
|
||||
sr r0, [_ARC_V2_AUX_IRQ_ACT]
|
||||
#endif
|
||||
|
||||
ld r3, [r2, _thread_offset_to_relinquish_cause]
|
||||
|
||||
|
@ -250,11 +253,24 @@ _rirq_return_from_coop:
|
|||
|
||||
/* fall through to rtie instruction */
|
||||
|
||||
/* stack now has the IRQ stack frame layout, pointing to sp */
|
||||
/* rtie will pop the rest from the stack */
|
||||
rtie
|
||||
|
||||
#endif /* CONFIG_PREEMPT_ENABLED */
|
||||
|
||||
.balign 4
|
||||
_rirq_return_from_firq:
|
||||
_rirq_return_from_rirq:
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
/*
|
||||
* need to recover the user/kernel status of interrupted thread
|
||||
*/
|
||||
pop_s r3
|
||||
lr r2, [_ARC_V2_AUX_IRQ_ACT]
|
||||
or r2, r2, r3
|
||||
sr r2, [_ARC_V2_AUX_IRQ_ACT]
|
||||
#endif
|
||||
#ifdef CONFIG_TRACING
|
||||
push_s blink
|
||||
|
||||
|
|
|
@ -194,6 +194,15 @@ return_loc:
|
|||
_swap_return_from_rirq:
|
||||
_swap_return_from_firq:
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
/*
|
||||
* need to recover the user/kernel status of interrupted thread
|
||||
*/
|
||||
pop_s r3
|
||||
lr r2, [_ARC_V2_AUX_IRQ_ACT]
|
||||
or r2, r2, r3
|
||||
sr r2, [_ARC_V2_AUX_IRQ_ACT]
|
||||
#endif
|
||||
lr r3, [_ARC_V2_STATUS32]
|
||||
bbit1 r3, _ARC_V2_STATUS32_AE_BIT, _return_from_exc_irq
|
||||
|
||||
|
@ -209,13 +218,10 @@ _swap_return_from_firq:
|
|||
#endif
|
||||
|
||||
lr r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
brne r3, 0, _swap_already_in_irq
|
||||
|
||||
/* use lowest interrupt priority */
|
||||
or r3, r3, (1<<(CONFIG_NUM_IRQ_PRIO_LEVELS-1))
|
||||
sr r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
|
||||
_swap_already_in_irq:
|
||||
#ifdef CONFIG_TRACING
|
||||
push_s blink
|
||||
|
||||
|
|
Loading…
Reference in New Issue