summaryrefslogtreecommitdiffstats
path: root/arch/x86_64/hal/paging.c
diff options
context:
space:
mode:
authorJon Santmyer <jon@jonsantmyer.com>2026-09-18 15:46:18 -0400
committerJon Santmyer <jon@jonsantmyer.com>2026-09-18 15:46:18 -0400
commit6da70f16c584ee897a4ac4f51d016a615c84042b (patch)
treece5458f9daa9f055340bfafc85d5197ce9aa678a /arch/x86_64/hal/paging.c
parent13adbc58eb9f5eb5d6f0e4454bd005e9adbb47c8 (diff)
downloadjove-kernel-6da70f16c584ee897a4ac4f51d016a615c84042b.tar.gz
jove-kernel-6da70f16c584ee897a4ac4f51d016a615c84042b.tar.bz2
jove-kernel-6da70f16c584ee897a4ac4f51d016a615c84042b.zip
cleanup for real hw attempt
Diffstat (limited to 'arch/x86_64/hal/paging.c')
-rw-r--r--arch/x86_64/hal/paging.c158
1 files changed, 134 insertions, 24 deletions
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;
}