Skip to content

Commit ffd8a91

Browse files
IRISZZWnashif
authored andcommitted
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 <[email protected]>
1 parent 991b0db commit ffd8a91

File tree

3 files changed

+92
-18
lines changed

3 files changed

+92
-18
lines changed

arch/arc/core/fast_irq.S

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,11 +222,36 @@ _firq_reschedule:
222222
* registers from the interrupted thread.
223223
*/
224224

225+
#if defined(CONFIG_USERSPACE)
226+
/* when USERSPACE is configured, here need to consider the case where firq comes
227+
* out in user mode, according to ARCv2 ISA and nsim, the following micro ops
228+
* will be executed:
229+
* sp<-reg bank1'sp
230+
* switch between sp and _ARC_V2_USER_SP
231+
* then:
232+
* sp is the sp of kernel stack of interrupted thread
233+
* _ARC_V2_USER_SP is reg bank1'sp
234+
* the sp of user stack of interrupted thread is reg bank0'sp
235+
* if firq comes out in kernel mode, the following micro ops will be executed:
236+
* sp<-reg bank'sp
237+
* so, sw needs to do necessary handling to set up the correct sp
238+
*/
239+
lr r0, [_ARC_V2_AUX_IRQ_ACT]
240+
bbit0 r0, 31, _firq_from_kernel
241+
aex sp, [_ARC_V2_USER_SP]
242+
lr r0, [_ARC_V2_STATUS32]
243+
and r0, r0, ~_ARC_V2_STATUS32_RB(7)
244+
kflag r0
245+
aex sp, [_ARC_V2_USER_SP]
246+
b _firq_create_irq_stack_frame
247+
_firq_from_kernel:
248+
#endif
225249
/* chose register bank #0 */
226250
lr r0, [_ARC_V2_STATUS32]
227251
and r0, r0, ~_ARC_V2_STATUS32_RB(7)
228252
kflag r0
229253

254+
_firq_create_irq_stack_frame:
230255
/* we're back on the outgoing thread's stack */
231256
_create_irq_stack_frame
232257

@@ -241,6 +266,24 @@ _firq_reschedule:
241266
st ilink, [sp, ___isf_t_pc_OFFSET] /* ilink into pc */
242267
#endif
243268

269+
#if defined(CONFIG_USERSPACE)
270+
/*
271+
* when USERSPACE is enabled, according to ARCv2 ISA, SP will be switched
272+
* if interrupt comes out in user mode, and will be recorded in bit 31
273+
* (U bit) of IRQ_ACT. when interrupt exits, SP will be switched back
274+
* according to U bit.
275+
*
276+
* need to remember the user/kernel status of interrupted thread, will be
277+
* restored when thread switched back
278+
*
279+
*/
280+
lr r4, [_ARC_V2_AUX_IRQ_ACT]
281+
and r3, r4, 0x80000000
282+
push_s r3
283+
284+
bclr r4, r4, 31
285+
sr r4, [_ARC_V2_AUX_IRQ_ACT]
286+
#endif
244287
mov_s r1, _kernel
245288
ld_s r2, [r1, _kernel_offset_to_current]
246289

@@ -323,6 +366,15 @@ _firq_return_from_coop:
323366
_firq_return_from_rirq:
324367
_firq_return_from_firq:
325368

369+
#if defined(CONFIG_USERSPACE)
370+
/*
371+
* need to recover the user/kernel status of interrupted thread
372+
*/
373+
pop_s r3
374+
lr r2, [_ARC_V2_AUX_IRQ_ACT]
375+
or r2, r2, r3
376+
sr r2, [_ARC_V2_AUX_IRQ_ACT]
377+
#endif
326378
_pop_irq_stack_frame
327379

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

arch/arc/core/regular_irq.S

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,24 @@ SECTION_FUNC(TEXT, _rirq_exit)
152152
.balign 4
153153
_rirq_reschedule:
154154

155+
#if defined(CONFIG_USERSPACE)
156+
/*
157+
* when USERSPACE is enabled, according to ARCv2 ISA, SP will be switched
158+
* if interrupt comes out in user mode, and will be recorded in bit 31
159+
* (U bit) of IRQ_ACT. when interrupt exits, SP will be switched back
160+
* according to U bit.
161+
*
162+
* need to remember the user/kernel status of interrupted thread, will be
163+
* restored when thread switched back
164+
*
165+
*/
166+
lr r4, [_ARC_V2_AUX_IRQ_ACT]
167+
and r3, r4, 0x80000000
168+
push_s r3
169+
170+
bclr r4, r4, 31
171+
sr r4, [_ARC_V2_AUX_IRQ_ACT]
172+
#endif
155173
/* _save_callee_saved_regs expects outgoing thread in r2 */
156174
_save_callee_saved_regs
157175

@@ -181,21 +199,6 @@ _rirq_common_interrupt_swap:
181199
pop_s r2
182200
#endif
183201

184-
#if defined(CONFIG_USERSPACE)
185-
/*
186-
* when USERSPACE is enabled, according to ARCv2 ISA, SP will be switched
187-
* if interrupt comes out in user mode, and will be recorded in bit 31
188-
* (U bit) of IRQ_ACT. when interrupt exits, SP will be switched back
189-
* according to U bit.
190-
*
191-
* For the case that context switches in interrupt, the target sp must be
192-
* thread's kernel stack, no need to do hardware sp switch. so, U bit should
193-
* be cleared.
194-
*/
195-
lr r0, [_ARC_V2_AUX_IRQ_ACT]
196-
bclr r0, r0, 31
197-
sr r0, [_ARC_V2_AUX_IRQ_ACT]
198-
#endif
199202

200203
ld r3, [r2, _thread_offset_to_relinquish_cause]
201204

@@ -250,11 +253,24 @@ _rirq_return_from_coop:
250253

251254
/* fall through to rtie instruction */
252255

256+
/* stack now has the IRQ stack frame layout, pointing to sp */
257+
/* rtie will pop the rest from the stack */
258+
rtie
259+
253260
#endif /* CONFIG_PREEMPT_ENABLED */
254261

255262
.balign 4
256263
_rirq_return_from_firq:
257264
_rirq_return_from_rirq:
265+
#if defined(CONFIG_USERSPACE)
266+
/*
267+
* need to recover the user/kernel status of interrupted thread
268+
*/
269+
pop_s r3
270+
lr r2, [_ARC_V2_AUX_IRQ_ACT]
271+
or r2, r2, r3
272+
sr r2, [_ARC_V2_AUX_IRQ_ACT]
273+
#endif
258274
#ifdef CONFIG_TRACING
259275
push_s blink
260276

arch/arc/core/swap.S

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,15 @@ return_loc:
194194
_swap_return_from_rirq:
195195
_swap_return_from_firq:
196196

197+
#if defined(CONFIG_USERSPACE)
198+
/*
199+
* need to recover the user/kernel status of interrupted thread
200+
*/
201+
pop_s r3
202+
lr r2, [_ARC_V2_AUX_IRQ_ACT]
203+
or r2, r2, r3
204+
sr r2, [_ARC_V2_AUX_IRQ_ACT]
205+
#endif
197206
lr r3, [_ARC_V2_STATUS32]
198207
bbit1 r3, _ARC_V2_STATUS32_AE_BIT, _return_from_exc_irq
199208

@@ -209,13 +218,10 @@ _swap_return_from_firq:
209218
#endif
210219

211220
lr r3, [_ARC_V2_AUX_IRQ_ACT]
212-
brne r3, 0, _swap_already_in_irq
213-
214221
/* use lowest interrupt priority */
215222
or r3, r3, (1<<(CONFIG_NUM_IRQ_PRIO_LEVELS-1))
216223
sr r3, [_ARC_V2_AUX_IRQ_ACT]
217224

218-
_swap_already_in_irq:
219225
#ifdef CONFIG_TRACING
220226
push_s blink
221227

0 commit comments

Comments
 (0)