From 272e1889ce14aaea9e3431a93c406d347f5b3c54 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Thu, 23 Dec 2021 17:30:40 +0200 Subject: Added stat/mod_vmem + In general improved riscv vmem.c --- arch/riscv/kernel/vmem.c | 109 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 87 insertions(+), 22 deletions(-) (limited to 'arch/riscv/kernel/vmem.c') diff --git a/arch/riscv/kernel/vmem.c b/arch/riscv/kernel/vmem.c index 744f633..d1d77a1 100644 --- a/arch/riscv/kernel/vmem.c +++ b/arch/riscv/kernel/vmem.c @@ -10,11 +10,84 @@ #define pte_flags(pte) (((pm_t)(pte)) & 0xff) #define to_pte(p, f) ((pm_to_pnum((pm_t)__pa(p)) << 10) | (f)) #define pte_addr(pte) __va(pnum_to_paddr(pte_ppn(pte))) +#define pte_paddr(pte) (pnum_to_paddr(pte_ppn(pte))) #define vm_to_index(a, o) (pm_to_index(a, o)) +#define is_active(pte) (pte_flags(pte) & VM_V) +#define is_leaf(pte) (is_active(pte) && (pte_flags(pte) & ~VM_V)) +#define is_branch(pte) (is_active(pte) && !(pte_flags(pte) & ~VM_V)) -void mod_vmem(struct vm_branch_t *branch, vm_t vaddr, uint8_t flags, enum mm_order_t order) +static pm_t *__find_vmem(struct vm_branch_t *b, vm_t v, enum mm_order_t *o) { - /* todo */ + enum mm_order_t top = __mm_max_order; + *o = MM_O0; + do { + size_t idx = vm_to_index(v, top); + pm_t pte = (pm_t)b->leaf[idx]; + + if(!pte) + return 0; + + if(is_leaf(pte)){ + if(o) + *o = top; + + return (pm_t *)&b->leaf[idx]; + } + + b = (struct vm_branch_t *)pte_addr(pte); + } while (top--); + + return 0; +} + +int mod_vmem(struct vm_branch_t *branch, vm_t vaddr, pm_t paddr, uint8_t flags) +{ + pm_t *pte = __find_vmem(branch, vaddr, 0); + if(pte){ + *pte = to_pte(paddr, flags); + return 0; + } + + return -1; +} + +/* huh, should probably add status flags etc. to all my API functions. Damn, I'm + * lazy. */ +int stat_vmem(struct vm_branch_t *branch, vm_t vaddr, pm_t *paddr, + enum mm_order_t *order, uint8_t *flags) +{ + pm_t *pte = __find_vmem(branch, vaddr, order); + if(pte){ + if(paddr) + *paddr = pte_paddr(*pte); + + if(flags) + *flags = pte_flags(*pte); + + return 0; + } + + return -1; +} + +static struct vm_branch_t *__create_leaf() +{ + pm_t new_leaf = alloc_page(MM_KPAGE, 0); + memset((void *)new_leaf, 0, sizeof(struct vm_branch_t)); + return (struct vm_branch_t *)to_pte(new_leaf, VM_V); +} + +static void __destroy_branch(struct vm_branch_t *b) +{ + if(!b) + return; + + for(size_t i = 0; i < BASE_PAGE_SIZE / sizeof(pm_t); ++i){ + if(is_branch(b->leaf[i])); + __destroy_branch((struct vm_branch_t *)pte_addr(b->leaf[i])); + + free_page(MM_KPAGE, (pm_t)pte_addr(b->leaf[i])); + } } void map_vmem(struct vm_branch_t *branch, @@ -24,18 +97,16 @@ void map_vmem(struct vm_branch_t *branch, while (top != order) { size_t idx = vm_to_index(vaddr, top); - if (!branch->leaf[idx]) { - pm_t new_leaf = alloc_page(MM_KPAGE, 0); - branch->leaf[idx] = - (struct vm_branch_t *)to_pte(new_leaf, VM_V); - - void *leaf_ptr = (void *)new_leaf; - memset(leaf_ptr, 0, sizeof(struct vm_branch_t)); + if (is_branch(branch->leaf[idx])){ + __destroy_branch(branch->leaf[idx]); + branch->leaf[idx] = 0; } - pm_t pte = (pm_t)branch->leaf[idx]; - pm_t branch_pptr = (pm_t)pte_addr(pte); - branch = (struct vm_branch_t *)branch_pptr; + if (!branch->leaf[idx]) + branch->leaf[idx] = __create_leaf(); + + + branch = (struct vm_branch_t *)pte_addr(branch->leaf[idx]); top--; } @@ -43,16 +114,10 @@ void map_vmem(struct vm_branch_t *branch, branch->leaf[idx] = (struct vm_branch_t *)to_pte(paddr, flags); } -void unmap_vmem(struct vm_branch_t *branch, vm_t vaddr, enum mm_order_t order) +void unmap_vmem(struct vm_branch_t *branch, vm_t vaddr) { - while (order) { - size_t idx = pm_to_index(vaddr, order); - branch = (struct vm_branch_t *)pte_addr(branch->leaf[idx]); - } - - size_t idx = pm_to_index(vaddr, order); - if (branch->leaf[idx]) - free_page(order, (pm_t)pte_addr(branch->leaf[idx])); - branch->leaf[idx] = 0; + pm_t *pte = __find_vmem(branch, vaddr, 0); + if(pte) + *pte = 0; } -- cgit v1.3