arch/xtensa: Fix return context for nested interupts

The xtensa interrupt return path was forgetting to check the nested
interrupt state and calling into the scheduler to select the context
to which to return, which of course is completely wrong.  We MUST
return to the ISR we interrupted.

In fact in practice this was only visible in the case of a nested
interrupt that causes a context switch, otherwise the "interrupted"
argument just gets returned and things work.  In particular, it can
happen when the nested context is a fatal exception that aborts the
current thread, which is how this was discovered.  The timing required
to see this on live interrupts on real applications is likely to have
been extremely difficult to detect.

Fixes #45779

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This commit is contained in:
Andy Ross 2022-05-19 11:26:05 -07:00 committed by Carles Cufí
commit 58eb132d06

View file

@ -151,6 +151,12 @@ static ALWAYS_INLINE void usage_stop(void)
#endif
}
static inline void *return_to(void *interrupted)
{
return _current_cpu->nested <= 1 ?
z_get_next_switch_handle(interrupted) : interrupted;
}
/* The wrapper code lives here instead of in the python script that
* generates _xtensa_handle_one_int*(). Seems cleaner, still kind of
* ugly.
@ -170,7 +176,7 @@ __unused void *xtensa_int##l##_c(void *interrupted_stack) \
irqs ^= m; \
__asm__ volatile("wsr.intclear %0" : : "r"(m)); \
} \
return z_get_next_switch_handle(interrupted_stack); \
return return_to(interrupted_stack); \
}
#if XCHAL_NMILEVEL >= 2
@ -254,7 +260,7 @@ void *xtensa_excint1_c(int *interrupted_stack)
(void *)interrupted_stack);
}
return z_get_next_switch_handle(interrupted_stack);
return return_to(interrupted_stack);
}
#if defined(CONFIG_GDBSTUB)
@ -264,7 +270,7 @@ void *xtensa_debugint_c(int *interrupted_stack)
z_gdb_isr((void *)interrupted_stack);
return z_get_next_switch_handle(interrupted_stack);
return return_to(interrupted_stack);
}
#endif