summaryrefslogtreecommitdiffstats
path: root/arch/x86_64/hal/paging.c
diff options
context:
space:
mode:
authorJon Santmyer <jon@jonsantmyer.com>2026-09-04 11:31:40 -0400
committerJon Santmyer <jon@jonsantmyer.com>2026-09-04 11:31:40 -0400
commit8251da342161767fe203627223ccd4a7026701c6 (patch)
treeaf2db0f11b0ea8ad35f88663a855bab39a80f679 /arch/x86_64/hal/paging.c
downloadjove-kernel-8251da342161767fe203627223ccd4a7026701c6.tar.gz
jove-kernel-8251da342161767fe203627223ccd4a7026701c6.tar.bz2
jove-kernel-8251da342161767fe203627223ccd4a7026701c6.zip
initial commit. working on tasking
Diffstat (limited to 'arch/x86_64/hal/paging.c')
-rw-r--r--arch/x86_64/hal/paging.c174
1 files changed, 174 insertions, 0 deletions
diff --git a/arch/x86_64/hal/paging.c b/arch/x86_64/hal/paging.c
new file mode 100644
index 0000000..c1a22a2
--- /dev/null
+++ b/arch/x86_64/hal/paging.c
@@ -0,0 +1,174 @@
+#include "paging.h"
+#include "arch/x86_64/x86_64.h"
+#include "jove.h"
+#include "config.h"
+#include "smp.h"
+#include "lib/string.h"
+#include "lib/printf.h"
+#include "lib/panic.h"
+#include "idt.h"
+
+PAGEALIGN page_t _kernel_pml4[512];
+PAGEALIGN page_t _kernel_pml3[512];
+PAGEALIGN page_t _kernel_pml2[512];
+PAGEALIGN page_t _kernel_pml1[512];
+
+#define IDENT_HUGEPAGES ((PHYS_BIGPAGES_MAX + 511) / 512)
+#define IDENT_GIANTPAGES ((IDENT_HUGEPAGES + 511) / 512)
+
+PAGEALIGN static page_t ident_pml3[IDENT_GIANTPAGES][512];
+PAGEALIGN static page_t ident_pml2[IDENT_HUGEPAGES][512];
+
+void*
+phys_tovirt(uintptr_t phys)
+{
+ return (void*)(phys | IDENT_VIRT_BASE);
+}
+
+uintptr_t
+paging_get_pml4(void)
+{
+ uintptr_t ret = 0;
+ __asm__ volatile("movq %%cr3, %0": "=r"(ret));
+ return ret;
+}
+
+void
+paging_pml4_switch(uintptr_t pml4)
+{
+ __asm__ volatile("movq %0, %%cr3":: "r"(pml4));
+}
+
+static struct int_stackframe*
+s_int_handle_pf_early(struct int_stackframe *frame)
+{
+ extern int _kernel_panic_unlock;
+ _kernel_panic_unlock = 1;
+
+ union {
+ struct {
+ uint8_t p : 1;
+ uint8_t wr : 1;
+ uint8_t us : 1;
+ uint8_t rsvd : 1;
+ uint8_t id : 1;
+ uint8_t pk : 1;
+ };
+ uint64_t value;
+ } pf_error = { .value = frame->int_err };
+
+ kprintf("Kernel has encountered a page fault exception early in initializaiton\n");
+ kprintf("%s %s during %s\n",
+ pf_error.wr ? "Wrote to" : "Read from",
+ pf_error.p ? "Present" : "Non-present",
+ pf_error.id ? "Instruction fetch" : "Data access");
+ uintptr_t cr2 = 0;
+ __asm__ volatile("movq %%cr2, %0": "=r"(cr2));
+ kprintf("Faulting address: %p\n", cr2);
+ kprintf("RIP: %p | RSP: %p\n", frame->int_rip, frame->int_rsp);
+ print_state(&frame->state);
+
+ hcf();
+}
+
+void
+paging_pml4_init(void)
+{
+ //Setup kernel pages
+ memset(_kernel_pml4, 0, 0x1000);
+ memset(_kernel_pml3, 0, 0x1000);
+ memset(_kernel_pml2, 0, 0x1000);
+ memset(_kernel_pml1, 0, 0x1000);
+
+ /*Paging entries depend on physical addresses to properly map.
+ * Since the virtual kernel address differs from the physical memory address,
+ * we need to convert the pointers using the physical memory pointer passed
+ * to us by the bootloader.*/
+ uintptr_t kernel_pml4_pptr = KPTR_TOPHYS((uintptr_t)_kernel_pml4);
+ uintptr_t kernel_pml3_pptr = KPTR_TOPHYS((uintptr_t)_kernel_pml3);
+ uintptr_t kernel_pml2_pptr = KPTR_TOPHYS((uintptr_t)_kernel_pml2);
+ uintptr_t kernel_pml1_pptr = KPTR_TOPHYS((uintptr_t)_kernel_pml1);
+
+ /*Maps pml4-2 as global writeable pages.*/
+ _kernel_pml4[511].value = kernel_pml3_pptr | PAGE_PRESENT | PAGE_WRITEABLE | PAGE_GLOBAL;
+ _kernel_pml3[510].value = kernel_pml2_pptr | PAGE_PRESENT | PAGE_WRITEABLE | PAGE_GLOBAL;
+ _kernel_pml2[0].value = kernel_pml1_pptr | PAGE_PRESENT | PAGE_WRITEABLE | PAGE_GLOBAL;
+
+ /*text*/
+ extern void *_kernel_text_start;
+ extern void *_kernel_text_end;
+ uintptr_t kernel_text_start_pptr = KPTR_TOPHYS((uintptr_t)&_kernel_text_start);
+ uintptr_t kernel_text_end_pptr = KPTR_TOPHYS((uintptr_t)&_kernel_text_end);
+ size_t kernel_text_pages = ((kernel_text_end_pptr - kernel_text_start_pptr) / 0x1000) + 1;
+
+ uintptr_t kernel_text_off = (((uintptr_t)&_kernel_text_start) - KERNEL_VIRT_BASE) >> 12;
+
+ for(size_t i = 0; i < kernel_text_pages; i++) {
+ size_t off = i + kernel_text_off;
+ uintptr_t page_off = kernel_text_start_pptr + (i << 12);
+ _kernel_pml1[off].value = page_off | PAGE_PRESENT | PAGE_GLOBAL;
+ }
+
+ /*rodata*/
+ extern void *_kernel_rodata_start;
+ extern void *_kernel_rodata_end;
+ uintptr_t kernel_rodata_start_pptr = KPTR_TOPHYS((uintptr_t)&_kernel_rodata_start);
+ uintptr_t kernel_rodata_end_pptr = KPTR_TOPHYS((uintptr_t)&_kernel_rodata_end);
+ size_t kernel_rodata_pages = ((kernel_rodata_end_pptr - kernel_rodata_start_pptr) / 0x1000) + 1;
+
+ 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);
+ _kernel_pml1[off].value = page_off | PAGE_PRESENT | PAGE_GLOBAL | PAGE_XD;
+ }
+
+ /*data/bss*/
+ extern void *_kernel_data_start;
+ extern void *_kernel_bss_end;
+ uintptr_t kernel_data_start_pptr = KPTR_TOPHYS((uintptr_t)&_kernel_data_start);
+ uintptr_t kernel_data_end_pptr = KPTR_TOPHYS((uintptr_t)&_kernel_bss_end);
+ size_t kernel_data_pages = ((kernel_data_end_pptr - kernel_data_start_pptr) / 0x1000) + 1;
+
+ 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);
+ _kernel_pml1[off].value = page_off | PAGE_PRESENT | PAGE_WRITEABLE | PAGE_GLOBAL | PAGE_XD;
+ }
+
+ /*Identity pages are mapped as huge pages starting at the 256'th PML3 entry.
+ *We want to support any range of physical memory up to several TiB, so
+ *the mapper has to consider multiple heirarchies of huge pages.*/
+ for(size_t l3 = 0; l3 < IDENT_GIANTPAGES; l3++) {
+ memset(ident_pml3[l3], 0, 0x1000);
+ uintptr_t ident_pml3_pptr = KPTR_TOPHYS((uintptr_t)ident_pml3[l3]);
+
+ _kernel_pml4[256 + l3].value = ident_pml3_pptr | PAGE_PRESENT | PAGE_WRITEABLE | PAGE_GLOBAL;
+ }
+
+ for(size_t l2 = 0; l2 < IDENT_HUGEPAGES; l2++) {
+ size_t l3 = l2 / 512;
+ size_t l2_mod = l2 % 512;
+
+ memset(ident_pml2[l2], 0, 0x1000);
+ uintptr_t ident_pml2_pptr = KPTR_TOPHYS((uintptr_t)ident_pml2[l2]);
+
+ ident_pml3[l3][l2_mod].value = ident_pml2_pptr | PAGE_PRESENT | PAGE_WRITEABLE | PAGE_GLOBAL;
+ }
+
+ for(size_t l1 = 0; l1 < PHYS_BIGPAGES_MAX; l1++) {
+ size_t l2 = l1 / 512;
+ size_t l1_mod = l1 % 512;
+
+ ident_pml2[l2][l1_mod].value = (l1 << 21) | PAGE_PRESENT | PAGE_WRITEABLE | PAGE_PS | PAGE_GLOBAL;
+ ident_pml2[l2][l1_mod].xd = 1;
+ }
+
+ paging_pml4_switch(kernel_pml4_pptr);
+
+ /*Before tasking, if the kernel has a bug and crashes we need some
+ * information about what happened.*/
+ extern struct int_stackframe *(*__int_handles[])(struct int_stackframe*);
+ __int_handles[IDT_EXCEPT_PF] = s_int_handle_pf_early;
+}