vmm.c (1693B)
1 // Copyright 2022, Brian Swetland <swetland@frotz.net> 2 // Licensed under the Apache License, Version 2.0 3 4 #include "kernel.h" 5 6 #include <string.h> 7 8 static paddr_t pa_top; 9 static paddr_t pa_bottom; 10 11 void vmm_init(paddr_t start, paddr_t end) { 12 pa_bottom = start; 13 pa_top = end; 14 } 15 16 paddr_t ppage_alloc_z(void) { 17 if (pa_top == pa_bottom) { 18 panic("out of physical pages"); 19 } 20 pa_top -= PAGE_SIZE; 21 memset(pa_to_kva(pa_top), 0, PAGE_SIZE); 22 return pa_top; 23 } 24 25 void *kpage_alloc_z(void) { 26 return pa_to_kva(ppage_alloc_z()); 27 } 28 29 #define PTE_PA(pte) (((pte) & 0xFFFFFC00) << 2) 30 31 status_t vm_map_4k(uint32_t* pdir, vaddr_t va, paddr_t pa, uint32_t flags) { 32 uint32_t idx1 = va >> 22; 33 uint32_t idx0 = (va >> 12) & 0x3FF; 34 uint32_t *ptbl; 35 36 if ((va & 0x00000FFF) || (pa & 0x00000FFF)) { 37 return XOS_ERR_BAD_PARAM; 38 } 39 40 uint32_t pte = pdir[idx1]; 41 if (pte & PTE_V) { // valid pgdir entry 42 if (pte & (PTE_X|PTE_W|PTE_R)) { 43 return XOS_ERR_CONFLICT; 44 } 45 ptbl = pa_to_kva(PTE_PA(pte)); 46 } else { // no entry, allocate a pagetable 47 uint32_t ptbl_pa = ppage_alloc_z(); 48 ptbl = pa_to_kva(ptbl_pa); 49 pdir[idx1] = (ptbl_pa >> 2) | PTE_V; 50 } 51 52 pte = ptbl[idx0]; 53 if (pte & PTE_V) { 54 return -1; // 4KB page already here 55 } 56 57 ptbl[idx0] = ((pa & 0xFFFFF000) >> 2) | (flags & 0x3FF); 58 59 tlb_flush_all(); 60 return XOS_OK; 61 } 62 63 status_t vm_map_4m(uint32_t* pdir, vaddr_t va, paddr_t pa, uint32_t flags) { 64 uint32_t idx1 = va >> 22; 65 66 if ((va & 0x003FFFFF) || (pa & 0x003FFFFF)) { 67 return XOS_ERR_BAD_PARAM; 68 } 69 70 uint32_t pte = pdir[idx1]; 71 if (pte & PTE_V) { // valid pgdir entry 72 return XOS_ERR_CONFLICT; 73 } 74 pdir[idx1] = ((pa & 0xFFFFF000) >> 2) | (flags & 0x3FF); 75 76 tlb_flush_all(); 77 return XOS_OK; 78 } 79 80