diff --git a/.gdbinit b/.gdbinit new file mode 100644 index 0000000..ad7a6f7 --- /dev/null +++ b/.gdbinit @@ -0,0 +1 @@ +target remote :1234 diff --git a/kernel/Makefile b/kernel/Makefile index 8ad125b..b4b423e 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -47,7 +47,7 @@ SRCFILES := $(wildcard *.c) \ $(wildcard fs/littlefs/*.c) \ $(wildcard fs/portlfs/*.c) \ $(wildcard baseimg/*.c) \ - $(wildcard task/*.c) \ + $(wildcard proc/*.c) \ $(wildcard hal/*.c) \ $(wildcard hal/$(ARCH)/*.c) \ $(wildcard hal/$(ARCH)/*.S) \ diff --git a/kernel/hal/hal.h b/kernel/hal/hal.h index 7dee641..2fe9749 100644 --- a/kernel/hal/hal.h +++ b/kernel/hal/hal.h @@ -23,6 +23,10 @@ void hal_init_withmalloc(void); #if defined(__x86_64__) # define HAL_PAGE_SIZE 0x1000 # include "x86_64/vmm.h" +# include "x86_64/proc.h" +# include "x86_64/switch.h" +# include "x86_64/paging.h" +# include "x86_64/cpu.h" #endif #endif // KERNEL_HAL_HAL_H_ diff --git a/kernel/hal/x86_64/cpu.c b/kernel/hal/x86_64/cpu.c index 9b9077d..264a0ca 100644 --- a/kernel/hal/x86_64/cpu.c +++ b/kernel/hal/x86_64/cpu.c @@ -1,13 +1,13 @@ #include #include -uint64_t cpu_rdmsr(uint32_t id) { +uint64_t hal_cpu_rdmsr(uint32_t id) { uint32_t lo, hi; asm volatile("rdmsr" : "=m"(lo), "=d"(hi) : "c"(id)); return ((uint64_t)lo) | ((uint64_t)hi << 32); } -uint64_t cpu_wrmsr(uint32_t id, uint64_t val) { +uint64_t hal_cpu_wrmsr(uint32_t id, uint64_t val) { uint32_t lo = val & 0xffffffff, hi = (val >> 32) & 0xffffffff; asm volatile("wrmsr" :: "a"(lo), "d"(hi), "c"(id) : "memory"); return val; diff --git a/kernel/hal/x86_64/cpu.h b/kernel/hal/x86_64/cpu.h index ae92118..a546fae 100644 --- a/kernel/hal/x86_64/cpu.h +++ b/kernel/hal/x86_64/cpu.h @@ -1,7 +1,11 @@ #ifndef HAL_CPU_H_ #define HAL_CPU_H_ -uint64_t cpu_rdmsr(uint32_t id); -uint64_t cpu_wrmsr(uint32_t id, uint64_t val); +#define HAL_CPU_FSBASE 0xC0000100 +#define HAL_CPU_GSBASE 0xC0000101 +#define HAL_CPU_KGSBASE 0xC0000102 + +uint64_t hal_cpu_rdmsr(uint32_t id); +uint64_t hal_cpu_wrmsr(uint32_t id, uint64_t val); #endif // HAL_CPU_H_ diff --git a/kernel/hal/x86_64/intr.c b/kernel/hal/x86_64/intr.c index 3c645a9..ea50ec9 100644 --- a/kernel/hal/x86_64/intr.c +++ b/kernel/hal/x86_64/intr.c @@ -10,6 +10,7 @@ #include "pic.h" #include "apic.h" #include "pit.h" +#include "proc/proc.h" void hal_intr_disable(void) { asm volatile("cli"); @@ -151,7 +152,7 @@ void intr_dumpframe(IntrStackFrame *frame) { void intr_handleintr(IntrStackFrame *frame) { if (frame->trapnum >= 0 && frame->trapnum <= 31) { // EXCEPTION - kprintf_unsafe("ERROR", "%s, 0x%lX\n", exceptions[frame->trapnum], frame->errnum); + kprintf_unsafe("ERROR %s, 0x%lX\n", exceptions[frame->trapnum], frame->errnum); intr_dumpframe(frame); hal_hang(); } else if (frame->trapnum >= 32 && frame->trapnum <= 47) { @@ -161,6 +162,8 @@ void intr_handleintr(IntrStackFrame *frame) { } io_out8(PIC1_CMD, 0x20); lapic_write(LAPIC_EOI, 0x00); + + proc_sched((void *)frame); } } diff --git a/kernel/hal/x86_64/intr0.S b/kernel/hal/x86_64/intr0.S index 5547480..c905969 100644 --- a/kernel/hal/x86_64/intr0.S +++ b/kernel/hal/x86_64/intr0.S @@ -1,3 +1,5 @@ +#include "regs.S" + .extern intr_handleintr .global intr_vec0 @@ -49,38 +51,6 @@ .global intr_vec46 .global intr_vec47 -.macro _push_regs - push %rax - push %rcx - push %rdx - push %rsi - push %rdi - push %r8 - push %r9 - push %r10 - push %r11 - push %r12 - push %r13 - push %r14 - push %r15 -.endm - -.macro _pop_regs - pop %r15 - pop %r14 - pop %r13 - pop %r12 - pop %r11 - pop %r10 - pop %r9 - pop %r8 - pop %rdi - pop %rsi - pop %rdx - pop %rcx - pop %rax -.endm - .macro _vecintr_errorcode_present_save num pushq $\num .endm diff --git a/kernel/hal/x86_64/paging.S b/kernel/hal/x86_64/paging.S index e54570e..9e1a9de 100644 --- a/kernel/hal/x86_64/paging.S +++ b/kernel/hal/x86_64/paging.S @@ -2,8 +2,3 @@ hal_loadpd: mov %rdi, %cr3 retq - -.global hal_invalpg -hal_invalpg: - invlpg (%rdi) - retq diff --git a/kernel/hal/x86_64/paging.h b/kernel/hal/x86_64/paging.h new file mode 100644 index 0000000..e50679b --- /dev/null +++ b/kernel/hal/x86_64/paging.h @@ -0,0 +1,6 @@ +#ifndef HAL_PAGING_H_ +#define HAL_PAGING_H_ + +void hal_loadpd(PgTable *cr3); + +#endif // HAL_PAGING_H_ diff --git a/kernel/hal/x86_64/proc.h b/kernel/hal/x86_64/proc.h new file mode 100644 index 0000000..cf6932b --- /dev/null +++ b/kernel/hal/x86_64/proc.h @@ -0,0 +1,15 @@ +#ifndef HAL_PROC_H_ +#define HAL_PROC_H_ + +#include +#include "intr.h" +#include "vmm.h" + +typedef struct { + uint64_t fsbase; + IntrStackFrame trapframe; + uint8_t *kstack; + PgTable *cr3; +} ProcPlatformData; + +#endif // HAL_PROC_H_ diff --git a/kernel/hal/x86_64/regs.S b/kernel/hal/x86_64/regs.S new file mode 100644 index 0000000..862af16 --- /dev/null +++ b/kernel/hal/x86_64/regs.S @@ -0,0 +1,31 @@ +.macro _push_regs + push %rax + push %rcx + push %rdx + push %rsi + push %rdi + push %r8 + push %r9 + push %r10 + push %r11 + push %r12 + push %r13 + push %r14 + push %r15 +.endm + +.macro _pop_regs + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %r11 + pop %r10 + pop %r9 + pop %r8 + pop %rdi + pop %rsi + pop %rdx + pop %rcx + pop %rax +.endm diff --git a/kernel/hal/x86_64/switch.S b/kernel/hal/x86_64/switch.S new file mode 100644 index 0000000..3e344ea --- /dev/null +++ b/kernel/hal/x86_64/switch.S @@ -0,0 +1,19 @@ +#include "regs.S" + +siema: + jmp siema + +.global hal_switchproc +hal_switchproc: + mov %cr3, %rcx + cmp %rsi, %rcx + je .done + mov %rsi, %cr3 +.done: + mov %rdi, %rsp + + _pop_regs + add $0x10, %rsp + + iretq + diff --git a/kernel/hal/x86_64/switch.h b/kernel/hal/x86_64/switch.h new file mode 100644 index 0000000..5112a87 --- /dev/null +++ b/kernel/hal/x86_64/switch.h @@ -0,0 +1,6 @@ +#ifndef HAL_SWITCH_H_ +#define HAL_SWITCH_H_ + +extern void hal_switchproc(void *newsp, PgTable *cr3); + +#endif // HAL_SWITCH_H_ diff --git a/kernel/hal/x86_64/vmm.c b/kernel/hal/x86_64/vmm.c index c5b5e98..3b73f31 100644 --- a/kernel/hal/x86_64/vmm.c +++ b/kernel/hal/x86_64/vmm.c @@ -4,6 +4,7 @@ #include "hal/hal.h" #include "bootinfo/bootinfo.h" #include "pmm/pmm.h" +#include "paging.h" PgTable *KERNEL_CR3 = NULL; @@ -60,6 +61,41 @@ void hal_vmm_unmap_page(PgTable *pml4, uint64_t virtaddr, uint64_t physaddr) { *pte &= ~HAL_PG_PRESENT; } +void hal_vmm_map_range(PgTable *cr3, void *virtstart, void *physstart, size_t size, uint32_t flags) { + if (size % HAL_PAGE_SIZE != 0 || (uint64_t)virtstart % HAL_PAGE_SIZE != 0 || (uint64_t)physstart % HAL_PG_PRESENT != 0) { + return; + } + + uint8_t *vaddr = virtstart, *paddr = physstart; + + for (; vaddr <= ((uint8_t *)virtstart + size); vaddr += HAL_PAGE_SIZE, paddr += HAL_PAGE_SIZE) { + hal_vmm_map_page(cr3, (uint64_t)vaddr, (uint64_t)paddr, flags); + } +} + +void hal_vmm_unmap_range(PgTable *cr3, void *virtstart, void *physstart, size_t size, uint32_t flags) { + if (size % HAL_PAGE_SIZE != 0 || (uint64_t)virtstart % HAL_PAGE_SIZE != 0 || (uint64_t)physstart % HAL_PG_PRESENT != 0) { + return; + } + + uint8_t *vaddr = virtstart, *paddr = physstart; + + for (; vaddr <= ((uint8_t *)virtstart + size); vaddr += HAL_PAGE_SIZE, paddr += HAL_PAGE_SIZE) { + hal_vmm_unmap_page(cr3, (uint64_t)vaddr, (uint64_t)paddr); + } +} + +void hal_vmm_map_kern(PgTable *cr3) { + PgTable *kcr3 = BOOT_INFO.hhdm_off + KERNEL_CR3; + for (size_t i = 256; i < 512; i++) { + cr3->ents[i] = kcr3->ents[i]; + } +} + +void hal_vmm_switch_pd(PgTable *cr3) { + hal_loadpd(cr3); +} + void hal_vmm_init(void) { KERNEL_CR3 = hal_vmm_current_cr3(); } diff --git a/kernel/hal/x86_64/vmm.h b/kernel/hal/x86_64/vmm.h index 7d60869..6a8622f 100644 --- a/kernel/hal/x86_64/vmm.h +++ b/kernel/hal/x86_64/vmm.h @@ -41,5 +41,8 @@ extern PgTable *KERNEL_CR3; void hal_vmm_init(void); void hal_vmm_unmap_page(PgTable *pml4, uint64_t virtaddr, uint64_t physaddr); void hal_vmm_map_page(PgTable *pml4, uint64_t virtaddr, uint64_t physaddr, uint32_t flags); +PgTable *hal_vmm_current_cr3(void); +void hal_vmm_map_range(PgTable *cr3, void *virtstart, void *physstart, size_t size, uint32_t flags); +void hal_vmm_unmap_range(PgTable *cr3, void *virtstart, void *physstart, size_t size, uint32_t flags); #endif // HAL_VMM_H_ diff --git a/kernel/kmain.c b/kernel/kmain.c index 49ed0d5..01bd6b3 100644 --- a/kernel/kmain.c +++ b/kernel/kmain.c @@ -11,6 +11,7 @@ #include "baseimg/baseimg.h" #include "storedev/storedev.h" #include "util/util.h" +#include "proc/proc.h" const char *human_size(uint64_t bytes, char *buf, size_t bufsize) { static const char *units[] = { "B", "KiB", "MiB", "GiB", "TiB", "PiB" }; @@ -56,7 +57,7 @@ void kmain(void) { } bootinfo_init(); - term_init(); + term_init(BOOT_INFO.fb->address); log_bootinfo(); hal_init(); pmm_init(); @@ -66,9 +67,7 @@ void kmain(void) { baseimg_init(); vfs_init(); hal_init_withmalloc(); - - /* hal_intr_enable(); */ - kprintf(BANNER_TEXT "\n"); + proc_init(); for(;;); } diff --git a/kernel/proc/proc.c b/kernel/proc/proc.c new file mode 100644 index 0000000..3a16f1d --- /dev/null +++ b/kernel/proc/proc.c @@ -0,0 +1,159 @@ +#include +#include +#include "hal/hal.h" +#include "vmm/vmm.h" +#include "spinlock/spinlock.h" +#include "proc.h" +#include "dlmalloc/malloc.h" +#include "pmm/pmm.h" +#include "util/util.h" +#include "kprintf.h" + +#define PROC_REAPER_FREQ 30 + +uint64_t pids = 0; +uint64_t sched_ticks = 0; + +Procs PROCS; + +Proc *proc_spawnkern(void (*ent)(void), char *name) { + Proc *proc = dlmalloc(sizeof(*proc)); + if (proc == NULL) { + return NULL; + } + hal_memset(proc, 0, sizeof(*proc)); + hal_memcpy(proc->name, name, PROC_NAME_MAX); + + proc->kern = true; + + uint8_t *sp = (uint8_t *)pmm_alloc(PROC_STACKBLOCKS) + PROC_STACKSIZE; + + #if defined(__x86_64__) + proc->platformdata.kstack = sp; + hal_memset(&proc->platformdata.trapframe, 0, sizeof(proc->platformdata.trapframe)); + + proc->platformdata.trapframe.ss = 0x10; + proc->platformdata.trapframe.rsp = (uint64_t)VIRT(sp); + proc->platformdata.trapframe.rflags = 0x202; + proc->platformdata.trapframe.cs = 0x08; + proc->platformdata.trapframe.rip = (uint64_t)ent; + proc->platformdata.cr3 = hal_vmm_current_cr3(); + proc->state = PROC_READY; + proc->pid = pids++; + #endif + + return proc; +} + +void proc_register(Proc *proc) { + spinlock_acquire(&PROCS.spinlock); + LL_APPEND(PROCS.procs, proc); + spinlock_release(&PROCS.spinlock); +} + +Proc *proc_nextready(void) { + Proc *next = PROCS.current->next; + Proc *proc = next == NULL ? PROCS.procs : next; + return proc; +} + +void proc_sched(void *cpustate) { + hal_intr_disable(); + sched_ticks++; + + if (sched_ticks % PROC_REAPER_FREQ == 0) { + Proc *head = PROCS.procs; + while (head) { + if (head->state == PROC_ZOMBIE) { + Proc *zombie = head; + head = head->next; + + LL_REMOVE(PROCS.procs, zombie); + pmm_free((uintptr_t)(zombie->platformdata.kstack - PROC_STACKSIZE), PROC_STACKBLOCKS); + dlfree(zombie); + } else { + head = head->next; + } + } + } + + #if defined(__x86_64__) + IntrStackFrame *frame = cpustate; + + PROCS.current->platformdata.trapframe = *frame; + PROCS.current->platformdata.fsbase = hal_cpu_rdmsr(HAL_CPU_FSBASE); + #endif + + PROCS.current = proc_nextready(); + PROCS.current->state = PROC_RUNNING; + + #if defined(__x86_64__) + hal_cpu_wrmsr(HAL_CPU_FSBASE, PROCS.current->platformdata.fsbase); + hal_switchproc(&PROCS.current->platformdata.trapframe, (void *)PROCS.current->platformdata.cr3); + #endif +} + +void proc_kill(Proc *proc) { + proc->state = PROC_ZOMBIE; +} + +void proc_killself(void) { + spinlock_acquire(&PROCS.spinlock); + Proc *proc = PROCS.current; + proc_kill(proc); + spinlock_release(&PROCS.spinlock); +} + +void proc_idle(void) { + for(;;) { + // . + } +} + +int a = 0; + +void proc_print(void) { + for (;;) { + for (volatile size_t i = 0; i < 0x1000000; i++) { + } + + if (a == 10) { + proc_killself(); + for(;;); + } + kprintf("A"); + a++; + } +} + +int b = 0; + +void proc_print2(void) { + for (;;) { + for (volatile size_t i = 0; i < 0x1000000; i++) { + } + + if (b == 20) { + proc_killself(); + for(;;); + } + kprintf("B"); + b++; + } +} + +void proc_init(void) { + spinlock_init(&PROCS.spinlock); + PROCS.procs = NULL; + + Proc *idle = proc_spawnkern(&proc_idle, "kIDLE"); + proc_register(idle); + PROCS.current = idle; + + proc_register(proc_spawnkern(&proc_print, "print")); + proc_register(proc_spawnkern(&proc_print2, "print")); + + #if defined(__x86_64__) + hal_switchproc(&PROCS.current->platformdata.trapframe, (void *)PROCS.current->platformdata.cr3); + #endif +} diff --git a/kernel/proc/proc.h b/kernel/proc/proc.h new file mode 100644 index 0000000..61461a9 --- /dev/null +++ b/kernel/proc/proc.h @@ -0,0 +1,44 @@ +#ifndef PROC_PROC_H_ +#define PROC_PROC_H_ + +#include +#include "hal/hal.h" +#include "vmm/vmm.h" +#include "spinlock/spinlock.h" +#include "bitmap/bitmap.h" + +#define PROC_NAME_MAX 0x100 + +#define PROC_STACKBLOCKS 32 +#define PROC_STACKSIZE (PROC_STACKBLOCKS * BITMAP_BLOCK_SIZE) + +enum { + PROC_READY, + PROC_RUNNING, + PROC_ZOMBIE, + PROC_WAITING, +}; + +typedef struct Proc { + struct Proc *next; + uint64_t pid; + char name[PROC_NAME_MAX]; + ProcPlatformData platformdata; + uint8_t state; + VasRange *vas; + bool kern; +} Proc; + +typedef struct { + SpinLock spinlock; + Proc *procs; + Proc *current; +} Procs; + +extern Procs PROCS; + +void proc_init(void); +Proc *proc_spawnkern(void (*ent)(void), char *name); +void proc_sched(void *cpustate); + +#endif // PROC_PROC_H_ diff --git a/kernel/term/term.c b/kernel/term/term.c index a118914..ebd000d 100644 --- a/kernel/term/term.c +++ b/kernel/term/term.c @@ -7,11 +7,10 @@ Term TERM; -void term_init(void) { - spinlock_init(&TERM.spinlock); +void term_doinit(void *addr) { TERM.ftctx = flanterm_fb_init( NULL, NULL, - BOOT_INFO.fb->address, + addr, BOOT_INFO.fb->width, BOOT_INFO.fb->height, BOOT_INFO.fb->pitch, @@ -31,6 +30,11 @@ void term_init(void) { ); } +void term_init(void *addr) { + spinlock_init(&TERM.spinlock); + term_doinit(addr); +} + void term_write_unsafe(const char *s, size_t len) { flanterm_write(TERM.ftctx, s, len); } diff --git a/kernel/term/term.h b/kernel/term/term.h index d0367bf..fe91fe2 100644 --- a/kernel/term/term.h +++ b/kernel/term/term.h @@ -12,7 +12,7 @@ typedef struct { extern Term TERM; -void term_init(void); +void term_init(void *addr); void term_write_unsafe(const char *s, size_t len); #endif // TERM_TERM_H_ diff --git a/kernel/vmm/vmm.c b/kernel/vmm/vmm.c index ba766d9..e1a8856 100644 --- a/kernel/vmm/vmm.c +++ b/kernel/vmm/vmm.c @@ -12,26 +12,42 @@ VirtMem VIRT_MEM; void vmm_map_kern_page(uint64_t virtaddr, uint64_t physaddr, uint32_t flags) { + spinlock_acquire(&VIRT_MEM.spinlock); #if defined(__x86_64__) hal_vmm_map_page(KERNEL_CR3, virtaddr, physaddr, flags); - #else - # error "arch" #endif + spinlock_release(&VIRT_MEM.spinlock); } void vmm_unmap_kern_page(uint64_t virtaddr, uint64_t physaddr) { + spinlock_acquire(&VIRT_MEM.spinlock); #if defined(__x86_64__) hal_vmm_unmap_page(KERNEL_CR3, virtaddr, physaddr); - #else - # error "arch" #endif + spinlock_release(&VIRT_MEM.spinlock); +} + +void vmm_map_kern_range(void *virtstart, void *physstart, size_t size, uint32_t flags) { + spinlock_acquire(&VIRT_MEM.spinlock); + #if defined(__x86_64__) + hal_vmm_map_range(KERNEL_CR3, virtstart, physstart, size, flags); + #endif + spinlock_release(&VIRT_MEM.spinlock); +} + +void vmm_unmap_kern_range(void *virtstart, void *physstart, size_t size, uint32_t flags) { + spinlock_acquire(&VIRT_MEM.spinlock); + #if defined(__x86_64__) + hal_vmm_unmap_range(KERNEL_CR3, virtstart, physstart, size, flags); + #endif + spinlock_release(&VIRT_MEM.spinlock); } void vmm_init(void) { spinlock_init(&VIRT_MEM.spinlock); hal_vmm_init(); - + LOG("vmm", "init\n"); } diff --git a/kernel/vmm/vmm.h b/kernel/vmm/vmm.h index b1a7de2..ec3e2b8 100644 --- a/kernel/vmm/vmm.h +++ b/kernel/vmm/vmm.h @@ -4,11 +4,21 @@ #include #include "spinlock/spinlock.h" #include "bootinfo/bootinfo.h" +#include "compiler/attr.h" typedef struct { SpinLock spinlock; } VirtMem; +typedef struct VasRange { + struct VasRange *next; + + uint8_t *virtstart; + uint8_t *physstart; + size_t size; + uint8_t pgflags; +} PACKED VasRange; + extern VirtMem VIRT_MEM; void vmm_init(void);