diff options
author | dzwdz | 2022-07-16 22:50:34 +0200 |
---|---|---|
committer | dzwdz | 2022-07-16 22:50:34 +0200 |
commit | a251c14f1a745f3388ce73a5a45ebc73cd1782b5 (patch) | |
tree | 2eab140ce2bcc729d8836e97a61bd0d731bb44d6 /src/kernel/arch | |
parent | c8ed6aa7476b7f506366d9fe56ed6f2e7a12b40d (diff) |
amd64: back at the shell!
Diffstat (limited to 'src/kernel/arch')
-rw-r--r-- | src/kernel/arch/amd64/32/boot.s | 1 | ||||
-rw-r--r-- | src/kernel/arch/amd64/32/gdt.c | 8 | ||||
-rw-r--r-- | src/kernel/arch/amd64/boot.c | 6 | ||||
-rw-r--r-- | src/kernel/arch/amd64/driver/fsroot.c | 2 | ||||
-rw-r--r-- | src/kernel/arch/amd64/interrupts/isr.c | 19 | ||||
-rw-r--r-- | src/kernel/arch/amd64/pagedir.c | 45 | ||||
-rw-r--r-- | src/kernel/arch/amd64/sysenter.s | 11 |
7 files changed, 47 insertions, 45 deletions
diff --git a/src/kernel/arch/amd64/32/boot.s b/src/kernel/arch/amd64/32/boot.s index 06de66e..af32007 100644 --- a/src/kernel/arch/amd64/32/boot.s +++ b/src/kernel/arch/amd64/32/boot.s @@ -80,6 +80,7 @@ cpu_halt: .global cpu_pause .type cpu_pause, @function cpu_pause: + xchgw %bx, %bx sti hlt cli diff --git a/src/kernel/arch/amd64/32/gdt.c b/src/kernel/arch/amd64/32/gdt.c index 2229330..d3d4aed 100644 --- a/src/kernel/arch/amd64/32/gdt.c +++ b/src/kernel/arch/amd64/32/gdt.c @@ -87,15 +87,15 @@ void gdt_init(void) { gdt_fillout(&GDT[SEG_r3data], 3, false); lgdt_arg.limit = sizeof(GDT) - 1; - lgdt_arg.base = (uint64_t) &GDT; + lgdt_arg.base = (uint64_t)(int)&GDT; memset32(&TSS, 0, sizeof(TSS)); for (int i = 0; i < 3; i++) - TSS.rsp[i] = (uint64_t) &_isr_mini_stack; - TSS.ist[1] = (uint64_t) &_isr_mini_stack; + TSS.rsp[i] = (uint64_t)(int)&_isr_mini_stack; + TSS.ist[1] = (uint64_t)(int)&_isr_mini_stack; - uint64_t tss_addr = (uint64_t) &TSS; + uint64_t tss_addr = (uint64_t)(int)&TSS; GDT[SEG_TSS] = (struct gdt_entry) { .limit_low = sizeof(TSS), .limit_high = sizeof(TSS) >> 16, diff --git a/src/kernel/arch/amd64/boot.c b/src/kernel/arch/amd64/boot.c index 0e61ed3..56cf8c8 100644 --- a/src/kernel/arch/amd64/boot.c +++ b/src/kernel/arch/amd64/boot.c @@ -15,13 +15,13 @@ static void find_init(struct multiboot_info *multiboot, struct kmain_info *info) { - struct multiboot_mod *module = (void*)multiboot->mods; + struct multiboot_mod *module = (void*)(long)multiboot->mods; kprintf("mods count 0x%x", multiboot->mods_count); if (multiboot->mods_count < 1) { kprintf("can't find init! "); panic_invalid_state(); } - info->init.at = module->start; + info->init.at = (void*)(long)module->start; info->init.size = module->end - module->start; } @@ -34,7 +34,7 @@ void kmain_early(struct multiboot_info *multiboot) { kprintf("irq..."); irq_init(); - info.memtop = (void*) (multiboot->mem_upper * 1024); + info.memtop = (void*)(long)(multiboot->mem_upper * 1024); find_init(multiboot, &info); kprintf("mem...\n"); mem_init(&info); diff --git a/src/kernel/arch/amd64/driver/fsroot.c b/src/kernel/arch/amd64/driver/fsroot.c index 02a4a21..e651c47 100644 --- a/src/kernel/arch/amd64/driver/fsroot.c +++ b/src/kernel/arch/amd64/driver/fsroot.c @@ -45,7 +45,7 @@ static void req_preprocess(struct vfs_request *req, size_t max_len) { static int handle(struct vfs_request *req) { assert(req->caller); - int id = (int)req->id; + int id = (int)(long)req->id; switch (req->type) { case VFSOP_OPEN: if (exacteq(req, "/")) return HANDLE_ROOT; diff --git a/src/kernel/arch/amd64/interrupts/isr.c b/src/kernel/arch/amd64/interrupts/isr.c index 4df8e57..bd560f5 100644 --- a/src/kernel/arch/amd64/interrupts/isr.c +++ b/src/kernel/arch/amd64/interrupts/isr.c @@ -11,20 +11,19 @@ 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]); +static void log_interrupt(int interrupt, uint64_t *stackframe) { + kprintf("interrupt %x, rip = k/%08x, cs 0x%x, code 0x%x\n", + interrupt, stackframe[0], stackframe[1], 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); + kprintf("addr 0x%x\n", addr); } +} +void isr_stage3(int interrupt, uint64_t *stackframe) { + if (interrupt == 0xe || interrupt == 0xd) stackframe++; switch (interrupt) { - case 0x08: // double fault - kprintf("#DF"); - panic_invalid_state(); - case 0x34: asm("nop" ::: "memory"); isr_test_interrupt_called = true; @@ -41,8 +40,8 @@ void isr_stage3(int interrupt, uint64_t *stackframe) { return; default: - if (stackframe[1] & 0x3 == 0) { - kprintf("bye o7\n"); + if ((stackframe[1] & 0x3) == 0) { + log_interrupt(interrupt, stackframe); cpu_halt(); } else { process_kill(process_current, interrupt); diff --git a/src/kernel/arch/amd64/pagedir.c b/src/kernel/arch/amd64/pagedir.c index 0d6078b..2075aac 100644 --- a/src/kernel/arch/amd64/pagedir.c +++ b/src/kernel/arch/amd64/pagedir.c @@ -69,35 +69,39 @@ struct pagedir *pagedir_new(void) { } void pagedir_free(struct pagedir *dir) { - (void)dir; - panic_unimplemented(); - /* - // assumes all user pages are unique and can be freed - struct pagetable_entry *pt; - void *page; - - for (int i = 0; i < 1024; i++) { + for (int i = 0; i < 512; i++) { if (!dir->e[i].present) continue; + assert(!dir->e[i].large); + pe_generic_t *pdpt = addr_extract(dir->e[i]); - pt = (void*)(dir->e[i].address << 11); + for (int j = 0; j < 512; j++) { + if (!pdpt[j].present) continue; + assert(!pdpt[j].large); + pe_generic_t *pd = addr_extract(pdpt[j]); - for (int j = 0; j < 1024; j++) { - if (!pt[j].present) continue; - if (!pt[j].user) continue; + for (int k = 0; k < 512; k++) { + if (!pd[k].present) continue; + assert(!pd[k].large); + pe_generic_t *pt = addr_extract(pd[k]); - page = (void*)(pt[j].address << 11); - page_free(page, 1); + for (int l = 0; l < 512; l++) { + if (!pt[l].present) continue; + if (!pt[l].user) continue; + page_free(addr_extract(pt[l]), 1); + } + page_free(pt, 1); + } + page_free(pd, 1); } - page_free(pt, 1); + page_free(pdpt, 1); } page_free(dir, 1); - */ } static pe_generic_t* get_entry(struct pagedir *dir, const void __user *virt) { pe_generic_t *pml4e, *pdpte, *pde, *pte; - const union virt_addr v = {.full = (void*)virt}; + const union virt_addr v = {.full = (void __user *)virt}; // TODO check if sign extension is valid @@ -208,11 +212,12 @@ struct pagedir *pagedir_copy(const struct pagedir *pml4_old) { 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; + if (!pt_old[l].present) continue; + pt_new[l] = pt_old[l]; + + if (!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; } } diff --git a/src/kernel/arch/amd64/sysenter.s b/src/kernel/arch/amd64/sysenter.s index 74db018..3f035dc 100644 --- a/src/kernel/arch/amd64/sysenter.s +++ b/src/kernel/arch/amd64/sysenter.s @@ -12,15 +12,16 @@ .global sysenter_setup .type sysenter_setup, @function sysenter_setup: - xor %rdx, %rdx // the intel docs don't mention the lower 32 bits - mov $( ((SEG_r3code << 3 | 3) << 48) | ((SEG_r0code << 3) << 32) ), %rax + mov $0, %eax + mov $( ((SEG_r3code << 3 | 3) << 16) | (SEG_r0code << 3) ), %edx mov $IA32_STAR, %rcx wrmsr + mov $sysenter_stage1, %eax + mov $0, %edx mov $IA32_LSTAR, %rcx - mov $sysenter_stage1, %rax wrmsr // hoping that the default RFLAGS mask is fine... @@ -50,8 +51,6 @@ _sysexit_real: mov %ax, %gs */ - xchgw %bx, %bx - mov $_sysexit_regs, %rsp pop %r15 pop %r14 @@ -77,12 +76,10 @@ _sysexit_real: mov (pagedir_current), %rsp mov %rsp, %cr3 mov (stored_rsp), %rsp - nop sysretq sysenter_stage1: cli - xchgw %bx, %bx mov %rsp, (stored_rsp) |