From f46ab8ca2050ee77edf6e6b979875426bdaf29dc Mon Sep 17 00:00:00 2001 From: Jon Santmyer Date: Wed, 13 Mar 2024 09:58:22 -0400 Subject: fix incorrect tss rsp assignment --- arch/x86_64/elf.d | 2 - arch/x86_64/gdt.c | 42 +++++++++++++------- arch/x86_64/gdt.d | 2 - arch/x86_64/idt.c | 19 ++++++--- arch/x86_64/idt.d | 2 - arch/x86_64/int.S | 3 +- arch/x86_64/interrupt.h | 11 ++++++ arch/x86_64/loadgdt.S | 4 +- arch/x86_64/paging.c | 35 ++++++++++++++++- arch/x86_64/paging.d | 2 - arch/x86_64/serial.d | 2 - arch/x86_64/syscall.d | 1 - arch/x86_64/syscall_setup.S | 21 ++++++---- arch/x86_64/tables.d | 1 - arch/x86_64/tables.h | 2 +- arch/x86_64/tasking.c | 93 +++++++++++++++++++++++++++++++++++++++++++++ arch/x86_64/thread.c | 85 ----------------------------------------- arch/x86_64/thread.d | 3 -- arch/x86_64/tss.h | 6 ++- 19 files changed, 201 insertions(+), 135 deletions(-) delete mode 100644 arch/x86_64/elf.d delete mode 100644 arch/x86_64/gdt.d delete mode 100644 arch/x86_64/idt.d create mode 100644 arch/x86_64/interrupt.h delete mode 100644 arch/x86_64/paging.d delete mode 100644 arch/x86_64/serial.d delete mode 100644 arch/x86_64/syscall.d delete mode 100644 arch/x86_64/tables.d create mode 100644 arch/x86_64/tasking.c delete mode 100644 arch/x86_64/thread.c delete mode 100644 arch/x86_64/thread.d (limited to 'arch/x86_64') diff --git a/arch/x86_64/elf.d b/arch/x86_64/elf.d deleted file mode 100644 index f57bbe6..0000000 --- a/arch/x86_64/elf.d +++ /dev/null @@ -1,2 +0,0 @@ -arch/x86_64/elf.o: arch/x86_64/elf.c arch/x86_64/elf.h lib/string.h \ - usr/elf.h io/log.h mem/memory.h mem/slab.h diff --git a/arch/x86_64/gdt.c b/arch/x86_64/gdt.c index d996dcb..07a8097 100644 --- a/arch/x86_64/gdt.c +++ b/arch/x86_64/gdt.c @@ -25,14 +25,15 @@ static struct SegmentDescriptor s_gdtd[GDT_SEGMENT_COUNT] = .limit_0_15 = 0xFFFF, .base_0_15 = 0, .base_16_23 = 0, - .type = CD_SEGMENT_TYPE_CODE | CD_SEGMENT_TYPE_CODE_CONFORMING, + .type = CD_SEGMENT_TYPE_CODE | CD_SEGMENT_TYPE_WRITEABLE, .s = 1, .dpl = 0, .p = 1, .limit_16_19 = 0xF, + .avl = 0, .l = 1, .d_b = 0, - .g = 0, + .g = 1, .base_24_31 = 0 }, { /* Kernel Data (64-bit RW DPL0) */ @@ -44,9 +45,10 @@ static struct SegmentDescriptor s_gdtd[GDT_SEGMENT_COUNT] = .dpl = 0, .p = 1, .limit_16_19 = 0xF, - .l = 1, - .d_b = 0, - .g = 0, + .avl = 0, + .l = 0, + .d_b = 1, + .g = 1, .base_24_31 = 0 }, { 0 }, /* User NULL */ @@ -59,36 +61,38 @@ static struct SegmentDescriptor s_gdtd[GDT_SEGMENT_COUNT] = .dpl = 3, .p = 1, .limit_16_19 = 0xF, - .l = 1, - .d_b = 0, - .g = 0, + .avl = 0, + .l = 0, + .d_b = 1, + .g = 1, .base_24_31 = 0, }, { /* User Code (64-bit RO EX DPL3)*/ .limit_0_15 = 0xFFFF, .base_0_15 = 0, .base_16_23 = 0, - .type = CD_SEGMENT_TYPE_CODE | CD_SEGMENT_TYPE_CODE_CONFORMING, + .type = CD_SEGMENT_TYPE_CODE | CD_SEGMENT_TYPE_WRITEABLE, .s = 1, .dpl = 3, .p = 1, .limit_16_19 = 0xF, + .avl = 0, .l = 1, .d_b = 0, - .g = 0, + .g = 1, .base_24_31 = 0, }, { /* TSS Low */ - .limit_0_15 = sizeof(struct TSS), + .limit_0_15 = 0, .base_0_15 = 0, .base_16_23 = 0, .type = S_SEGMENT_TYPE_TSS_AVAIL, - .avl = 1, + .avl = 0, .s = 0, .dpl = 0, .p = 1, .limit_16_19 = 0, - .l = 1, + .l = 0, .d_b = 0, .g = 0, .base_24_31 = 0, @@ -118,8 +122,20 @@ x86_64_load_gdt(void) tss_lo->base_24_31 = (tssb >> 24) & 0xFF; tss_hi->limit_0_15 = (tssb >> 32) & 0xFFFF; tss_hi->base_0_15 = (tssb >> 48) & 0xFFFF; + + size_t tssl = sizeof(struct TSS) - 1; + tss_lo->limit_0_15 = tssl & 0xFFFF; + tss_lo->limit_16_19 = (tssl >> 16) & 0xF; + + s_tss.iobp = sizeof(struct TSS); } x86_64_lgdt(&s_gdtr); x86_64_flush_tss(); } + +void tss_set_rsp(uint8_t dpl, uintptr_t rsp) +{ + s_tss.rsp[dpl][0] = rsp & 0xFFFFFFFF; + s_tss.rsp[dpl][1] = (rsp >> 32) & 0xFFFFFFFF; +} diff --git a/arch/x86_64/gdt.d b/arch/x86_64/gdt.d deleted file mode 100644 index 7b43bdb..0000000 --- a/arch/x86_64/gdt.d +++ /dev/null @@ -1,2 +0,0 @@ -arch/x86_64/gdt.o: arch/x86_64/gdt.c arch/x86_64/tables.h \ - arch/x86_64/tss.h diff --git a/arch/x86_64/idt.c b/arch/x86_64/idt.c index 567dead..05dcf43 100644 --- a/arch/x86_64/idt.c +++ b/arch/x86_64/idt.c @@ -5,7 +5,7 @@ PAGEALIGN static struct InterruptTrapGate s_idtd[48]; -static struct InterruptState *(*s_int_handlers[48])(struct Registers*); +static struct Registers *(*s_int_handlers[48])(struct Registers*); static struct XDTR s_idtr = { .length = sizeof(s_idtd) - 1, .address = (uintptr_t)&s_idtd @@ -14,13 +14,19 @@ static struct XDTR s_idtr = { uint64_t __isr_err; uint64_t __isr_num; +void +int_set_handler(uint8_t code, struct Registers *(*handler)(struct Registers*)) +{ + if(code >= 48) return; + s_int_handlers[code] = handler; +} + struct Registers* irq_handle(struct Registers *state) { if(__isr_num < 48) { if(s_int_handlers[__isr_num] != NULL) { - s_int_handlers[__isr_num](state); - return state; + return s_int_handlers[__isr_num](state); } } klogf("Interrupt %i\nerror code %#016X\n", __isr_num, __isr_err); @@ -52,10 +58,9 @@ x86_64_load_idt(void) for(int i = 0; i < 22; i++) { uintptr_t base = __isr_stubs[i]; - klogf("INT %2i : %#016X\n", i, base); s_idtd[i] = (struct InterruptTrapGate){ .base_0_15 = (base & 0xFFFF), - .segment_selector = 0x10, + .segment_selector = 0x8, .ist = 0, .zero_0 = 0, .type = 0xE, @@ -63,8 +68,10 @@ x86_64_load_idt(void) .dpl = 0, .p = 1, .base_16_31 = (base >> 16) & 0xFFFF, - .base_32_63 = (base >> 32) & 0xFFFFFFFF + .base_32_63 = (base >> 32) & 0xFFFFFFFF, + .resv = 0 }; + klogf("INT %2i : %#016X (%016X)\n", i, base, s_idtd[i]); } x86_64_lidt(&s_idtr); } diff --git a/arch/x86_64/idt.d b/arch/x86_64/idt.d deleted file mode 100644 index 7e976e7..0000000 --- a/arch/x86_64/idt.d +++ /dev/null @@ -1,2 +0,0 @@ -arch/x86_64/idt.o: arch/x86_64/idt.c arch/x86_64/tables.h \ - arch/x86_64/cpu.h lib/jove.h io/log.h diff --git a/arch/x86_64/int.S b/arch/x86_64/int.S index 96c62d9..e00760a 100644 --- a/arch/x86_64/int.S +++ b/arch/x86_64/int.S @@ -3,6 +3,7 @@ .type x86_64_lidt @function x86_64_lidt: lidt (%rdi) + sti retq .macro irq_preserve @@ -54,7 +55,6 @@ irq_stub: movq %rax, %rsp irq_restore - addq $128, %rsp iretq .extern __isr_err @@ -63,7 +63,6 @@ irq_stub: .macro isr_error num:req .type __isr\num @function isr\num: - subq $128, %rsp pushq %rbx movq 8(%rsp), %rbx movq %rbx, __isr_err diff --git a/arch/x86_64/interrupt.h b/arch/x86_64/interrupt.h new file mode 100644 index 0000000..9ae63f9 --- /dev/null +++ b/arch/x86_64/interrupt.h @@ -0,0 +1,11 @@ +#ifndef JOVE_ARCH_INTERRUPT_H +#define JOVE_ARCH_INTERRUPT_H 1 + +#include "cpu.h" + +/**Register a handler for a specified interrupt code. + * @param code interrupt to handle. + * @param handler to call.*/ +void int_set_handler(unsigned char code, struct Registers *(*handler)(struct Registers*)); + +#endif diff --git a/arch/x86_64/loadgdt.S b/arch/x86_64/loadgdt.S index e183850..a293bae 100644 --- a/arch/x86_64/loadgdt.S +++ b/arch/x86_64/loadgdt.S @@ -6,7 +6,7 @@ x86_64_lgdt: pushq $0x8 leaq .reload_cs, %rax pushq %rax - retfq + lretq .reload_cs: movw $0x10, %ax movw %ax, %ds @@ -15,6 +15,7 @@ x86_64_lgdt: movw %ax, %gs movw %ax, %ss retq +.size x86_64_lgdt, . - x86_64_lgdt .global x86_64_flush_tss .type x86_64_flush_tss @function @@ -22,3 +23,4 @@ x86_64_flush_tss: movw $0x30, %ax ltr %ax retq +.size x86_64_flush_tss, . - x86_64_flush_tss diff --git a/arch/x86_64/paging.c b/arch/x86_64/paging.c index 76b5735..29c4863 100644 --- a/arch/x86_64/paging.c +++ b/arch/x86_64/paging.c @@ -1,4 +1,5 @@ #include "paging.h" +#include "interrupt.h" #include #include "lib/jove.h" #include "io/log.h" @@ -128,10 +129,16 @@ mem_pd_ensure_range(struct PageDirectory *pd, uintptr_t from, uintptr_t to, uint mem_pd_ensure_4k(pd, from, flg); } +void +mem_ensure_range_for(void *pd, uintptr_t from, uintptr_t to, bool rw, bool user) +{ + mem_pd_ensure_range((struct PageDirectory*)pd, from, to, 1 | (rw << 1) | (user << 2)); +} + void mem_ensure_range(uintptr_t from, uintptr_t to, bool rw, bool user) { - mem_pd_ensure_range(mem_current_pd, from, to, 1 | (rw << 1) | (user << 2)); + mem_ensure_range_for(mem_current_pd, from, to, rw, user); } void mem_pd_new(struct PageDirectory *pd) @@ -152,10 +159,33 @@ void mem_pd_clone(struct PageDirectory *pd, struct PageDirectory *parent) { mem_pd_new(pd); for(size_t i = 0; i < 256; i++) { - + //TODO: Impl pd cloning } } +struct Registers* +s_pagefault_handler(struct Registers *state) +{ + extern uint64_t __isr_err; + + uintptr_t fault_addr = 0; + __asm__ volatile("movq %%cr2, %0": "=r"(fault_addr)); + + bool present = __isr_err & 1; + bool write = __isr_err & 2; + bool user = __isr_err & 4; + bool fetch = __isr_err & 16; + + klogf("Page fault at %016X\n", fault_addr); + klogf("%s %s from a %s address\n", + user ? "user" : "kernel", + write ? "wrote" : "read", + present ? "present" : "non-present"); + + kpanic("Unhandled page fault at %016X\n", state->ip); + return state; +} + void mem_paging_setup(void) { @@ -198,5 +228,6 @@ mem_paging_setup(void) s_kernel_initial_pml1[0][i] = (i * PAGESIZE) + boot_kernel_physical_address | 3; } + int_set_handler(14, s_pagefault_handler); __asm__ volatile("mov %0, %%cr3":: "r"(s_kernel_initial_pd.pml4_paddr)); } diff --git a/arch/x86_64/paging.d b/arch/x86_64/paging.d deleted file mode 100644 index bb3ea83..0000000 --- a/arch/x86_64/paging.d +++ /dev/null @@ -1,2 +0,0 @@ -arch/x86_64/paging.o: arch/x86_64/paging.c arch/x86_64/paging.h \ - mem/memory.h mem/slab.h lib/jove.h io/log.h lib/string.h boot/boot.h diff --git a/arch/x86_64/serial.d b/arch/x86_64/serial.d deleted file mode 100644 index a0b0756..0000000 --- a/arch/x86_64/serial.d +++ /dev/null @@ -1,2 +0,0 @@ -arch/x86_64/serial.o: arch/x86_64/serial.c arch/x86_64/serial.h \ - arch/x86_64/uart.h lib/jove.h io/log.h diff --git a/arch/x86_64/syscall.d b/arch/x86_64/syscall.d deleted file mode 100644 index bb8f166..0000000 --- a/arch/x86_64/syscall.d +++ /dev/null @@ -1 +0,0 @@ -arch/x86_64/syscall.o: arch/x86_64/syscall.c usr/umode.h diff --git a/arch/x86_64/syscall_setup.S b/arch/x86_64/syscall_setup.S index cbd3220..972e345 100644 --- a/arch/x86_64/syscall_setup.S +++ b/arch/x86_64/syscall_setup.S @@ -1,11 +1,12 @@ -.extern _kernel_thread_sp +.extern _kernel_task_sp .extern syscall_handler .global syscall_entry .type syscall_entry @function syscall_entry: + swapgs movq %rsp, %rax - movq (_kernel_thread_bp), %rsp + movq (_kernel_task_bp), %rsp pushq %rax pushq %rbp pushq %rcx @@ -16,22 +17,26 @@ syscall_entry: popq %rcx popq %rbp popq %rsp + swapgs sysretq .global syscall_setup_syscall .type syscall_setup_syscall @function syscall_setup_syscall: - movq $0xc0000082, %rcx - leaq syscall_entry, %rdx - mov %edx, %eax - shr $32, %rdx - wrmsr movq $0xc0000080, %rcx rdmsr or $1, %eax wrmsr + movq $0xc0000081, %rcx rdmsr - mov $0x00180008, %edx + mov $0x001b0008, %edx + wrmsr + + movq $0xc0000082, %rcx + leaq syscall_entry, %rdx + mov %edx, %eax + shr $32, %rdx wrmsr + retq diff --git a/arch/x86_64/tables.d b/arch/x86_64/tables.d deleted file mode 100644 index 6b10ebe..0000000 --- a/arch/x86_64/tables.d +++ /dev/null @@ -1 +0,0 @@ -arch/x86_64/tables.o: arch/x86_64/tables.c arch/x86_64/tables.h diff --git a/arch/x86_64/tables.h b/arch/x86_64/tables.h index 8e43bec..e160c66 100644 --- a/arch/x86_64/tables.h +++ b/arch/x86_64/tables.h @@ -45,7 +45,7 @@ struct InterruptTrapGate uint8_t p : 1; uint16_t base_16_31; uint32_t base_32_63; - + uint32_t resv; }__attribute__((packed)); struct XDTR /* Generic table descriptor struct */ diff --git a/arch/x86_64/tasking.c b/arch/x86_64/tasking.c new file mode 100644 index 0000000..fe6ecdb --- /dev/null +++ b/arch/x86_64/tasking.c @@ -0,0 +1,93 @@ +#include "tsk/tasking.h" +#include "mem/memory.h" +#include "io/log.h" +#include "lib/hashtable.h" +#include "lib/string.h" +#include "paging.h" +#include "cpu.h" +#include "tss.h" + +struct TaskBody { + struct Task base; + struct PageDirectory *pd; + struct Registers state; +}; + +struct Task *task_current; +uintptr_t _kernel_task_bp = 0; + +//static struct SLinkedList s_tasks; +static struct HashTable s_tasks; + +static struct SlabCache s_task_cache; +static struct SlabCache s_kbp_cache; + +static tid_t s_task_id_next = 1; + +static size_t +s_task_hash_func(const void* tid, size_t _) +{ + return (tid_t)tid; +} + +void +tasking_setup(void) +{ + hashtable_new(&s_tasks, struct TaskBody*, tid_t); + s_tasks.hash_function = s_task_hash_func; + + mem_slabcache_new(&s_task_cache, "tasks", sizeof(struct TaskBody)); + mem_slabcache_new(&s_kbp_cache, "kernel stacks", 4096); + + struct TaskBody *ktask = mem_slab_alloc(&s_task_cache); + *ktask = (struct TaskBody){ + .base.id = s_task_id_next++, + .base.kbp = ((uintptr_t)mem_slab_alloc(&s_kbp_cache)) + 0xFF0, + .base.perm = (size_t)-1, + .pd = mem_current_pd + }; + hashtable_insert(&s_tasks, 0, ktask); + + task_current = (struct Task*)ktask; + tss_set_rsp(0, task_current->kbp); + _kernel_task_bp = task_current->kbp; +} + +struct Task* +task_new(struct Task *parent) +{ + struct TaskBody *new = mem_slab_alloc(&s_task_cache); + memcpy(new, parent, sizeof(struct TaskBody)); + new->base.id = s_task_id_next++; + + uintptr_t ksp_base = (uintptr_t)mem_slab_alloc(&s_kbp_cache); + new->base.kbp = ksp_base + 0xFFF; + new->base.perm = parent->perm; + + hashtable_insert(&s_tasks, (void*)new->base.id, new); + return (struct Task*)new; +} + +struct Task* +task_get(tid_t id) +{ + struct Task **task = hashtable_get(&s_tasks, (void*)id, struct Task*); + if(task == NULL) return NULL; + return *task; +} + +void +task_free(struct Task *task) +{ + struct TaskBody *body = (struct TaskBody*)task; + body->pd->references--; + task->kbp -= 0xFFF; + mem_slab_free(&s_kbp_cache, (void*)(task->kbp)); + klogf("Need impl for task_free\n"); +} + +void* +task_get_pd(struct Task *task) +{ + return ((struct TaskBody*)task)->pd; +} diff --git a/arch/x86_64/thread.c b/arch/x86_64/thread.c deleted file mode 100644 index da20067..0000000 --- a/arch/x86_64/thread.c +++ /dev/null @@ -1,85 +0,0 @@ -#include "tsk/tasking.h" -#include "mem/memory.h" -#include "io/log.h" -#include "lib/hashtable.h" -#include "lib/string.h" -#include "paging.h" -#include "cpu.h" - -struct ThreadBody { - struct Thread base; - struct PageDirectory pd; - struct Registers state; -}; - -struct Thread *thread_current; -uintptr_t _kernel_thread_bp = 0; - -//static struct SLinkedList s_threads; -static struct HashTable s_threads; - -static struct SlabCache s_thread_cache; -static struct SlabCache s_kbp_cache; - -static tid_t s_thread_id_next = 1; - -static size_t -s_thread_hash_func(const void* tid, size_t _) -{ - return (tid_t)tid; -} - -void -tasking_setup(void) -{ - hashtable_new(&s_threads, struct ThreadBody*, tid_t); - s_threads.hash_function = s_thread_hash_func; - - mem_slabcache_new(&s_thread_cache, "threads", sizeof(struct ThreadBody)); - mem_slabcache_new(&s_kbp_cache, "kernel stacks", 4096); - - struct ThreadBody *kthread = mem_slab_alloc(&s_thread_cache); - *kthread = (struct ThreadBody){ - .base.id = s_thread_id_next++, - .base.kbp = ((uintptr_t)mem_slab_alloc(&s_kbp_cache)) + 0xFFF, - .base.perm = (size_t)-1, - .pd = *mem_current_pd - }; - hashtable_insert(&s_threads, 0, kthread); - - thread_current = (struct Thread*)kthread; - _kernel_thread_bp = thread_current->kbp; -} - -struct Thread* -thread_new(struct Thread *parent) -{ - struct ThreadBody *new = mem_slab_alloc(&s_thread_cache); - memcpy(new, parent, sizeof(struct ThreadBody)); - new->base.id = s_thread_id_next++; - - uintptr_t ksp_base = (uintptr_t)mem_slab_alloc(&s_kbp_cache); - new->base.kbp = ksp_base + 0xFFF; - new->base.perm = parent->perm; - - hashtable_insert(&s_threads, (void*)new->base.id, new); - return (struct Thread*)new; -} - -struct Thread* -thread_get(tid_t id) -{ - struct Thread **thread = hashtable_get(&s_threads, (void*)id, struct Thread*); - if(thread == NULL) return NULL; - return *thread; -} - -void -thread_free(struct Thread *thread) -{ - struct ThreadBody *body = (struct ThreadBody*)thread; - body->pd.references--; - thread->kbp -= 0xFFF; - mem_slab_free(&s_kbp_cache, (void*)(thread->kbp)); - klogf("Need impl for thread_free\n"); -} diff --git a/arch/x86_64/thread.d b/arch/x86_64/thread.d deleted file mode 100644 index c78e4a9..0000000 --- a/arch/x86_64/thread.d +++ /dev/null @@ -1,3 +0,0 @@ -arch/x86_64/thread.o: arch/x86_64/thread.c tsk/tasking.h mem/memory.h \ - mem/slab.h io/log.h lib/hashtable.h lib/linkedlist.h lib/string.h \ - arch/x86_64/paging.h arch/x86_64/cpu.h diff --git a/arch/x86_64/tss.h b/arch/x86_64/tss.h index 34ec444..dcdd01c 100644 --- a/arch/x86_64/tss.h +++ b/arch/x86_64/tss.h @@ -7,12 +7,14 @@ struct TSS { uint32_t resv0; - uint64_t rsp[3]; + uint32_t rsp[3][2]; uint64_t resv1; - uint64_t ist[8]; + uint32_t ist[8][2]; uint64_t resv2; uint16_t resv3; uint16_t iobp; }; +void tss_set_rsp(uint8_t dpl, uintptr_t rsp); + #endif -- cgit v1.2.1