Skip to content

Commit 75ad20b

Browse files
Pataterbulislaw
authored andcommitted
RTX5: uVisor: Switch threads very carefully
uVisor doesn't set the PSP of the target thread. The RTOS sets the PSP of the target thread from the target thread's TCB. However, when interrupts of higher priority than PendSV happen between the call to uVisor to switch boxes, and the RTOS setting PSP, the uVisor vIRQ interrupt handler will attempt to use an invalid PSP (the PSP from before the box and thread switch). This leads to a crash. Make box and thread switching atomic by disabling interrupts immediately before the box switching until immediately after the new PSP is set.
1 parent 474f6c6 commit 75ad20b

File tree

3 files changed

+34
-1
lines changed

3 files changed

+34
-1
lines changed

rtos/TARGET_CORTEX/rtx5/RTX/Source/TOOLCHAIN_GCC/TARGET_M3/irq_cm3.S

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,27 @@ SVC_ContextSave:
7373
STR R12,[R1,#TCB_SP_OFS] // Store SP
7474

7575
SVC_ContextSwitch:
76+
#ifdef FEATURE_UVISOR
77+
CPSID I // The call to the thread switch helper and PSP loading must be atomic.
78+
#endif
79+
/* The call to thread_switch_helper can clobber R2 and R3, but we don't
80+
* want to clobber R2 or R3. We can't save R2 and R3 to the stack (as
81+
* the stack we save them onto is likely to be inaccessible after the
82+
* call to thread_switch_helper). So, we just re-obtain the values from
83+
* osRtxInfo again. */
84+
BL thread_switch_helper
85+
LDR R3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.run
86+
LDM R3,{R1,R2} // Load osRtxInfo.thread.run: curr & next
87+
7688
STR R2,[R3] // osRtxInfo.thread.run: curr = next
7789

7890
SVC_ContextRestore:
7991
LDR R0,[R2,#TCB_SP_OFS] // Load SP
8092
LDMIA R0!,{R4-R11} // Restore R4..R11
8193
MSR PSP,R0 // Set PSP
94+
#ifdef FEATURE_UVISOR
95+
CPSIE I // The PSP has been set. Re-enable interrupts.
96+
#endif
8297
MVN LR,#~0xFFFFFFFD // Set EXC_RETURN value
8398

8499
SVC_Exit:

rtos/TARGET_CORTEX/rtx5/RTX/Source/TOOLCHAIN_GCC/TARGET_RTOS_M4_M7/irq_cm4f.S

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,18 @@ SVC_ContextSave:
9090
STRB LR, [R1,#TCB_SF_OFS] // Store stack frame information
9191

9292
SVC_ContextSwitch:
93+
#ifdef FEATURE_UVISOR
94+
CPSID I // The call to the thread switch helper and PSP loading must be atomic.
95+
#endif
96+
/* The call to thread_switch_helper can clobber R2 and R3, but we don't
97+
* want to clobber R2 or R3. We can't save R2 and R3 to the stack (as
98+
* the stack we save them onto is likely to be inaccessible after the
99+
* call to thread_switch_helper). So, we just re-obtain the values from
100+
* osRtxInfo again. */
101+
BL thread_switch_helper
102+
LDR R3,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.run
103+
LDM R3,{R1,R2} // Load osRtxInfo.thread.run: curr & next
104+
93105
STR R2,[R3] // osRtxInfo.thread.run: curr = next
94106

95107
SVC_ContextRestore:
@@ -104,6 +116,9 @@ SVC_ContextRestore:
104116
#endif
105117
LDMIA R0!,{R4-R11} // Restore R4..R11
106118
MSR PSP,R0 // Set PSP
119+
#ifdef FEATURE_UVISOR
120+
CPSIE I // The PSP has been set. Re-enable interrupts.
121+
#endif
107122

108123
SVC_Exit:
109124
BX LR // Exit from handler

rtos/TARGET_CORTEX/rtx5/RTX/Source/rtx_thread.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,9 +413,12 @@ void osRtxThreadSwitch (os_thread_t *thread) {
413413
osRtxInfo.thread.run.next = thread;
414414
osRtxThreadStackCheck();
415415
EvrRtxThreadSwitch(thread);
416+
}
416417

418+
/// Notify the OS event observer of an imminent thread switch.
419+
void thread_switch_helper(void) {
417420
if (osEventObs && osEventObs->thread_switch) {
418-
osEventObs->thread_switch(thread->context);
421+
osEventObs->thread_switch(osRtxInfo.thread.run.next->context);
419422
}
420423
}
421424

0 commit comments

Comments
 (0)