From 0dd74e3c9dc9e808c3fda88967417d0d5fdd017e Mon Sep 17 00:00:00 2001 From: Bananymous Date: Wed, 3 Apr 2024 02:23:23 +0300 Subject: [PATCH] Kernel: Implement syscalls for i686 and cleanup x86_64 This actually allows i686 to boot properly! --- kernel/arch/i686/Syscall.S | 28 ++++++++++++++++++-------- kernel/arch/i686/Thread.S | 36 ++++++++++++++++++++++++++++++++- kernel/arch/i686/interrupts.S | 38 ++++++++++++++++++++++------------- kernel/arch/x86_64/Syscall.S | 13 ++++++++++-- kernel/arch/x86_64/Thread.S | 4 ++-- kernel/kernel/Syscall.cpp | 4 ++-- kernel/kernel/Thread.cpp | 10 +++++++-- libc/arch/i686/crt0.S | 35 ++++++++++++++++---------------- 8 files changed, 120 insertions(+), 48 deletions(-) diff --git a/kernel/arch/i686/Syscall.S b/kernel/arch/i686/Syscall.S index 39f89201..7a31dcd1 100644 --- a/kernel/arch/i686/Syscall.S +++ b/kernel/arch/i686/Syscall.S @@ -1,19 +1,31 @@ .global sys_fork_trampoline sys_fork_trampoline: - ud2 - subl $4, %esp - pushl %ebx pushl %ebp + pushl %ebx + pushl %esi + pushl %edi + call read_ip testl %eax, %eax - je .done + jz .reload_stack + + movl %esp, %ebx + subl $8, %esp pushl %eax - pushl %esp + pushl %ebx call sys_fork addl $16, %esp -.done: - popl %ebp + + .done: + popl %edi + popl %esi popl %ebx - addl $4, %esp + popl %ebp ret + + .reload_stack: + call get_thread_start_sp + movl %eax, %esp + xorl %eax, %eax + jmp .done diff --git a/kernel/arch/i686/Thread.S b/kernel/arch/i686/Thread.S index c6f78c89..ef8dd7d7 100644 --- a/kernel/arch/i686/Thread.S +++ b/kernel/arch/i686/Thread.S @@ -7,7 +7,7 @@ read_ip: # void start_kernel_thread() .global start_kernel_thread start_kernel_thread: - call get_start_kernel_thread_sp + call get_thread_start_sp movl %eax, %esp # STACK LAYOUT @@ -32,3 +32,37 @@ start_kernel_thread: pushl %edi call *%esi addl $16, %esp + + +.global start_userspace_thread +start_userspace_thread: + call get_thread_start_sp + movl %eax, %esp + + # STACK LAYOUT + # entry + # argc + # argv + # envp + # userspace stack + + call get_userspace_thread_stack_top + + movw $(0x20 | 3), %bx + movw %bx, %ds + movw %bx, %es + movw %bx, %fs + movw %bx, %gs + xorw %bx, %bx + + popl %edx + popl %esi + popl %edi + popl %ecx + + pushl $(0x20 | 3) + pushl %eax + pushl $0x202 + pushl $(0x18 | 3) + pushl %ecx + iret diff --git a/kernel/arch/i686/interrupts.S b/kernel/arch/i686/interrupts.S index 60dd8b80..9328ad1f 100644 --- a/kernel/arch/i686/interrupts.S +++ b/kernel/arch/i686/interrupts.S @@ -24,6 +24,22 @@ popw %gs .endm +.macro pop_userspace_skip_eax + popl %edi + popl %esi + popl %ebp + addl $4, %esp + popl %ebx + popl %edx + popl %ecx + addl $4, %esp + + popw %ds + popw %es + popw %fs + popw %gs +.endm + isr_stub: push_userspace load_kernel_segments @@ -85,11 +101,12 @@ asm_reschedule_handler: // arguments in EAX, EBX, ECX, EDX, ESI, EDI .global syscall_asm syscall_asm: - ud2 - pusha + push_userspace + + subl $8, %esp pushl %esp - addl $36, (%esp) + addl $48, (%esp) pushl %edi pushl %esi @@ -98,19 +115,12 @@ syscall_asm: pushl %ebx pushl %eax + load_kernel_segments + call cpp_syscall_handler + addl $36, %esp - addl $60, %esp - - popl %edi - popl %esi - popl %ebp - addl $4, %esp - popl %ebx - popl %edx - popl %ecx - addl $4, %esp - + pop_userspace_skip_eax iret .macro isr n diff --git a/kernel/arch/x86_64/Syscall.S b/kernel/arch/x86_64/Syscall.S index 45c16560..91cc85fd 100644 --- a/kernel/arch/x86_64/Syscall.S +++ b/kernel/arch/x86_64/Syscall.S @@ -6,13 +6,16 @@ sys_fork_trampoline: pushq %r13 pushq %r14 pushq %r15 + call read_ip testq %rax, %rax - je .done + je .reload_stack + movq %rax, %rsi movq %rsp, %rdi call sys_fork -.done: + + .done: popq %r15 popq %r14 popq %r13 @@ -20,3 +23,9 @@ sys_fork_trampoline: popq %rbp popq %rbx ret + + .reload_stack: + call get_thread_start_sp + movq %rax, %rsp + xorq %rax, %rax + jmp .done diff --git a/kernel/arch/x86_64/Thread.S b/kernel/arch/x86_64/Thread.S index ad307709..a1757157 100644 --- a/kernel/arch/x86_64/Thread.S +++ b/kernel/arch/x86_64/Thread.S @@ -7,7 +7,7 @@ read_ip: # void start_kernel_thread() .global start_kernel_thread start_kernel_thread: - call get_start_kernel_thread_sp + call get_thread_start_sp movq %rax, %rsp # STACK LAYOUT @@ -27,7 +27,7 @@ start_kernel_thread: .global start_userspace_thread start_userspace_thread: - call get_start_kernel_thread_sp + call get_thread_start_sp movq %rax, %rsp # STACK LAYOUT diff --git a/kernel/kernel/Syscall.cpp b/kernel/kernel/Syscall.cpp index 22ca55e1..ab979b68 100644 --- a/kernel/kernel/Syscall.cpp +++ b/kernel/kernel/Syscall.cpp @@ -28,9 +28,9 @@ namespace Kernel #undef O }; - extern "C" long cpp_syscall_handler(int syscall, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, InterruptStack& interrupt_stack) + extern "C" long cpp_syscall_handler(int syscall, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, InterruptStack* interrupt_stack) { - ASSERT((interrupt_stack.cs & 0b11) == 0b11); + ASSERT(GDT::is_user_segment(interrupt_stack->cs)); asm volatile("sti"); diff --git a/kernel/kernel/Thread.cpp b/kernel/kernel/Thread.cpp index 06041d06..12fd4589 100644 --- a/kernel/kernel/Thread.cpp +++ b/kernel/kernel/Thread.cpp @@ -24,9 +24,9 @@ namespace Kernel *(uintptr_t*)rsp = (uintptr_t)value; } - extern "C" uintptr_t get_start_kernel_thread_sp() + extern "C" uintptr_t get_thread_start_sp() { - return Thread::current().kernel_stack_top() - 4 * sizeof(uintptr_t); + return Thread::current().interrupt_stack().sp; } extern "C" uintptr_t get_userspace_thread_stack_top() @@ -192,6 +192,12 @@ namespace Kernel thread->m_interrupt_stack.sp = sp; thread->m_interrupt_stack.ss = 0x10; +#if ARCH(x86_64) + thread->m_interrupt_registers.rax = 0; +#elif ARCH(i686) + thread->m_interrupt_registers.eax = 0; +#endif + thread_deleter.disable(); return thread; diff --git a/libc/arch/i686/crt0.S b/libc/arch/i686/crt0.S index 66678945..d44ffdce 100644 --- a/libc/arch/i686/crt0.S +++ b/libc/arch/i686/crt0.S @@ -2,31 +2,32 @@ .global _start _start: - # zero out stack frame pushl $0 - pushl $0 - movl %esp, %ebp - - # FIXME: handle stack alignment - ud2 - - # push argc, argv, environ for call to main - pushl %edx - pushl %esi pushl %edi - - # initialize libc + pushl %esi pushl %edx - call _init_libc - addl $4, %esp - # call global constructos + # STACK LAYOUT + # null + # argc + # argv + # envp + + xorl %ebp, %ebp + + # init libc (envp already as argument) + call _init_libc + + # call global constructors call _init - # call main, arguments are already on stack + # call main + movl 0(%esp), %eax + xchgl %eax, 8(%esp) + movl %eax, (%esp) call main - # cleanly exit the process + subl $12, %esp pushl %eax call exit