From 6da70f16c584ee897a4ac4f51d016a615c84042b Mon Sep 17 00:00:00 2001 From: Jon Santmyer Date: Fri, 18 Sep 2026 15:46:18 -0400 Subject: cleanup for real hw attempt --- arch/x86_64/hal/paging.c | 158 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 134 insertions(+), 24 deletions(-) (limited to 'arch/x86_64/hal/paging.c') diff --git a/arch/x86_64/hal/paging.c b/arch/x86_64/hal/paging.c index 7b45005..47c79f3 100644 --- a/arch/x86_64/hal/paging.c +++ b/arch/x86_64/hal/paging.c @@ -1,5 +1,6 @@ #include "paging.h" #include "arch/x86_64/x86_64.h" +#include "hal/memory.h" #include "jove.h" #include "init.h" #include "config.h" @@ -73,45 +74,91 @@ s_int_handle_pf_early(struct int_stackframe *frame) hcf(); } -int pagedir_map_frame( - jove_owned_obj_t *tgt, jove_owned_obj_t *untyped_obj, - uintptr_t vptr, struct syscall_pagedir_flags flg) +static page_t* +s_pagedir_get_pml1(page_t *pml4, uintptr_t vptr) { - page_t *pml4 = obj_deref(tgt); - uintptr_t frame = obj_getvalue(untyped_obj); - + errno = 0; size_t pml4i = PML4I(vptr); - if(!pml4[pml4i].p) return ENOMAP; + if(!pml4[pml4i].p) { + errno = ENOMAP; + return 0; + } page_t *pml3 = (page_t*)(((uintptr_t)pml4[pml4i].paddr << 12) | IDENT_VIRT_BASE); size_t pml3i = PML3I(vptr); - if(!pml3[pml3i].p) return ENOMAP; + if(!pml3[pml3i].p) { + errno = ENOMAP; + return 0; + } page_t *pml2 = (page_t*)(((uintptr_t)pml3[pml3i].paddr << 12) | IDENT_VIRT_BASE); size_t pml2i = PML2I(vptr); - if(!pml2[pml2i].p) return ENOMAP; + if(!pml2[pml2i].p) { + errno = ENOMAP; + return 0; + } + + return (page_t*)(((uintptr_t)pml2[pml2i].paddr << 12) | IDENT_VIRT_BASE); +} + +int pagedir_map_frame(page_t *pml4, + uintptr_t pptr, uintptr_t vptr, + uintmax_t flg) +{ + page_t *pml1 = s_pagedir_get_pml1(pml4, vptr); + if(!pml1) + return errno; - page_t *pml1 = (page_t*)(((uintptr_t)pml2[pml2i].paddr << 12) | IDENT_VIRT_BASE); size_t pml1i = PML1I(vptr); if(pml1[pml1i].p) return EEXIST; - pml1[pml1i].value = frame | - PAGE_PRESENT | - PAGE_USER | - (flg.writeable ? PAGE_WRITETHROUGH : 0) | - (flg.executable ? 0 : PAGE_XD); + pml1[pml1i].value = pptr | PAGE_PRESENT | flg; + __asm__ volatile("invlpg (%0)":: "r"(vptr): "memory"); return 0; } -int pagedir_map_table( +int pagedir_map_untyped_frame( jove_owned_obj_t *tgt, jove_owned_obj_t *untyped_obj, uintptr_t vptr, struct syscall_pagedir_flags flg) { - page_t *target_table = NULL; page_t *pml4 = obj_deref(tgt); uintptr_t frame = obj_getvalue(untyped_obj); - void *frame_ident = obj_deref(untyped_obj); + return pagedir_map_frame(pml4, frame, vptr, + (flg.writeable ? PAGE_WRITEABLE : 0) | + (flg.executable ? PAGE_XD : 0)); +} + +int pagedir_unmap_untyped_frame( + jove_owned_obj_t *tgt, jove_owned_obj_t *dst, uintptr_t vptr) +{ + page_t *pml4 = obj_deref(tgt); + + size_t pml4i = PML4I(vptr); + if(!pml4[pml4i].p) return ENOMAP; + + page_t *pml1 = s_pagedir_get_pml1(pml4, vptr); + size_t pml1i = PML1I(vptr); + if(!pml1[pml1i].p) return ENOMAP; + + uintptr_t untyped_pptr = (pml1[pml1i].paddr << 12); + + obj_settype(dst, JOVE_OBJ_UNTYPED); + obj_setvalue(dst, untyped_pptr); + + jove_untyped_t *untyped_data = obj_deref(dst); + untyped_data->limit = 0x1000; + __asm__ volatile("invlpg (%0)":: "r"(vptr): "memory"); + + return 0; +} + +int pagedir_map_table(page_t *pml4, + uintptr_t pptr, uintptr_t vptr) +{ + page_t *target_table = NULL; + + void *frame_ident = (void*)(pptr | IDENT_VIRT_BASE); memset(frame_ident, 0, 0x1000); size_t pml4i = PML4I(vptr); @@ -136,14 +183,77 @@ int pagedir_map_table( return EHASMAP; map_table: - target_table->value = frame | + target_table->value = pptr | PAGE_PRESENT | - PAGE_USER | - (flg.writeable ? PAGE_WRITETHROUGH : 0) | - (flg.executable ? 0 : PAGE_XD); + (pptr > IDENT_VIRT_BASE ? 0 : PAGE_USER) | + PAGE_WRITEABLE; + __asm__ volatile("invlpg (%0)":: "r"(vptr): "memory"); return 0; } +int pagedir_map_untyped_table( + jove_owned_obj_t *tgt, jove_owned_obj_t *untyped_obj, + uintptr_t vptr, struct syscall_pagedir_flags flg) +{ + page_t *pml4 = obj_deref(tgt); + uintptr_t frame = obj_getvalue(untyped_obj); + + return pagedir_map_table(pml4, frame, vptr); +} + +int pagedir_unmap_untyped_table( + jove_owned_obj_t *tgt, jove_owned_obj_t *dst, uintptr_t vptr) +{ + page_t *target_table = NULL; + page_t *pml4 = obj_deref(tgt); + + //If the PML4 entry does not exist at this virtual ptr, the user may be + //trying to unmap the entire address space. We don't support this. + size_t pml4i = PML4I(vptr); + if(!pml4[pml4i].p) { + return ENOMAP; + } + target_table = &pml4[pml4i]; + + //Try to unmap the pml4 entry if the pml3 entry does not exist. + page_t *pml3 = (page_t*)(((uintptr_t)pml4[pml4i].paddr << 12) | IDENT_VIRT_BASE); + size_t pml3i = PML3I(vptr); + if(!pml3[pml3i].p) { + goto unmap_table; + } + target_table = &pml3[pml3i]; + + //Try to unmap the pml3 entry if the pml2 entry does not exist. + page_t *pml2 = (page_t*)(((uintptr_t)pml3[pml3i].paddr << 12) | IDENT_VIRT_BASE); + size_t pml2i = PML2I(vptr); + if(!pml2[pml2i].p) { + goto unmap_table; + } + //We are unmapping a pml2 entry. + target_table = &pml2[pml2i]; + +unmap_table: +{ + uintptr_t frame = target_table->paddr << 12; + page_t *target_vals = (page_t*)(frame | IDENT_VIRT_BASE); + + //Check that the page table at our target entry is empty. + //If it's not, we return an error saying that the entry contains a map. + for(size_t i = 0; i < 512; i++) { + if(target_vals[i].p) return EHASMAP; + } + + //Populate the none object with an untyped object at the free'd page frame. + obj_settype(dst, JOVE_OBJ_UNTYPED); + obj_setvalue(dst, frame); + + jove_untyped_t *untyped = obj_deref(dst); + untyped->limit = 0x1000; + + __asm__ volatile("invlpg (%0)":: "r"(vptr): "memory"); + return 0; +} +} void paging_pml4_init(void) @@ -196,7 +306,7 @@ paging_pml4_init(void) uintptr_t kernel_rodata_off = kernel_text_off + kernel_text_pages; for(size_t i = 0; i < kernel_rodata_pages; i++) { size_t off = i + kernel_rodata_off; - uintptr_t page_off = kernel_text_start_pptr + (off << 12); + uintptr_t page_off = kernel_rodata_start_pptr + (i << 12); _kernel_pml1[off].value = page_off | PAGE_PRESENT | PAGE_GLOBAL | PAGE_XD; } @@ -210,7 +320,7 @@ paging_pml4_init(void) uintptr_t kernel_data_off = kernel_rodata_off + kernel_rodata_pages; for(size_t i = 0; i < kernel_data_pages; i++) { size_t off = i + kernel_data_off; - uintptr_t page_off = kernel_text_start_pptr + (off << 12); + uintptr_t page_off = kernel_data_start_pptr + (i << 12); _kernel_pml1[off].value = page_off | PAGE_PRESENT | PAGE_WRITEABLE | PAGE_GLOBAL | PAGE_XD; } -- cgit v1.2.3