Kernel: Rework scheduler/processor stacks.
This commit is contained in:
parent
5050047cef
commit
2106a9e373
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 };
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
|
Loading…
Reference in New Issue