summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2023-09-20 09:21:10 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2023-09-20 09:21:10 +0200
commitfc66e4f5d3c8a65c734c340dd63c10fe3193d163 (patch)
tree097d4196fe428e2b2ed7e4cfb10403ef14990a9e
parentb7391a6214f1e89172a17d07b81262751aed8dc7 (diff)
sparc: Fix stack corruptionqual-96
Fix a potential stack corruption in uniprocessor configurations during start multitasking . The system initialization uses the interrupt stack. A first level interrupt shall never interrupt a context which uses the interrupt stack. Such a use would lead to stack corruption and undefined system behaviour. Unfortunately, in uniprocessor configurations this was the case. Multiprocessing is started using _CPU_Context_restore(). The caller of this function (_Thread_Start_multitasking()) uses the interrupt stack. Later we have in cpukit/score/cpu/sparc/cpu_asm.S: mov %g1, %psr ! restore status register and ! **** ENABLE TRAPS **** ld [%o1 + G5_OFFSET], %g5 ! restore the global registers ld [%o1 + G7_OFFSET], %g7 ! Load thread specific ISR dispatch prevention flag ld [%o1 + ISR_DISPATCH_DISABLE_STACK_OFFSET], %o2 ! Store it to memory later to use the cycles ldd [%o1 + L0_OFFSET], %l0 ! restore the local registers ldd [%o1 + L2_OFFSET], %l2 ldd [%o1 + L4_OFFSET], %l4 ldd [%o1 + L6_OFFSET], %l6 ! Now restore thread specific ISR dispatch prevention flag st %o2, [%g6 + PER_CPU_ISR_DISPATCH_DISABLE] ldd [%o1 + I0_OFFSET], %i0 ! restore the input registers ldd [%o1 + I2_OFFSET], %i2 ldd [%o1 + I4_OFFSET], %i4 ldd [%o1 + I6_FP_OFFSET], %i6 ldd [%o1 + O6_SP_OFFSET], %o6 ! restore the output registers Between the ENABLE TRAPS and the restore of the output registers, we still use the stack of the caller and interrupts may be enabled. If an interrupt happens in this code block, the interrupt stack is concurrently used which may lead to a crash. Fix this by adding a new function _SPARC_Start_multiprocessing() for uniprocessor configurations. This function first sets the stack pointer to use the stack of the heir thread. Close #4955.
-rw-r--r--cpukit/score/cpu/sparc/cpu_asm.S29
-rw-r--r--cpukit/score/cpu/sparc/include/rtems/score/cpu.h19
2 files changed, 47 insertions, 1 deletions
diff --git a/cpukit/score/cpu/sparc/cpu_asm.S b/cpukit/score/cpu/sparc/cpu_asm.S
index 287c2c4cd9..fd7186b499 100644
--- a/cpukit/score/cpu/sparc/cpu_asm.S
+++ b/cpukit/score/cpu/sparc/cpu_asm.S
@@ -246,6 +246,14 @@ done_flushing:
mov %g1, %psr ! restore status register and
! **** ENABLE TRAPS ****
+ /*
+ * WARNING: This code does not run with the restored stack pointer. In
+ * SMP configurations, it uses a processor-specific stack. In
+ * uniprocessor configurations, it uses the stack of the caller. In
+ * this case, the caller shall ensure that it is not the interrupt
+ * stack (which is also the system initialization stack).
+ */
+
ld [%o1 + G5_OFFSET], %g5 ! restore the global registers
ld [%o1 + G7_OFFSET], %g7
@@ -266,7 +274,9 @@ done_flushing:
ldd [%o1 + I4_OFFSET], %i4
ldd [%o1 + I6_FP_OFFSET], %i6
- ldd [%o1 + O6_SP_OFFSET], %o6 ! restore the output registers
+ ldd [%o1 + O6_SP_OFFSET], %o6 ! restore the non-volatile output
+ ! registers (stack pointer,
+ ! link register)
jmp %o7 + 8 ! return
nop ! delay slot
@@ -325,6 +335,23 @@ SYM(_CPU_Context_restore):
ba SYM(_CPU_Context_restore_heir)
mov %i0, %o1 ! in the delay slot
+#if !defined(RTEMS_SMP)
+ .align 4
+ PUBLIC(_SPARC_Start_multitasking)
+SYM(_SPARC_Start_multitasking):
+ /*
+ * Restore the stack pointer right now, so that the window flushing and
+ * interrupts during _CPU_Context_restore_heir() use the stack of the
+ * heir thread. This is crucial for the interrupt handling to prevent
+ * a concurrent use of the interrupt stack (which is also the system
+ * initialization stack).
+ */
+ ld [%o0 + O6_SP_OFFSET], %o6
+
+ ba SYM(_CPU_Context_restore)
+ nop
+#endif
+
/*
* void _SPARC_Interrupt_trap()
*
diff --git a/cpukit/score/cpu/sparc/include/rtems/score/cpu.h b/cpukit/score/cpu/sparc/include/rtems/score/cpu.h
index 2021b108db..a21cef371f 100644
--- a/cpukit/score/cpu/sparc/include/rtems/score/cpu.h
+++ b/cpukit/score/cpu/sparc/include/rtems/score/cpu.h
@@ -993,6 +993,25 @@ RTEMS_NO_RETURN void _CPU_Context_switch_no_return(
*/
RTEMS_NO_RETURN void _CPU_Context_restore( Context_Control *new_context );
+#if !defined(RTEMS_SMP)
+/**
+ * @brief Starts multitasking in uniprocessor configurations.
+ *
+ * This function just sets the stack of the heir thread and then calls
+ * _CPU_Context_restore().
+ *
+ * This is causes that the window flushing and interrupts during
+ * _CPU_Context_restore() use the stack of the heir thread. This is crucial
+ * for the interrupt handling to prevent a concurrent use of the interrupt
+ * stack (which is also the system initialization stack).
+ *
+ * @param[in] heir is the context of the heir thread.
+ */
+RTEMS_NO_RETURN void _SPARC_Start_multitasking( Context_Control *heir );
+
+#define _CPU_Start_multitasking( _heir ) _SPARC_Start_multitasking( _heir )
+#endif
+
#if defined(RTEMS_SMP)
uint32_t _CPU_SMP_Initialize( void );