WIP ring3
This commit is contained in:
@@ -12,6 +12,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
addr_t isr_handler(addr_t, cpu_state);
|
addr_t isr_handler(addr_t, cpu_state);
|
||||||
void irq_handler(cpu_state);
|
void irq_handler(cpu_state);
|
||||||
|
void syscall_handler(cpu_state);
|
||||||
|
|
||||||
#define ISR(i, name) extern void name ();
|
#define ISR(i, name) extern void name ();
|
||||||
#define EISR(i, name) extern void name ();
|
#define EISR(i, name) extern void name ();
|
||||||
@@ -322,3 +323,36 @@ irq_handler(cpu_state regs)
|
|||||||
*reinterpret_cast<uint32_t *>(0xffffff80fee000b0) = 0;
|
*reinterpret_cast<uint32_t *>(0xffffff80fee000b0) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
syscall_handler(cpu_state regs)
|
||||||
|
{
|
||||||
|
console *cons = console::get();
|
||||||
|
cons->printf("SYSCALL\n");
|
||||||
|
|
||||||
|
cons->puts("\n");
|
||||||
|
print_reg("rax", regs.rax);
|
||||||
|
print_reg("rbx", regs.rbx);
|
||||||
|
print_reg("rcx", regs.rcx);
|
||||||
|
print_reg("rdx", regs.rdx);
|
||||||
|
print_reg("rdi", regs.rdi);
|
||||||
|
print_reg("rsi", regs.rsi);
|
||||||
|
|
||||||
|
cons->puts("\n");
|
||||||
|
print_reg(" r8", regs.r8);
|
||||||
|
print_reg(" r9", regs.r9);
|
||||||
|
print_reg("r10", regs.r10);
|
||||||
|
print_reg("r11", regs.r11);
|
||||||
|
print_reg("r12", regs.r12);
|
||||||
|
print_reg("r13", regs.r13);
|
||||||
|
print_reg("r14", regs.r14);
|
||||||
|
print_reg("r15", regs.r15);
|
||||||
|
|
||||||
|
cons->puts("\n");
|
||||||
|
print_reg("rbp", regs.rbp);
|
||||||
|
print_reg("rsp", regs.user_rsp);
|
||||||
|
print_reg("sp0", tss_get_stack(0));
|
||||||
|
|
||||||
|
cons->puts("\n");
|
||||||
|
print_reg("rip", regs.rip);
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -150,3 +150,100 @@ irq_handler_prelude:
|
|||||||
|
|
||||||
section .isrs
|
section .isrs
|
||||||
%include "interrupt_isrs.inc"
|
%include "interrupt_isrs.inc"
|
||||||
|
|
||||||
|
extern syscall_handler
|
||||||
|
syscall_handler_prelude:
|
||||||
|
push 0 ; ss, doesn't matter here
|
||||||
|
push rsp
|
||||||
|
pushf
|
||||||
|
push 0 ; cs, doesn't matter here
|
||||||
|
push rcx ; user rip
|
||||||
|
push 0 ; bogus interrupt
|
||||||
|
push 0 ; bogus errorcode
|
||||||
|
push_all_and_segments
|
||||||
|
|
||||||
|
call syscall_handler
|
||||||
|
|
||||||
|
pop_all_and_segments
|
||||||
|
add rsp, 16 ; ignore bogus interrupt / error
|
||||||
|
pop rcx ; user rip
|
||||||
|
add rsp, 32 ; ignore cs, flags, rsp, ss
|
||||||
|
|
||||||
|
o64 sysret
|
||||||
|
|
||||||
|
global syscall_enable
|
||||||
|
syscall_enable:
|
||||||
|
; IA32_EFER - set bit 0, syscall enable
|
||||||
|
mov rcx, 0xc0000080
|
||||||
|
rdmsr
|
||||||
|
or rax, 0x1
|
||||||
|
wrmsr
|
||||||
|
|
||||||
|
; IA32_STAR - cs for syscall
|
||||||
|
mov rcx, 0xc0000081
|
||||||
|
mov rax, 0 ; not used
|
||||||
|
mov rdx, 0x00180008 ; GDT:3 (user code), GDT:1 (kernel code)
|
||||||
|
wrmsr
|
||||||
|
|
||||||
|
; IA32_LSTAR - RIP for syscall
|
||||||
|
mov rcx, 0xc0000082
|
||||||
|
lea rax, [rel syscall_handler_prelude]
|
||||||
|
mov rdx, rax
|
||||||
|
shr rdx, 32
|
||||||
|
wrmsr
|
||||||
|
|
||||||
|
; IA32_FMASK - FLAGS mask inside syscall
|
||||||
|
mov rcx, 0xc0000084
|
||||||
|
mov rax, 0x200
|
||||||
|
mov rdx, 0
|
||||||
|
wrmsr
|
||||||
|
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
global taskA
|
||||||
|
taskA:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
push 0x123456789abcdef0
|
||||||
|
push 0x0fedcba987654321
|
||||||
|
|
||||||
|
.loop:
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
syscall
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
jmp .loop
|
||||||
|
|||||||
@@ -20,8 +20,8 @@
|
|||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void do_the_set_registers(popcorn_data *header);
|
|
||||||
void kernel_main(popcorn_data *header);
|
void kernel_main(popcorn_data *header);
|
||||||
|
void syscall_enable();
|
||||||
|
|
||||||
void *__bss_start, *__bss_end;
|
void *__bss_start, *__bss_end;
|
||||||
}
|
}
|
||||||
@@ -135,6 +135,7 @@ kernel_main(popcorn_data *header)
|
|||||||
|
|
||||||
// pager->dump_pml4();
|
// pager->dump_pml4();
|
||||||
|
|
||||||
|
syscall_enable();
|
||||||
scheduler *sched = new (&scheduler::get()) scheduler(devices->get_lapic());
|
scheduler *sched = new (&scheduler::get()) scheduler(devices->get_lapic());
|
||||||
sched->start();
|
sched->start();
|
||||||
|
|
||||||
|
|||||||
@@ -10,25 +10,18 @@ scheduler scheduler::s_instance(nullptr);
|
|||||||
static const uint32_t quantum = 5000000;
|
static const uint32_t quantum = 5000000;
|
||||||
|
|
||||||
const int stack_size = 0x1000;
|
const int stack_size = 0x1000;
|
||||||
char taskAstack[stack_size];
|
char taskAstack0[stack_size];
|
||||||
char taskBstack[stack_size];
|
char taskAstack3[stack_size];
|
||||||
|
char taskBstack0[stack_size];
|
||||||
|
char taskBstack3[stack_size];
|
||||||
|
|
||||||
uint64_t taskAcount = 0;
|
uint64_t taskAcount = 0;
|
||||||
|
|
||||||
void taskA()
|
extern "C" void taskA();
|
||||||
{
|
|
||||||
console *cons = console::get();
|
|
||||||
while(1) {
|
|
||||||
cons->putc('.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void taskB()
|
void taskB()
|
||||||
{
|
{
|
||||||
console *cons = console::get();
|
while (1);
|
||||||
while(1) {
|
|
||||||
cons->putc('+');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -40,7 +33,7 @@ scheduler::scheduler(lapic *apic) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
static process
|
static process
|
||||||
create_process(uint16_t pid, void *stack, void (*rip)())
|
create_process(uint16_t pid, void *stack0, void *stack3, void (*rip)())
|
||||||
{
|
{
|
||||||
uint64_t flags;
|
uint64_t flags;
|
||||||
__asm__ __volatile__ ( "pushf; pop %0" : "=r" (flags) );
|
__asm__ __volatile__ ( "pushf; pop %0" : "=r" (flags) );
|
||||||
@@ -48,21 +41,26 @@ create_process(uint16_t pid, void *stack, void (*rip)())
|
|||||||
// This is a hack for now, until we get a lot more set up.
|
// This is a hack for now, until we get a lot more set up.
|
||||||
// I just want to see task switching working inside ring0 first
|
// I just want to see task switching working inside ring0 first
|
||||||
uint16_t kcs = (1 << 3) | 0;
|
uint16_t kcs = (1 << 3) | 0;
|
||||||
uint16_t cs = (3 << 3) | 3;
|
uint16_t cs = (5 << 3) | 3;
|
||||||
|
|
||||||
uint16_t kss = (2 << 3) | 0;
|
uint16_t kss = (2 << 3) | 0;
|
||||||
uint16_t ss = (4 << 3) | 3;
|
uint16_t ss = (4 << 3) | 3;
|
||||||
|
|
||||||
void *sp = kutil::offset_pointer(stack, stack_size);
|
void *sp0 = kutil::offset_pointer(stack0, stack_size);
|
||||||
cpu_state *state = reinterpret_cast<cpu_state *>(sp) - 1;
|
cpu_state *state = reinterpret_cast<cpu_state *>(sp0) - 1;
|
||||||
kutil::memset(state, 0, sizeof(cpu_state));
|
kutil::memset(state, 0, sizeof(cpu_state));
|
||||||
state->ds = state->ss = kss;
|
|
||||||
state->cs = kcs;
|
state->ds = state->ss = ss;
|
||||||
state->rflags = 0x202;
|
state->cs = cs;
|
||||||
state->user_rsp = reinterpret_cast<uint64_t>(sp);
|
state->rflags = 0x202; // testing. TODO: 0x202
|
||||||
state->rip = reinterpret_cast<uint64_t>(rip);
|
state->rip = reinterpret_cast<uint64_t>(rip);
|
||||||
|
|
||||||
log::debug(logs::task, "Creating a user RSP of %016lx", state->user_rsp);
|
void *sp3 = kutil::offset_pointer(stack3, stack_size);
|
||||||
|
state->user_rsp = reinterpret_cast<uint64_t>(sp3);
|
||||||
|
|
||||||
|
log::debug(logs::task, "Creating PID %d:", pid);
|
||||||
|
log::debug(logs::task, " RSP0 %016lx", state);
|
||||||
|
log::debug(logs::task, " RSP3 %016lx", sp3);
|
||||||
|
|
||||||
return {pid, reinterpret_cast<addr_t>(state)};
|
return {pid, reinterpret_cast<addr_t>(state)};
|
||||||
}
|
}
|
||||||
@@ -73,8 +71,8 @@ scheduler::start()
|
|||||||
m_apic->enable_timer(isr::isrTimer, 128, quantum, false);
|
m_apic->enable_timer(isr::isrTimer, 128, quantum, false);
|
||||||
|
|
||||||
m_processes.append({0, 0}); // The kernel idle task
|
m_processes.append({0, 0}); // The kernel idle task
|
||||||
m_processes.append(create_process(1, &taskAstack[0], &taskA));
|
m_processes.append(create_process(1, &taskAstack0[0], &taskAstack3[0], &taskA));
|
||||||
m_processes.append(create_process(2, &taskBstack[0], &taskB));
|
m_processes.append(create_process(2, &taskBstack0[0], &taskBstack3[0], &taskB));
|
||||||
}
|
}
|
||||||
|
|
||||||
addr_t
|
addr_t
|
||||||
@@ -85,7 +83,9 @@ scheduler::tick(addr_t rsp0)
|
|||||||
m_processes[m_current].rsp = rsp0;
|
m_processes[m_current].rsp = rsp0;
|
||||||
m_current = (m_current + 1) % m_processes.count();
|
m_current = (m_current + 1) % m_processes.count();
|
||||||
rsp0 = m_processes[m_current].rsp;
|
rsp0 = m_processes[m_current].rsp;
|
||||||
tss_set_stack(0, rsp0);
|
|
||||||
|
// Set rsp0 to after the end of the about-to-be-popped cpu state
|
||||||
|
tss_set_stack(0, rsp0 + sizeof(cpu_state));
|
||||||
|
|
||||||
m_apic->reset_timer(quantum);
|
m_apic->reset_timer(quantum);
|
||||||
return rsp0;
|
return rsp0;
|
||||||
|
|||||||
Reference in New Issue
Block a user