freertos: Xtensa FreeRTOS saves threadptr in solicited stack frame

The Xtensa FreeRTOS port does not save the threadptr register when
doing a voluntary yield. This can result in a crash when multiple
tasks used the threadptr register and call "taskYIELD()".

This commit adds the threadptr register to the solicited stack frame.
This commit is contained in:
Darian Leung
2022-07-04 18:16:13 +08:00
parent 42ea9b7cb1
commit 0a894c2b30
2 changed files with 46 additions and 22 deletions

View File

@@ -188,6 +188,14 @@ STRUCT_END(XtExcFrame)
by the callee according to the compiler's ABI conventions, some space to save by the callee according to the compiler's ABI conventions, some space to save
the return address for returning to the caller, and the caller's PS register. the return address for returning to the caller, and the caller's PS register.
Note: Although the xtensa ABI considers the threadptr as "global" across
functions (meaning it is neither caller or callee saved), it is treated as a
callee-saved register in a solicited stack frame. This omits the need for the
OS to include extra logic to save "global" registers on each context switch.
Only the threadptr register is treated as callee-saved, as all other NCP
(non-coprocessor extra) registers are caller-saved. See "tie.h" for more
details.
For Windowed ABI, this stack frame includes the caller's base save area. For Windowed ABI, this stack frame includes the caller's base save area.
Note on XT_SOL_EXIT field: Note on XT_SOL_EXIT field:
@@ -204,7 +212,11 @@ STRUCT_BEGIN
STRUCT_FIELD (long, 4, XT_SOL_EXIT, exit) STRUCT_FIELD (long, 4, XT_SOL_EXIT, exit)
STRUCT_FIELD (long, 4, XT_SOL_PC, pc) STRUCT_FIELD (long, 4, XT_SOL_PC, pc)
STRUCT_FIELD (long, 4, XT_SOL_PS, ps) STRUCT_FIELD (long, 4, XT_SOL_PS, ps)
STRUCT_FIELD (long, 4, XT_SOL_NEXT, next) #if XCHAL_HAVE_THREADPTR
STRUCT_FIELD (long, 4, XT_SOL_THREADPTR, threadptr)
#else
STRUCT_FIELD (long, 4, XT_SOL_NEXT, next) /* Dummy register for 16-byte alignment */
#endif
STRUCT_FIELD (long, 4, XT_SOL_A12, a12) /* should be on 16-byte alignment */ STRUCT_FIELD (long, 4, XT_SOL_A12, a12) /* should be on 16-byte alignment */
STRUCT_FIELD (long, 4, XT_SOL_A13, a13) STRUCT_FIELD (long, 4, XT_SOL_A13, a13)
STRUCT_FIELD (long, 4, XT_SOL_A14, a14) STRUCT_FIELD (long, 4, XT_SOL_A14, a14)
@@ -213,7 +225,11 @@ STRUCT_FIELD (long, 4, XT_SOL_A15, a15)
STRUCT_FIELD (long, 4, XT_SOL_EXIT, exit) STRUCT_FIELD (long, 4, XT_SOL_EXIT, exit)
STRUCT_FIELD (long, 4, XT_SOL_PC, pc) STRUCT_FIELD (long, 4, XT_SOL_PC, pc)
STRUCT_FIELD (long, 4, XT_SOL_PS, ps) STRUCT_FIELD (long, 4, XT_SOL_PS, ps)
STRUCT_FIELD (long, 4, XT_SOL_NEXT, next) #if XCHAL_HAVE_THREADPTR
STRUCT_FIELD (long, 4, XT_SOL_THREADPTR, threadptr)
#else
STRUCT_FIELD (long, 4, XT_SOL_NEXT, next) /* Dummy register for 16-byte alignment */
#endif
STRUCT_FIELD (long, 4, XT_SOL_A0, a0) /* should be on 16-byte alignment */ STRUCT_FIELD (long, 4, XT_SOL_A0, a0) /* should be on 16-byte alignment */
STRUCT_FIELD (long, 4, XT_SOL_A1, a1) STRUCT_FIELD (long, 4, XT_SOL_A1, a1)
STRUCT_FIELD (long, 4, XT_SOL_A2, a2) STRUCT_FIELD (long, 4, XT_SOL_A2, a2)

View File

@@ -444,6 +444,10 @@ _frxt_dispatch:
.L_frxt_dispatch_sol: .L_frxt_dispatch_sol:
/* Solicited stack frame. Restore minimal context and return from vPortYield(). */ /* Solicited stack frame. Restore minimal context and return from vPortYield(). */
#if XCHAL_HAVE_THREADPTR
l32i a2, sp, XT_SOL_THREADPTR
wur.threadptr a2
#endif
l32i a3, sp, XT_SOL_PS l32i a3, sp, XT_SOL_PS
#ifdef __XTENSA_CALL0_ABI__ #ifdef __XTENSA_CALL0_ABI__
l32i a12, sp, XT_SOL_A12 l32i a12, sp, XT_SOL_A12
@@ -531,6 +535,10 @@ vPortYield:
rsr a2, PS rsr a2, PS
s32i a0, sp, XT_SOL_PC s32i a0, sp, XT_SOL_PC
s32i a2, sp, XT_SOL_PS s32i a2, sp, XT_SOL_PS
#if XCHAL_HAVE_THREADPTR
rur.threadptr a2
s32i a2, sp, XT_SOL_THREADPTR
#endif
#ifdef __XTENSA_CALL0_ABI__ #ifdef __XTENSA_CALL0_ABI__
s32i a12, sp, XT_SOL_A12 /* save callee-saved registers */ s32i a12, sp, XT_SOL_A12 /* save callee-saved registers */
s32i a13, sp, XT_SOL_A13 s32i a13, sp, XT_SOL_A13