Skip to content

Commit 8450d26

Browse files
Wayne Renandrewboie
authored andcommitted
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 <[email protected]>
1 parent 05a669c commit 8450d26

File tree

1 file changed

+46
-1
lines changed

1 file changed

+46
-1
lines changed

arch/arc/core/fast_irq.S

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,12 +207,36 @@ _firq_reschedule:
207207
* point, so when switching back to register bank 0, it will contain the
208208
* registers from the interrupted thread.
209209
*/
210-
210+
#if defined(CONFIG_USERSPACE)
211+
/* when USERSPACE is configured, here need to consider the case where firq comes
212+
* out in user mode, according to ARCv2 ISA and nsim, the following micro ops
213+
* will be executed:
214+
* sp<-reg bank1'sp
215+
* switch between sp and _ARC_V2_USER_SP
216+
* then:
217+
* sp is the sp of kernel stack of interrupted thread
218+
* _ARC_V2_USER_SP is reg bank1'sp
219+
* the sp of user stack of interrupted thread is reg bank0'sp
220+
* if firq comes out in kernel mode, the following micro ops will be executed:
221+
* sp<-reg bank'sp
222+
* so, sw needs to do necessary handling to set up the correct sp
223+
*/
224+
lr r0, [_ARC_V2_AUX_IRQ_ACT]
225+
bbit0 r0, 31, _firq_from_kernel
226+
aex sp, [_ARC_V2_USER_SP]
227+
lr r0, [_ARC_V2_STATUS32]
228+
and r0, r0, ~_ARC_V2_STATUS32_RB(7)
229+
kflag r0
230+
aex sp, [_ARC_V2_USER_SP]
231+
b _firq_create_irq_stack_frame
232+
_firq_from_kernel:
233+
#endif
211234
/* chose register bank #0 */
212235
lr r0, [_ARC_V2_STATUS32]
213236
and r0, r0, ~_ARC_V2_STATUS32_RB(7)
214237
kflag r0
215238

239+
_firq_create_irq_stack_frame:
216240
/* we're back on the outgoing thread's stack */
217241
_create_irq_stack_frame
218242

@@ -225,6 +249,7 @@ _firq_reschedule:
225249
st_s r0, [sp, ___isf_t_status32_OFFSET]
226250

227251
st ilink, [sp, ___isf_t_pc_OFFSET] /* ilink into pc */
252+
228253
#ifdef CONFIG_SMP
229254
/*
230255
* load r0, r1 from irq stack
@@ -235,6 +260,16 @@ _firq_reschedule:
235260
#endif
236261
#endif
237262

263+
#if defined(CONFIG_USERSPACE)
264+
/*
265+
* need to remember the user/kernel status of interrupted thread, will be
266+
* restored when thread switched back
267+
*/
268+
lr r3, [_ARC_V2_AUX_IRQ_ACT]
269+
and r3, r3, 0x80000000
270+
push_s r3
271+
#endif
272+
238273
#ifdef CONFIG_SMP
239274
mov_s r2, r1
240275
#else
@@ -300,6 +335,16 @@ _firq_return_from_coop:
300335
_firq_return_from_rirq:
301336
_firq_return_from_firq:
302337

338+
#if defined(CONFIG_USERSPACE)
339+
/*
340+
* need to recover the user/kernel status of interrupted thread
341+
*/
342+
pop_s r3
343+
lr r2, [_ARC_V2_AUX_IRQ_ACT]
344+
or r2, r2, r3
345+
sr r2, [_ARC_V2_AUX_IRQ_ACT]
346+
#endif
347+
303348
_pop_irq_stack_frame
304349

305350
ld ilink, [sp, -4] /* status32 into ilink */

0 commit comments

Comments
 (0)