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:
parent
5d80dbd388
commit
58eb132d06
1 changed files with 9 additions and 3 deletions
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue