WIP ring3

This commit is contained in:
Justin C. Miller
2018-05-20 01:03:04 -07:00
parent 814d6f1de6
commit 24ccf65aba
4 changed files with 158 additions and 26 deletions

View File

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

View File

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

View File

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

View File

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