arch: arc: fix the bug of context switch in interrupt
* the bug comes out when a context switch happens in interrupt * the bug only affects the em7d in emsk 2.3 * the bug is caused by * wrong operations of stack * wrong setting of SEC_STAT's IRM bit Signed-off-by: Wayne Ren <wei.ren@synopsys.com>
This commit is contained in:
parent
6612c9f683
commit
2c577ff90e
|
@ -180,44 +180,27 @@ _rirq_common_interrupt_swap:
|
|||
.balign 4
|
||||
_rirq_return_from_coop:
|
||||
|
||||
/* status32 and pc (blink) are already on the stack in the right order */
|
||||
/*
|
||||
* status32, sec_stat (when CONFIG_ARC_HAS_SECURE is enabled) and pc
|
||||
* (blink) are already on the stack in the right order
|
||||
*/
|
||||
ld_s r0, [sp, ___isf_t_status32_OFFSET - ___isf_t_pc_OFFSET]
|
||||
|
||||
/* update status32.ie (explanation in firq_exit:_firq_return_from_coop) */
|
||||
ld_s r0, [sp, 4]
|
||||
|
||||
ld_s r3, [r2, _thread_offset_to_intlock_key]
|
||||
st 0, [r2, _thread_offset_to_intlock_key]
|
||||
cmp r3, 0
|
||||
or.ne r0, r0, _ARC_V2_STATUS32_IE
|
||||
st_s r0, [sp, 4]
|
||||
|
||||
st_s r0, [sp, ___isf_t_status32_OFFSET - ___isf_t_pc_OFFSET]
|
||||
|
||||
/* carve fake stack */
|
||||
sub sp, sp, ___isf_t_pc_OFFSET
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
/* a) status32/pc are already on the stack
|
||||
* pc
|
||||
* status
|
||||
* b) make a space for sec_stat
|
||||
* c) adjust the right place for sec_stat and pc
|
||||
* pc
|
||||
* sec_stat
|
||||
* status
|
||||
* d) a real value will be pushed in r0
|
||||
*/
|
||||
ld_s r0, [sp]
|
||||
push_s r0
|
||||
lr r0, [_ARC_V2_SEC_STAT]
|
||||
st_s r0, [sp, 4]
|
||||
sub sp, sp, (___isf_t_SIZEOF - 16)
|
||||
#else
|
||||
/*
|
||||
* a) status32/pc are already on the stack
|
||||
* b) a real value will be pushed in r0
|
||||
*/
|
||||
sub sp, sp, (___isf_t_SIZEOF - 12)
|
||||
#endif
|
||||
/* push return value on stack */
|
||||
/* update return value on stack */
|
||||
ld_s r0, [r2, _thread_offset_to_return_value]
|
||||
push_s r0
|
||||
st_s r0, [sp, ___isf_t_r0_OFFSET]
|
||||
|
||||
/*
|
||||
* r13 is part of both the callee and caller-saved register sets because
|
||||
|
|
|
@ -163,10 +163,21 @@ _swap_return_from_firq:
|
|||
bbit1 r3, _ARC_V2_STATUS32_AE_BIT, _return_from_exc_irq
|
||||
|
||||
/* pretend interrupt happened to use rtie instruction */
|
||||
lr r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
brne r3,0,_swap_already_in_irq
|
||||
|
||||
or r3,r3,(1<<(CONFIG_NUM_IRQ_PRIO_LEVELS-1)) /* use lowest */
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
lr r3, [_ARC_V2_SEC_STAT]
|
||||
/* set SEC_STAT.IRM = SECURE for interrupt return */
|
||||
bset r3, r3, 3
|
||||
/* sflag r3 */
|
||||
/* sflag instruction is not supported in current ARC GNU */
|
||||
.long 0x00ff302f
|
||||
#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:
|
||||
|
|
Loading…
Reference in a new issue