Skip to content

Commit 27af123

Browse files
committed
Fix Cortex-R5 context save r4 clobber in non-nested IRQ path
SVC/SYS mode-switching code (introduced in b0c54c6) used r4 as scratch to determine the interrupted thread's processor mode. r4 is callee-saved but not part of the minimal interrupt frame (r0-r3, r10, r12, PC, CPSR), so it was silently corrupted when the thread resumed via the no-preempt restore path. The preemption path also propagated the corrupted r4 into the full context frame. This caused intermittent (~5%) failures on ZynqMP: "FIFO order broken" (queue corruption) and "counter mismatch" (mutex protection broken), depending on whether the compiler had a live value in r4 at interrupt point. Replace r4 with r0 at all three clobber sites: 1. Mode-bit extraction (AND/CMP for SVC vs SYS check) 2. CPSR switch (MOV/MSR for SYS_MODE and SVC_MODE) 3. IRQ mode re-entry (MOV/MSR for IRQ_MODE after saving context) r0 is safe because it is overwritten by LDMIA r2,{r0-r3} (recovering thread registers from the IRQ stack) before being saved to the minimal frame, and at the IRQ re-entry point r0 has had its last use as the thread pointer for STR sp,[r0,eclipse-threadx#8].
1 parent de4a8af commit 27af123

1 file changed

Lines changed: 9 additions & 8 deletions

File tree

ports/cortex_r5/gnu/src/tx_thread_context_save.S

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -159,20 +159,21 @@ __tx_thread_not_nested_save:
159159
@
160160
@ /* Switch to the thread's actual mode (from SPSR) to access its stack */
161161
@ /* r3 contains SPSR_irq = thread's saved CPSR */
162-
AND r4, r3, #0x1F @ r4 = thread's mode bits
163-
CMP r4, #0x13 @ Was thread in SVC mode?
162+
AND r0, r3, #0x1F @ r0 = thread's mode bits (r0 is scratch;
163+
@ restored from IRQ stack by LDMIA below)
164+
CMP r0, #0x13 @ Was thread in SVC mode?
164165
BEQ __tx_save_svc_mode
165166
@
166167
@ /* Thread was in SYS/USR mode - switch to SYS mode */
167168
@ /* Note: USR and SYS share the same sp/lr register bank */
168-
MOV r4, #SYS_MODE @ SYS mode + interrupts disabled
169-
MSR CPSR_c, r4 @ Switch to SYS mode
169+
MOV r0, #SYS_MODE @ SYS mode + interrupts disabled
170+
MSR CPSR_c, r0 @ Switch to SYS mode
170171
B __tx_save_context_on_stack
171172
@
172173
__tx_save_svc_mode:
173174
@ /* Thread was in SVC mode - switch to SVC mode */
174-
MOV r4, #SVC_MODE @ SVC mode + interrupts disabled
175-
MSR CPSR_c, r4 @ Switch to SVC mode
175+
MOV r0, #SVC_MODE @ SVC mode + interrupts disabled
176+
MSR CPSR_c, r0 @ Switch to SVC mode
176177
@
177178
__tx_save_context_on_stack:
178179
@ /* Now sp = thread's actual stack pointer (sp_sys or sp_svc) */
@@ -195,8 +196,8 @@ __tx_save_context_on_stack:
195196
STR sp, [r0, #8] @ Save updated thread stack pointer
196197
@
197198
@ /* Switch to IRQ mode to use dedicated IRQ stack for ISR execution. */
198-
MOV r4, #IRQ_MODE @ IRQ mode + interrupts disabled
199-
MSR CPSR_c, r4 @ Switch to IRQ mode
199+
MOV r0, #IRQ_MODE @ IRQ mode + interrupts disabled
200+
MSR CPSR_c, r0 @ Switch to IRQ mode
200201
ADD sp, sp, #16 @ Pop stale r0-r3 from IRQ stack (4 regs * 4 bytes)
201202
MOV r10, #0 @ Clear stack limit
202203

0 commit comments

Comments
 (0)