@@ -523,9 +523,15 @@ void *hal_build_initial_frame(void *stack_top,
523523 frame [1 ] = (uint32_t ) & _gp ; /* gp - global pointer */
524524 frame [2 ] = tp_val ; /* tp - thread pointer */
525525
526- uint32_t mstatus_val = MSTATUS_MIE | MSTATUS_MPIE |
527- (user_mode ? MSTATUS_MPP_USER : MSTATUS_MPP_MACH );
528- frame [FRAME_MSTATUS ] = mstatus_val ; /* mstatus - enable interrupts */
526+ /* Initialize mstatus for new task:
527+ * - MPIE=1: mret will copy this to MIE, enabling interrupts after task
528+ * starts
529+ * - MPP: Set privilege level (U-mode or M-mode)
530+ * - MIE=0: Keep interrupts disabled during frame restoration
531+ */
532+ uint32_t mstatus_val =
533+ MSTATUS_MPIE | (user_mode ? MSTATUS_MPP_USER : MSTATUS_MPP_MACH );
534+ frame [FRAME_MSTATUS ] = mstatus_val ;
529535
530536 frame [FRAME_EPC ] = (uint32_t ) task_entry ; /* mepc - entry point */
531537
@@ -792,23 +798,102 @@ static void __attribute__((naked, used)) __dispatch_init(void)
792798 "mret\n" ); /* Jump to the task's entry point */
793799}
794800
795- /* Transfers control from the kernel's main thread to the first task */
796- __attribute__((noreturn )) void hal_dispatch_init (jmp_buf env )
801+ /* Low-level routine to restore context from ISR frame and jump to task.
802+ * This is used in preemptive mode where tasks are managed via ISR frames.
803+ */
804+ static void __attribute__((naked , used )) __dispatch_init_isr (void )
797805{
798- if (unlikely (!env ))
806+ asm volatile (
807+ /* a0 contains the ISR frame pointer (sp value) */
808+ "mv sp, a0\n"
809+
810+ /* Restore mstatus from frame[32] */
811+ "lw t0, 32*4(sp)\n"
812+ "csrw mstatus, t0\n"
813+
814+ /* Restore mepc from frame[31] */
815+ "lw t1, 31*4(sp)\n"
816+ "csrw mepc, t1\n"
817+
818+ /* Restore all general-purpose registers */
819+ "lw ra, 0*4(sp)\n"
820+ "lw gp, 1*4(sp)\n"
821+ "lw tp, 2*4(sp)\n"
822+ "lw t0, 3*4(sp)\n"
823+ "lw t1, 4*4(sp)\n"
824+ "lw t2, 5*4(sp)\n"
825+ "lw s0, 6*4(sp)\n"
826+ "lw s1, 7*4(sp)\n"
827+ "lw a0, 8*4(sp)\n"
828+ "lw a1, 9*4(sp)\n"
829+ "lw a2, 10*4(sp)\n"
830+ "lw a3, 11*4(sp)\n"
831+ "lw a4, 12*4(sp)\n"
832+ "lw a5, 13*4(sp)\n"
833+ "lw a6, 14*4(sp)\n"
834+ "lw a7, 15*4(sp)\n"
835+ "lw s2, 16*4(sp)\n"
836+ "lw s3, 17*4(sp)\n"
837+ "lw s4, 18*4(sp)\n"
838+ "lw s5, 19*4(sp)\n"
839+ "lw s6, 20*4(sp)\n"
840+ "lw s7, 21*4(sp)\n"
841+ "lw s8, 22*4(sp)\n"
842+ "lw s9, 23*4(sp)\n"
843+ "lw s10, 24*4(sp)\n"
844+ "lw s11, 25*4(sp)\n"
845+ "lw t3, 26*4(sp)\n"
846+ "lw t4, 27*4(sp)\n"
847+ "lw t5, 28*4(sp)\n"
848+ "lw t6, 29*4(sp)\n"
849+
850+ /* Deallocate stack frame */
851+ "addi sp, sp, %0\n"
852+
853+ /* Return from trap - jump to task entry point */
854+ "mret\n"
855+ :
856+ : "i" (ISR_STACK_FRAME_SIZE )
857+ : "memory" );
858+ }
859+
860+ /* Transfers control from the kernel's main thread to the first task.
861+ * In preemptive mode, ctx should be the ISR frame pointer (void *sp).
862+ * In cooperative mode, ctx should be the jmp_buf context.
863+ */
864+ __attribute__((noreturn )) void hal_dispatch_init (void * ctx )
865+ {
866+ if (unlikely (!ctx ))
799867 hal_panic (); /* Cannot proceed without valid context */
800868
801- if (kcb -> preemptive )
802- hal_timer_enable ();
869+ if (kcb -> preemptive ) {
870+ /* Preemptive mode: ctx is ISR frame pointer, restore from it.
871+ * Enable timer before jumping to task. Global interrupts will be
872+ * enabled by mret based on MPIE bit in restored mstatus.
873+ */
874+ /* Save ctx before hal_timer_enable modifies registers */
875+ void * saved_ctx = ctx ;
803876
804- _ei (); /* Enable global interrupts just before launching the first task */
877+ hal_timer_enable ();
805878
806- asm volatile (
807- "mv a0, %0\n" /* Move @env (the task's context) into 'a0' */
808- "call __dispatch_init\n" /* Call the low-level restore routine */
809- :
810- : "r" (env )
811- : "a0" , "memory" );
879+ /* Restore ISR frame pointer and call dispatch */
880+ asm volatile (
881+ "mv a0, %0\n" /* Load ISR frame pointer into a0 */
882+ "call __dispatch_init_isr\n" /* Restore from ISR frame */
883+ :
884+ : "r" (saved_ctx )
885+ : "a0" , "memory" );
886+ } else {
887+ /* Cooperative mode: ctx is jmp_buf, use standard dispatch */
888+ _ei (); /* Enable global interrupts */
889+
890+ asm volatile (
891+ "mv a0, %0\n" /* Move @env (the task's context) into 'a0' */
892+ "call __dispatch_init\n" /* Call the low-level restore routine */
893+ :
894+ : "r" (ctx )
895+ : "a0" , "memory" );
896+ }
812897 __builtin_unreachable ();
813898}
814899
@@ -865,6 +950,8 @@ void hal_context_init(jmp_buf *ctx,
865950 */
866951 (* ctx )[CONTEXT_SP ] = (uint32_t ) stack_top ;
867952 (* ctx )[CONTEXT_RA ] = (uint32_t ) ra ;
868- (* ctx )[CONTEXT_MSTATUS ] = MSTATUS_MIE | MSTATUS_MPIE |
869- (user_mode ? MSTATUS_MPP_USER : MSTATUS_MPP_MACH );
953+ /* Note: CONTEXT_MSTATUS not used in cooperative mode (setjmp/longjmp),
954+ * but set it for consistency with ISR frame initialization */
955+ (* ctx )[CONTEXT_MSTATUS ] =
956+ MSTATUS_MPIE | (user_mode ? MSTATUS_MPP_USER : MSTATUS_MPP_MACH );
870957}
0 commit comments