diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2023-06-14 02:51:18 +0300 |
---|---|---|
committer | Max Filippov <jcmvbkbc@gmail.com> | 2023-06-14 07:56:27 +0300 |
commit | f29cf77609cc401d28e2e7ec5c57d9d178ef347d (patch) | |
tree | 54198dcf0f6c2fd2d1720845d9b1f2302211cb55 /arch/xtensa/kernel/traps.c | |
parent | 651d4aff6892f630d399201f9ce94e240d932520 (diff) | |
download | linux-f29cf77609cc401d28e2e7ec5c57d9d178ef347d.tar.xz |
xtensa: add load/store exception handler
Memory attached to instruction bus of the xtensa CPU is only accessible
for a limited subset of opcodes. Other opcodes generate an exception
with the load/store error cause code. This property complicates use of
such systems. Provide a handler that recognizes and transparently fixes
such exceptions. The following opcodes are recognized when used outside
of FLIX bundles: l32i, l32i.n, l16ui, l16si, l8ui.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Diffstat (limited to 'arch/xtensa/kernel/traps.c')
-rw-r--r-- | arch/xtensa/kernel/traps.c | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index c6d93a95db1a..71588bf55632 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c @@ -54,6 +54,9 @@ static void do_interrupt(struct pt_regs *regs); #if XTENSA_FAKE_NMI static void do_nmi(struct pt_regs *regs); #endif +#ifdef CONFIG_XTENSA_LOAD_STORE +static void do_load_store(struct pt_regs *regs); +#endif static void do_unaligned_user(struct pt_regs *regs); static void do_multihit(struct pt_regs *regs); #if XTENSA_HAVE_COPROCESSORS @@ -89,7 +92,10 @@ static dispatch_init_table_t __initdata dispatch_init_table[] = { { EXCCAUSE_SYSTEM_CALL, USER, fast_syscall_user }, { EXCCAUSE_SYSTEM_CALL, 0, system_call }, /* EXCCAUSE_INSTRUCTION_FETCH unhandled */ -/* EXCCAUSE_LOAD_STORE_ERROR unhandled*/ +#ifdef CONFIG_XTENSA_LOAD_STORE +{ EXCCAUSE_LOAD_STORE_ERROR, USER|KRNL, fast_load_store }, +{ EXCCAUSE_LOAD_STORE_ERROR, 0, do_load_store }, +#endif { EXCCAUSE_LEVEL1_INTERRUPT, 0, do_interrupt }, #ifdef SUPPORT_WINDOWED { EXCCAUSE_ALLOCA, USER|KRNL, fast_alloca }, @@ -347,6 +353,19 @@ static void do_div0(struct pt_regs *regs) force_sig_fault(SIGFPE, FPE_INTDIV, (void __user *)regs->pc); } +#ifdef CONFIG_XTENSA_LOAD_STORE +static void do_load_store(struct pt_regs *regs) +{ + __die_if_kernel("Unhandled load/store exception in kernel", + regs, SIGKILL); + + pr_info_ratelimited("Load/store error to %08lx in '%s' (pid = %d, pc = %#010lx)\n", + regs->excvaddr, current->comm, + task_pid_nr(current), regs->pc); + force_sig_fault(SIGBUS, BUS_ADRERR, (void *)regs->excvaddr); +} +#endif + /* * Handle unaligned memory accesses from user space. Kill task. * |