1/** 2 * \file 3 * \brief architecture-independent shadow page table traversal code for 4 * linked-list pmap implementation. 5 */ 6 7/* 8 * Copyright (c) 2018, ETH Zurich. 9 * All rights reserved. 10 * 11 * This file is distributed under the terms in the attached LICENSE file. 12 * If you do not find this file, copies can be found by writing to: 13 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 14 */ 15 16#include <barrelfish/barrelfish.h> 17#include <barrelfish/pmap_target.h> 18 19#include <pmap_ds.h> 20#include <pmap_priv.h> 21 22/** 23 * \brief Starting at a given root, return the vnode with entry equal to #entry 24 */ 25struct vnode *pmap_find_vnode(struct vnode *root, uint16_t entry) 26{ 27 assert(root != NULL); 28 assert(root->v.is_vnode); 29 assert(entry < PTABLE_ENTRIES); 30 struct vnode *n; 31 32 for(n = root->v.u.vnode.children; n != NULL; n = n->v.meta.next) { 33 if (!n->v.is_vnode) { 34 // check whether entry is inside a large region 35 uint16_t end = n->v.entry + n->v.u.frame.pte_count; 36 if (n->v.entry <= entry && entry < end) { 37 //if (n->v.entry < entry) { 38 // debug_printf("%d \\in [%d, %d]\n", entry, n->v.entry, end); 39 //} 40 return n; 41 } 42 } 43 else if(n->v.entry == entry) { 44 // return n if n is a vnode and the indices match 45 return n; 46 } 47 } 48 return NULL; 49} 50 51bool pmap_inside_region(struct vnode *root, uint16_t entry, uint16_t npages) 52{ 53 assert(root != NULL); 54 assert(root->v.is_vnode); 55 56 struct vnode *n; 57 58 for (n = root->v.u.vnode.children; n; n = n->v.meta.next) { 59 if (!n->v.is_vnode) { 60 uint16_t end = n->v.entry + n->v.u.frame.pte_count; 61 if (n->v.entry <= entry && entry + npages <= end) { 62 return true; 63 } 64 } 65 } 66 67 return false; 68} 69 70void pmap_remove_vnode(struct vnode *root, struct vnode *item) 71{ 72 assert(root->v.is_vnode); 73 struct vnode *walk = root->v.u.vnode.children; 74 struct vnode *prev = NULL; 75 while (walk) { 76 if (walk == item) { 77 if (prev) { 78 prev->v.meta.next = walk->v.meta.next; 79 return; 80 } else { 81 root->v.u.vnode.children = walk->v.meta.next; 82 return; 83 } 84 } 85 prev = walk; 86 walk = walk->v.meta.next; 87 } 88 USER_PANIC("Should not get here"); 89} 90 91errval_t pmap_vnode_mgmt_init(struct pmap *pmap) 92{ 93 struct pmap_vnode_mgmt *m = &pmap->m; 94 if (get_current_pmap() == pmap) { 95 slab_init(&m->slab, sizeof(struct vnode), NULL); 96 /* use static buffer for own pmap */ 97 slab_grow(&m->slab, m->slab_buffer, INIT_SLAB_BUFFER_SIZE); 98 } else { 99 /* malloc initial buffer for other pmaps */ 100 uint8_t *buf = malloc(INIT_SLAB_BUFFER_SIZE); 101 if (!buf) { 102 return LIB_ERR_MALLOC_FAIL; 103 } 104 slab_init(&m->slab, sizeof(struct vnode), NULL); 105 slab_grow(&m->slab, buf, INIT_SLAB_BUFFER_SIZE); 106 } 107 108 return SYS_ERR_OK; 109} 110 111void pmap_vnode_init(struct pmap *p, struct vnode *v) 112{ 113 v->v.u.vnode.children = NULL; 114 v->v.meta.next = NULL; 115} 116 117void pmap_vnode_insert_child(struct vnode *root, struct vnode *newvnode) 118{ 119 newvnode->v.meta.next = root->v.u.vnode.children; 120 root->v.u.vnode.children = newvnode; 121} 122 123void pmap_vnode_free(struct pmap *pmap, struct vnode *n) 124{ 125 slab_free(&pmap->m.slab, n); 126} 127 128errval_t pmap_refill_slabs(struct pmap *pmap, size_t max_slabs) 129{ 130 return pmap_slab_refill(pmap, &pmap->m.slab, max_slabs); 131} 132