xtensa: mmu: do not fault for known exceptions

There are known exceptions which are not fatal, and we need to
handle them properly by returning to the fixup addresses as
indicated. This adds the code necessary in the exception
handler for this situation.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
This commit is contained in:
Daniel Leung 2023-03-16 14:34:28 -07:00 committed by Carles Cufí
commit e9c449a737
2 changed files with 34 additions and 12 deletions

View file

@ -121,14 +121,6 @@ void z_xtensa_fatal_error(unsigned int reason, const z_arch_esf_t *esf)
z_fatal_error(reason, esf);
}
#ifdef CONFIG_USERSPACE
Z_EXC_DECLARE(z_xtensa_user_string_nlen);
static const struct z_exc_handle exceptions[] = {
Z_EXC_HANDLE(z_xtensa_user_string_nlen)
};
#endif /* CONFIG_USERSPACE */
#ifdef XT_SIMULATOR
void exit(int return_code)
{

View file

@ -15,11 +15,20 @@
#include <zephyr/logging/log.h>
#include <offsets.h>
#include <zsr.h>
#include <zephyr/arch/common/exc_handle.h>
LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL);
extern char xtensa_arch_except_epc[];
#ifdef CONFIG_USERSPACE
Z_EXC_DECLARE(z_xtensa_user_string_nlen);
static const struct z_exc_handle exceptions[] = {
Z_EXC_HANDLE(z_xtensa_user_string_nlen)
};
#endif /* CONFIG_USERSPACE */
void *xtensa_init_stack(struct k_thread *thread, int *stack_top,
void (*entry)(void *, void *, void *),
void *arg1, void *arg2, void *arg3)
@ -335,6 +344,21 @@ void *xtensa_excint1_c(int *interrupted_stack)
ps = bsa->ps;
pc = (void *)bsa->pc;
#ifdef CONFIG_USERSPACE
/* If the faulting address is from one of the known
* exceptions that should not be fatal, return to
* the fixup address.
*/
for (int i = 0; i < ARRAY_SIZE(exceptions); i++) {
if ((pc >= exceptions[i].start) &&
(pc < exceptions[i].end)) {
bsa->pc = (uintptr_t)exceptions[i].fixup;
goto fixup_out;
}
}
#endif /* CONFIG_USERSPACE */
__asm__ volatile("rsr.excvaddr %0" : "=r"(vaddr));
/* Default for exception */
@ -397,10 +421,6 @@ void *xtensa_excint1_c(int *interrupted_stack)
is_fatal_error = true;
break;
}
if (is_dblexc) {
__asm__ volatile("wsr.depc %0" : : "r"(0));
}
#endif /* CONFIG_XTENSA_MMU */
if (is_dblexc || is_fatal_error) {
@ -432,6 +452,16 @@ void *xtensa_excint1_c(int *interrupted_stack)
_current_cpu->nested = 1;
}
#ifdef CONFIG_XTENSA_MMU
#ifdef CONFIG_USERSPACE
fixup_out:
#endif
if (is_dblexc) {
__asm__ volatile("wsr.depc %0" : : "r"(0));
}
#endif /* CONFIG_XTENSA_MMU */
return return_to(interrupted_stack);
}