@@ -534,9 +534,15 @@ void *hal_build_initial_frame(void *stack_top,
534534 frame [1 ] = (uint32_t ) & _gp ; /* gp - global pointer */
535535 frame [2 ] = tp_val ; /* tp - thread pointer */
536536
537- uint32_t mstatus_val = MSTATUS_MIE | MSTATUS_MPIE |
538- (user_mode ? MSTATUS_MPP_USER : MSTATUS_MPP_MACH );
539- frame [FRAME_MSTATUS ] = mstatus_val ; /* mstatus - enable interrupts */
537+ /* Initialize mstatus for new task:
538+ * - MPIE=1: mret will copy this to MIE, enabling interrupts after task
539+ * starts
540+ * - MPP: Set privilege level (U-mode or M-mode)
541+ * - MIE=0: Keep interrupts disabled during frame restoration
542+ */
543+ uint32_t mstatus_val =
544+ MSTATUS_MPIE | (user_mode ? MSTATUS_MPP_USER : MSTATUS_MPP_MACH );
545+ frame [FRAME_MSTATUS ] = mstatus_val ;
540546
541547 frame [FRAME_EPC ] = (uint32_t ) task_entry ; /* mepc - entry point */
542548
@@ -803,23 +809,102 @@ static void __attribute__((naked, used)) __dispatch_init(void)
803809 "mret\n" ); /* Jump to the task's entry point */
804810}
805811
806- /* Transfers control from the kernel's main thread to the first task */
807- __attribute__((noreturn )) void hal_dispatch_init (jmp_buf env )
812+ /* Low-level routine to restore context from ISR frame and jump to task.
813+ * This is used in preemptive mode where tasks are managed via ISR frames.
814+ */
815+ static void __attribute__((naked , used )) __dispatch_init_isr (void )
808816{
809- if (unlikely (!env ))
817+ asm volatile (
818+ /* a0 contains the ISR frame pointer (sp value) */
819+ "mv sp, a0\n"
820+
821+ /* Restore mstatus from frame[32] */
822+ "lw t0, 32*4(sp)\n"
823+ "csrw mstatus, t0\n"
824+
825+ /* Restore mepc from frame[31] */
826+ "lw t1, 31*4(sp)\n"
827+ "csrw mepc, t1\n"
828+
829+ /* Restore all general-purpose registers */
830+ "lw ra, 0*4(sp)\n"
831+ "lw gp, 1*4(sp)\n"
832+ "lw tp, 2*4(sp)\n"
833+ "lw t0, 3*4(sp)\n"
834+ "lw t1, 4*4(sp)\n"
835+ "lw t2, 5*4(sp)\n"
836+ "lw s0, 6*4(sp)\n"
837+ "lw s1, 7*4(sp)\n"
838+ "lw a0, 8*4(sp)\n"
839+ "lw a1, 9*4(sp)\n"
840+ "lw a2, 10*4(sp)\n"
841+ "lw a3, 11*4(sp)\n"
842+ "lw a4, 12*4(sp)\n"
843+ "lw a5, 13*4(sp)\n"
844+ "lw a6, 14*4(sp)\n"
845+ "lw a7, 15*4(sp)\n"
846+ "lw s2, 16*4(sp)\n"
847+ "lw s3, 17*4(sp)\n"
848+ "lw s4, 18*4(sp)\n"
849+ "lw s5, 19*4(sp)\n"
850+ "lw s6, 20*4(sp)\n"
851+ "lw s7, 21*4(sp)\n"
852+ "lw s8, 22*4(sp)\n"
853+ "lw s9, 23*4(sp)\n"
854+ "lw s10, 24*4(sp)\n"
855+ "lw s11, 25*4(sp)\n"
856+ "lw t3, 26*4(sp)\n"
857+ "lw t4, 27*4(sp)\n"
858+ "lw t5, 28*4(sp)\n"
859+ "lw t6, 29*4(sp)\n"
860+
861+ /* Deallocate stack frame */
862+ "addi sp, sp, %0\n"
863+
864+ /* Return from trap - jump to task entry point */
865+ "mret\n"
866+ :
867+ : "i" (ISR_STACK_FRAME_SIZE )
868+ : "memory" );
869+ }
870+
871+ /* Transfers control from the kernel's main thread to the first task.
872+ * In preemptive mode, ctx should be the ISR frame pointer (void *sp).
873+ * In cooperative mode, ctx should be the jmp_buf context.
874+ */
875+ __attribute__((noreturn )) void hal_dispatch_init (void * ctx )
876+ {
877+ if (unlikely (!ctx ))
810878 hal_panic (); /* Cannot proceed without valid context */
811879
812- if (kcb -> preemptive )
813- hal_timer_enable ();
880+ if (kcb -> preemptive ) {
881+ /* Preemptive mode: ctx is ISR frame pointer, restore from it.
882+ * Enable timer before jumping to task. Global interrupts will be
883+ * enabled by mret based on MPIE bit in restored mstatus.
884+ */
885+ /* Save ctx before hal_timer_enable modifies registers */
886+ void * saved_ctx = ctx ;
814887
815- _ei (); /* Enable global interrupts just before launching the first task */
888+ hal_timer_enable ();
816889
817- asm volatile (
818- "mv a0, %0\n" /* Move @env (the task's context) into 'a0' */
819- "call __dispatch_init\n" /* Call the low-level restore routine */
820- :
821- : "r" (env )
822- : "a0" , "memory" );
890+ /* Restore ISR frame pointer and call dispatch */
891+ asm volatile (
892+ "mv a0, %0\n" /* Load ISR frame pointer into a0 */
893+ "call __dispatch_init_isr\n" /* Restore from ISR frame */
894+ :
895+ : "r" (saved_ctx )
896+ : "a0" , "memory" );
897+ } else {
898+ /* Cooperative mode: ctx is jmp_buf, use standard dispatch */
899+ _ei (); /* Enable global interrupts */
900+
901+ asm volatile (
902+ "mv a0, %0\n" /* Move @env (the task's context) into 'a0' */
903+ "call __dispatch_init\n" /* Call the low-level restore routine */
904+ :
905+ : "r" (ctx )
906+ : "a0" , "memory" );
907+ }
823908 __builtin_unreachable ();
824909}
825910
@@ -876,6 +961,8 @@ void hal_context_init(jmp_buf *ctx,
876961 */
877962 (* ctx )[CONTEXT_SP ] = (uint32_t ) stack_top ;
878963 (* ctx )[CONTEXT_RA ] = (uint32_t ) ra ;
879- (* ctx )[CONTEXT_MSTATUS ] = MSTATUS_MIE | MSTATUS_MPIE |
880- (user_mode ? MSTATUS_MPP_USER : MSTATUS_MPP_MACH );
964+ /* Note: CONTEXT_MSTATUS not used in cooperative mode (setjmp/longjmp),
965+ * but set it for consistency with ISR frame initialization */
966+ (* ctx )[CONTEXT_MSTATUS ] =
967+ MSTATUS_MPIE | (user_mode ? MSTATUS_MPP_USER : MSTATUS_MPP_MACH );
881968}
0 commit comments