arch: xtensa: implement ARCH_EXCEPT
Triggers CPU exception with illegal instruction when z_except_reason is called (e.g. in k_panic, k_oops). Creates exception stack frame for use by coredump. Adds unique cause code for ARCH_EXCEPT. Disables test case failure for qemu_xtensa. Without an ARCH_EXCEPT implementation, z_except_reason calls z_fatal_error directly with a null ESF and bypasses xtensa_excint1_c's error logging. An ESF is required to coredump. Signed-off-by: Lauren Murphy <lauren.murphy@intel.com>
This commit is contained in:
parent
b6377ccdd7
commit
b034711f59
4 changed files with 52 additions and 7 deletions
|
@ -82,6 +82,9 @@ char *z_xtensa_exccause(unsigned int cause_code)
|
|||
return "store prohibited";
|
||||
case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39:
|
||||
return "coprocessor disabled";
|
||||
case 63:
|
||||
/* i.e. z_except_reason */
|
||||
return "zephyr exception";
|
||||
default:
|
||||
return "unknown/reserved";
|
||||
}
|
||||
|
|
|
@ -180,10 +180,26 @@ _restore_context:
|
|||
|
||||
rfi ZSR_RFI_LEVEL
|
||||
|
||||
/*
|
||||
* void xtensa_arch_except(int reason_p);
|
||||
*
|
||||
* Implements hardware exception for Xtensa ARCH_EXCEPT to save
|
||||
* interrupted stack frame and reason_p for use in exception handler
|
||||
* and coredump
|
||||
*/
|
||||
.global xtensa_arch_except
|
||||
.global xtensa_arch_except_epc
|
||||
.align 4
|
||||
xtensa_arch_except:
|
||||
entry a1, 16
|
||||
xtensa_arch_except_epc:
|
||||
ill
|
||||
retw
|
||||
|
||||
/*
|
||||
* void xtensa_switch(void *new, void **old_return);
|
||||
*
|
||||
* Context switches into the prevoiusly-saved "new" handle, placing
|
||||
* Context switches into the previously-saved "new" handle, placing
|
||||
* the saved "old" handle into the address provided by old_return.
|
||||
*/
|
||||
.global xtensa_switch
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL);
|
||||
|
||||
extern char xtensa_arch_except_epc[];
|
||||
|
||||
void *xtensa_init_stack(struct k_thread *thread, int *stack_top,
|
||||
void (*entry)(void *, void *, void *),
|
||||
void *arg1, void *arg2, void *arg3)
|
||||
|
@ -217,11 +219,8 @@ void *xtensa_excint1_c(int *interrupted_stack)
|
|||
__asm__ volatile("rsr.exccause %0" : "=r"(cause));
|
||||
|
||||
if (cause == EXCCAUSE_LEVEL1_INTERRUPT) {
|
||||
|
||||
return xtensa_int1_c(interrupted_stack);
|
||||
|
||||
} else if (cause == EXCCAUSE_SYSCALL) {
|
||||
|
||||
/* Just report it to the console for now */
|
||||
LOG_ERR(" ** SYSCALL PS %p PC %p",
|
||||
(void *)bsa[BSA_PS_OFF/4], (void *)bsa[BSA_PC_OFF/4]);
|
||||
|
@ -232,18 +231,39 @@ void *xtensa_excint1_c(int *interrupted_stack)
|
|||
* else it will just loop forever
|
||||
*/
|
||||
bsa[BSA_PC_OFF/4] += 3;
|
||||
|
||||
} else {
|
||||
uint32_t ps = bsa[BSA_PS_OFF/4];
|
||||
void *pc = (void *)bsa[BSA_PC_OFF/4];
|
||||
|
||||
__asm__ volatile("rsr.excvaddr %0" : "=r"(vaddr));
|
||||
|
||||
/* Default for exception */
|
||||
int reason = K_ERR_CPU_EXCEPTION;
|
||||
|
||||
/* We need to distinguish between an ill in xtensa_arch_except,
|
||||
* e.g for k_panic, and any other ill. For exceptions caused by
|
||||
* xtensa_arch_except calls, we also need to pass the reason_p
|
||||
* to z_xtensa_fatal_error. Since the ARCH_EXCEPT frame is in the
|
||||
* BSA, the first arg reason_p is stored at the A2 offset.
|
||||
* We assign EXCCAUSE the unused, reserved code 63; this may be
|
||||
* problematic if the app or new boards also decide to repurpose
|
||||
* this code.
|
||||
*/
|
||||
if ((pc == (void *) &xtensa_arch_except_epc) && (cause == 0)) {
|
||||
cause = 63;
|
||||
__asm__ volatile("wsr.exccause %0" : : "r"(cause));
|
||||
reason = bsa[BSA_A2_OFF/4];
|
||||
/* Skip ILL to RETW */
|
||||
bsa[BSA_PC_OFF/4] += 3;
|
||||
pc = (void *)bsa[BSA_PC_OFF/4];
|
||||
}
|
||||
|
||||
LOG_ERR(" ** FATAL EXCEPTION");
|
||||
LOG_ERR(" ** CPU %d EXCCAUSE %d (%s)",
|
||||
arch_curr_cpu()->id, cause,
|
||||
z_xtensa_exccause(cause));
|
||||
LOG_ERR(" ** PC %p VADDR %p",
|
||||
(void *)bsa[BSA_PC_OFF/4], (void *)vaddr);
|
||||
pc, (void *)vaddr);
|
||||
LOG_ERR(" ** PS %p", (void *)bsa[BSA_PS_OFF/4]);
|
||||
LOG_ERR(" ** (INTLEVEL:%d EXCM: %d UM:%d RING:%d WOE:%d OWB:%d CALLINC:%d)",
|
||||
get_bits(0, 4, ps), get_bits(4, 1, ps),
|
||||
|
@ -256,7 +276,7 @@ void *xtensa_excint1_c(int *interrupted_stack)
|
|||
* as these are software errors. Should clean this
|
||||
* up.
|
||||
*/
|
||||
z_xtensa_fatal_error(K_ERR_CPU_EXCEPTION,
|
||||
z_xtensa_fatal_error(reason,
|
||||
(void *)interrupted_stack);
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,12 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void xtensa_arch_except(int reason_p);
|
||||
|
||||
#define ARCH_EXCEPT(reason_p) do { \
|
||||
xtensa_arch_except(reason_p); \
|
||||
} while (false)
|
||||
|
||||
/* internal routine documented in C file, needed by IRQ_CONNECT() macro */
|
||||
extern void z_irq_priority_set(uint32_t irq, uint32_t prio, uint32_t flags);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue