Skip to content

Commit eb546a8

Browse files
dcpleungcarlescufi
authored andcommitted
xtensa: rework kernel oops exception path
When kernel OOPS is raised, we need to actually go through the process of terminating the offending thread, instead of simply printing the stack and continue running. This change employs similar mechanism to xtensa_arch_except() to use illegal instruction to raise hardware exception, and going through the fatal exception path. Signed-off-by: Daniel Leung <[email protected]> Signed-off-by: Flavio Ceolin <[email protected]>
1 parent 586bb92 commit eb546a8

File tree

4 files changed

+48
-11
lines changed

4 files changed

+48
-11
lines changed

arch/xtensa/core/fatal.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ char *z_xtensa_exccause(unsigned int cause_code)
8787
case 63:
8888
/* i.e. z_except_reason */
8989
return "zephyr exception";
90+
case 64:
91+
return "kernel oops";
9092
default:
9193
return "unknown/reserved";
9294
}
@@ -114,7 +116,6 @@ void z_xtensa_fatal_error(unsigned int reason, const z_arch_esf_t *esf)
114116
z_xtensa_backtrace_print(100, (int *)esf);
115117
#endif
116118
#endif
117-
118119
arch_irq_unlock(key);
119120
}
120121

@@ -144,9 +145,10 @@ FUNC_NORETURN void z_system_halt(unsigned int reason)
144145

145146
FUNC_NORETURN void arch_syscall_oops(void *ssf)
146147
{
147-
z_arch_esf_t *esf = ssf;
148+
ARG_UNUSED(ssf);
149+
150+
xtensa_arch_kernel_oops(K_ERR_KERNEL_OOPS, ssf);
148151

149-
z_xtensa_fatal_error(K_ERR_KERNEL_OOPS, esf);
150152
CODE_UNREACHABLE;
151153
}
152154

arch/xtensa/core/xtensa-asm2-util.S

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,20 @@ xtensa_arch_except_epc:
204204
ill
205205
retw
206206

207+
/*
208+
* void xtensa_arch_kernel_oops(int reason_p, void *ssf);
209+
*
210+
* Simply to raise hardware exception for Kernel OOPS.
211+
*/
212+
.global xtensa_arch_kernel_oops
213+
.global xtensa_arch_kernel_oops_epc
214+
.align 4
215+
xtensa_arch_kernel_oops:
216+
entry a1, 16
217+
xtensa_arch_kernel_oops_epc:
218+
ill
219+
retw
220+
207221
/*
208222
* void xtensa_switch(void *new, void **old_return);
209223
*

arch/xtensa/core/xtensa-asm2.c

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL);
2121

2222
extern char xtensa_arch_except_epc[];
23+
extern char xtensa_arch_kernel_oops_epc[];
2324

2425
#ifdef CONFIG_USERSPACE
2526
Z_EXC_DECLARE(z_xtensa_user_string_nlen);
@@ -202,11 +203,12 @@ static inline unsigned int get_bits(int offset, int num_bits, unsigned int val)
202203
return val & mask;
203204
}
204205

205-
static void print_fatal_exception(_xtensa_irq_bsa_t *bsa, int cause,
206+
static void print_fatal_exception(void *print_stack, int cause,
206207
bool is_dblexc, uint32_t depc)
207208
{
208209
void *pc;
209210
uint32_t ps, vaddr;
211+
_xtensa_irq_bsa_t *bsa = (void *)*(int **)print_stack;
210212

211213
ps = bsa->ps;
212214
pc = (void *)bsa->pc;
@@ -334,7 +336,7 @@ void *xtensa_excint1_c(int *interrupted_stack)
334336
bool is_fatal_error = false;
335337
bool is_dblexc = false;
336338
uint32_t ps;
337-
void *pc;
339+
void *pc, *print_stack = (void *)interrupted_stack;
338340
uint32_t depc = 0;
339341

340342
__asm__ volatile("rsr.exccause %0" : "=r"(cause));
@@ -399,22 +401,40 @@ void *xtensa_excint1_c(int *interrupted_stack)
399401
* We assign EXCCAUSE the unused, reserved code 63; this may be
400402
* problematic if the app or new boards also decide to repurpose
401403
* this code.
404+
*
405+
* Another intentionally ill is from xtensa_arch_kernel_oops.
406+
* Kernel OOPS has to be explicity raised so we can simply
407+
* set the reason and continue.
402408
*/
403-
if ((pc == (void *) &xtensa_arch_except_epc) && (cause == 0)) {
404-
cause = 63;
405-
__asm__ volatile("wsr.exccause %0" : : "r"(cause));
406-
reason = bsa->a2;
409+
if (cause == EXCCAUSE_ILLEGAL) {
410+
if (pc == (void *)&xtensa_arch_except_epc) {
411+
cause = 63;
412+
__asm__ volatile("wsr.exccause %0" : : "r"(cause));
413+
reason = bsa->a2;
414+
} else if (pc == (void *)&xtensa_arch_kernel_oops_epc) {
415+
cause = 64; /* kernel oops */
416+
reason = K_ERR_KERNEL_OOPS;
417+
418+
/* A3 contains the second argument to
419+
* xtensa_arch_kernel_oops(reason, ssf)
420+
* where ssf is the stack frame causing
421+
* the kernel oops.
422+
*/
423+
print_stack = (void *)bsa->a3;
424+
}
407425
}
408426

409-
print_fatal_exception(bsa, cause, is_dblexc, depc);
427+
if (reason != K_ERR_KERNEL_OOPS) {
428+
print_fatal_exception(print_stack, cause, is_dblexc, depc);
429+
}
410430

411431
/* FIXME: legacy xtensa port reported "HW" exception
412432
* for all unhandled exceptions, which seems incorrect
413433
* as these are software errors. Should clean this
414434
* up.
415435
*/
416436
z_xtensa_fatal_error(reason,
417-
(void *)interrupted_stack);
437+
(void *)print_stack);
418438
break;
419439
}
420440

include/zephyr/arch/xtensa/arch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ struct arch_mem_domain {
5454
};
5555

5656
extern void xtensa_arch_except(int reason_p);
57+
extern void xtensa_arch_kernel_oops(int reason_p, void *ssf);
5758

5859
#ifdef CONFIG_USERSPACE
5960

0 commit comments

Comments
 (0)