Kernel: Implement thread start trampoline for userspace

This is needed on i686 to set segment registers.
This commit is contained in:
Bananymous 2024-04-03 00:42:39 +03:00
parent 4d70322eab
commit fe386fa819
4 changed files with 49 additions and 12 deletions

View File

@ -24,3 +24,29 @@ start_kernel_thread:
movq 24(%rsp), %rdi movq 24(%rsp), %rdi
movq 16(%rsp), %rsi movq 16(%rsp), %rsi
call *%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

View File

@ -29,11 +29,6 @@ namespace Kernel
return *s_instance; 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() void Scheduler::start()
{ {
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled); ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);

View File

@ -13,6 +13,7 @@ namespace Kernel
{ {
extern "C" [[noreturn]] void start_kernel_thread(); extern "C" [[noreturn]] void start_kernel_thread();
extern "C" [[noreturn]] void start_userspace_thread();
extern "C" void signal_trampoline(); extern "C" void signal_trampoline();
@ -23,6 +24,16 @@ namespace Kernel
*(uintptr_t*)rsp = (uintptr_t)value; *(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; static pid_t s_next_tid = 1;
BAN::ErrorOr<Thread*> Thread::create_kernel(entry_t entry, void* data, Process* process) BAN::ErrorOr<Thread*> Thread::create_kernel(entry_t entry, void* data, Process* process)
@ -197,19 +208,19 @@ namespace Kernel
ASSERT(userspace_info.entry); ASSERT(userspace_info.entry);
// Initialize stack for returning // 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; 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.argc);
write_to_stack(sp, userspace_info.argv); write_to_stack(sp, userspace_info.argv);
write_to_stack(sp, userspace_info.envp); write_to_stack(sp, userspace_info.envp);
}); });
m_interrupt_stack.ip = userspace_info.entry; m_interrupt_stack.ip = reinterpret_cast<vaddr_t>(start_userspace_thread);;
m_interrupt_stack.cs = 0x18 | 3; m_interrupt_stack.cs = 0x08;
m_interrupt_stack.flags = 0x202; m_interrupt_stack.flags = 0x002;
m_interrupt_stack.sp = userspace_stack_top() - 4 * sizeof(uintptr_t); m_interrupt_stack.sp = kernel_stack_top() - 4 * sizeof(uintptr_t);
m_interrupt_stack.ss = 0x20 | 3; m_interrupt_stack.ss = 0x10;
memset(&m_interrupt_registers, 0, sizeof(InterruptRegisters)); memset(&m_interrupt_registers, 0, sizeof(InterruptRegisters));
} }

View File

@ -2,6 +2,11 @@
.global _start .global _start
_start: _start:
pushq $0
pushq %rdi
pushq %rsi
pushq %rdx
# STACK LAYOUT # STACK LAYOUT
# null # null
# argc # argc