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