mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 14:57:35 +00:00
Kernel: Add x86_64 support for fork()
This commit is contained in:
parent
811f9d562d
commit
df9e73de25
4 changed files with 42 additions and 35 deletions
|
@ -39,6 +39,7 @@ Atomic<u32> Processor::s_idle_cpu_mask { 0 };
|
||||||
|
|
||||||
extern "C" void thread_context_first_enter(void);
|
extern "C" void thread_context_first_enter(void);
|
||||||
extern "C" void exit_kernel_thread(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.
|
// The compiler can't see the calls to these functions inside assembly.
|
||||||
// Declare them, to avoid dead code warnings.
|
// Declare them, to avoid dead code warnings.
|
||||||
|
@ -1233,4 +1234,20 @@ extern "C" FlatPtr do_init_context(Thread* thread, u32 flags)
|
||||||
#endif
|
#endif
|
||||||
return Processor::current().init_context(*thread, true);
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ namespace Kernel {
|
||||||
|
|
||||||
#define ENTER_THREAD_CONTEXT_ARGS_SIZE (2 * 4) // to_thread, from_thread
|
#define ENTER_THREAD_CONTEXT_ARGS_SIZE (2 * 4) // to_thread, from_thread
|
||||||
extern "C" void thread_context_first_enter(void);
|
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);
|
extern "C" void exit_kernel_thread(void);
|
||||||
|
|
||||||
// clang-format off
|
// 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());
|
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)
|
UNMAP_AFTER_INIT void Processor::initialize_context_switching(Thread& initial_thread)
|
||||||
{
|
{
|
||||||
VERIFY(initial_thread.process().is_kernel_process());
|
VERIFY(initial_thread.process().is_kernel_process());
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
extern "C" void thread_context_first_enter(void);
|
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);
|
extern "C" void exit_kernel_thread(void);
|
||||||
|
|
||||||
// clang-format off
|
// 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 %rax, %rsp \n" // move stack pointer to what Processor::init_context set up for us
|
||||||
" movq %r12, %rdi \n" // to_thread
|
" movq %r12, %rdi \n" // to_thread
|
||||||
" movq %r12, %rsi \n" // from_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
|
" movabs $thread_context_first_enter, %r12 \n" // should be same as regs.rip
|
||||||
" pushq %r12 \n"
|
" pushq %r12 \n"
|
||||||
" jmp enter_thread_context \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());
|
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)
|
UNMAP_AFTER_INIT void Processor::initialize_context_switching(Thread& initial_thread)
|
||||||
{
|
{
|
||||||
VERIFY(initial_thread.process().is_kernel_process());
|
VERIFY(initial_thread.process().is_kernel_process());
|
||||||
|
|
|
@ -66,8 +66,29 @@ KResultOr<FlatPtr> Process::sys$fork(RegisterState& regs)
|
||||||
dbgln_if(FORK_DEBUG, "fork: child will begin executing at {:04x}:{:08x} with stack {:04x}:{:08x}, kstack {:04x}:{:08x}",
|
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);
|
child_regs.cs, child_regs.eip, child_regs.ss, child_regs.esp, child_regs.ss0, child_regs.esp0);
|
||||||
#else
|
#else
|
||||||
(void)regs;
|
auto& child_regs = child_first_thread->m_regs;
|
||||||
PANIC("Process::sys$fork() not implemented.");
|
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
|
#endif
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue