arch: arc: fix the bug where firq comes out in user mode
firq's case is similar to regular irq, it also needs to consider the case of reg bank switch. Signed-off-by: Wayne Ren <wei.ren@synopsys.com>
This commit is contained in:
parent
05a669c568
commit
8450d26b34
1 changed files with 46 additions and 1 deletions
|
@ -207,12 +207,36 @@ _firq_reschedule:
|
|||
* point, so when switching back to register bank 0, it will contain the
|
||||
* 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
|
||||
|
||||
|
@ -225,6 +249,7 @@ _firq_reschedule:
|
|||
st_s r0, [sp, ___isf_t_status32_OFFSET]
|
||||
|
||||
st ilink, [sp, ___isf_t_pc_OFFSET] /* ilink into pc */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/*
|
||||
* load r0, r1 from irq stack
|
||||
|
@ -235,6 +260,16 @@ _firq_reschedule:
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
/*
|
||||
* need to remember the user/kernel status of interrupted thread, will be
|
||||
* restored when thread switched back
|
||||
*/
|
||||
lr r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
and r3, r3, 0x80000000
|
||||
push_s r3
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
mov_s r2, r1
|
||||
#else
|
||||
|
@ -300,6 +335,16 @@ _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 */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue