]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
refactor: extract x86 kernel stack setup and register accessors from scheduler to...
authorTulio A M Mendes <[email protected]>
Fri, 13 Feb 2026 00:29:02 +0000 (21:29 -0300)
committerTulio A M Mendes <[email protected]>
Fri, 13 Feb 2026 02:44:55 +0000 (23:44 -0300)
- New include/arch_process.h: arch-agnostic prototypes for arch_kstack_init(),
  arch_regs_set_retval(), arch_regs_set_ustack()
- New src/arch/x86/arch_process.c: x86 implementation (EFLAGS 0x202, cdecl
  stack frame layout matching context_switch in process.S)
- scheduler.c: process_create_kernel, process_fork_create, process_clone_create
  now use arch_kstack_init() instead of inline x86 stack manipulation
- scheduler.c: process_clone_create uses arch_regs_set_retval/arch_regs_set_ustack
  instead of direct .eax/.useresp access

No x86-specific constants or register names remain in scheduler.c.

.gitignore
include/arch_process.h [new file with mode: 0644]
src/arch/x86/arch_process.c [new file with mode: 0644]
src/kernel/scheduler.c

index d541280a5b39d4bb5d6dc2464bfee4fa0dd6bdd3..1beace5600ab18b9cd9734233e53137981f28bb2 100644 (file)
@@ -38,3 +38,4 @@ supplementary-material
 *.swp
 *~
 third_party/
+user/doom/doomgeneric
diff --git a/include/arch_process.h b/include/arch_process.h
new file mode 100644 (file)
index 0000000..424ece9
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef ARCH_PROCESS_H
+#define ARCH_PROCESS_H
+
+#include <stdint.h>
+#include "interrupts.h"
+
+/*
+ * arch_kstack_init — Prepare a kernel stack for a brand-new process/thread
+ *                    so that context_switch will resume into wrapper(arg).
+ *
+ * stack_top  : pointer to the TOP of the kernel stack (base + size).
+ * wrapper    : function that context_switch's "ret" will jump to
+ *              (e.g. thread_wrapper).
+ * arg        : argument passed to wrapper (e.g. actual entry point or
+ *              fork_child_trampoline).
+ *
+ * Returns the initial SP value to store in proc->sp.
+ */
+uintptr_t arch_kstack_init(void* stack_top,
+                            void (*wrapper)(void (*)(void)),
+                            void (*arg)(void));
+
+/*
+ * Set the "return value" register in a saved trapframe.
+ * On x86 this is EAX; on ARM it would be R0, etc.
+ */
+void arch_regs_set_retval(struct registers* regs, uint32_t val);
+
+/*
+ * Set the user-mode stack pointer in a saved trapframe.
+ * On x86 this is useresp; on ARM it would be SP_usr, etc.
+ */
+void arch_regs_set_ustack(struct registers* regs, uintptr_t sp);
+
+#endif /* ARCH_PROCESS_H */
diff --git a/src/arch/x86/arch_process.c b/src/arch/x86/arch_process.c
new file mode 100644 (file)
index 0000000..08c9f7e
--- /dev/null
@@ -0,0 +1,52 @@
+#include "arch_process.h"
+#include "arch/x86/idt.h"
+
+#if defined(__i386__)
+
+/*
+ * x86 kernel stack layout expected by context_switch (process.S):
+ *
+ *   context_switch saves:  pushf, push edi, esi, ebx, ebp
+ *   context_switch restores: popf, pop edi, esi, ebx, ebp, ret
+ *
+ * So for a NEW process we build a fake frame that context_switch will
+ * "restore":
+ *
+ *   sp -> [EFLAGS  0x202]   <- popf  (IF=1, reserved bit 1)
+ *         [EDI     0]       <- pop edi
+ *         [ESI     0]       <- pop esi
+ *         [EBX     0]       <- pop ebx
+ *         [EBP     0]       <- pop ebp
+ *         [wrapper addr]    <- ret jumps here
+ *         [0  (fake retaddr for wrapper)]
+ *         [arg]             <- first argument to wrapper (cdecl)
+ */
+uintptr_t arch_kstack_init(void* stack_top,
+                            void (*wrapper)(void (*)(void)),
+                            void (*arg)(void))
+{
+    uint32_t* sp = (uint32_t*)stack_top;
+
+    *--sp = (uint32_t)(uintptr_t)arg;       /* argument for wrapper */
+    *--sp = 0;                               /* fake return address  */
+    *--sp = (uint32_t)(uintptr_t)wrapper;    /* ret target           */
+    *--sp = 0;                               /* EBP                  */
+    *--sp = 0;                               /* EBX                  */
+    *--sp = 0;                               /* ESI                  */
+    *--sp = 0;                               /* EDI                  */
+    *--sp = 0x202;                           /* EFLAGS: IF=1         */
+
+    return (uintptr_t)sp;
+}
+
+void arch_regs_set_retval(struct registers* regs, uint32_t val)
+{
+    if (regs) regs->eax = val;
+}
+
+void arch_regs_set_ustack(struct registers* regs, uintptr_t sp)
+{
+    if (regs) regs->useresp = (uint32_t)sp;
+}
+
+#endif /* __i386__ */
index ae87d434497f7edc61b0d1f9e14e7cb8ba52eb12..a77b0b4d8cdd673e52cfbbbce58db00f2c718de0 100644 (file)
@@ -9,6 +9,7 @@
 #include "errno.h"
 #include "hal/cpu.h"
 #include "hal/usermode.h"
+#include "arch_process.h"
 #include <stddef.h>
 
 struct process* current_process = NULL;
@@ -446,13 +447,8 @@ struct process* process_fork_create(uintptr_t child_as, const struct registers*
     }
     proc->kernel_stack = (uint32_t*)stack;
 
-    uint32_t* sp = (uint32_t*)((uint8_t*)stack + 4096);
-    *--sp = (uint32_t)fork_child_trampoline;
-    *--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->sp = arch_kstack_init((uint8_t*)stack + 4096,
+                                  thread_wrapper, fork_child_trampoline);
 
     proc->next = ready_queue_head;
     proc->prev = ready_queue_tail;
@@ -574,11 +570,11 @@ struct process* process_clone_create(uint32_t clone_flags,
 
     proc->has_user_regs = 1;
     proc->user_regs = *child_regs;
-    proc->user_regs.eax = 0; /* child returns 0 */
+    arch_regs_set_retval(&proc->user_regs, 0); /* child returns 0 */
 
-    /* If child_stack specified, override ESP */
+    /* If child_stack specified, override user stack pointer */
     if (child_stack) {
-        proc->user_regs.useresp = (uint32_t)child_stack;
+        arch_regs_set_ustack(&proc->user_regs, child_stack);
     }
 
     /* Allocate kernel stack */
@@ -593,13 +589,8 @@ struct process* process_clone_create(uint32_t clone_flags,
     }
     proc->kernel_stack = (uint32_t*)kstack;
 
-    uint32_t* sp = (uint32_t*)((uint8_t*)kstack + 4096);
-    *--sp = (uint32_t)clone_child_trampoline;
-    *--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->sp = arch_kstack_init((uint8_t*)kstack + 4096,
+                                  thread_wrapper, clone_child_trampoline);
 
     /* Insert into process list */
     proc->next = ready_queue_head;
@@ -742,15 +733,8 @@ struct process* process_create_kernel(void (*entry_point)(void)) {
 
     proc->kernel_stack = (uint32_t*)stack;
     
-    uint32_t* sp = (uint32_t*)((uint8_t*)stack + 4096);
-    
-    *--sp = (uint32_t)entry_point;
-    *--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->sp = arch_kstack_init((uint8_t*)stack + 4096,
+                                  thread_wrapper, entry_point);
 
     proc->next = ready_queue_head;
     proc->prev = ready_queue_tail;