Kernel: Rework scheduler/processor stacks.

This commit is contained in:
Bananymous 2024-04-02 12:34:42 +03:00
parent 5050047cef
commit 2106a9e373
7 changed files with 94 additions and 64 deletions

View File

@ -4,40 +4,31 @@ read_ip:
popl %eax popl %eax
jmp *%eax jmp *%eax
# void start_thread(uint32_t sp, uint32_t ip) # void start_kernel_thread()
.global start_thread .global start_kernel_thread
start_thread: start_kernel_thread:
movl 8(%esp), %edi # ip call get_start_kernel_thread_sp
movl 4(%esp), %esp # sp movl %eax, %esp
# STACK LAYOUT # STACK LAYOUT
# NULL # on_exit arg
# thread ptr # on_exit func
# &Thread::on_exit # entry arg
# data # entry func
xorl %ebp, %ebp movl 4(%esp), %edi
movl 0(%esp), %esi
subl $12, %esp
pushl %edi
sti 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 subl $12, %esp
movl %eax, (%esp) pushl %edi
call *%esi
call *%edi addl $16, %esp
# 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

View File

@ -26,17 +26,31 @@ isr_stub:
irq_stub: irq_stub:
pusha pusha
leal 40(%esp), %eax // interrupt stack ptr movl 32(%esp), %eax # interrupt number
movl 32(%esp), %ebx // irq 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 subl $12, %esp
pushl %eax pushl %eax
pushl %ebx pushl %ebx
call cpp_irq_handler call cpp_reschedule_handler
addl $20, %esp addl $20, %esp
popa popa
addl $8, %esp
iret iret
// arguments in EAX, EBX, ECX, EDX, ESI, EDI // arguments in EAX, EBX, ECX, EDX, ESI, EDI
@ -158,4 +172,3 @@ irq 28
irq 29 irq 29
irq 30 irq 30
irq 31 irq 31
irq 32

View File

@ -4,9 +4,12 @@ read_ip:
popq %rax popq %rax
jmp *%rax jmp *%rax
# void start_thread() # void start_kernel_thread()
.global start_kernel_thread .global start_kernel_thread
start_kernel_thread: start_kernel_thread:
call get_start_kernel_thread_sp
movq %rax, %rsp
# STACK LAYOUT # STACK LAYOUT
# on_exit arg # on_exit arg
# on_exit func # on_exit func
@ -15,6 +18,7 @@ start_kernel_thread:
movq 8(%rsp), %rdi movq 8(%rsp), %rdi
movq 0(%rsp), %rsi movq 0(%rsp), %rsi
sti
call *%rsi call *%rsi
movq 24(%rsp), %rdi movq 24(%rsp), %rdi

View File

@ -14,6 +14,7 @@ namespace Kernel
uintptr_t ss; uintptr_t ss;
}; };
#if ARCH(x86_64)
struct InterruptRegisters struct InterruptRegisters
{ {
uintptr_t r15; uintptr_t r15;
@ -33,5 +34,18 @@ namespace Kernel
uintptr_t rcx; uintptr_t rcx;
uintptr_t rax; 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
} }

View File

@ -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 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(); } 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; } InterruptStack& interrupt_stack() { return m_interrupt_stack; }
InterruptRegisters& interrupt_registers() { return m_interrupt_registers; } InterruptRegisters& interrupt_registers() { return m_interrupt_registers; }
@ -89,6 +88,8 @@ namespace Kernel
private: private:
Thread(pid_t tid, Process*); Thread(pid_t tid, Process*);
static void on_exit_trampoline(Thread*);
void on_exit(); void on_exit();
private: private:
@ -104,7 +105,6 @@ namespace Kernel
InterruptStack m_interrupt_stack { }; InterruptStack m_interrupt_stack { };
InterruptRegisters m_interrupt_registers { }; InterruptRegisters m_interrupt_registers { };
uintptr_t m_interrupt_sp { };
uint64_t m_signal_pending_mask { 0 }; uint64_t m_signal_pending_mask { 0 };
uint64_t m_signal_block_mask { 0 }; uint64_t m_signal_block_mask { 0 };

View File

@ -14,17 +14,6 @@ namespace Kernel
static Scheduler* s_instance = nullptr; static Scheduler* s_instance = nullptr;
static BAN::Atomic<bool> s_started { false }; static BAN::Atomic<bool> 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<void> Scheduler::initialize() BAN::ErrorOr<void> Scheduler::initialize()
{ {
ASSERT(s_instance == nullptr); ASSERT(s_instance == nullptr);
@ -40,6 +29,11 @@ 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);
@ -86,7 +80,6 @@ namespace Kernel
if (thread->state() != Thread::State::NotStarted) if (thread->state() != Thread::State::NotStarted)
{ {
thread->interrupt_stack() = Processor::get_interrupt_stack(); thread->interrupt_stack() = Processor::get_interrupt_stack();
thread->interrupt_stack().sp = thread->interrupt_sp();
thread->interrupt_registers() = Processor::get_interrupt_registers(); thread->interrupt_registers() = Processor::get_interrupt_registers();
} }
@ -155,15 +148,29 @@ namespace Kernel
auto state = Processor::get_interrupt_state(); auto state = Processor::get_interrupt_state();
Processor::set_interrupt_state(InterruptState::Disabled); Processor::set_interrupt_state(InterruptState::Disabled);
#if ARCH(x86_64)
asm volatile( asm volatile(
"movq %%rsp, %[save_sp];" "movq %%rsp, %%rcx;"
"movq %[load_sp], %%rsp;" "movq %[load_sp], %%rsp;"
"int %[ipi];" "int %[ipi];"
: [save_sp]"=m"(Thread::current().interrupt_sp()) "movq %%rcx, %%rsp;"
: [load_sp]"r"(Processor::current_stack_top()), :: [load_sp]"r"(Processor::current_stack_top()),
[ipi]"i"(IRQ_VECTOR_BASE + IRQ_IPI) [ipi]"i"(IRQ_VECTOR_BASE + IRQ_IPI)
: "memory" : "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); Processor::set_interrupt_state(state);
} }

View File

@ -12,19 +12,15 @@
namespace Kernel namespace Kernel
{ {
extern "C" [[noreturn]] void start_userspace_thread();
extern "C" [[noreturn]] void start_kernel_thread(); extern "C" [[noreturn]] void start_kernel_thread();
extern "C" void signal_trampoline(); extern "C" void signal_trampoline();
template<typename T> template<typename T>
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); rsp -= sizeof(uintptr_t);
if constexpr(sizeof(T) < sizeof(uintptr_t)) *(uintptr_t*)rsp = (uintptr_t)value;
*(uintptr_t*)rsp = (uintptr_t)value;
else
memcpy((void*)rsp, (void*)&value, sizeof(uintptr_t));
} }
static pid_t s_next_tid = 1; static pid_t s_next_tid = 1;
@ -50,13 +46,13 @@ namespace Kernel
// Initialize stack for returning // Initialize stack for returning
uintptr_t sp = thread->kernel_stack_top(); uintptr_t sp = thread->kernel_stack_top();
write_to_stack(sp, thread); 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, data);
write_to_stack(sp, entry); write_to_stack(sp, entry);
thread->m_interrupt_stack.ip = reinterpret_cast<vaddr_t>(start_kernel_thread); thread->m_interrupt_stack.ip = reinterpret_cast<vaddr_t>(start_kernel_thread);
thread->m_interrupt_stack.cs = 0x08; 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.sp = sp;
thread->m_interrupt_stack.ss = 0x10; 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), [&] { 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, this); 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, m_process);
write_to_stack(sp, entry); write_to_stack(sp, entry);
}); });
@ -422,6 +418,11 @@ namespace Kernel
return {}; return {};
} }
void Thread::on_exit_trampoline(Thread* thread)
{
thread->on_exit();
}
void Thread::on_exit() void Thread::on_exit()
{ {
ASSERT(this == &Thread::current()); ASSERT(this == &Thread::current());