From 8251da342161767fe203627223ccd4a7026701c6 Mon Sep 17 00:00:00 2001 From: Jon Santmyer Date: Fri, 4 Sep 2026 11:31:40 -0400 Subject: initial commit. working on tasking --- arch/x86_64/hal/paging.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 arch/x86_64/hal/paging.c (limited to 'arch/x86_64/hal/paging.c') 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; +} -- cgit v1.2.3