Compare commits
2 Commits
731330c6b5
...
7ef751ba95
Author | SHA1 | Date |
---|---|---|
|
7ef751ba95 | |
|
f8c01418b1 |
|
@ -1,3 +1,57 @@
|
||||||
|
// arguments in EAX, EBX, ECX, EDX, ESI, EDI
|
||||||
|
.global asm_syscall_handler
|
||||||
|
asm_syscall_handler:
|
||||||
|
# save segment registers
|
||||||
|
pushw %ds
|
||||||
|
pushw %es
|
||||||
|
pushw %fs
|
||||||
|
pushw %gs
|
||||||
|
|
||||||
|
# save general purpose registers
|
||||||
|
pushl %ebx
|
||||||
|
pushl %ecx
|
||||||
|
pushl %edx
|
||||||
|
pushl %edi
|
||||||
|
pushl %esi
|
||||||
|
pushl %ebp
|
||||||
|
|
||||||
|
# align stack and push arguments
|
||||||
|
pushl %esp
|
||||||
|
addl $32, (%esp)
|
||||||
|
pushl %edi
|
||||||
|
pushl %esi
|
||||||
|
pushl %edx
|
||||||
|
pushl %ecx
|
||||||
|
pushl %ebx
|
||||||
|
pushl %eax
|
||||||
|
|
||||||
|
# load kernel segments
|
||||||
|
movw $0x10, %ax
|
||||||
|
movw %ax, %ds
|
||||||
|
movw %ax, %es
|
||||||
|
movw %ax, %fs
|
||||||
|
movw $0x28, %ax
|
||||||
|
movw %ax, %gs
|
||||||
|
|
||||||
|
call cpp_syscall_handler
|
||||||
|
addl $28, %esp
|
||||||
|
|
||||||
|
# restore general purpose registers
|
||||||
|
popl %ebp
|
||||||
|
popl %esi
|
||||||
|
popl %edi
|
||||||
|
popl %edx
|
||||||
|
popl %ecx
|
||||||
|
popl %ebx
|
||||||
|
|
||||||
|
# restore segment registers
|
||||||
|
popw %gs
|
||||||
|
popw %fs
|
||||||
|
popw %es
|
||||||
|
popw %ds
|
||||||
|
|
||||||
|
iret
|
||||||
|
|
||||||
.global sys_fork_trampoline
|
.global sys_fork_trampoline
|
||||||
sys_fork_trampoline:
|
sys_fork_trampoline:
|
||||||
pushl %ebp
|
pushl %ebp
|
||||||
|
|
|
@ -24,22 +24,6 @@
|
||||||
popw %gs
|
popw %gs
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro pop_userspace_skip_eax
|
|
||||||
popl %edi
|
|
||||||
popl %esi
|
|
||||||
popl %ebp
|
|
||||||
addl $4, %esp
|
|
||||||
popl %ebx
|
|
||||||
popl %edx
|
|
||||||
popl %ecx
|
|
||||||
addl $4, %esp
|
|
||||||
|
|
||||||
popw %ds
|
|
||||||
popw %es
|
|
||||||
popw %fs
|
|
||||||
popw %gs
|
|
||||||
.endm
|
|
||||||
|
|
||||||
isr_stub:
|
isr_stub:
|
||||||
push_userspace
|
push_userspace
|
||||||
load_kernel_segments
|
load_kernel_segments
|
||||||
|
@ -81,46 +65,21 @@ irq_stub:
|
||||||
addl $8, %esp
|
addl $8, %esp
|
||||||
iret
|
iret
|
||||||
|
|
||||||
.global asm_reschedule_handler
|
.global asm_yield_handler
|
||||||
asm_reschedule_handler:
|
asm_yield_handler:
|
||||||
push_userspace
|
# This can only be called from kernel, so no segment saving is needed
|
||||||
load_kernel_segments
|
pushal
|
||||||
|
|
||||||
movl %esp, %eax # interrupt registers ptr
|
movl %esp, %eax # interrupt registers ptr
|
||||||
leal 40(%esp), %ebx # interrupt stack ptr
|
leal 32(%esp), %ebx # interrupt stack ptr
|
||||||
|
|
||||||
subl $12, %esp
|
subl $4, %esp
|
||||||
pushl %eax
|
pushl %eax
|
||||||
pushl %ebx
|
pushl %ebx
|
||||||
call cpp_reschedule_handler
|
call cpp_yield_handler
|
||||||
addl $20, %esp
|
addl $12, %esp
|
||||||
|
|
||||||
pop_userspace
|
popal
|
||||||
iret
|
|
||||||
|
|
||||||
// arguments in EAX, EBX, ECX, EDX, ESI, EDI
|
|
||||||
.global syscall_asm
|
|
||||||
syscall_asm:
|
|
||||||
push_userspace
|
|
||||||
|
|
||||||
subl $8, %esp
|
|
||||||
|
|
||||||
pushl %esp
|
|
||||||
addl $48, (%esp)
|
|
||||||
|
|
||||||
pushl %edi
|
|
||||||
pushl %esi
|
|
||||||
pushl %edx
|
|
||||||
pushl %ecx
|
|
||||||
pushl %ebx
|
|
||||||
pushl %eax
|
|
||||||
|
|
||||||
load_kernel_segments
|
|
||||||
|
|
||||||
call cpp_syscall_handler
|
|
||||||
addl $36, %esp
|
|
||||||
|
|
||||||
pop_userspace_skip_eax
|
|
||||||
iret
|
iret
|
||||||
|
|
||||||
.macro isr n
|
.macro isr n
|
||||||
|
@ -211,3 +170,4 @@ irq 28
|
||||||
irq 29
|
irq 29
|
||||||
irq 30
|
irq 30
|
||||||
irq 31
|
irq 31
|
||||||
|
irq 32
|
||||||
|
|
|
@ -1,3 +1,49 @@
|
||||||
|
// arguments in RAX, RBX, RCX, RDX, RSI, RDI
|
||||||
|
// System V ABI: RDI, RSI, RDX, RCX, R8, R9
|
||||||
|
.global asm_syscall_handler
|
||||||
|
asm_syscall_handler:
|
||||||
|
pushq %rbx
|
||||||
|
pushq %rcx
|
||||||
|
pushq %rdx
|
||||||
|
pushq %rdi
|
||||||
|
pushq %rsi
|
||||||
|
pushq %rbp
|
||||||
|
pushq %r8
|
||||||
|
pushq %r9
|
||||||
|
pushq %r10
|
||||||
|
pushq %r11
|
||||||
|
pushq %r12
|
||||||
|
pushq %r13
|
||||||
|
pushq %r14
|
||||||
|
pushq %r15
|
||||||
|
|
||||||
|
movq %rsi, %r8
|
||||||
|
movq %rdi, %r9
|
||||||
|
movq %rax, %rdi
|
||||||
|
movq %rbx, %rsi
|
||||||
|
xchgq %rcx, %rdx
|
||||||
|
leaq 112(%rsp), %rbx
|
||||||
|
pushq %rbx
|
||||||
|
call cpp_syscall_handler
|
||||||
|
addq $8, %rsp
|
||||||
|
|
||||||
|
popq %r15
|
||||||
|
popq %r14
|
||||||
|
popq %r13
|
||||||
|
popq %r12
|
||||||
|
popq %r11
|
||||||
|
popq %r10
|
||||||
|
popq %r9
|
||||||
|
popq %r8
|
||||||
|
popq %rbp
|
||||||
|
popq %rsi
|
||||||
|
popq %rdi
|
||||||
|
popq %rdx
|
||||||
|
popq %rcx
|
||||||
|
popq %rbx
|
||||||
|
iretq
|
||||||
|
|
||||||
|
|
||||||
.global sys_fork_trampoline
|
.global sys_fork_trampoline
|
||||||
sys_fork_trampoline:
|
sys_fork_trampoline:
|
||||||
pushq %rbx
|
pushq %rbx
|
||||||
|
|
|
@ -34,23 +34,6 @@
|
||||||
popq %rax
|
popq %rax
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro popaq_no_rax
|
|
||||||
popq %r15
|
|
||||||
popq %r14
|
|
||||||
popq %r13
|
|
||||||
popq %r12
|
|
||||||
popq %r11
|
|
||||||
popq %r10
|
|
||||||
popq %r9
|
|
||||||
popq %r8
|
|
||||||
popq %rdi
|
|
||||||
popq %rsi
|
|
||||||
popq %rbp
|
|
||||||
popq %rbx
|
|
||||||
popq %rdx
|
|
||||||
popq %rcx
|
|
||||||
.endm
|
|
||||||
|
|
||||||
isr_stub:
|
isr_stub:
|
||||||
pushaq
|
pushaq
|
||||||
|
|
||||||
|
@ -78,6 +61,15 @@ irq_stub:
|
||||||
addq $16, %rsp
|
addq $16, %rsp
|
||||||
iretq
|
iretq
|
||||||
|
|
||||||
|
.global asm_yield_handler
|
||||||
|
asm_yield_handler:
|
||||||
|
pushaq
|
||||||
|
leaq 120(%rsp), %rdi # interrupt stack ptr
|
||||||
|
movq %rsp, %rsi # interrupt register ptr
|
||||||
|
call cpp_yield_handler
|
||||||
|
popaq
|
||||||
|
iretq
|
||||||
|
|
||||||
.macro isr n
|
.macro isr n
|
||||||
.global isr\n
|
.global isr\n
|
||||||
isr\n:
|
isr\n:
|
||||||
|
@ -166,31 +158,4 @@ irq 28
|
||||||
irq 29
|
irq 29
|
||||||
irq 30
|
irq 30
|
||||||
irq 31
|
irq 31
|
||||||
|
irq 32
|
||||||
.global asm_reschedule_handler
|
|
||||||
asm_reschedule_handler:
|
|
||||||
pushaq
|
|
||||||
leaq 120(%rsp), %rdi # interrupt stack ptr
|
|
||||||
movq %rsp, %rsi # interrupt register ptr
|
|
||||||
call cpp_reschedule_handler
|
|
||||||
popaq
|
|
||||||
iretq
|
|
||||||
|
|
||||||
// arguments in RAX, RBX, RCX, RDX, RSI, RDI
|
|
||||||
// System V ABI: RDI, RSI, RDX, RCX, R8, R9
|
|
||||||
.global syscall_asm
|
|
||||||
syscall_asm:
|
|
||||||
pushaq
|
|
||||||
movq %rsi, %r8
|
|
||||||
movq %rdi, %r9
|
|
||||||
movq %rax, %rdi
|
|
||||||
movq %rbx, %rsi
|
|
||||||
xchgq %rcx, %rdx
|
|
||||||
movq %rsp, %rbx
|
|
||||||
addq $120, %rbx
|
|
||||||
pushq %rbx
|
|
||||||
call cpp_syscall_handler
|
|
||||||
addq $8, %rsp
|
|
||||||
popaq_no_rax
|
|
||||||
addq $8, %rsp
|
|
||||||
iretq
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
constexpr uint8_t IRQ_VECTOR_BASE = 0x20;
|
constexpr uint8_t IRQ_VECTOR_BASE = 0x20;
|
||||||
constexpr uint8_t IRQ_IPI = 32;
|
constexpr uint8_t IRQ_IPI = 32;
|
||||||
|
constexpr uint8_t IRQ_YIELD = 33;
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,7 +12,6 @@ namespace Kernel
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<void> initialize();
|
static BAN::ErrorOr<void> initialize();
|
||||||
static Scheduler& get();
|
static Scheduler& get();
|
||||||
static bool is_started();
|
|
||||||
|
|
||||||
[[noreturn]] void start();
|
[[noreturn]] void start();
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include <kernel/Timer/PIT.h>
|
#include <kernel/Timer/PIT.h>
|
||||||
|
|
||||||
#define ISR_LIST_X X(0) X(1) X(2) X(3) X(4) X(5) X(6) X(7) X(8) X(9) X(10) X(11) X(12) X(13) X(14) X(15) X(16) X(17) X(18) X(19) X(20) X(21) X(22) X(23) X(24) X(25) X(26) X(27) X(28) X(29) X(30) X(31)
|
#define ISR_LIST_X X(0) X(1) X(2) X(3) X(4) X(5) X(6) X(7) X(8) X(9) X(10) X(11) X(12) X(13) X(14) X(15) X(16) X(17) X(18) X(19) X(20) X(21) X(22) X(23) X(24) X(25) X(26) X(27) X(28) X(29) X(30) X(31)
|
||||||
#define IRQ_LIST_X X(0) X(1) X(2) X(3) X(4) X(5) X(6) X(7) X(8) X(9) X(10) X(11) X(12) X(13) X(14) X(15) X(16) X(17) X(18) X(19) X(20) X(21) X(22) X(23) X(24) X(25) X(26) X(27) X(28) X(29) X(30) X(31)
|
#define IRQ_LIST_X X(0) X(1) X(2) X(3) X(4) X(5) X(6) X(7) X(8) X(9) X(10) X(11) X(12) X(13) X(14) X(15) X(16) X(17) X(18) X(19) X(20) X(21) X(22) X(23) X(24) X(25) X(26) X(27) X(28) X(29) X(30) X(31) X(32)
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
@ -329,8 +329,11 @@ done:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void cpp_reschedule_handler(InterruptStack* interrupt_stack, InterruptRegisters* interrupt_registers)
|
extern "C" void cpp_yield_handler(InterruptStack* interrupt_stack, InterruptRegisters* interrupt_registers)
|
||||||
{
|
{
|
||||||
|
ASSERT(!InterruptController::get().is_in_service(IRQ_YIELD));
|
||||||
|
ASSERT(!GDT::is_user_segment(interrupt_stack->cs));
|
||||||
|
|
||||||
Processor::enter_interrupt(interrupt_stack, interrupt_registers);
|
Processor::enter_interrupt(interrupt_stack, interrupt_registers);
|
||||||
Scheduler::get().irq_reschedule();
|
Scheduler::get().irq_reschedule();
|
||||||
Processor::leave_interrupt();
|
Processor::leave_interrupt();
|
||||||
|
@ -346,8 +349,6 @@ done:
|
||||||
asm volatile("cli; 1: hlt; jmp 1b");
|
asm volatile("cli; 1: hlt; jmp 1b");
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(irq != IRQ_IPI);
|
|
||||||
|
|
||||||
if (!InterruptController::get().is_in_service(irq))
|
if (!InterruptController::get().is_in_service(irq))
|
||||||
dprintln("spurious irq 0x{2H}", irq);
|
dprintln("spurious irq 0x{2H}", irq);
|
||||||
else
|
else
|
||||||
|
@ -355,6 +356,8 @@ done:
|
||||||
InterruptController::get().eoi(irq);
|
InterruptController::get().eoi(irq);
|
||||||
if (auto* handler = s_interruptables[irq])
|
if (auto* handler = s_interruptables[irq])
|
||||||
handler->handle_irq();
|
handler->handle_irq();
|
||||||
|
else if (irq == IRQ_IPI)
|
||||||
|
Scheduler::get().yield();
|
||||||
else
|
else
|
||||||
dprintln("no handler for irq 0x{2H}", irq);
|
dprintln("no handler for irq 0x{2H}", irq);
|
||||||
}
|
}
|
||||||
|
@ -400,8 +403,8 @@ done:
|
||||||
IRQ_LIST_X
|
IRQ_LIST_X
|
||||||
#undef X
|
#undef X
|
||||||
|
|
||||||
extern "C" void asm_reschedule_handler();
|
extern "C" void asm_yield_handler();
|
||||||
extern "C" void syscall_asm();
|
extern "C" void asm_syscall_handler();
|
||||||
|
|
||||||
IDT* IDT::create()
|
IDT* IDT::create()
|
||||||
{
|
{
|
||||||
|
@ -418,9 +421,9 @@ done:
|
||||||
IRQ_LIST_X
|
IRQ_LIST_X
|
||||||
#undef X
|
#undef X
|
||||||
|
|
||||||
idt->register_interrupt_handler(IRQ_VECTOR_BASE + IRQ_IPI, asm_reschedule_handler);
|
idt->register_interrupt_handler(IRQ_VECTOR_BASE + IRQ_YIELD, asm_yield_handler);
|
||||||
|
|
||||||
idt->register_syscall_handler(0x80, syscall_asm);
|
idt->register_syscall_handler(0x80, asm_syscall_handler);
|
||||||
|
|
||||||
return idt;
|
return idt;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,6 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
static Scheduler* s_instance = nullptr;
|
static Scheduler* s_instance = nullptr;
|
||||||
static BAN::Atomic<bool> s_started { false };
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> Scheduler::initialize()
|
BAN::ErrorOr<void> Scheduler::initialize()
|
||||||
{
|
{
|
||||||
|
@ -33,13 +32,12 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
|
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
|
||||||
ASSERT(!m_active_threads.empty());
|
ASSERT(!m_active_threads.empty());
|
||||||
yield();
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Scheduler::is_started()
|
// broadcast ipi (yield) for each processor
|
||||||
{
|
InterruptController::get().broadcast_ipi();
|
||||||
return s_started;
|
yield();
|
||||||
|
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread& Scheduler::current_thread()
|
Thread& Scheduler::current_thread()
|
||||||
|
@ -122,20 +120,21 @@ namespace Kernel
|
||||||
|
|
||||||
void Scheduler::timer_reschedule()
|
void Scheduler::timer_reschedule()
|
||||||
{
|
{
|
||||||
// Broadcast IPI to all other processors for them
|
|
||||||
// to perform reschedule
|
|
||||||
InterruptController::get().broadcast_ipi();
|
|
||||||
|
|
||||||
{
|
{
|
||||||
SpinLockGuard _(m_lock);
|
SpinLockGuard _(m_lock);
|
||||||
m_blocking_threads.remove_with_wake_time(m_active_threads, SystemTimer::get().ms_since_boot());
|
m_blocking_threads.remove_with_wake_time(m_active_threads, SystemTimer::get().ms_since_boot());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Broadcast IPI to all other processors for them
|
||||||
|
// to perform reschedule
|
||||||
|
InterruptController::get().broadcast_ipi();
|
||||||
yield();
|
yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::yield()
|
void Scheduler::yield()
|
||||||
{
|
{
|
||||||
|
ASSERT(!m_lock.current_processor_has_lock());
|
||||||
|
|
||||||
auto state = Processor::get_interrupt_state();
|
auto state = Processor::get_interrupt_state();
|
||||||
Processor::set_interrupt_state(InterruptState::Disabled);
|
Processor::set_interrupt_state(InterruptState::Disabled);
|
||||||
|
|
||||||
|
@ -143,24 +142,24 @@ namespace Kernel
|
||||||
asm volatile(
|
asm volatile(
|
||||||
"movq %%rsp, %%rcx;"
|
"movq %%rsp, %%rcx;"
|
||||||
"movq %[load_sp], %%rsp;"
|
"movq %[load_sp], %%rsp;"
|
||||||
"int %[ipi];"
|
"int %[yield];"
|
||||||
"movq %%rcx, %%rsp;"
|
"movq %%rcx, %%rsp;"
|
||||||
// NOTE: This is offset by 2 pointers since interrupt without PL change
|
// NOTE: This is offset by 2 pointers since interrupt without PL change
|
||||||
// does not push SP and SS. This allows accessing "whole" interrupt stack.
|
// does not push SP and SS. This allows accessing "whole" interrupt stack.
|
||||||
:: [load_sp]"r"(Processor::current_stack_top() - 2 * sizeof(uintptr_t)),
|
:: [load_sp]"r"(Processor::current_stack_top() - 2 * sizeof(uintptr_t)),
|
||||||
[ipi]"i"(IRQ_VECTOR_BASE + IRQ_IPI)
|
[yield]"i"(IRQ_VECTOR_BASE + IRQ_YIELD)
|
||||||
: "memory", "rcx"
|
: "memory", "rcx"
|
||||||
);
|
);
|
||||||
#elif ARCH(i686)
|
#elif ARCH(i686)
|
||||||
asm volatile(
|
asm volatile(
|
||||||
"movl %%esp, %%ecx;"
|
"movl %%esp, %%ecx;"
|
||||||
"movl %[load_sp], %%esp;"
|
"movl %[load_sp], %%esp;"
|
||||||
"int %[ipi];"
|
"int %[yield];"
|
||||||
"movl %%ecx, %%esp;"
|
"movl %%ecx, %%esp;"
|
||||||
// NOTE: This is offset by 2 pointers since interrupt without PL change
|
// NOTE: This is offset by 2 pointers since interrupt without PL change
|
||||||
// does not push SP and SS. This allows accessing "whole" interrupt stack.
|
// does not push SP and SS. This allows accessing "whole" interrupt stack.
|
||||||
:: [load_sp]"r"(Processor::current_stack_top() - 2 * sizeof(uintptr_t)),
|
:: [load_sp]"r"(Processor::current_stack_top() - 2 * sizeof(uintptr_t)),
|
||||||
[ipi]"i"(IRQ_VECTOR_BASE + IRQ_IPI)
|
[yield]"i"(IRQ_VECTOR_BASE + IRQ_YIELD)
|
||||||
: "memory", "ecx"
|
: "memory", "ecx"
|
||||||
);
|
);
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -265,7 +265,7 @@ namespace Kernel
|
||||||
|
|
||||||
m_interrupt_stack.ip = reinterpret_cast<vaddr_t>(start_kernel_thread);
|
m_interrupt_stack.ip = reinterpret_cast<vaddr_t>(start_kernel_thread);
|
||||||
m_interrupt_stack.cs = 0x08;
|
m_interrupt_stack.cs = 0x08;
|
||||||
m_interrupt_stack.flags = 0x202;
|
m_interrupt_stack.flags = 0x002;
|
||||||
m_interrupt_stack.sp = kernel_stack_top() - 4 * sizeof(uintptr_t);
|
m_interrupt_stack.sp = kernel_stack_top() - 4 * sizeof(uintptr_t);
|
||||||
m_interrupt_stack.ss = 0x10;
|
m_interrupt_stack.ss = 0x10;
|
||||||
|
|
||||||
|
|
|
@ -218,7 +218,9 @@ extern "C" void ap_main()
|
||||||
|
|
||||||
dprintln("ap{} initialized", Processor::current_id());
|
dprintln("ap{} initialized", Processor::current_id());
|
||||||
|
|
||||||
while (!Scheduler::is_started())
|
// wait until scheduler is started and we get irq for reschedule
|
||||||
__builtin_ia32_pause();
|
Processor::set_interrupt_state(InterruptState::Enabled);
|
||||||
Scheduler::get().start();
|
while (true)
|
||||||
|
asm volatile("hlt");
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue