summaryrefslogtreecommitdiff
path: root/arch/i386/kernel
diff options
context:
space:
mode:
authorDanny Holman <dholman@gymli.org>2024-06-21 21:48:46 -0500
committerDanny Holman <dholman@gymli.org>2024-06-21 21:50:55 -0500
commit056087596de64696f18f9b32f604b69280be079e (patch)
tree4ebdbe12197736d69898ff7437ff9e6af97940ed /arch/i386/kernel
parentf1a0f10f54e17803f7d7095a61117aec52fafbf0 (diff)
arch: i386: paging: do the recursive paging trick
Map the page directory to the last page table. This allows the kernel to access every page table on the system from the address 0xFFC00000 plus an offset. Signed-off-by: Danny Holman <dholman@gymli.org>
Diffstat (limited to 'arch/i386/kernel')
-rw-r--r--arch/i386/kernel/paging.c122
1 files changed, 58 insertions, 64 deletions
diff --git a/arch/i386/kernel/paging.c b/arch/i386/kernel/paging.c
index 96ad2ce..b8e00af 100644
--- a/arch/i386/kernel/paging.c
+++ b/arch/i386/kernel/paging.c
@@ -1,96 +1,88 @@
#include <kernel/paging.h>
#include <kernel/asm.h>
+#include <kernel/vmem.h>
#include <kernel/pmem.h>
#include <kernel/panic.h>
#include <kernel/syscall.h>
#include <libk/io.h>
#include <libk/string.h>
-uintptr_t *kpgdir = NULL;
-
-static uintptr_t kernel_pd[1024] __attribute__((aligned(PAGE_SIZE)));
-static uintptr_t kernel_pt[1024] __attribute__((aligned(PAGE_SIZE)));
-static uintptr_t accnt_pt[1024] __attribute__((aligned(PAGE_SIZE)));
static int paging_enabled = 0;
-void _copy_kernel_maps(uintptr_t *new_pd) {
- int pdx = GET_PDX(GET_VADDR(KSTART));
- new_pd[pdx] = GET_PADDR(kernel_pt) | PD_PRES | PD_RW;
- new_pd[832] = GET_PADDR(accnt_pt) | PD_PRES | PD_RW;
-}
-
-uintptr_t* init_page_table(void) {
- uintptr_t *ret = (uintptr_t*)pfa_alloc();
- if ((uintptr_t)ret == PFA_ALLOC_ERR)
- return NULL;
-
- uintptr_t *temp_map = (uintptr_t*)0xD0001000;
- map_page(NULL, (uintptr_t)ret, (uintptr_t)temp_map, PD_PRES | PD_RW);
- memset((char*)temp_map, 0, PAGE_SIZE);
- unmap_page(NULL, (uintptr_t)temp_map);
- return ret;
-}
-
-uintptr_t* init_page_directory(void) {
- uintptr_t *ret = (uintptr_t*)pfa_alloc();
- if ((uintptr_t)ret == PFA_ALLOC_ERR)
- return NULL;
-
- map_page(NULL, (uintptr_t)ret, (uintptr_t)ret, PD_PRES | PD_RW);
- memset(ret, 0, PAGE_SIZE);
- _copy_kernel_maps(ret);
- unmap_page(NULL, (uintptr_t)ret);
-
- return ret;
-}
-
void paging_init(void) {
if (paging_enabled == 1)
return;
-
- _copy_kernel_maps(kernel_pd);
+
+ uintptr_t phys_pt = pfa_alloc(1);
+ map_page(phys_pt, PAGE_TMP_MAP, PD_PRES | PD_RW);
+ uintptr_t *pt = (uintptr_t*)PAGE_TMP_MAP;
for (uintptr_t i = KSTART; i < KEND; i += PAGE_SIZE)
- map_page(kernel_pd, i, GET_VADDR(i), PD_PRES);
+ pt[GET_PTX(GET_VADDR(i))] = i | PD_PRES;
+ unmap_page(PAGE_TMP_MAP);
- map_page(kernel_pd, 0xB8000, 0xC03FF000, PD_PRES | PD_RW);
- kpgdir = kernel_pd;
- enable_paging(GET_PADDR(kpgdir));
+ uintptr_t phys_pd = pfa_alloc(1);
+ map_page(phys_pd, PAGE_TMP_MAP, PD_PRES | PD_RW);
+ uintptr_t *pd = (uintptr_t*)PAGE_TMP_MAP;
+ pd[GET_PDX(GET_VADDR(KSTART))] = phys_pt | PD_PRES | PD_RW;
+ pd[1023] = phys_pd | PD_PRES | PD_RW;
+ unmap_page(PAGE_TMP_MAP);
+
+ enable_paging(phys_pd);
paging_enabled = 1;
return;
}
-void map_page(uint32_t *pd, uintptr_t paddr, uintptr_t vaddr, uint32_t flags) {
- if (pd == NULL)
- pd = kpgdir;
+void init_page_table(int pdindex, uint32_t flags) {
+ uintptr_t *pd = (uintptr_t*)PAGE_DIR_MAP;
+ if ((pd[pdindex] & PD_PRES) != 0)
+ return;
+
+ uintptr_t paddr = pfa_alloc(1);
+ pd[pdindex] = paddr | PD_PRES | PD_RW | flags;
+
+ uintptr_t *pt = ((uintptr_t*)PAGE_TAB_MAP) + (pdindex << 12);
+ pd[GET_PDX(pt)] = paddr | PD_PRES | PD_RW;
+}
+
+uintptr_t init_page_directory(void) {
+ uintptr_t ret = pfa_alloc(1);
+ map_page(ret, PAGE_TMP_MAP, PD_RW);
+
+ uintptr_t *new_pd = (uintptr_t*)PAGE_TMP_MAP;
+ uintptr_t *cur_pd = (uintptr_t*)PAGE_DIR_MAP;
+ int kernel_pdx = GET_PDX(GET_VADDR(KSTART));
+ new_pd[kernel_pdx] = cur_pd[kernel_pdx];
+ unmap_page(PAGE_TMP_MAP);
+ return ret;
+}
+
+void map_page(uintptr_t paddr, uintptr_t vaddr, uint32_t flags) {
paddr = PGROUNDDN(paddr);
vaddr = PGROUNDDN(vaddr);
- uintptr_t pdindex = GET_PDX(vaddr);
- uintptr_t ptindex = GET_PTX(vaddr);
+ int pdindex = GET_PDX(vaddr);
+ int ptindex = GET_PTX(vaddr);
- uintptr_t *pt = (uintptr_t*)(GET_VADDR(pd[pdindex]) & 0xFFFFF000);
- if (pd[pdindex] == 0)
- pd[pdindex] = (uintptr_t)init_page_table();
+ uintptr_t *pd = (uintptr_t*)PAGE_DIR_MAP;
+ if ((pd[pdindex] & PD_PRES) == 0)
+ init_page_table(pdindex, 0);
- uintptr_t *pte = (uintptr_t*)(&pt[ptindex]);
- *pte |= paddr | (flags & 0xFFF) | 0x01;
+ uintptr_t *pt = (uintptr_t*)(PAGE_TAB_MAP + (pdindex << 12));
+ pt[ptindex] = paddr | PD_PRES | flags;
invlpg((void*)vaddr);
}
-void unmap_page(uint32_t *pd, uintptr_t vaddr) {
- if (pd == NULL)
- pd = kpgdir;
-
+void unmap_page(uintptr_t vaddr) {
uintptr_t pdindex = GET_PDX(vaddr);
uintptr_t ptindex = GET_PTX(vaddr);
- uintptr_t *pt = (uintptr_t*)(GET_VADDR(pd[pdindex]) & 0xFFFFF000);
- if (pd[pdindex] == 0)
+ uintptr_t *pd = (uintptr_t*)PAGE_DIR_MAP;
+ if ((pd[pdindex] & PD_PRES) == 0)
return;
- uintptr_t *pte = (uintptr_t*)(&pt[ptindex]);
- *pte &= 0;
+ uintptr_t *pt = (uintptr_t*)(PAGE_TAB_MAP + (pdindex << 12));
+ pt[ptindex] = 0;
invlpg((void*)vaddr);
}
@@ -98,28 +90,30 @@ void page_fault_handler(struct isr_frame *frame) {
uintptr_t fault_addr;
__asm__ volatile("movl %%cr2, %0" : "=r"(fault_addr));
+ kprintf("Faulting address: %x\n", fault_addr);
+ panic("Page fault not operational");
switch (frame->isr_err) {
case 0:
- map_page((uintptr_t*)GET_VADDR(frame->cr3), pfa_alloc(), fault_addr, PD_PRES);
+ //map_page((uintptr_t*)GET_VADDR(frame->cr3), pfa_alloc(), fault_addr, PD_PRES);
break;
case 1:
panic("Kernel process caused protection fault on read\n");
break;
case 2:
- map_page((uintptr_t*)GET_VADDR(frame->cr3), pfa_alloc(), fault_addr, PD_PRES | PD_RW);
+ //map_page((uintptr_t*)GET_VADDR(frame->cr3), pfa_alloc(), fault_addr, PD_PRES | PD_RW);
break;
case 3:
panic("Kernel process caused protection fault on write\n");
break;
case 4:
- map_page((uintptr_t*)GET_VADDR(frame->cr3), pfa_alloc(), fault_addr, PD_PRES | PD_USR);
+ //map_page((uintptr_t*)GET_VADDR(frame->cr3), pfa_alloc(), fault_addr, PD_PRES | PD_USR);
break;
case 5:
// TODO: instead of panicking, kill process
panic("User process caused protection fault on read\n");
break;
case 6:
- map_page((uintptr_t*)GET_VADDR(frame->cr3), pfa_alloc(), fault_addr, PD_PRES | PD_RW | PD_USR);
+ //map_page((uintptr_t*)GET_VADDR(frame->cr3), pfa_alloc(), fault_addr, PD_PRES | PD_RW | PD_USR);
break;
case 7:
// TODO: see case 101