The previous SMP multitasking start assumed that the initial heir thread of a processor starts execution in _Thread_Handler(). The _Thread_Handler() sets the interrupt state explicitly by _ISR_Set_level() before it calls the thread entry. Under certain timing conditions, processors may perform an initial context switch to a thread which already executes its thread body (see smptests/smpstart01). In this case, interrupts are disabled after the context switch on targets which do not save/restore the interrupt state during a context switch (aarch64, arm, and riscv).
Close #4627. --- cpukit/score/cpu/aarch64/cpu_asm.S | 17 +++++++++++++++++ .../score/cpu/aarch64/include/rtems/score/cpu.h | 4 ++++ cpukit/score/cpu/arm/cpu_asm.S | 12 ++++++++++++ cpukit/score/cpu/arm/include/rtems/score/cpu.h | 4 ++++ .../score/cpu/riscv/include/rtems/score/cpu.h | 4 ++++ cpukit/score/cpu/riscv/riscv-context-switch.S | 15 +++++++++++++++ cpukit/score/src/threadstartmultitasking.c | 3 +++ 7 files changed, 59 insertions(+) diff --git a/cpukit/score/cpu/aarch64/cpu_asm.S b/cpukit/score/cpu/aarch64/cpu_asm.S index 2379698336..6321acde90 100644 --- a/cpukit/score/cpu/aarch64/cpu_asm.S +++ b/cpukit/score/cpu/aarch64/cpu_asm.S @@ -202,5 +202,22 @@ DEFINE_FUNCTION_AARCH64(_CPU_Context_restore) str x5, [x2, #PER_CPU_OFFSET_EXECUTING] #endif + b .L_check_is_executing + +DEFINE_FUNCTION_AARCH64(_AArch64_Start_multitasking) +#ifdef AARCH64_MULTILIB_ARCH_V8_ILP32 + /* Sanitize input for ILP32 ABI */ + mov w0, w0 +#endif + + mov x1, x0 + GET_SELF_CPU_CONTROL reg_2 + + /* Switch the stack to the temporary interrupt stack of this processor */ + add sp, x2, #(PER_CPU_INTERRUPT_FRAME_AREA + CPU_INTERRUPT_FRAME_SIZE) + + /* Enable interrupts */ + msr DAIFClr, #0x2 + b .L_check_is_executing #endif diff --git a/cpukit/score/cpu/aarch64/include/rtems/score/cpu.h b/cpukit/score/cpu/aarch64/include/rtems/score/cpu.h index e1d9f0a5c2..fdc0e3d929 100644 --- a/cpukit/score/cpu/aarch64/include/rtems/score/cpu.h +++ b/cpukit/score/cpu/aarch64/include/rtems/score/cpu.h @@ -285,6 +285,10 @@ void _CPU_Context_Initialize( { context->is_executing = is_executing; } + + RTEMS_NO_RETURN void _AArch64_Start_multitasking( Context_Control *heir ); + + #define _CPU_Start_multitasking( _heir ) _AArch64_Start_multitasking( _heir ) #endif #define _CPU_Context_Restart_self( _the_context ) \ diff --git a/cpukit/score/cpu/arm/cpu_asm.S b/cpukit/score/cpu/arm/cpu_asm.S index 54d6f70b0d..d52a43f70d 100644 --- a/cpukit/score/cpu/arm/cpu_asm.S +++ b/cpukit/score/cpu/arm/cpu_asm.S @@ -181,6 +181,18 @@ DEFINE_FUNCTION_ARM(_CPU_Context_restore) /* Update the executing */ str r5, [r2, #PER_CPU_OFFSET_EXECUTING] + b .L_check_is_executing + +DEFINE_FUNCTION_ARM(_ARM_Start_multitasking) + mov r1, r0 + GET_SELF_CPU_CONTROL r2 + + /* Switch the stack to the temporary interrupt stack of this processor */ + add sp, r2, #(PER_CPU_INTERRUPT_FRAME_AREA + CPU_INTERRUPT_FRAME_SIZE) + + /* Enable IRQ interrupts */ + cpsie i + b .L_check_is_executing #endif diff --git a/cpukit/score/cpu/arm/include/rtems/score/cpu.h b/cpukit/score/cpu/arm/include/rtems/score/cpu.h index da521528a4..7ac180ac26 100644 --- a/cpukit/score/cpu/arm/include/rtems/score/cpu.h +++ b/cpukit/score/cpu/arm/include/rtems/score/cpu.h @@ -443,6 +443,10 @@ void _CPU_Context_Initialize( { context->is_executing = is_executing; } + + RTEMS_NO_RETURN void _ARM_Start_multitasking( Context_Control *heir ); + + #define _CPU_Start_multitasking( _heir ) _ARM_Start_multitasking( _heir ) #endif #define _CPU_Context_Restart_self( _the_context ) \ diff --git a/cpukit/score/cpu/riscv/include/rtems/score/cpu.h b/cpukit/score/cpu/riscv/include/rtems/score/cpu.h index 05ef2709ba..471c6c6c3e 100644 --- a/cpukit/score/cpu/riscv/include/rtems/score/cpu.h +++ b/cpukit/score/cpu/riscv/include/rtems/score/cpu.h @@ -509,6 +509,10 @@ static inline void _CPU_Context_Set_is_executing( context->is_executing = is_executing; } +RTEMS_NO_RETURN void _RISCV_Start_multitasking( Context_Control *heir ); + +#define _CPU_Start_multitasking( _heir ) _RISCV_Start_multitasking( _heir ) + #endif /* RTEMS_SMP */ /** Type that can store a 32-bit integer or a pointer. */ diff --git a/cpukit/score/cpu/riscv/riscv-context-switch.S b/cpukit/score/cpu/riscv/riscv-context-switch.S index 3c0368886e..cfaff444b0 100644 --- a/cpukit/score/cpu/riscv/riscv-context-switch.S +++ b/cpukit/score/cpu/riscv/riscv-context-switch.S @@ -40,6 +40,9 @@ PUBLIC(_CPU_Context_switch) PUBLIC(_CPU_Context_switch_no_return) PUBLIC(_CPU_Context_restore) +#ifdef RTEMS_SMP +PUBLIC(_RISCV_Start_multitasking) +#endif SYM(_CPU_Context_switch): SYM(_CPU_Context_switch_no_return): @@ -174,5 +177,17 @@ SYM(_CPU_Context_restore): /* Update the executing */ sw a5, PER_CPU_OFFSET_EXECUTING(a2) + j .Ltry_update_is_executing + +SYM(_RISCV_Start_multitasking): + mv a1, a0 + GET_SELF_CPU_CONTROL a2 + + /* Switch the stack to the temporary interrupt stack of this processor */ + addi sp, a2, PER_CPU_INTERRUPT_FRAME_AREA + CPU_INTERRUPT_FRAME_SIZE + + /* Enable interrupts */ + csrrs zero, mstatus, RISCV_MSTATUS_MIE + j .Ltry_update_is_executing #endif diff --git a/cpukit/score/src/threadstartmultitasking.c b/cpukit/score/src/threadstartmultitasking.c index 5cc2051be4..d97d2e0c82 100644 --- a/cpukit/score/src/threadstartmultitasking.c +++ b/cpukit/score/src/threadstartmultitasking.c @@ -64,6 +64,9 @@ void _Thread_Start_multitasking( void ) #if defined(_CPU_Start_multitasking) _CPU_Start_multitasking( &heir->Registers ); #elif defined(RTEMS_SMP) +#if CPU_ENABLE_ROBUST_THREAD_DISPATCH == TRUE +#error "The CPU port has to provide _CPU_Start_multitasking()" +#endif { Context_Control trash; -- 2.34.1 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel