diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | src/kernel/arch/amd64/debug.c | 2 | ||||
-rw-r--r-- | src/kernel/arch/amd64/interrupts/isr.c | 22 | ||||
-rw-r--r-- | src/kernel/arch/amd64/pagedir.c | 117 | ||||
-rw-r--r-- | src/kernel/arch/amd64/sysenter.c | 7 | ||||
-rw-r--r-- | src/kernel/arch/amd64/sysenter.h | 2 | ||||
-rw-r--r-- | src/kernel/main.c | 9 | ||||
-rw-r--r-- | src/kernel/proc.c | 2 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 1 | ||||
-rw-r--r-- | src/user/app/main.c | 2 |
10 files changed, 80 insertions, 86 deletions
@@ -4,7 +4,7 @@ AS = x86_64-elf-as CC = x86_64-elf-gcc CHECK = sparse CFLAGS += -g -std=gnu99 -ffreestanding -O2 -Wall -Wextra -Wold-style-definition -Werror=implicit-function-declaration -ftrack-macro-expansion=0 -CFLAGS += -mgeneral-regs-only +CFLAGS += -mgeneral-regs-only -Wno-address-of-packed-member CFLAGS += -Isrc/ SPARSEFLAGS = -Wno-non-pointer-null LFLAGS = -ffreestanding -O2 -nostdlib -lgcc -Wl,-zmax-page-size=4096 -Wl,--no-warn-mismatch diff --git a/src/kernel/arch/amd64/debug.c b/src/kernel/arch/amd64/debug.c index 52127da..c17c906 100644 --- a/src/kernel/arch/amd64/debug.c +++ b/src/kernel/arch/amd64/debug.c @@ -2,7 +2,7 @@ void *debug_caller(size_t depth) { void **rbp; - asm("mov %%rbp, %0" + asm("mov %%rbp, %0" : "=r" (rbp)); while (depth--) { if (!rbp) return NULL; diff --git a/src/kernel/arch/amd64/interrupts/isr.c b/src/kernel/arch/amd64/interrupts/isr.c index b55bc8b..4df8e57 100644 --- a/src/kernel/arch/amd64/interrupts/isr.c +++ b/src/kernel/arch/amd64/interrupts/isr.c @@ -14,17 +14,17 @@ bool isr_test_interrupt_called = false; void isr_stage3(int interrupt, uint64_t *stackframe) { if (interrupt == 0xe) stackframe++; kprintf("interrupt %x, rip = k/%08x, cs 0x%x\n", interrupt, stackframe[0], stackframe[1]); + if (interrupt == 0xe) { + uint64_t addr = 0x69; + asm("mov %%cr2, %0" : "=r"(addr)); + kprintf("error code 0x%x, addr 0x%x\n", stackframe[-1], addr); + } + switch (interrupt) { case 0x08: // double fault kprintf("#DF"); panic_invalid_state(); - case 0xe: - uint64_t addr = 0x69; - asm("mov %%cr2, %0" : "=r"(addr)); - kprintf("error code 0x%x, addr 0x%x\n", stackframe[-1], addr); - panic_unimplemented(); - case 0x34: asm("nop" ::: "memory"); isr_test_interrupt_called = true; @@ -41,8 +41,12 @@ void isr_stage3(int interrupt, uint64_t *stackframe) { return; default: - // TODO check if the exception was in the kernel - process_kill(process_current, interrupt); - process_switch_any(); + if (stackframe[1] & 0x3 == 0) { + kprintf("bye o7\n"); + cpu_halt(); + } else { + process_kill(process_current, interrupt); + process_switch_any(); + } } } diff --git a/src/kernel/arch/amd64/pagedir.c b/src/kernel/arch/amd64/pagedir.c index 56c541a..0d6078b 100644 --- a/src/kernel/arch/amd64/pagedir.c +++ b/src/kernel/arch/amd64/pagedir.c @@ -94,19 +94,28 @@ void pagedir_free(struct pagedir *dir) { */ } -/* -static struct pagetable_entry* +static pe_generic_t* get_entry(struct pagedir *dir, const void __user *virt) { - uint32_t pd_idx = ((uintptr_t)virt) >> 22; - uint32_t pt_idx = ((uintptr_t)virt) >> 12 & 0x03FF; - struct pagetable_entry *pagetable; + pe_generic_t *pml4e, *pdpte, *pde, *pte; + const union virt_addr v = {.full = (void*)virt}; + + // TODO check if sign extension is valid + + pml4e = &dir->e[v.pml4]; + if (!pml4e->present) return NULL; + assert(!pml4e->large); + + pdpte = &((pe_generic_t*)addr_extract(*pml4e))[v.pdpt]; + if (!pdpte->present) return NULL; + assert(!pdpte->large); - if (!dir->e[pd_idx].present) return NULL; + pde = &((pe_generic_t*)addr_extract(*pdpte))[v.pd]; + if (!pde->present) return NULL; + assert(!pde->large); - pagetable = (void*)(dir->e[pd_idx].address << 11); - return &pagetable[pt_idx]; + pte = &((pe_generic_t*)addr_extract(*pde))[v.pt]; + return pte; } -*/ void *pagedir_unmap(struct pagedir *dir, void __user *virt) { (void)dir; (void)virt; @@ -129,7 +138,6 @@ void pagedir_map(struct pagedir *dir, void __user *virt, void *phys, pml4e = &dir->e[v.pml4]; if (!pml4e->present) { - kprintf("allocating pdpt\n"); pml4e->as_ptr = addr_validate(page_zalloc(1)); pml4e->present = 1; pml4e->writeable = 1; @@ -139,7 +147,6 @@ void pagedir_map(struct pagedir *dir, void __user *virt, void *phys, pdpte = &((pe_generic_t*)addr_extract(*pml4e))[v.pdpt]; if (!pdpte->present) { - kprintf("allocating pd\n"); pdpte->as_ptr = addr_validate(page_zalloc(1)); pdpte->present = 1; pdpte->writeable = 1; @@ -149,7 +156,6 @@ void pagedir_map(struct pagedir *dir, void __user *virt, void *phys, pde = &((pe_generic_t*)addr_extract(*pdpte))[v.pd]; if (!pde->present) { - kprintf("allocating pt\n"); pde->as_ptr = addr_validate(page_zalloc(1)); pde->present = 1; pde->writeable = 1; @@ -174,68 +180,67 @@ void pagedir_switch(struct pagedir *dir) { } // creates a new pagedir with exact copies of the user pages -struct pagedir *pagedir_copy(const struct pagedir *orig) { - /* - struct pagedir *clone = page_alloc(1); - struct pagetable_entry *orig_pt, *clone_pt; - void *orig_page, *clone_page; - - for (int i = 0; i < 1024; i++) { - clone->e[i] = orig->e[i]; - if (!orig->e[i].present) continue; - - orig_pt = (void*)(orig->e[i].address << 11); - clone_pt = page_alloc(1); - clone->e[i].address = (uintptr_t) clone_pt >> 11; - - for (int j = 0; j < 1024; j++) { - clone_pt[j] = orig_pt[j]; - if (!orig_pt[j].present) continue; - if (!orig_pt[j].user) continue; - // i could use .global? - - orig_page = (void*)(orig_pt[j].address << 11); - clone_page = page_alloc(1); - clone_pt[j].address = (uintptr_t) clone_page >> 11; - - memcpy(clone_page, orig_page, PAGE_SIZE); +struct pagedir *pagedir_copy(const struct pagedir *pml4_old) { + struct pagedir *pml4_new = page_zalloc(1); + + for (int i = 0; i < 512; i++) { + if (!pml4_old->e[i].present) continue; + assert(!pml4_old->e[i].large); + const pe_generic_t *pdpt_old = addr_extract(pml4_old->e[i]); + pe_generic_t *pdpt_new = page_zalloc(1); + pml4_new->e[i] = pml4_old->e[i]; + pml4_new->e[i].address = (uintptr_t) pdpt_new >> 12; + + for (int j = 0; j < 512; j++) { + if (!pdpt_old[j].present) continue; + assert(!pdpt_old[j].large); + const pe_generic_t *pd_old = addr_extract(pdpt_old[j]); + pe_generic_t *pd_new = page_zalloc(1); + pdpt_new[j] = pdpt_old[j]; + pdpt_new[j].address = (uintptr_t) pd_new >> 12; + + for (int k = 0; k < 512; k++) { + if (!pd_old[k].present) continue; + assert(!pd_old[k].large); + const pe_generic_t *pt_old = addr_extract(pd_old[k]); + pe_generic_t *pt_new = page_zalloc(1); + pd_new[k] = pd_old[k]; + pd_new[k].address = (uintptr_t) pt_new >> 12; + + for (int l = 0; l < 512; l++) { + if (!pt_old[l].present || !pt_old[l].user) + continue; + void *page_new = page_alloc(1); + memcpy(page_new, addr_extract(pt_old[l]), PAGE_SIZE); + pt_new[l] = pt_old[l]; + pt_new[l].address = (uintptr_t) page_new >> 12; + } + } } } - return clone; - */ - panic_unimplemented(); + return pml4_new; } bool pagedir_iskern(struct pagedir *dir, const void __user *virt) { - /* - struct pagetable_entry *page = get_entry(dir, virt); + pe_generic_t *page = get_entry(dir, virt); return page && page->present && !page->user; - */ - panic_unimplemented(); } void *pagedir_virt2phys(struct pagedir *dir, const void __user *virt, bool user, bool writeable) { - /* - struct pagetable_entry *page; - uintptr_t phys; - page = get_entry(dir, virt); + pe_generic_t *page = get_entry(dir, virt); if (!page || !page->present) return NULL; if (user && !page->user) return NULL; if (writeable && !page->writeable) return NULL; - phys = page->address << 11; - phys |= ((uintptr_t)virt) & 0xFFF; - return (void*)phys; - */ - panic_unimplemented(); + return addr_extract(*page) + ((uintptr_t)virt & PAGE_MASK); } void __user *pagedir_findfree(struct pagedir *dir, char __user *start, size_t len) { - /* - struct pagetable_entry *page; + // TODO dogshit slow + pe_generic_t *page; char __user *iter; start = (userptr_t)(((uintptr_t __force)start + PAGE_MASK) & ~PAGE_MASK); // round up to next page iter = start; @@ -251,6 +256,4 @@ void __user *pagedir_findfree(struct pagedir *dir, char __user *start, size_t le iter += PAGE_SIZE; } return NULL; - */ - panic_unimplemented(); } diff --git a/src/kernel/arch/amd64/sysenter.c b/src/kernel/arch/amd64/sysenter.c index 543e5bc..7591d83 100644 --- a/src/kernel/arch/amd64/sysenter.c +++ b/src/kernel/arch/amd64/sysenter.c @@ -5,19 +5,14 @@ struct registers _sysexit_regs; -void sysexit(struct registers regs) { +_Noreturn void sysexit(struct registers regs) { _sysexit_regs = regs; - kprintf("ring3...\n"); _sysexit_real(); - __builtin_unreachable(); } _Noreturn void sysenter_stage2(void) { struct registers *regs = &process_current->regs; *regs = _sysexit_regs; - - kprintf("ring0!\n"); - _syscall(regs->rdi, regs->rsi, regs->rdx, regs->r10, regs->r8); process_switch_any(); } diff --git a/src/kernel/arch/amd64/sysenter.h b/src/kernel/arch/amd64/sysenter.h index b88c186..d1274de 100644 --- a/src/kernel/arch/amd64/sysenter.h +++ b/src/kernel/arch/amd64/sysenter.h @@ -5,4 +5,4 @@ extern struct registers _sysexit_regs; _Noreturn void sysenter_stage2(void); // sysenter.s -void _sysexit_real(void); +_Noreturn void _sysexit_real(void); diff --git a/src/kernel/main.c b/src/kernel/main.c index bbdd234..75d9a29 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -18,14 +18,7 @@ void kmain(struct kmain_info info) { } void shutdown(void) { - size_t states[PS_LAST] = {0}; - for (struct process *p = process_first; p; p = process_next(p)) - states[p->state]++; - - kprintf("\n\n\nshutting off\n"); - for (size_t i = 0; i < sizeof(states) / sizeof(*states); i++) - kprintf("state 0x%x: 0x%x\n", i, states[i]); - + kprintf("shutting off\n"); mem_debugprint(); cpu_shutdown(); } diff --git a/src/kernel/proc.c b/src/kernel/proc.c index a202549..4719a93 100644 --- a/src/kernel/proc.c +++ b/src/kernel/proc.c @@ -23,10 +23,8 @@ struct process *process_seed(struct kmain_info *info) { process_first->id = next_pid++; // map the stack to the last page in memory - kprintf("0x%x\n", (userptr_t)~PAGE_MASK); pagedir_map(process_first->pages, (userptr_t)~PAGE_MASK, page_zalloc(1), true, true); process_first->regs.rsp = (userptr_t) ~0xF; - kprintf("post stack\n"); // map .shared extern char _shared_len; diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index 293edae..1d18ad1 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -368,7 +368,6 @@ void _syscall_debug_klog(const void __user *buf, size_t len) { } int _syscall(int num, int a, int b, int c, int d) { - kprintf("%x %x %x %x %x\n", num, a, b, c, d); switch (num) { case _SYSCALL_EXIT: _syscall_exit(a); diff --git a/src/user/app/main.c b/src/user/app/main.c index 92aa56c..527d29f 100644 --- a/src/user/app/main.c +++ b/src/user/app/main.c @@ -23,6 +23,8 @@ int main(void) { file_reopen(stdout, "/com1", 0); printf("preinit\n"); + _syscall_exit(0); // temporary + /* move everything provided by the kernel to /kdev */ MOUNT("/kdev/", fs_passthru(NULL)); if (!fork2_n_mount("/")) { |