os-workshop

same materials and sample source for RV32 OS projects
git clone http://frotz.net/git/os-workshop.git
Log | Files | Refs

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