--- /dev/null
+#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 */
--- /dev/null
+#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__ */
#include "errno.h"
#include "hal/cpu.h"
#include "hal/usermode.h"
+#include "arch_process.h"
#include <stddef.h>
struct process* current_process = NULL;
}
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;
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 */
}
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;
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;