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
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

View File

@ -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

View File

@ -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

View File

@ -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
}

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 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 };

View File

@ -14,17 +14,6 @@ namespace Kernel
static Scheduler* s_instance = nullptr;
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()
{
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);
}

View File

@ -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<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);
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<vaddr_t>(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());