Skip to content

Commit c256915

Browse files
committed
ThreadX: Fix context switch logic
- Disable interrupts prior to allocating a large exception frame; only reenable them after deallocating the extra memory. - Any user tasks with stacks based on TX_MINIMUM_STACK do not have sufficient space for both a context switch frame and an ISR frame; ill-timed interrupts were causing stack overruns.
1 parent 3c2b7df commit c256915

2 files changed

Lines changed: 39 additions & 17 deletions

File tree

ports/xtensa/xcc/src/tx_thread_schedule.S

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -229,14 +229,24 @@ _tx_thread_schedule:
229229
rsync /* ensure wsr.CPENABLE has completed */
230230
#endif
231231

232-
wsr a3, PS /* no need to sync PS, delay is OK */
233-
234-
/* This does not return to its caller, but to the selected thread. */
232+
/* De-allocate the remainder of the frame before reenabling interrupts
233+
* to avoid overrunning a task stack of TX_MINIMUM_STACK bytes, which
234+
* can only handle one XT_STK_FRMSZ.
235+
*/
235236
#ifdef __XTENSA_CALL0_ABI__
236237
/* 'addi sp, sp, imm' could turn into 'addmi, addi' sequence and make */
237238
/* the sp briefly point to an illegal stack location. Avoid that. */
238-
addi a2, sp, XT_STK_FRMSZ
239+
addi a2, sp, XT_STK_FRMSZ /* fully deallocate stack frame */
239240
mov sp, a2
241+
#else
242+
addi a2, sp, XT_STK_FRMSZ - 48 /* initial SP at solicited entry; */
243+
movsp sp, a2 /* retw will deallocate remainder */
244+
#endif
245+
246+
wsr a3, PS /* no need to sync PS, delay is OK */
247+
248+
/* This does not return to its caller, but to the selected thread. */
249+
#ifdef __XTENSA_CALL0_ABI__
240250
ret
241251
#else
242252
retw

ports/xtensa/xcc/src/tx_thread_system_return.S

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -70,20 +70,14 @@ _tx_thread_system_return:
7070
Since this is solicited, no need to save regs compiler doesn't preserve.
7171
*/
7272

73-
#if XCHAL_HAVE_XEA3
7473
#ifdef __XTENSA_CALL0_ABI__
75-
addi sp, sp, -16
74+
addi a2, sp, -16 /* avoid addi/addmi relaxation that */
75+
mov sp, a2 /* might temporarily move sp up */
7676
#else
7777
entry sp, 48
7878
#endif
79+
#if XCHAL_HAVE_XEA3
7980
s32i a0, sp, 0 /* save return address */
80-
#else
81-
#ifdef __XTENSA_CALL0_ABI__
82-
addi a2, sp, -XT_STK_FRMSZ /* avoid addi/addmi relaxation that */
83-
mov sp, a2 /* might temporarily move sp up */
84-
#else
85-
entry sp, XT_STK_FRMSZ
86-
#endif
8781
#endif
8882

8983
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
@@ -109,6 +103,7 @@ _tx_thread_system_return:
109103
interrupts enabled, but we will have to revert SP to point above
110104
the exception frame because that is what the dispatch code expects.
111105
Must disable interrupts before that.
106+
TODO: disable interrupts prior to stack allocation as we do for XEA2
112107
*/
113108

114109
movi a0, .Lret
@@ -185,7 +180,27 @@ _tx_thread_system_return:
185180

186181
#else /* XEA1 or XEA2 */
187182

183+
/* Disable interrupts before allocating the full stack frame. Taking
184+
* an interrupt will allocate a second exception stack frame, which will
185+
* overrun a task stack of TX_MINIMUM_STACK bytes.
186+
* Read PS so it can be saved off after stack adjustment.
187+
*/
188188
rsr a2, PS
189+
XT_INTS_DISABLE(a3)
190+
191+
/* Allocate the remainder of the frame here; we already allocated
192+
* 16 bytes for call0 or 48 bytes for windowed upon entry.
193+
* This memory will be deallocated in the solicited exit logic prior
194+
* to reenabling interrupts.
195+
*/
196+
#ifdef __XTENSA_CALL0_ABI__
197+
addi a3, sp, -XT_STK_FRMSZ + 16 // avoid addi/addmi relaxation again
198+
mov sp, a3
199+
#else
200+
addi a3, sp, -XT_STK_FRMSZ + 48
201+
movsp sp, a3
202+
#endif
203+
189204
s32i a0, sp, XT_STK_PC
190205
s32i a2, sp, XT_STK_PS
191206
#ifdef __XTENSA_CALL0_ABI__
@@ -205,8 +220,6 @@ _tx_thread_system_return:
205220
wsr a2, PS
206221
rsync
207222
call0 xthal_window_spill_nw
208-
l32i a0, sp, XT_STK_PS
209-
wsr a0, PS // Restore PS value
210223
rsync
211224
#endif
212225

@@ -226,10 +239,9 @@ _tx_thread_system_return:
226239
a4 = &_tx_timer_time_slice
227240
*/
228241

229-
/* Lock out interrupts (except hi-pri). */
242+
/* Already locked out interrupts (except hi-pri). */
230243
/* Grab thread control block of current thread. */
231244
movi a2, _tx_thread_current_ptr /* a2 = &_tx_thread_current_ptr */
232-
XT_INTS_DISABLE(a0)
233245
l32i a3, a2, 0 /* a3 points to TCB */
234246

235247
/* Mark as having solicited entry to kernel (used on exit). */

0 commit comments

Comments
 (0)