diff --git a/arch/xtensa/core/xtensa-asm2-util.S b/arch/xtensa/core/xtensa-asm2-util.S index 2febda46803..f2c6750313f 100644 --- a/arch/xtensa/core/xtensa-asm2-util.S +++ b/arch/xtensa/core/xtensa-asm2-util.S @@ -265,6 +265,30 @@ DEF_EXCINT 6, _handle_excint, xtensa_int6_c DEF_EXCINT 7, _handle_excint, xtensa_int7_c #endif +/* The user exception vector is defined here, as we need to handle + * MOVSP exceptions in assembly (the result has to be to unspill the + * caller function of the code that took the exception, and that can't + * be done in C). A prototype exists which mucks with the stack frame + * from the C handler instead, but that would add a LARGE overhead to + * some alloca() calls (those whent he caller has been spilled) just + * to save these five cycles during other exceptions and L1 + * interrupts. Maybe revisit at some point, with better benchmarking. + * Note that _xt_alloca_exc is Xtensa-authored code which expects A0 + * to have been saved to EXCSAVE1, which is an unfortunate ABI given + * that Zephyr code otherwise does not use the EXCSAVE registers. + */ +.pushsection .UserExceptionVector.text, "ax" +.global _Level1RealVector +_Level1RealVector: + wsr.excsave1 a0 + rsr.exccause a0 + bnei a0, EXCCAUSE_ALLOCA, _not_alloca + j _xt_alloca_exc +_not_alloca: + rsr.excsave1 a0 + j _Level1Vector +.popsection + /* In theory you can have levels up to 15, but known hardware only uses 7. */ #if XCHAL_NMILEVEL > 7 #error More interrupts than expected. diff --git a/arch/xtensa/include/xtensa-asm2-s.h b/arch/xtensa/include/xtensa-asm2-s.h index 08881cbb2d1..6567c509320 100644 --- a/arch/xtensa/include/xtensa-asm2-s.h +++ b/arch/xtensa/include/xtensa-asm2-s.h @@ -322,11 +322,14 @@ _restore_\@: * Note that the linker sections for some levels get special names for * no particularly good reason. Only level 1 has any code generation * difference, because it is the legacy exception level that predates - * the EPS/EPC registers. + * the EPS/EPC registers. It also lives in the "iram0.text" segment + * (which is linked immediately after the vectors) so that an assembly + * stub can be loaded into the vector area instead and reach this code + * with a simple jump instruction. */ .macro DEF_EXCINT LVL, ENTRY_SYM, C_HANDLER_SYM .if \LVL == 1 -.pushsection .UserExceptionVector.text, "ax" +.pushsection .iram0.text, "ax" .elseif \LVL == XCHAL_DEBUGLEVEL .pushsection .DebugExceptionVector.text, "ax" .elseif \LVL == XCHAL_NMILEVEL