diff --git a/kernel/include/kernel/Thread.h b/kernel/include/kernel/Thread.h index cd7a86e1..ce99d8c6 100644 --- a/kernel/include/kernel/Thread.h +++ b/kernel/include/kernel/Thread.h @@ -46,6 +46,9 @@ namespace Kernel uintptr_t stack_base() const { return (uintptr_t)m_stack_base; } size_t stack_size() const { return m_stack_size; } + uintptr_t interrupt_stack_base() const { return (uintptr_t)m_interrupt_stack; } + uintptr_t interrupt_stack_size() const { return m_interrupt_stack_size; } + static Thread& current() ; Process& process(); bool has_process() const { return m_process; } @@ -55,25 +58,22 @@ namespace Kernel private: Thread(pid_t tid, Process*); - void validate_stack() const - { - if (!m_in_syscall) - if (!(stack_base() <= m_rsp && m_rsp <= stack_base() + stack_size())) - Kernel::panic("rsp {8H}, stack {8H}->{8H}", m_rsp, stack_base(), stack_base() + stack_size()); - } + void validate_stack() const; BAN::ErrorOr initialize(entry_t, void*); void on_exit(); private: - static constexpr size_t m_stack_size = 4096 * 1; - void* m_stack_base { nullptr }; - uintptr_t m_rip { 0 }; - uintptr_t m_rsp { 0 }; - const pid_t m_tid { 0 }; - State m_state { State::NotStarted }; - Process* m_process { nullptr }; - bool m_in_syscall { false }; + static constexpr size_t m_stack_size = 4096 * 1; + static constexpr size_t m_interrupt_stack_size = 4096; + void* m_interrupt_stack { nullptr }; + void* m_stack_base { nullptr }; + uintptr_t m_rip { 0 }; + uintptr_t m_rsp { 0 }; + const pid_t m_tid { 0 }; + State m_state { State::NotStarted }; + Process* m_process { nullptr }; + bool m_in_syscall { false }; friend class Scheduler; }; diff --git a/kernel/kernel/Thread.cpp b/kernel/kernel/Thread.cpp index ca365fd7..73bb4799 100644 --- a/kernel/kernel/Thread.cpp +++ b/kernel/kernel/Thread.cpp @@ -38,6 +38,12 @@ namespace Kernel ASSERT_NOT_REACHED(); }, (void*)entry, process )); + thread->m_interrupt_stack = kmalloc(m_interrupt_stack_size, PAGE_SIZE); + if (thread->m_interrupt_stack == nullptr) + { + delete thread; + return BAN::Error::from_errno(ENOMEM); + } process->mmu().map_range(thread->stack_base(), thread->stack_size(), MMU::Flags::UserSupervisor | MMU::Flags::ReadWrite | MMU::Flags::Present); return thread; } @@ -75,6 +81,8 @@ namespace Kernel Thread::~Thread() { dprintln("thread {} ({}) exit", tid(), m_process->pid()); + if (m_interrupt_stack) + kfree(m_interrupt_stack); kfree(m_stack_base); } @@ -83,6 +91,18 @@ namespace Kernel thread_jump_userspace(rsp(), rip); } + void Thread::validate_stack() const + { + if (stack_base() <= m_rsp && m_rsp <= stack_base() + stack_size()) + return; + if (interrupt_stack_base() <= m_rsp && m_rsp <= interrupt_stack_base() + interrupt_stack_size()) + return; + Kernel::panic("rsp {8H}, stack {8H}->{8H}, interrupt_stack {8H}->{8H}", m_rsp, + stack_base(), stack_base() + stack_size(), + interrupt_stack_base(), interrupt_stack_base() + interrupt_stack_size() + ); + } + void Thread::on_exit() { if (m_process)