diff --git a/kernel/arch/i686/Thread.S b/kernel/arch/i686/Thread.S index 42fc440071..c6f78c89dc 100644 --- a/kernel/arch/i686/Thread.S +++ b/kernel/arch/i686/Thread.S @@ -4,40 +4,31 @@ read_ip: popl %eax jmp *%eax -# void start_thread(uint32_t sp, uint32_t ip) -.global start_thread -start_thread: - movl 8(%esp), %edi # ip - movl 4(%esp), %esp # sp +# void start_kernel_thread() +.global start_kernel_thread +start_kernel_thread: + call get_start_kernel_thread_sp + movl %eax, %esp # STACK LAYOUT - # NULL - # thread ptr - # &Thread::on_exit - # data + # on_exit arg + # on_exit func + # entry arg + # entry func - xorl %ebp, %ebp + movl 4(%esp), %edi + movl 0(%esp), %esi + subl $12, %esp + pushl %edi sti - call *%edi + call *%esi + addl $16, %esp - movl 4(%esp), %edi # &Thread::on_exit + movl 12(%esp), %edi + movl 8(%esp), %esi - movl 8(%esp), %eax # thread ptr - movl %eax, (%esp) - - call *%edi - - -# void continue_thread(uint32_t sp, uint32_t ip) -.global continue_thread -continue_thread: - movl 8(%esp), %edi # ip - movl 4(%esp), %esp # sp - xorl %eax, %eax - jmp *%edi - -# void thread_userspace_trampoline(uint32_t sp, uint32_t ip, int argc, char** argv, char** envp) -.global thread_userspace_trampoline -thread_userspace_trampoline: - ud2 + subl $12, %esp + pushl %edi + call *%esi + addl $16, %esp diff --git a/kernel/arch/i686/interrupts.S b/kernel/arch/i686/interrupts.S index f48bcab18d..335dd45315 100644 --- a/kernel/arch/i686/interrupts.S +++ b/kernel/arch/i686/interrupts.S @@ -26,17 +26,31 @@ isr_stub: irq_stub: pusha - leal 40(%esp), %eax // interrupt stack ptr - movl 32(%esp), %ebx // irq number + movl 32(%esp), %eax # interrupt number + + subl $8, %esp + pushl %eax + call cpp_irq_handler + addl $12, %esp + + popa + addl $8, %esp + iret + +.global asm_reschedule_handler +asm_reschedule_handler: + pusha + + movl %esp, %eax # interrupt registers ptr + leal 32(%esp), %ebx # interrupt stack ptr subl $12, %esp pushl %eax pushl %ebx - call cpp_irq_handler + call cpp_reschedule_handler addl $20, %esp popa - addl $8, %esp iret // arguments in EAX, EBX, ECX, EDX, ESI, EDI @@ -158,4 +172,3 @@ irq 28 irq 29 irq 30 irq 31 -irq 32 diff --git a/kernel/arch/x86_64/Thread.S b/kernel/arch/x86_64/Thread.S index e7ec70154a..46eea1b08b 100644 --- a/kernel/arch/x86_64/Thread.S +++ b/kernel/arch/x86_64/Thread.S @@ -4,9 +4,12 @@ read_ip: popq %rax jmp *%rax -# void start_thread() +# void start_kernel_thread() .global start_kernel_thread start_kernel_thread: + call get_start_kernel_thread_sp + movq %rax, %rsp + # STACK LAYOUT # on_exit arg # on_exit func @@ -15,6 +18,7 @@ start_kernel_thread: movq 8(%rsp), %rdi movq 0(%rsp), %rsi + sti call *%rsi movq 24(%rsp), %rdi diff --git a/kernel/include/kernel/InterruptStack.h b/kernel/include/kernel/InterruptStack.h index cd91c0fb77..f08581ca91 100644 --- a/kernel/include/kernel/InterruptStack.h +++ b/kernel/include/kernel/InterruptStack.h @@ -14,6 +14,7 @@ namespace Kernel uintptr_t ss; }; +#if ARCH(x86_64) struct InterruptRegisters { uintptr_t r15; @@ -33,5 +34,18 @@ namespace Kernel uintptr_t rcx; uintptr_t rax; }; +#elif ARCH(i686) + struct InterruptRegisters + { + uintptr_t edi; + uintptr_t esi; + uintptr_t ebp; + uintptr_t unused; + uintptr_t ebx; + uintptr_t edx; + uintptr_t ecx; + uintptr_t eax; + }; +#endif } diff --git a/kernel/include/kernel/Thread.h b/kernel/include/kernel/Thread.h index fb3b0d799e..f232bdccc6 100644 --- a/kernel/include/kernel/Thread.h +++ b/kernel/include/kernel/Thread.h @@ -77,7 +77,6 @@ namespace Kernel size_t virtual_page_count() const { return (m_kernel_stack->size() / PAGE_SIZE) + (m_userspace_stack->size() / PAGE_SIZE); } size_t physical_page_count() const { return virtual_page_count(); } - uintptr_t& interrupt_sp() { return m_interrupt_sp; } InterruptStack& interrupt_stack() { return m_interrupt_stack; } InterruptRegisters& interrupt_registers() { return m_interrupt_registers; } @@ -89,6 +88,8 @@ namespace Kernel private: Thread(pid_t tid, Process*); + + static void on_exit_trampoline(Thread*); void on_exit(); private: @@ -104,7 +105,6 @@ namespace Kernel InterruptStack m_interrupt_stack { }; InterruptRegisters m_interrupt_registers { }; - uintptr_t m_interrupt_sp { }; uint64_t m_signal_pending_mask { 0 }; uint64_t m_signal_block_mask { 0 }; diff --git a/kernel/kernel/Scheduler.cpp b/kernel/kernel/Scheduler.cpp index 4e33af3343..0031c9ba5d 100644 --- a/kernel/kernel/Scheduler.cpp +++ b/kernel/kernel/Scheduler.cpp @@ -14,17 +14,6 @@ namespace Kernel static Scheduler* s_instance = nullptr; static BAN::Atomic s_started { false }; - ALWAYS_INLINE static void load_temp_stack() - { -#if ARCH(x86_64) - asm volatile("movq %0, %%rsp" :: "rm"(Processor::current_stack_top())); -#elif ARCH(i686) - asm volatile("movl %0, %%esp" :: "rm"(Processor::current_stack_top())); -#else - #error -#endif - } - BAN::ErrorOr Scheduler::initialize() { ASSERT(s_instance == nullptr); @@ -40,6 +29,11 @@ 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); @@ -86,7 +80,6 @@ namespace Kernel if (thread->state() != Thread::State::NotStarted) { thread->interrupt_stack() = Processor::get_interrupt_stack(); - thread->interrupt_stack().sp = thread->interrupt_sp(); thread->interrupt_registers() = Processor::get_interrupt_registers(); } @@ -155,15 +148,29 @@ namespace Kernel auto state = Processor::get_interrupt_state(); Processor::set_interrupt_state(InterruptState::Disabled); +#if ARCH(x86_64) asm volatile( - "movq %%rsp, %[save_sp];" + "movq %%rsp, %%rcx;" "movq %[load_sp], %%rsp;" "int %[ipi];" - : [save_sp]"=m"(Thread::current().interrupt_sp()) - : [load_sp]"r"(Processor::current_stack_top()), - [ipi]"i"(IRQ_VECTOR_BASE + IRQ_IPI) - : "memory" + "movq %%rcx, %%rsp;" + :: [load_sp]"r"(Processor::current_stack_top()), + [ipi]"i"(IRQ_VECTOR_BASE + IRQ_IPI) + : "memory", "rcx" ); +#elif ARCH(i686) + asm volatile( + "movl %%esp, %%ecx;" + "movl %[load_sp], %%esp;" + "int %[ipi];" + "movl %%ecx, %%esp;" + :: [load_sp]"r"(Processor::current_stack_top()), + [ipi]"i"(IRQ_VECTOR_BASE + IRQ_IPI) + : "memory", "ecx" + ); +#else + #error +#endif Processor::set_interrupt_state(state); } diff --git a/kernel/kernel/Thread.cpp b/kernel/kernel/Thread.cpp index a7ad2e22f9..c75dfc2f3d 100644 --- a/kernel/kernel/Thread.cpp +++ b/kernel/kernel/Thread.cpp @@ -12,19 +12,15 @@ namespace Kernel { - extern "C" [[noreturn]] void start_userspace_thread(); extern "C" [[noreturn]] void start_kernel_thread(); extern "C" void signal_trampoline(); template - static void write_to_stack(uintptr_t& rsp, const T& value) + static void write_to_stack(uintptr_t& rsp, const T& value) requires(sizeof(T) <= sizeof(uintptr_t)) { rsp -= sizeof(uintptr_t); - if constexpr(sizeof(T) < sizeof(uintptr_t)) - *(uintptr_t*)rsp = (uintptr_t)value; - else - memcpy((void*)rsp, (void*)&value, sizeof(uintptr_t)); + *(uintptr_t*)rsp = (uintptr_t)value; } static pid_t s_next_tid = 1; @@ -50,13 +46,13 @@ namespace Kernel // Initialize stack for returning uintptr_t sp = thread->kernel_stack_top(); write_to_stack(sp, thread); - write_to_stack(sp, &Thread::on_exit); + write_to_stack(sp, &Thread::on_exit_trampoline); write_to_stack(sp, data); write_to_stack(sp, entry); thread->m_interrupt_stack.ip = reinterpret_cast(start_kernel_thread); thread->m_interrupt_stack.cs = 0x08; - thread->m_interrupt_stack.flags = 0x202; + thread->m_interrupt_stack.flags = 0x002; thread->m_interrupt_stack.sp = sp; thread->m_interrupt_stack.ss = 0x10; @@ -245,7 +241,7 @@ namespace Kernel 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, this); - write_to_stack(sp, &Thread::on_exit); + write_to_stack(sp, &Thread::on_exit_trampoline); write_to_stack(sp, m_process); write_to_stack(sp, entry); }); @@ -422,6 +418,11 @@ namespace Kernel return {}; } + void Thread::on_exit_trampoline(Thread* thread) + { + thread->on_exit(); + } + void Thread::on_exit() { ASSERT(this == &Thread::current());