From: Tulio A M Mendes Date: Thu, 12 Feb 2026 06:21:08 +0000 (-0300) Subject: fix: save/restore EFLAGS in context_switch instead of forcing sti after schedule() X-Git-Url: https://projects.tadryanom.me/docs/static/gitweb.js?a=commitdiff_plain;h=9dadf00e8747fa97b3df43f5de6c8e12224b96bc;p=AdrOS.git fix: save/restore EFLAGS in context_switch instead of forcing sti after schedule() context_switch now uses pushf/popf to properly save and restore the EFLAGS register (including the IF bit) across context switches. This replaces the unconditional hal_cpu_enable_interrupts() call after context_switch in schedule(), which broke the interrupt-state semantics for callers that needed atomicity. All process creation functions (fork, clone, kernel thread) now push EFLAGS=0x202 (IF=1) onto the initial stack so new processes start with interrupts enabled via popf in context_switch. --- diff --git a/src/arch/x86/process.S b/src/arch/x86/process.S index b1528a9..df6d3f5 100644 --- a/src/arch/x86/process.S +++ b/src/arch/x86/process.S @@ -11,19 +11,20 @@ context_switch: push %ebx push %esi push %edi + pushf /* Save EFLAGS (including IF) */ /* 2. Save the old ESP */ - /* Get the location of old_esp_ptr. - Stack is: [RetAddr] [old_esp_ptr] [new_esp] - ESP points to EDI (last push) */ + /* Stack is: [RetAddr] [old_esp_ptr] [new_esp] + 5 pushes (20 bytes) + ESP points to EFLAGS (last push) */ - mov 20(%esp), %eax /* EAX = old_esp_ptr */ + mov 24(%esp), %eax /* EAX = old_esp_ptr */ mov %esp, (%eax) /* *old_esp_ptr = ESP */ /* 3. Switch to the NEW process stack */ - mov 24(%esp), %esp /* ESP = new_esp */ + mov 28(%esp), %esp /* ESP = new_esp */ /* 4. Restore state of the NEW process */ + popf /* Restore EFLAGS (including IF) from saved context */ pop %edi pop %esi pop %ebx diff --git a/src/kernel/scheduler.c b/src/kernel/scheduler.c index 654f07d..766c49d 100644 --- a/src/kernel/scheduler.c +++ b/src/kernel/scheduler.c @@ -406,6 +406,7 @@ struct process* process_fork_create(uintptr_t child_as, const struct registers* *--sp = 0; *--sp = (uint32_t)thread_wrapper; *--sp = 0; *--sp = 0; *--sp = 0; *--sp = 0; + *--sp = 0x202; /* EFLAGS: IF=1, reserved bit 1 */ proc->sp = (uintptr_t)sp; proc->next = ready_queue_head; @@ -559,6 +560,7 @@ struct process* process_clone_create(uint32_t clone_flags, *--sp = 0; *--sp = (uint32_t)thread_wrapper; *--sp = 0; *--sp = 0; *--sp = 0; *--sp = 0; + *--sp = 0x202; /* EFLAGS: IF=1, reserved bit 1 */ proc->sp = (uintptr_t)sp; /* Insert into process list */ @@ -700,6 +702,7 @@ struct process* process_create_kernel(void (*entry_point)(void)) { *--sp = 0; *--sp = (uint32_t)thread_wrapper; *--sp = 0; *--sp = 0; *--sp = 0; *--sp = 0; + *--sp = 0x202; /* EFLAGS: IF=1, reserved bit 1 */ proc->sp = (uintptr_t)sp; @@ -798,7 +801,8 @@ void schedule(void) { context_switch(&prev->sp, current_process->sp); - hal_cpu_enable_interrupts(); + /* EFLAGS (including IF) is now restored by context_switch via popf, + * so we no longer force-enable interrupts here. */ } void process_sleep(uint32_t ticks) {