From 0e1cf97e19971f743a7e7ee591bf667917018248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Lov=C3=A9n?= Date: Fri, 14 Jan 2022 22:01:28 +0100 Subject: [PATCH] Turn threads into processes by giving them unique page directories --- src/kernel/boot/TEMP-test_scheduler.c | 21 ++++++++++++--- src/kernel/cpu/registers.S | 5 ++++ src/kernel/include/cpu.h | 3 ++- src/kernel/include/memory.h | 2 +- src/kernel/include/proc.h | 19 ++++++------- src/kernel/memory/vmm.c | 7 +++++ src/kernel/proc/process.c | 39 +++++++++++++++++++++++++++ src/kernel/proc/scheduler.c | 32 +++++++++++----------- src/kernel/proc/thread.c | 38 -------------------------- 9 files changed, 98 insertions(+), 68 deletions(-) create mode 100644 src/kernel/proc/process.c delete mode 100644 src/kernel/proc/thread.c diff --git a/src/kernel/boot/TEMP-test_scheduler.c b/src/kernel/boot/TEMP-test_scheduler.c index d427010..6846859 100644 --- a/src/kernel/boot/TEMP-test_scheduler.c +++ b/src/kernel/boot/TEMP-test_scheduler.c @@ -1,16 +1,19 @@ #include #include #include +#include extern gfx_context *term_fb; extern gfx_context kernel_fb; +int *position = (void *)0x20000; + void thread1() { int a = 1; gfx_context *ctx = framebuffer_make_subcontext(&kernel_fb, 700, 300, 100, 100); while(1) { - putCharacter(term_fb, 0, 0, RGB(255,255,0), RGB(0,0,0), '0'+(a++%10)); + putCharacter(term_fb, *position, *position, RGB(255,255,0), RGB(0,0,0), '0'+(a++%10)); flip(term_fb); draw_line(ctx, 0, 100, 50, ((a-1)%100), RGB(0,0,0)); draw_line(ctx, 0, 100, 50, (a%100), RGB(255,0,0)); @@ -24,7 +27,7 @@ void thread2() { int a = 0; while(1) { - putCharacter(term_fb, 10, 10, RGB(0,255,255), RGB(0,0,0), 'A'+(a++%10)); + putCharacter(term_fb, *position, *position, RGB(0,255,255), RGB(0,0,0), 'A'+(a++%10)); flip(term_fb); sched_yield(); @@ -34,9 +37,19 @@ void thread2() void TEMP_test_scheduler() { - struct thread *th1 = new_thread(thread1); + struct process *th1 = new_process(thread1); scheduler_insert(th1); - struct thread *th2 = new_thread(thread2); + struct process *th2 = new_process(thread2); scheduler_insert(th2); + + uint64_t p1 = pmm_alloc(); + uint64_t p2 = pmm_alloc(); + vmm_set_page(th1->P4, 0x20000, p1, PAGE_PRESENT); + vmm_set_page(th2->P4, 0x20000, p2, PAGE_PRESENT); + // Write different values into the position variable for the two processes + int *a = P2V(p1); + *a = 20; + a = P2V(p2); + *a = 70; } \ No newline at end of file diff --git a/src/kernel/cpu/registers.S b/src/kernel/cpu/registers.S index e97c8b4..651fffb 100644 --- a/src/kernel/cpu/registers.S +++ b/src/kernel/cpu/registers.S @@ -3,4 +3,9 @@ .global load_idt load_idt: lidt [rdi] + ret + +.global write_cr3 +write_cr3: + mov cr3, rdi ret \ No newline at end of file diff --git a/src/kernel/include/cpu.h b/src/kernel/include/cpu.h index 2b1604d..3c38f83 100644 --- a/src/kernel/include/cpu.h +++ b/src/kernel/include/cpu.h @@ -4,4 +4,5 @@ void cpu_init(); // cpu/registers.S -void load_idt(void *); \ No newline at end of file +void load_idt(void *); +void write_cr3(uint64_t); \ No newline at end of file diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index 50ee225..d0a14f3 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -32,7 +32,7 @@ extern uint64_t kernel_P4; // memory/vmm.c - void vmm_init(); + uint64_t new_P4(); uint64_t vmm_get_page(uint64_t P4, uint64_t addr); int vmm_set_page(uint64_t P4, uint64_t addr, uint64_t page, uint16_t flags); void vmm_clear_page(uint64_t P4, uint64_t addr, int free); diff --git a/src/kernel/include/proc.h b/src/kernel/include/proc.h index 09a0367..2597bea 100644 --- a/src/kernel/include/proc.h +++ b/src/kernel/include/proc.h @@ -1,25 +1,26 @@ #pragma once #include -struct thread +struct process { - struct thread *q_next; - uint64_t tid; + uint64_t pid; void *stack_ptr; uint64_t state; + uint64_t P4; + struct process *q_next; uint8_t stack[]; }; -// proc/thread.c -extern struct thread *current_thread; +// proc/process.c +extern struct process *current_proc; // proc/swtch.S void *switch_stack(void *out, void *in); -// proc/thread.c -struct thread *new_thread(void (*function)(void)); -struct thread *thread(); +// proc/process.c +struct process *new_process(void (*function)(void)); +struct process *proc(); // proc/scheduler.c -void scheduler_insert(struct thread *new); +void scheduler_insert(struct process *new); void start_scheduler(); \ No newline at end of file diff --git a/src/kernel/memory/vmm.c b/src/kernel/memory/vmm.c index a6c40d8..7ceed69 100644 --- a/src/kernel/memory/vmm.c +++ b/src/kernel/memory/vmm.c @@ -42,6 +42,13 @@ static int touch_P1(uint64_t P4, uint64_t addr, uint16_t flags) return 0; } +uint64_t new_P4() +{ + uint64_t p4 = pmm_alloc(); + memcpy(P2V(p4), (void *)kernel_P4, PAGE_SIZE); + return p4; +} + uint64_t vmm_get_page(uint64_t P4, uint64_t addr) { if(P1_exists(P4, addr)) diff --git a/src/kernel/proc/process.c b/src/kernel/proc/process.c new file mode 100644 index 0000000..e55bc1d --- /dev/null +++ b/src/kernel/proc/process.c @@ -0,0 +1,39 @@ +#include +#include +#include + +struct swtch_stack +{ + uint64_t RBP; + uint64_t RBX; + uint64_t R12; + uint64_t R13; + uint64_t R14; + uint64_t R15; + uint64_t RBP2; + uint64_t ret; +}; + +static uint64_t next_pid = 1; + +struct process *current_proc; + +struct process *new_process(void (*function)(void)) +{ + struct process *p = P2V(pmm_calloc()); + p->pid = next_pid++; + p->stack_ptr = incptr(p, PAGE_SIZE - sizeof(struct swtch_stack)); + p->q_next = 0; + p->P4 = new_P4(); + + struct swtch_stack *stck = p->stack_ptr; + stck->RBP = (uint64_t)&stck->RBP2; + stck->ret = (uint64_t)function; + + return p; +} + +struct process *proc() +{ + return current_proc; +} \ No newline at end of file diff --git a/src/kernel/proc/scheduler.c b/src/kernel/proc/scheduler.c index e195e14..85270d9 100644 --- a/src/kernel/proc/scheduler.c +++ b/src/kernel/proc/scheduler.c @@ -1,21 +1,22 @@ #include +#include static struct { - struct thread *first; - struct thread *last; + struct process *first; + struct process *last; } run_q = {0,0}; -static struct thread *scheduler_thread; +static struct process *scheduler_proc; -static struct thread *scheduler_next() +static struct process *scheduler_next() { - struct thread *ret = run_q.first; + struct process *ret = run_q.first; if(run_q.first && !(run_q.first = run_q.first->q_next)) run_q.last = 0; return ret; } -void scheduler_insert(struct thread *new) +void scheduler_insert(struct process *new) { if(run_q.last) { run_q.last->q_next = new; @@ -30,28 +31,29 @@ void scheduler() { while(1) { - struct thread *new = 0; + struct process *new = 0; while(!(new = scheduler_next())); - current_thread = new; - switch_stack(&scheduler_thread->stack_ptr, &new->stack_ptr); + current_proc = new; + write_cr3(new->P4); + switch_stack(&scheduler_proc->stack_ptr, &new->stack_ptr); - scheduler_insert(current_thread); - current_thread = 0; + scheduler_insert(current_proc); + current_proc = 0; } } long k_sched_yield(long, long, long, long, long, long) { - switch_stack(¤t_thread->stack_ptr, &scheduler_thread->stack_ptr); + switch_stack(¤t_proc->stack_ptr, &scheduler_proc->stack_ptr); return 0; } void start_scheduler() { - scheduler_thread = new_thread(scheduler); - scheduler_thread->tid = (uint64_t)-1; + scheduler_proc = new_process(scheduler); + scheduler_proc->pid = (uint64_t)-1; uint64_t stack; - switch_stack(&stack, &scheduler_thread->stack_ptr); + switch_stack(&stack, &scheduler_proc->stack_ptr); } \ No newline at end of file diff --git a/src/kernel/proc/thread.c b/src/kernel/proc/thread.c deleted file mode 100644 index bf1a81a..0000000 --- a/src/kernel/proc/thread.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include -#include - -struct swtch_stack -{ - uint64_t RBP; - uint64_t RBX; - uint64_t R12; - uint64_t R13; - uint64_t R14; - uint64_t R15; - uint64_t RBP2; - uint64_t ret; -}; - -static uint64_t next_tid = 1; - -struct thread *current_thread; - -struct thread *new_thread(void (*function)(void)) -{ - struct thread *th = P2V(pmm_calloc()); - th->tid = next_tid++; - th->stack_ptr = incptr(th, PAGE_SIZE - sizeof(struct swtch_stack)); - th->q_next = 0; - - struct swtch_stack *stck = th->stack_ptr; - stck->RBP = (uint64_t)&stck->RBP2; - stck->ret = (uint64_t)function; - - return th; -} - -struct thread *thread() -{ - return current_thread; -} \ No newline at end of file