arch: arc: fix the bug that interrupt stack is not switched
For the old codes, if nest interrupts come out after _isr_wrapper and before _check_nest_int_by_irq_act, then multi-bits in irq_act will be set, this will result irq stack will not be switched in correctly As a fix, it's still need to use nest interrupt counter to do interrupt stack switch as before The difference is in the past exc_nest_count is used, but here _kernel.nested/_kernel.cpus[cpu_id].nested is used. Signed-off-by: Wayne Ren <wei.ren@synopsys.com>
This commit is contained in:
parent
146c7e8c7e
commit
44c917e6b2
4 changed files with 51 additions and 5 deletions
|
@ -76,7 +76,8 @@ SECTION_FUNC(TEXT, _firq_enter)
|
||||||
lr r25, [_ARC_V2_LP_END]
|
lr r25, [_ARC_V2_LP_END]
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_check_nest_int_by_irq_act r0, r1
|
/* check whether irq stack is used */
|
||||||
|
_check_and_inc_int_nest_counter r0, r1
|
||||||
|
|
||||||
bne.d firq_nest
|
bne.d firq_nest
|
||||||
mov r0, sp
|
mov r0, sp
|
||||||
|
@ -138,6 +139,7 @@ SECTION_FUNC(TEXT, _firq_exit)
|
||||||
sr r24, [_ARC_V2_LP_START]
|
sr r24, [_ARC_V2_LP_START]
|
||||||
sr r25, [_ARC_V2_LP_END]
|
sr r25, [_ARC_V2_LP_END]
|
||||||
#endif
|
#endif
|
||||||
|
_dec_int_nest_counter r0, r1
|
||||||
|
|
||||||
_check_nest_int_by_irq_act r0, r1
|
_check_nest_int_by_irq_act r0, r1
|
||||||
|
|
||||||
|
|
|
@ -246,9 +246,9 @@ _do_non_syscall_trap:
|
||||||
st_s r0, [sp, ___isf_t_pc_OFFSET] /* eret into pc */
|
st_s r0, [sp, ___isf_t_pc_OFFSET] /* eret into pc */
|
||||||
|
|
||||||
|
|
||||||
lr r0, [_ARC_V2_AUX_IRQ_ACT]
|
/* check whether irq stack is used */
|
||||||
and r0, r0, 0xffff
|
_check_and_inc_int_nest_counter r0, r1
|
||||||
cmp r0, 0
|
|
||||||
bne.d exc_nest_handle
|
bne.d exc_nest_handle
|
||||||
mov r0, sp
|
mov r0, sp
|
||||||
|
|
||||||
|
@ -260,6 +260,8 @@ exc_nest_handle:
|
||||||
|
|
||||||
pop sp
|
pop sp
|
||||||
|
|
||||||
|
_dec_int_nest_counter r0, r1
|
||||||
|
|
||||||
lr r0, [_ARC_V2_AUX_IRQ_ACT]
|
lr r0, [_ARC_V2_AUX_IRQ_ACT]
|
||||||
and r0, r0, 0xffff
|
and r0, r0, 0xffff
|
||||||
cmp r0, 0
|
cmp r0, 0
|
||||||
|
|
|
@ -67,7 +67,8 @@ SECTION_FUNC(TEXT, _rirq_enter)
|
||||||
#endif
|
#endif
|
||||||
clri
|
clri
|
||||||
|
|
||||||
_check_nest_int_by_irq_act r0, r1
|
/* check whether irq stack is used */
|
||||||
|
_check_and_inc_int_nest_counter r0, r1
|
||||||
|
|
||||||
bne.d rirq_nest
|
bne.d rirq_nest
|
||||||
mov r0, sp
|
mov r0, sp
|
||||||
|
@ -92,6 +93,8 @@ SECTION_FUNC(TEXT, _rirq_exit)
|
||||||
|
|
||||||
pop sp
|
pop sp
|
||||||
|
|
||||||
|
_dec_int_nest_counter r0, r1
|
||||||
|
|
||||||
_check_nest_int_by_irq_act r0, r1
|
_check_nest_int_by_irq_act r0, r1
|
||||||
|
|
||||||
jne _rirq_no_reschedule
|
jne _rirq_no_reschedule
|
||||||
|
|
|
@ -294,6 +294,45 @@
|
||||||
#endif /* CONFIG_ARC_SECURE_FIRMWARE */
|
#endif /* CONFIG_ARC_SECURE_FIRMWARE */
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
/* check and increase the interrupt nest counter
|
||||||
|
* after increase, check whether nest counter == 1
|
||||||
|
* the result will be EQ bit of status32
|
||||||
|
*/
|
||||||
|
.macro _check_and_inc_int_nest_counter reg1 reg2
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
_get_cpu_id \reg1
|
||||||
|
ld.as \reg1, [@_curr_cpu, \reg1]
|
||||||
|
ld \reg2, [\reg1, ___cpu_t_nested_OFFSET]
|
||||||
|
#else
|
||||||
|
mov \reg1, _kernel
|
||||||
|
ld \reg2, [\reg1, ___kernel_t_nested_OFFSET]
|
||||||
|
#endif
|
||||||
|
add \reg2, \reg2, 1
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
st \reg2, [\reg1, ___cpu_t_nested_OFFSET]
|
||||||
|
#else
|
||||||
|
st \reg2, [\reg1, ___kernel_t_nested_OFFSET]
|
||||||
|
#endif
|
||||||
|
cmp \reg2, 1
|
||||||
|
.endm
|
||||||
|
|
||||||
|
/* decrease interrupt nest counter */
|
||||||
|
.macro _dec_int_nest_counter reg1 reg2
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
_get_cpu_id \reg1
|
||||||
|
ld.as \reg1, [@_curr_cpu, \reg1]
|
||||||
|
ld \reg2, [\reg1, ___cpu_t_nested_OFFSET]
|
||||||
|
#else
|
||||||
|
mov \reg1, _kernel
|
||||||
|
ld \reg2, [\reg1, ___kernel_t_nested_OFFSET]
|
||||||
|
#endif
|
||||||
|
sub \reg2, \reg2, 1
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
st \reg2, [\reg1, ___cpu_t_nested_OFFSET]
|
||||||
|
#else
|
||||||
|
st \reg2, [\reg1, ___kernel_t_nested_OFFSET]
|
||||||
|
#endif
|
||||||
|
.endm
|
||||||
|
|
||||||
/* If multi bits in IRQ_ACT are set, i.e. last bit != fist bit, it's
|
/* If multi bits in IRQ_ACT are set, i.e. last bit != fist bit, it's
|
||||||
* in nest interrupt. The result will be EQ bit of status32
|
* in nest interrupt. The result will be EQ bit of status32
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue