diff --git a/Kernel/Arch/x86/common/Processor.cpp b/Kernel/Arch/x86/common/Processor.cpp index cbff6fcdb7..60947f8734 100644 --- a/Kernel/Arch/x86/common/Processor.cpp +++ b/Kernel/Arch/x86/common/Processor.cpp @@ -39,6 +39,7 @@ Atomic Processor::s_idle_cpu_mask { 0 }; extern "C" void thread_context_first_enter(void); extern "C" void exit_kernel_thread(void); +extern "C" void do_assume_context(Thread* thread, u32 flags); // The compiler can't see the calls to these functions inside assembly. // Declare them, to avoid dead code warnings. @@ -1233,4 +1234,20 @@ extern "C" FlatPtr do_init_context(Thread* thread, u32 flags) #endif return Processor::current().init_context(*thread, true); } + +void Processor::assume_context(Thread& thread, FlatPtr flags) +{ + dbgln_if(CONTEXT_SWITCH_DEBUG, "Assume context for thread {} {}", VirtualAddress(&thread), thread); + + VERIFY_INTERRUPTS_DISABLED(); + Scheduler::prepare_after_exec(); + // in_critical() should be 2 here. The critical section in Process::exec + // and then the scheduler lock + VERIFY(Processor::current().in_critical() == 2); + + do_assume_context(&thread, flags); + + VERIFY_NOT_REACHED(); +} + } diff --git a/Kernel/Arch/x86/i386/Processor.cpp b/Kernel/Arch/x86/i386/Processor.cpp index af5d14d93d..801d928bd2 100644 --- a/Kernel/Arch/x86/i386/Processor.cpp +++ b/Kernel/Arch/x86/i386/Processor.cpp @@ -17,7 +17,6 @@ namespace Kernel { #define ENTER_THREAD_CONTEXT_ARGS_SIZE (2 * 4) // to_thread, from_thread extern "C" void thread_context_first_enter(void); -extern "C" void do_assume_context(Thread* thread, u32 flags); extern "C" void exit_kernel_thread(void); // clang-format off @@ -236,21 +235,6 @@ void Processor::switch_context(Thread*& from_thread, Thread*& to_thread) Processor::current().restore_in_critical(to_thread->saved_critical()); } -void Processor::assume_context(Thread& thread, FlatPtr flags) -{ - dbgln_if(CONTEXT_SWITCH_DEBUG, "Assume context for thread {} {}", VirtualAddress(&thread), thread); - - VERIFY_INTERRUPTS_DISABLED(); - Scheduler::prepare_after_exec(); - // in_critical() should be 2 here. The critical section in Process::exec - // and then the scheduler lock - VERIFY(Processor::current().in_critical() == 2); - - do_assume_context(&thread, flags); - - VERIFY_NOT_REACHED(); -} - UNMAP_AFTER_INIT void Processor::initialize_context_switching(Thread& initial_thread) { VERIFY(initial_thread.process().is_kernel_process()); diff --git a/Kernel/Arch/x86/x86_64/Processor.cpp b/Kernel/Arch/x86/x86_64/Processor.cpp index ccf46873b3..acb409b8b8 100644 --- a/Kernel/Arch/x86/x86_64/Processor.cpp +++ b/Kernel/Arch/x86/x86_64/Processor.cpp @@ -16,7 +16,6 @@ namespace Kernel { extern "C" void thread_context_first_enter(void); -extern "C" void do_assume_context(Thread* thread, u32 flags); extern "C" void exit_kernel_thread(void); // clang-format off @@ -50,6 +49,8 @@ asm( " movq %rax, %rsp \n" // move stack pointer to what Processor::init_context set up for us " movq %r12, %rdi \n" // to_thread " movq %r12, %rsi \n" // from_thread +" pushq %r12 \n" // to_thread (for thread_context_first_enter) +" pushq %r12 \n" // from_thread (for thread_context_first_enter) " movabs $thread_context_first_enter, %r12 \n" // should be same as regs.rip " pushq %r12 \n" " jmp enter_thread_context \n" @@ -238,22 +239,6 @@ void Processor::switch_context(Thread*& from_thread, Thread*& to_thread) Processor::current().restore_in_critical(to_thread->saved_critical()); } -void Processor::assume_context(Thread& thread, FlatPtr flags) -{ - dbgln_if(CONTEXT_SWITCH_DEBUG, "Assume context for thread {} {}", VirtualAddress(&thread), thread); - - VERIFY_INTERRUPTS_DISABLED(); - Scheduler::prepare_after_exec(); - // in_critical() should be 2 here. The critical section in Process::exec - // and then the scheduler lock - VERIFY(Processor::current().in_critical() == 2); - - (void)flags; - TODO(); - - VERIFY_NOT_REACHED(); -} - UNMAP_AFTER_INIT void Processor::initialize_context_switching(Thread& initial_thread) { VERIFY(initial_thread.process().is_kernel_process()); diff --git a/Kernel/Syscalls/fork.cpp b/Kernel/Syscalls/fork.cpp index 1a819f7dd9..1021233f03 100644 --- a/Kernel/Syscalls/fork.cpp +++ b/Kernel/Syscalls/fork.cpp @@ -66,8 +66,29 @@ KResultOr Process::sys$fork(RegisterState& regs) dbgln_if(FORK_DEBUG, "fork: child will begin executing at {:04x}:{:08x} with stack {:04x}:{:08x}, kstack {:04x}:{:08x}", child_regs.cs, child_regs.eip, child_regs.ss, child_regs.esp, child_regs.ss0, child_regs.esp0); #else - (void)regs; - PANIC("Process::sys$fork() not implemented."); + auto& child_regs = child_first_thread->m_regs; + child_regs.rax = 0; // fork() returns 0 in the child :^) + child_regs.rbx = regs.rbx; + child_regs.rcx = regs.rcx; + child_regs.rdx = regs.rdx; + child_regs.rbp = regs.rbp; + child_regs.rsp = regs.userspace_rsp; + child_regs.rsi = regs.rsi; + child_regs.rdi = regs.rdi; + child_regs.r8 = regs.r8; + child_regs.r9 = regs.r9; + child_regs.r10 = regs.r10; + child_regs.r11 = regs.r11; + child_regs.r12 = regs.r12; + child_regs.r13 = regs.r13; + child_regs.r14 = regs.r14; + child_regs.r15 = regs.r15; + child_regs.rflags = regs.rflags; + child_regs.rip = regs.rip; + child_regs.cs = regs.cs; + + dbgln_if(FORK_DEBUG, "fork: child will begin executing at {:04x}:{:16x} with stack {:08x}, kstack {:08x}", + child_regs.cs, child_regs.rip, child_regs.rsp, child_regs.rsp0); #endif {