Running in user mode

This commit is contained in:
Thomas Lovén 2018-02-22 12:16:20 +01:00
parent 6c078289f9
commit 68ec6fa575
9 changed files with 52 additions and 29 deletions

View File

@ -8,16 +8,9 @@
#include <process.h> #include <process.h>
#include <scheduler.h> #include <scheduler.h>
int *pid = (int *)0x20000;
void thread_function() void thread_function()
{ {
*pid = process()->pid; while(1);
while(1)
{
debug("Process %d\n", *pid);
yield();
}
} }
@ -35,16 +28,12 @@ void kmain(uint64_t multiboot_magic, void *multiboot_data)
cpu_init(); cpu_init();
struct process *p1 = new_process(thread_function); struct process *p1 = new_process((void (*)(void))0x10000);
vmm_set_page(p1->P4, 0x20000, pmm_alloc(), PAGE_WRITE | PAGE_PRESENT); uint64_t page = pmm_alloc();
struct process *p2 = new_process(thread_function); vmm_set_page(p1->P4, 0x10000, page, PAGE_WRITE | PAGE_PRESENT | PAGE_USER);
vmm_set_page(p2->P4, 0x20000, pmm_alloc(), PAGE_WRITE | PAGE_PRESENT); memcpy(P2V(page), (void *)(uintptr_t)thread_function, PAGE_SIZE);
struct process *p3 = new_process(thread_function);
vmm_set_page(p3->P4, 0x20000, pmm_alloc(), PAGE_WRITE | PAGE_PRESENT);
ready(p1); ready(p1);
ready(p2);
ready(p3);
debug_ok("Boot \"Complete\"\n"); debug_ok("Boot \"Complete\"\n");

View File

@ -1,7 +1,7 @@
#include <cpu.h> #include <cpu.h>
#include <interrupts.h> #include <interrupts.h>
uint64_t gdt[5]; uint64_t gdt[6];
uint8_t tss[104]; uint8_t tss[104];
void gdt_init(uint64_t *, void *); void gdt_init(uint64_t *, void *);

View File

@ -6,7 +6,7 @@
#define GDT_DPL(lvl) ((lvl)<<13) #define GDT_DPL(lvl) ((lvl)<<13)
#define GDT_PRESENT (1<<15) #define GDT_PRESENT (1<<15)
#define GDT_LONG (1<<21) #define GDT_LONG (1<<21)
#define GDT_TSS (1<<8) #define GDT_TSS (9<<8)
struct gdt struct gdt
{ {
@ -44,6 +44,7 @@ struct gdt BootGDT[] = {
{0, 0}, {0, 0},
{0, GDT_PRESENT | GDT_DPL(0) | GDT_CODE | GDT_LONG}, {0, GDT_PRESENT | GDT_DPL(0) | GDT_CODE | GDT_LONG},
{0, GDT_PRESENT | GDT_DPL(3) | GDT_CODE | GDT_LONG}, {0, GDT_PRESENT | GDT_DPL(3) | GDT_CODE | GDT_LONG},
{0, GDT_PRESENT | GDT_DPL(3) | (1<<12) | (1<<9)},
{0, 0}, {0, 0},
{0, 0}, {0, 0},
}; };
@ -56,18 +57,27 @@ void gdt_init(uint64_t *_gdt, void *_tss)
struct gdt *gdt = (struct gdt *)_gdt; struct gdt *gdt = (struct gdt *)_gdt;
memcpy(gdt, BootGDT, sizeof(BootGDT)); memcpy(gdt, BootGDT, sizeof(BootGDT));
struct tss *tss = _tss;
tss->io_mba = sizeof(struct tss);
uint32_t tss_limit = sizeof(struct tss); uint32_t tss_limit = sizeof(struct tss);
uint64_t tss_base = (uint64_t)_tss; uint64_t tss_base = (uint64_t)_tss;
gdt[3].flags = GDT_PRESENT | GDT_TSS; gdt[4].flags = GDT_PRESENT | GDT_TSS;
gdt[3].flags |= (((tss_base >> 24) & 0xFF) << 24); gdt[4].flags |= (((tss_base >> 24) & 0xFF) << 24);
gdt[3].flags |= ((tss_base >> 16) & 0xFF); gdt[4].flags |= ((tss_base >> 16) & 0xFF);
gdt[3].flags |= (((tss_limit >> 16) & 0xF) << 16); gdt[4].flags |= (((tss_limit >> 16) & 0xF) << 16);
gdt[3].addr = ((tss_base & 0xFFFF) << 16) | (tss_limit & 0xFFFF); gdt[4].addr = ((tss_base & 0xFFFF) << 16) | (tss_limit & 0xFFFF);
gdt[4].flags = 0; gdt[5].flags = 0;
gdt[4].addr = ((tss_base >> 32) & 0xFFFF); gdt[5].addr = ((tss_base >> 32) & 0xFFFFFFFF);
GDTp.len = 5*8 - 1; GDTp.len = 6*8 - 1;
GDTp.gdt = gdt; GDTp.gdt = gdt;
load_gdt(&GDTp); load_gdt(&GDTp);
} }
void set_tss_rsp0(void *_tss, void *rsp0)
{
struct tss *tss = _tss;
tss->rsp0 = (uint64_t)rsp0;
}

View File

@ -17,7 +17,7 @@ load_gdt:
push rax push rax
retfq retfq
.load_gdt: .load_gdt:
mov rax, 0x18 mov rax, 0x20
ltr ax ltr ax
ret ret

View File

@ -3,6 +3,8 @@
void cpu_init(); void cpu_init();
extern uint8_t tss[];
void set_tss_rsp0(void *tss, void *rsp0);
void load_idt(void *); void load_idt(void *);

View File

@ -18,6 +18,7 @@
#define PAGE_PRESENT 0x001 #define PAGE_PRESENT 0x001
#define PAGE_WRITE 0x002 #define PAGE_WRITE 0x002
#define PAGE_USER 0x004
#define PAGE_HUGE 0x080 #define PAGE_HUGE 0x080
#define PAGE_GLOBAL 0x100 #define PAGE_GLOBAL 0x100

View File

@ -2,6 +2,7 @@
#include <queue.h> #include <queue.h>
#include <scheduler.h> #include <scheduler.h>
#include <stdint.h> #include <stdint.h>
#include <interrupts.h>
struct process struct process
{ {

View File

@ -11,8 +11,10 @@ struct swtch_stack
uint64_t R13; uint64_t R13;
uint64_t R14; uint64_t R14;
uint64_t R15; uint64_t R15;
uint64_t isr_return_arg;
uint64_t RBP2; uint64_t RBP2;
uint64_t ret; uint64_t ret;
registers r;
}__attribute__((packed)); }__attribute__((packed));
struct process *sched_proc = 0; struct process *sched_proc = 0;
@ -28,7 +30,15 @@ struct process *new_process(void (*function)(void))
struct swtch_stack *stk = proc->stack_ptr; struct swtch_stack *stk = proc->stack_ptr;
stk->RBP = (uint64_t)&stk->RBP2; stk->RBP = (uint64_t)&stk->RBP2;
stk->ret = (uint64_t)function;
stk->ret = (uint64_t)isr_return;
stk->isr_return_arg = (uint64_t)&stk->r;
stk->r.rip = (uint64_t)function;
stk->r.cs = 0x10 | 3;
stk->r.ss = 0x18 | 3;
stk->r.rflags = 3<<12;
stk->r.rsp = 0x10FFF;
return proc; return proc;
} }
@ -52,6 +62,7 @@ void scheduler()
_proc = new; _proc = new;
write_cr3(new->P4); write_cr3(new->P4);
set_tss_rsp0(tss, new + PAGE_SIZE);
switch_stack(&sched_proc->stack_ptr, &new->stack_ptr); switch_stack(&sched_proc->stack_ptr, &new->stack_ptr);
ready(_proc); ready(_proc);
@ -61,8 +72,15 @@ void scheduler()
void start_scheduler() void start_scheduler()
{ {
sched_proc = new_process(scheduler); sched_proc = P2V(pmm_calloc());
sched_proc->pid = (uint64_t)-1; sched_proc->pid = (uint64_t)-1;
sched_proc->stack_ptr = incptr(sched_proc, PAGE_SIZE - sizeof(struct swtch_stack) + sizeof(registers));
sched_proc->P4 = kernel_P4;
struct swtch_stack *stk = sched_proc->stack_ptr;
stk->RBP = (uint64_t)&stk->RBP2;
stk->ret = (uint64_t)scheduler;
uint64_t stack; uint64_t stack;
switch_stack(&stack, &sched_proc->stack_ptr); switch_stack(&stack, &sched_proc->stack_ptr);

View File

@ -5,6 +5,7 @@
switch_stack: switch_stack:
push rbp push rbp
mov rbp, rsp mov rbp, rsp
push rdi
push r15 push r15
push r14 push r14
push r13 push r13
@ -21,5 +22,6 @@ switch_stack:
pop r13 pop r13
pop r14 pop r14
pop r15 pop r15
pop rdi
leaveq leaveq
ret ret