From fe386fa819d4f62bd9d895bd4945617842bf7456 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Wed, 3 Apr 2024 00:42:39 +0300 Subject: [PATCH] Kernel: Implement thread start trampoline for userspace This is needed on i686 to set segment registers. --- kernel/arch/x86_64/Thread.S | 26 ++++++++++++++++++++++++++ kernel/kernel/Scheduler.cpp | 5 ----- kernel/kernel/Thread.cpp | 25 ++++++++++++++++++------- libc/arch/x86_64/crt0.S | 5 +++++ 4 files changed, 49 insertions(+), 12 deletions(-) diff --git a/kernel/arch/x86_64/Thread.S b/kernel/arch/x86_64/Thread.S index 46eea1b08b..ad30770977 100644 --- a/kernel/arch/x86_64/Thread.S +++ b/kernel/arch/x86_64/Thread.S @@ -24,3 +24,29 @@ start_kernel_thread: movq 24(%rsp), %rdi movq 16(%rsp), %rsi call *%rsi + +.global start_userspace_thread +start_userspace_thread: + call get_start_kernel_thread_sp + movq %rax, %rsp + + # STACK LAYOUT + # entry + # argc + # argv + # envp + # userspace stack + + call get_userspace_thread_stack_top + + popq %rdx + popq %rsi + popq %rdi + popq %rcx + + pushq $(0x20 | 3) + pushq %rax + pushq $0x202 + pushq $(0x18 | 3) + pushq %rcx + iretq diff --git a/kernel/kernel/Scheduler.cpp b/kernel/kernel/Scheduler.cpp index 0031c9ba5d..0f0ff63bd9 100644 --- a/kernel/kernel/Scheduler.cpp +++ b/kernel/kernel/Scheduler.cpp @@ -29,11 +29,6 @@ namespace Kernel return *s_instance; } - extern "C" uintptr_t get_start_kernel_thread_sp() - { - return Scheduler::get().current_thread().kernel_stack_top() - 4 * sizeof(uintptr_t); - } - void Scheduler::start() { ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled); diff --git a/kernel/kernel/Thread.cpp b/kernel/kernel/Thread.cpp index c75dfc2f3d..06041d06cd 100644 --- a/kernel/kernel/Thread.cpp +++ b/kernel/kernel/Thread.cpp @@ -13,6 +13,7 @@ namespace Kernel { extern "C" [[noreturn]] void start_kernel_thread(); + extern "C" [[noreturn]] void start_userspace_thread(); extern "C" void signal_trampoline(); @@ -23,6 +24,16 @@ namespace Kernel *(uintptr_t*)rsp = (uintptr_t)value; } + extern "C" uintptr_t get_start_kernel_thread_sp() + { + return Thread::current().kernel_stack_top() - 4 * sizeof(uintptr_t); + } + + extern "C" uintptr_t get_userspace_thread_stack_top() + { + return Thread::current().userspace_stack_top() - 4 * sizeof(uintptr_t); + } + static pid_t s_next_tid = 1; BAN::ErrorOr Thread::create_kernel(entry_t entry, void* data, Process* process) @@ -197,19 +208,19 @@ namespace Kernel ASSERT(userspace_info.entry); // Initialize stack for returning - PageTable::with_fast_page(process().page_table().physical_address_of(userspace_stack_top() - PAGE_SIZE), [&] { + PageTable::with_fast_page(process().page_table().physical_address_of(kernel_stack_top() - PAGE_SIZE), [&] { uintptr_t sp = PageTable::fast_page() + PAGE_SIZE; - write_to_stack(sp, nullptr); + write_to_stack(sp, userspace_info.entry); write_to_stack(sp, userspace_info.argc); write_to_stack(sp, userspace_info.argv); write_to_stack(sp, userspace_info.envp); }); - m_interrupt_stack.ip = userspace_info.entry; - m_interrupt_stack.cs = 0x18 | 3; - m_interrupt_stack.flags = 0x202; - m_interrupt_stack.sp = userspace_stack_top() - 4 * sizeof(uintptr_t); - m_interrupt_stack.ss = 0x20 | 3; + m_interrupt_stack.ip = reinterpret_cast(start_userspace_thread);; + m_interrupt_stack.cs = 0x08; + m_interrupt_stack.flags = 0x002; + m_interrupt_stack.sp = kernel_stack_top() - 4 * sizeof(uintptr_t); + m_interrupt_stack.ss = 0x10; memset(&m_interrupt_registers, 0, sizeof(InterruptRegisters)); } diff --git a/libc/arch/x86_64/crt0.S b/libc/arch/x86_64/crt0.S index 474a8bf4d4..e4176a9fa5 100644 --- a/libc/arch/x86_64/crt0.S +++ b/libc/arch/x86_64/crt0.S @@ -2,6 +2,11 @@ .global _start _start: + pushq $0 + pushq %rdi + pushq %rsi + pushq %rdx + # STACK LAYOUT # null # argc