From 2740284a344209146fdc9b9fd852f277616e1fba Mon Sep 17 00:00:00 2001 From: Danny Holman Date: Sun, 26 Nov 2023 18:50:16 -0600 Subject: arch: i386: paging: add a proper paging API Add a proper page control API. These functions allow the kernel to directly map and unmap pages in the logical address space. Signed-off-by: Danny Holman --- arch/i386/kernel/paging.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 arch/i386/kernel/paging.c (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/paging.c b/arch/i386/kernel/paging.c new file mode 100644 index 0000000..d8f72a3 --- /dev/null +++ b/arch/i386/kernel/paging.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include +#include + +extern int halt_catch_fire(); +extern uint32_t _kernel_start; +extern uint32_t _kernel_end; +static uint32_t *kstart = &_kernel_start; +static uint32_t *kend = (uint32_t)(&_kernel_end) - 0xC0000000; + +static uint32_t page_directory[1024] __attribute__((aligned(PAGE_SIZE))); +static uint32_t first_page_table[1024] __attribute__((aligned(PAGE_SIZE))); + +static int paging_enabled = 0; + +void paging_init(void) { + for (int i = 0; i < 1024; i++) + page_directory[i] = 0x00000002; + + page_directory[1023] = ((uint32_t)&page_directory - 0xC0000000) | 3; + page_directory[0] = ((uint32_t)&first_page_table - 0xC0000000) | 3; + page_directory[768] = ((uint32_t)&first_page_table - 0xC0000000) | 3; + for (uint32_t i = kstart; i < kend; i += 4096) { + map_page(i, get_vaddr(i), 0x003); + mark_bitmap(i, 1); + } + + map_page(0xB8000, 0xC03FF000, 0x003); + mark_bitmap(0xB8000, 1); + + load_page_dir(((uint32_t)&page_directory) - 0xC0000000); + enable_paging(); + paging_enabled = 1; + return; +} + +void page_fault_handler(struct isr_frame *frame) { + kprintf("Page fault detected\n"); + uint32_t errno = frame->errno; + + uint32_t fault_addr; + __asm__ volatile("movl %%cr2, %0" : "=r"(fault_addr)); + kprintf("Fault occured at address %x\n", fault_addr); + uint32_t present = errno & ERR_PRESENT; + uint32_t rw = errno & ERR_RW; + uint32_t user = errno & ERR_USER; + uint32_t reserved = errno & ERR_RESERVED; + uint32_t ifetch = errno & ERR_INST; + kprintf("Possible causes:\n"); + if (!present) kprintf("\tPage not present\n"); + if (rw || user) kprintf("\tPage is read only\n"); + if (reserved) kprintf("\tOverwrote reserved bits\n"); + if (ifetch) kprintf("\tInstruction fetch\n"); + halt_catch_fire(frame); +} + +uint32_t get_paddr(uint32_t vaddr) { + uint32_t pdindex = vaddr >> 22; + uint32_t ptindex = vaddr >> 12 & 0x03FF; + + uint32_t *page_table = (page_directory[pdindex] + 0xC0000000 & 0xFFFFF000); + return (page_table[ptindex] & 0xFFFFF000) | (vaddr & 0x00000FFF); +} + +uint32_t get_vaddr(uint32_t paddr) { + return paddr + 0xC0000000; +} + +void map_page(uint32_t paddr, uint32_t vaddr, uint32_t flags) { + uint32_t pdindex = vaddr >> 22; + uint32_t ptindex = vaddr >> 12 & 0x03FF; + + uint32_t *page_table = (page_directory[pdindex] + 0xC0000000 & 0xFFFFF000); + uint32_t *pte = (uint32_t*)(&page_table[ptindex]); + *pte |= paddr | (flags & 0xFFF) | 0x01; +} + +void unmap_page(uint32_t vaddr) { + uint32_t pdindex = vaddr >> 22; + uint32_t ptindex = vaddr >> 12 & 0x03FF; + + uint32_t *page_table = (page_directory[pdindex] + 0xC0000000 & 0xFFFFF000); + uint32_t *pte = (uint32_t*)(&page_table[ptindex]); + *pte &= 0; +} -- cgit v1.2.3