diff options
author | Jon Santmyer <jon@jonsantmyer.com> | 2025-08-17 14:16:55 -0400 |
---|---|---|
committer | Jon Santmyer <jon@jonsantmyer.com> | 2025-08-17 14:16:55 -0400 |
commit | 7ee9347560768641096df68c545ac085a20233e4 (patch) | |
tree | 5b567f2e98cd9e6aeee33eeecd7fbf6f2fafdeab /arch/x86_64 | |
parent | f466364b8a3858e7b3f19258d142851cb4a7e6d6 (diff) | |
download | jove-kernel-7ee9347560768641096df68c545ac085a20233e4.tar.gz jove-kernel-7ee9347560768641096df68c545ac085a20233e4.tar.bz2 jove-kernel-7ee9347560768641096df68c545ac085a20233e4.zip |
working usermode pager. fix usermode interrupts
Diffstat (limited to 'arch/x86_64')
-rw-r--r-- | arch/x86_64/gdt.c | 93 | ||||
-rw-r--r-- | arch/x86_64/idt.c | 15 | ||||
-rw-r--r-- | arch/x86_64/ivt.s | 12 | ||||
-rw-r--r-- | arch/x86_64/lgdt.s | 3 | ||||
-rw-r--r-- | arch/x86_64/processor.c | 4 | ||||
-rw-r--r-- | arch/x86_64/syscall-invoke-mapping.c | 58 | ||||
-rw-r--r-- | arch/x86_64/usermode.c | 9 |
7 files changed, 100 insertions, 94 deletions
diff --git a/arch/x86_64/gdt.c b/arch/x86_64/gdt.c index e8ca912..3756d21 100644 --- a/arch/x86_64/gdt.c +++ b/arch/x86_64/gdt.c @@ -1,105 +1,96 @@ #include "arch/x86_64/tables.h" #include "arch/x86_64/processor.h" #include "string.h" +#include "print.h" static segment_descriptor_t s_gdt[] = { + [GDT_ENTRY_KERNEL_NULL] = { 0 }, //Kernel NULL + [GDT_ENTRY_KERNEL_CODE] = { //Kernel Code .limit_0_15 = 0xFFFF, .base_0_15 = 0x0, - .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 = 1, + .type_flags = CD_SEGMENT_TYPE_CODE | CD_SEGMENT_TYPE_WRITEABLE | + GDT_SEGMENT_FLAG_S | + GDT_SEGMENT_FLAG_DPL(0) | + GDT_SEGMENT_FLAG_P, + .limit_16_19_avlx = 0xF | GDT_SEGMENT_AVLX_L | GDT_SEGMENT_AVLX_G, .base_24_31 = 0x0 }, + [GDT_ENTRY_KERNEL_DATA] = { //Kernel Data .limit_0_15 = 0xFFFF, .base_0_15 = 0x0, - .type = CD_SEGMENT_TYPE_WRITEABLE, - .s = 1, - .dpl = 0, - .p = 1, - .limit_16_19 = 0xF, - .avl = 0, - .l = 0, - .d_b = 1, - .g = 1, + .type_flags = CD_SEGMENT_TYPE_WRITEABLE | + GDT_SEGMENT_FLAG_S | + GDT_SEGMENT_FLAG_DPL(0) | + GDT_SEGMENT_FLAG_P, + .limit_16_19_avlx = 0xF | GDT_SEGMENT_AVLX_L | GDT_SEGMENT_AVLX_G, .base_24_31 = 0x0 }, + [GDT_ENTRY_USER_NULL] = { 0 }, //User NULL + [GDT_ENTRY_USER_DATA] = { //User Data .limit_0_15 = 0xFFFF, .base_0_15 = 0x0, - .type = CD_SEGMENT_TYPE_WRITEABLE, - .s = 1, - .dpl = 3, - .p = 1, - .limit_16_19 = 0xF, - .avl = 0, - .l = 0, - .d_b = 1, - .g = 1, + .type_flags = CD_SEGMENT_TYPE_WRITEABLE | + GDT_SEGMENT_FLAG_S | + GDT_SEGMENT_FLAG_DPL(3) | + GDT_SEGMENT_FLAG_P, + .limit_16_19_avlx = 0xF | GDT_SEGMENT_AVLX_L | GDT_SEGMENT_AVLX_G, .base_24_31 = 0x0 }, + [GDT_ENTRY_USER_CODE] = { //User Code .limit_0_15 = 0xFFFF, .base_0_15 = 0x0, - .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 = 1, + .type_flags = CD_SEGMENT_TYPE_CODE | CD_SEGMENT_TYPE_WRITEABLE | + GDT_SEGMENT_FLAG_S | + GDT_SEGMENT_FLAG_DPL(3) | + GDT_SEGMENT_FLAG_P, + .limit_16_19_avlx = 0xF | GDT_SEGMENT_AVLX_L | GDT_SEGMENT_AVLX_G, .base_24_31 = 0x0 }, + [GDT_ENTRY_TSS_LOW] = { //TSS Low .limit_0_15 = 0, .base_0_15 = 0, .base_16_23 = 0, - .type = S_SEGMENT_TYPE_TSS_AVAIL, - .avl = 0, - .s = 0, - .dpl = 0, - .p = 1, - .limit_16_19 = 0, - .l = 0, - .d_b = 0, - .g = 0, + .type_flags = GDT_SEGMENT_TYPE_TSS_AVAIL | + GDT_SEGMENT_FLAG_DPL(0) | + GDT_SEGMENT_FLAG_P, + .limit_16_19_avlx = 0, .base_24_31 = 0 }, + [GDT_ENTRY_TSS_HIGH] = { 0 } //TSS High }; void gdt_setup(processor_t *processor) { - memcpy(processor->gdt, s_gdt, sizeof(s_gdt)); + size_t gdtw = GDT_ENTRY_COUNT * sizeof(segment_descriptor_t); + klogf("%X\n", gdtw); + memcpy(processor->gdt, &s_gdt, gdtw); processor->gdtr.base = (uintptr_t)&s_gdt; - processor->gdtr.length = sizeof(s_gdt) - 1; + processor->gdtr.length = gdtw - 1; segment_descriptor_t *tss_lo = &processor->gdt[GDT_ENTRY_TSS_LOW]; segment_descriptor_t *tss_hi = &processor->gdt[GDT_ENTRY_TSS_HIGH]; uintptr_t tssb = (uintptr_t)&processor->tss; + size_t tssl = sizeof(tss_t); + + tss_lo->limit_0_15 = tssl & 0xFF; tss_lo->base_0_15 = tssb & 0xFFFF; tss_lo->base_16_23 = (tssb >> 16) & 0xFF; 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(tss_t); - tss_lo->limit_0_15 = tssl & 0xFFFF; - tss_lo->limit_16_19 = (tssl >> 16) & 0xF; + tss_lo->limit_16_19_avlx = (tssl >> 16) & 0xF; processor->tss.iopb = tssl; @@ -107,5 +98,5 @@ gdt_setup(processor_t *processor) gdt_load(&processor->gdtr); extern void tss_flush(uint16_t); - tss_flush(GDT_ENTRY_TSS_LOW * sizeof(segment_descriptor_t)); + tss_flush(GDT_OFFSET_TSS); } diff --git a/arch/x86_64/idt.c b/arch/x86_64/idt.c index 99e1da1..1080f92 100644 --- a/arch/x86_64/idt.c +++ b/arch/x86_64/idt.c @@ -1,16 +1,13 @@ #include "arch/x86_64/tables.h" #include "arch/x86_64/idt.h" -__attribute__((aligned(4096))) +__attribute__((aligned(0x10))) interrupt_gate_t s_idtd[256]; -int64_t __isr_err; -int64_t __isr_num; - void isr_handle(ivt_state_t* state) { - kpanic_state(state, "Unhandled interrupt %i", __isr_num); + kpanic_state(state, "Unhandled interrupt %i", state->num); } void @@ -21,13 +18,9 @@ ivt_setup(void) uintptr_t base = __ivt[i]; s_idtd[i] = (interrupt_gate_t) { .base_0_15 = (base & 0xFFFF), - .segment_selector = 0x8, + .cs = GDT_OFFSET_KERNEL_CODE, .ist = 0, - .zero_0 = 0, - .type = 0xE, - .zero_1 = 0, - .dpl = 0, - .p = 1, + .type_flags = IDT_TYPE_INT_GATE | IDT_FLAG_DPL(0) | IDT_FLAG_P, .base_16_31 = (base >> 16) & 0xFFFF, .base_32_63 = (base >> 32) & 0xFFFFFFFF, .resv = 0 diff --git a/arch/x86_64/ivt.s b/arch/x86_64/ivt.s index d2d504b..0005686 100644 --- a/arch/x86_64/ivt.s +++ b/arch/x86_64/ivt.s @@ -18,6 +18,8 @@ __isr_head: call isr_handle popall + + addq $16, %rsp iretq .extern __isr_err @@ -26,12 +28,7 @@ __isr_head: .macro defn_isr_err num:req .type __isr\num @function __isr\num: - pushq %rbx - movq 8(%rsp), %rbx - movq %rbx, __isr_err - popq %rbx - addq $8, %rsp - movq $\num, __isr_num + pushq $\num jmp __isr_head .size __isr\num, . - __isr\num .endm @@ -39,7 +36,8 @@ __isr\num: .macro defn_isr num:req .type __isr\num @function __isr\num: - movq $\num, __isr_num + pushq $0 + pushq $\num jmp __isr_head .size __isr\num, . - __isr\num .endm diff --git a/arch/x86_64/lgdt.s b/arch/x86_64/lgdt.s index 7122ef9..55e37b5 100644 --- a/arch/x86_64/lgdt.s +++ b/arch/x86_64/lgdt.s @@ -20,7 +20,6 @@ gdt_load: .global tss_flush .type tss_flush @function tss_flush: - movw %di, %ax - ltr %ax + ltr %di retq .size tss_flush, . - tss_flush diff --git a/arch/x86_64/processor.c b/arch/x86_64/processor.c index 3ebf1ee..f7e5cac 100644 --- a/arch/x86_64/processor.c +++ b/arch/x86_64/processor.c @@ -66,8 +66,8 @@ s_enable_sce(void) wrmsr(MSR_EFER, feat.v[0], feat.v[1]); msr_star_t star; - star.kcs = GDT_ENTRY_KERNEL_CODE * sizeof(segment_descriptor_t); - star.ucs = GDT_ENTRY_USER_CODE * sizeof(segment_descriptor_t); + star.kcs = GDT_OFFSET_KERNEL_CODE; + star.ucs = GDT_OFFSET_USER_CODE; wrmsr(MSR_STAR, star.v[0], star.v[1]); extern void _syscall_entry(void); diff --git a/arch/x86_64/syscall-invoke-mapping.c b/arch/x86_64/syscall-invoke-mapping.c index efecbdf..5b79239 100644 --- a/arch/x86_64/syscall-invoke-mapping.c +++ b/arch/x86_64/syscall-invoke-mapping.c @@ -4,6 +4,9 @@ #include <stddef.h> #include "error.h" #include "lock.h" +#include "string.h" +#include "memory.h" +#include "print.h" static int s_handle_invoke_mapping_release( @@ -13,6 +16,9 @@ s_handle_invoke_mapping_release( size_t payload_at ) { +#ifdef DBG_SYSCALL + klogf("release mapping %p\n", target_entry); +#endif target_entry->data = 0; target_entry->type = KO_NONE; return 0; @@ -29,25 +35,29 @@ s_handle_invoke_mapping_get( pmli_t pmli; SYSCALL_PAYLOAD_TAKEL(payload, payload_at, pmli, pmli_t); - if(pmli > 511) return -KE_OOB; + if(pmli > 511) return KE_OOB; uint8_t level = target_entry->data & 3; pmle_t *target_pml = (pmle_t*)vmem_phys_tovirt(target_entry->data & ~3ULL); - if(level == 3 && pmli > 255) return -KE_OOB; - if(level == 0) return -KE_BADOBJ; - + if(level == 3 && pmli > 255) return KE_OOB; + if(level < 0) return KE_BADOBJ; + size_t dest_pathw; objdir_entry_t *dest_entry; SYSCALL_PAYLOAD_TAKEOBJ(payload, payload_at, dest_pathw, dest_entry); - if(dest_entry->type != KO_NONE) return -KE_FULL; + + if(dest_entry->type != KO_NONE) return KE_FULL; pmle_t pmle = target_pml[pmli]; - if(!pmle.p) return -KE_DNE; + if(!pmle.p) return KE_DNE; *dest_entry = (objdir_entry_t) { .type = KO_MEMORY_MAPPING, .data = (((uintptr_t)target_pml[pmli].paddr) << 12ULL) | (level - 1) }; +#ifdef DBG_SYSCALL + klogf("Get pml%i %p[%i] -> %p\n", level, target_pml, pmli, dest_entry->data & ~3ULL); +#endif return 0; } @@ -65,37 +75,47 @@ s_handle_invoke_mapping_map( pmli_t pmli; SYSCALL_PAYLOAD_TAKEL(payload, payload_at, pmli, pmli_t); - if(pmli > 511) return -KE_OOB; - if(level == 3 && pmli > 255) return -KE_OOB; + if(pmli > 511) return KE_OOB; + if(level == 3 && pmli > 255) return KE_OOB; + if(level < 0) return KE_BADOBJ; size_t untyped_pathw; objdir_entry_t *untyped_entry; SYSCALL_PAYLOAD_TAKEOBJ(payload, payload_at, untyped_pathw, untyped_entry); - if(untyped_entry->type != KO_MEMORY_UNTYPED) return -KE_BADOBJ; + if(untyped_entry->type != KO_MEMORY_UNTYPED) return KE_BADOBJ; mtx_acquire(&untyped_entry->lock); if((untyped_entry->data & 0xFFF) != 0) { mtx_release(&untyped_entry->lock); - return -KE_ALIGN; + return KE_ALIGN; } - size_t *untyped_data = (size_t*)untyped_entry->data; - size_t untyped_size = *untyped_data; + + uintptr_t untyped_phys = untyped_entry->data; + size_t *untyped = ko_entry_data(untyped_entry); + size_t untyped_size = *untyped; if(untyped_size != 0x1000) { mtx_release(&untyped_entry->lock); - return -KE_BADSIZE; + return KE_BADSIZE; } pmle_t pmle = target_pml[pmli]; if(pmle.p) { mtx_release(&untyped_entry->lock); - return -KE_OCCUPIED; + return KE_OCCUPIED; } - target_pml[pmli].value = vmem_ident_tophys((void*)untyped_entry->data) | PAGE_RW | PAGE_US | PAGE_PRESENT; + target_pml[pmli].value = untyped_phys | PAGE_RW | PAGE_US | PAGE_PRESENT; + if(level != 0) { + memset(untyped, 0, 0x1000); + } untyped_entry->type = KO_MEMORY_MAPPING; untyped_entry->data |= level - 1; +#ifdef DBG_SYSCALL + klogf("map %p[%p] to pml%i %p[%i]\n", untyped_entry, untyped_phys, level, target_pml, pmli); +#endif + mtx_release(&untyped_entry->lock); return 0; } @@ -119,6 +139,10 @@ syscall_handle_invoke_mapping( uint8_t funcid; SYSCALL_PAYLOAD_TAKEL(payload, payload_at, funcid, uint8_t); - if(funcid >= s_invoke_handles_count) return -KE_BADFUNC; - return s_invoke_handles[funcid](root_dir, target, payload, payload_at); + if(funcid >= s_invoke_handles_count) return KE_BADFUNC; + int r = s_invoke_handles[funcid](root_dir, target, payload, payload_at); +#ifdef DBG_SYSCALL + klogf("Call returns %i\n", r); +#endif + return r; } diff --git a/arch/x86_64/usermode.c b/arch/x86_64/usermode.c index 68cb45a..99ee128 100644 --- a/arch/x86_64/usermode.c +++ b/arch/x86_64/usermode.c @@ -7,6 +7,7 @@ #include "string.h" #include "device/processor.h" #include "arch/x86_64/page.h" +#include "print.h" static tcb_t s_init_tcb; @@ -99,7 +100,7 @@ init_load(void) _initDirectory.entries[INIT_OBJECT_TCB] = (objdir_entry_t) { .type = KO_TCB, - .data = (uintptr_t)&s_init_tcb + .data = vmem_tophys_koff((uintptr_t)&s_init_tcb) }; objdir_t *untyped_dir = (objdir_t*)_initDirectory.entries[INIT_OBJECT_UNTYPED_DIR].data; @@ -123,11 +124,12 @@ init_load(void) uintptr_t sp = stack_base + 0xFF0; //Create a kernel stack for the init TCB - uintptr_t ksp_base = (uintptr_t)s_init_tcb.kstack; + uintptr_t ksp_base = (uintptr_t)&s_init_tcb.kstack; s_init_tcb.ksp = ksp_base + 0xFF0; processor_t *proc = (processor_t*)processor_current(); - proc->tss.rsp[0] = ksp_base; + proc->tss.rsp0 = s_init_tcb.ksp; + klogf("RSP0 %p\n", s_init_tcb.ksp); //Create a message object for init uintptr_t message_base = init_base + (init_pages << 12); @@ -145,6 +147,5 @@ init_load(void) //Setup usermode and jump proc->tcb = &s_init_tcb; - proc->tss.rsp[0] = s_init_tcb.ksp; s_enter_usermode((void*)init_base, (void*)sp); } |