Skip to content

Commit 97d0436

Browse files
Wayne RenMaureenHelm
authored andcommitted
arch: arc: use top of isr stack as exception stack and bug fixes
* re-use top of isr stack as exception stack * bug fixes in irq offload's implementation * improve kernel oops implementation Signed-off-by: Wayne Ren <[email protected]>
1 parent 1c4fe3e commit 97d0436

File tree

3 files changed

+112
-48
lines changed

3 files changed

+112
-48
lines changed

arch/arc/core/fatal.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,6 @@ void _NanoFatalErrorHandler(unsigned int reason, const NANO_ESF *pEsf)
8181
_SysFatalErrorHandler(reason, pEsf);
8282
}
8383

84-
void _do_kernel_oops(const NANO_ESF *esf)
85-
{
86-
_NanoFatalErrorHandler(esf->r0, esf);
87-
}
88-
8984
FUNC_NORETURN void _arch_syscall_oops(void *ssf_ptr)
9085
{
9186
_SysFatalErrorHandler(_NANO_ERR_KERNEL_OOPS, ssf_ptr);

arch/arc/core/fault.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ void _Fault(const NANO_ESF *esf)
3939
code = _ARC_V2_ECR_CODE(ecr);
4040
parameter = _ARC_V2_ECR_PARAMETER(ecr);
4141

42+
43+
/* exception raised by kernel */
44+
if (vector == 0x9 && parameter == _TRAP_S_CALL_RUNTIME_EXCEPT) {
45+
_NanoFatalErrorHandler(esf->r0, esf);
46+
return;
47+
}
48+
4249
printk("Exception vector: 0x%x, cause code: 0x%x, parameter 0x%x\n",
4350
vector, code, parameter);
4451
printk("Address 0x%x\n", exc_addr);

arch/arc/core/fault_s.S

Lines changed: 105 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,18 @@ GTEXT(__ev_extension)
3333
GTEXT(__ev_div_zero)
3434
GTEXT(__ev_dc_error)
3535
GTEXT(__ev_maligned)
36+
#ifdef CONFIG_IRQ_OFFLOAD
37+
GTEXT(_irq_do_offload);
38+
#endif
3639

3740
GDATA(exc_nest_count)
3841

3942
.balign 4
4043
SECTION_VAR(BSS, saved_value)
4144
.word 0
4245

43-
#define EXCEPTION_STACK_SIZE 256
44-
45-
SECTION_VAR(NOINIT, _exception_stack)
46-
.space EXCEPTION_STACK_SIZE
46+
/* the necessary stack size for exception handling */
47+
#define EXCEPTION_STACK_SIZE 384
4748

4849
/*
4950
* @brief Fault handler installed in the fault and reserved vectors
@@ -62,6 +63,7 @@ SECTION_SUBSEC_FUNC(TEXT,__fault,__ev_div_zero)
6263
SECTION_SUBSEC_FUNC(TEXT,__fault,__ev_dc_error)
6364
SECTION_SUBSEC_FUNC(TEXT,__fault,__ev_maligned)
6465

66+
_exc_entry:
6567

6668
#ifdef CONFIG_ARC_STACK_CHECKING
6769
st r0, [saved_value]
@@ -72,10 +74,24 @@ SECTION_SUBSEC_FUNC(TEXT,__fault,__ev_maligned)
7274
ld r0, [saved_value]
7375
#endif
7476
st sp, [saved_value]
75-
mov_s sp, _exception_stack
77+
/*
78+
* re-use the top part of interrupt stack as exception
79+
* stack. If this top part is used by interrupt handling,
80+
* and exception is raised, then here it's guaranteed that
81+
* exception handling has necessary stack to use
82+
*/
83+
mov_s sp, _interrupt_stack
7684
add sp, sp, EXCEPTION_STACK_SIZE
7785

78-
/* save caller saved registers */
86+
/*
87+
* save caller saved registers
88+
* this stack frame is set up in exception stack,
89+
* not in the original sp (thread stack or interrupt stack).
90+
* Because the exception may be raised by stack checking or
91+
* mpu protect violation related to stack. If this stack frame
92+
* is setup in original sp, double exception may be raised during
93+
* _create_irq_stack_frame, which is unrecoverable.
94+
*/
7995
_create_irq_stack_frame
8096

8197
#ifdef CONFIG_ARC_HAS_SECURE
@@ -87,8 +103,8 @@ SECTION_SUBSEC_FUNC(TEXT,__fault,__ev_maligned)
87103
lr r0,[_ARC_V2_ERET]
88104
st_s r0, [sp, ___isf_t_pc_OFFSET] /* eret into pc */
89105

106+
/* sp is parameter of _Fault */
90107
mov r0, sp
91-
92108
jl _Fault
93109

94110
_exc_return:
@@ -138,18 +154,13 @@ _exc_return_from_exc:
138154
rtie
139155

140156

141-
#ifdef CONFIG_IRQ_OFFLOAD
142-
GTEXT(_irq_do_offload);
143-
#endif
144-
145-
146157
SECTION_SUBSEC_FUNC(TEXT,__fault,__ev_trap)
147158
/* get the id of trap_s */
148159
lr ilink, [_ARC_V2_ECR]
149160
and ilink, ilink, 0x3f
150161
#ifdef CONFIG_USERSPACE
151162
cmp ilink, _TRAP_S_CALL_SYSTEM_CALL
152-
bne _do_other_trap
163+
bne _do_non_syscall_trap
153164
/* do sys_call */
154165
mov ilink, _SYSCALL_LIMIT
155166
cmp r6, ilink
@@ -177,27 +188,16 @@ valid_syscall_id:
177188

178189
rtie
179190

191+
_do_non_syscall_trap:
192+
#endif /* CONFIG_USERSPACE */
193+
#ifdef CONFIG_IRQ_OFFLOAD
180194
/*
181-
* Before invoking exception handler, the kernel switches to an exception
182-
* stack to save the faulting thread's registers.
183-
* The exception is fatal and all the kernel can do is just print
184-
* a diagnostic message and halt.
195+
* IRQ_OFFLOAD is to simulate interrupt handling through exception,
196+
* so its entry is different with normal exception handling, it is
197+
* handled in isr stack
185198
*/
186-
187-
_do_other_trap:
188-
#endif /* CONFIG_USERSPACE */
189-
#ifdef CONFIG_ARC_STACK_CHECKING
190-
st r0, [saved_value]
191-
/* disable stack checking */
192-
lr r0, [_ARC_V2_STATUS32]
193-
bclr r0, r0, _ARC_V2_STATUS32_SC_BIT
194-
kflag r0
195-
ld r0, [saved_value]
196-
#endif
197-
st sp, [saved_value]
198-
mov_s sp, _exception_stack
199-
add sp, sp, EXCEPTION_STACK_SIZE
200-
199+
cmp ilink, _TRAP_S_SCALL_IRQ_OFFLOAD
200+
bne _exc_entry
201201
/* save caller saved registers */
202202
_create_irq_stack_frame
203203

@@ -210,21 +210,83 @@ _do_other_trap:
210210
lr r0,[_ARC_V2_ERET]
211211
st_s r0, [sp, ___isf_t_pc_OFFSET] /* eret into pc */
212212

213+
#ifdef CONFIG_ARC_STACK_CHECKING
214+
/* disable stack checking */
215+
lr r0, [_ARC_V2_STATUS32]
216+
bclr r0, r0, _ARC_V2_STATUS32_SC_BIT
217+
kflag r0
218+
#endif
219+
220+
ld r1, [exc_nest_count]
221+
add r0, r1, 1
222+
st r0, [exc_nest_count]
223+
cmp r1, 0
224+
225+
bgt.d exc_nest_handle
213226
mov r0, sp
214227

215-
mov blink, _exc_return
228+
mov r1, _kernel
229+
ld sp, [r1, _kernel_offset_to_irq_stack]
230+
exc_nest_handle:
231+
push_s r0
216232

217-
cmp ilink, _TRAP_S_CALL_RUNTIME_EXCEPT
218-
beq _oops
233+
jl _irq_do_offload
219234

220-
#ifdef CONFIG_IRQ_OFFLOAD
221-
cmp ilink, _TRAP_S_SCALL_IRQ_OFFLOAD
222-
bne _trap_fault
223-
j _irq_do_offload
235+
pop sp
236+
237+
mov r1, exc_nest_count
238+
ld r0, [r1]
239+
sub r0, r0, 1
240+
cmp r0, 0
241+
bne.d _exc_return_from_exc
242+
st r0, [r1]
243+
244+
#ifdef CONFIG_PREEMPT_ENABLED
245+
mov_s r1, _kernel
246+
ld_s r2, [r1, _kernel_offset_to_current]
247+
248+
/* check if the current thread needs to be rescheduled */
249+
ld_s r0, [r1, _kernel_offset_to_ready_q_cache]
250+
breq r0, r2, _exc_return_from_irqoffload_trap
251+
252+
_save_callee_saved_regs
253+
254+
st _CAUSE_RIRQ, [r2, _thread_offset_to_relinquish_cause]
255+
/* note: Ok to use _CAUSE_RIRQ since everything is saved */
256+
257+
ld_s r2, [r1, _kernel_offset_to_ready_q_cache]
258+
st_s r2, [r1, _kernel_offset_to_current]
259+
260+
#ifdef CONFIG_ARC_HAS_SECURE
261+
/*
262+
* sync up the ERSEC_STAT.ERM and SEC_STAT.IRM.
263+
* use a fake interrupt return to simulate an exception turn.
264+
* ERM and IRM record which mode the cpu should return, 1: secure
265+
* 0: normal
266+
*/
267+
lr r3,[_ARC_V2_ERSEC_STAT]
268+
btst r3, 31
269+
bset.nz r3, r3, 3
270+
bclr.z r3, r3, 3
271+
/* sflag r3 */
272+
/* sflag instruction is not supported in current ARC GNU */
273+
.long 0x00ff302f
224274
#endif
275+
/* clear AE bit to forget this was an exception */
276+
lr r3, [_ARC_V2_STATUS32]
277+
and r3,r3,(~_ARC_V2_STATUS32_AE)
278+
kflag r3
279+
/* pretend lowest priority interrupt happened to use common handler */
280+
lr r3, [_ARC_V2_AUX_IRQ_ACT]
281+
or r3,r3,(1<<(CONFIG_NUM_IRQ_PRIO_LEVELS-1)) /* use lowest */
282+
sr r3, [_ARC_V2_AUX_IRQ_ACT]
225283

226-
_trap_fault:
227-
j _Fault
284+
/* Assumption: r2 has current thread */
285+
b _rirq_common_interrupt_swap
286+
#endif
228287

229-
_oops:
230-
j _do_kernel_oops
288+
_exc_return_from_irqoffload_trap:
289+
_pop_irq_stack_frame
290+
rtie
291+
#endif /* CONFIG_IRQ_OFFLOAD */
292+
b _exc_entry

0 commit comments

Comments
 (0)