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 31 if (root->v.u.vnode.children) { 32 return root->v.u.vnode.children[entry]; 33 } else { 34 return NULL; 35 } 36} 37 38bool pmap_inside_region(struct vnode *root, uint16_t entry, uint16_t npages) 39{ 40 assert(root != NULL); 41 assert(root->v.is_vnode); 42 43 struct vnode *n = root->v.u.vnode.children[entry]; 44 45 // empty or ptable 46 if (!n || n->v.is_vnode) { 47 return false; 48 } 49 50 uint16_t end = n->v.entry + n->v.u.frame.pte_count; 51 if (n->v.entry <= entry && entry + npages <= end) { 52 return true; 53 } 54 55 return false; 56} 57 58void pmap_remove_vnode(struct vnode *root, struct vnode *item) 59{ 60 assert(root->v.is_vnode); 61 size_t pte_count = item->v.is_vnode ? 1 : item->v.u.frame.pte_count; 62 // check that we don't overflow children buffer 63 assert(item->v.entry + pte_count <= PTABLE_ENTRIES); 64 for (int i = 0; i < pte_count; i++) { 65 root->v.u.vnode.children[item->v.entry+i] = NULL; 66 } 67} 68 69errval_t pmap_vnode_mgmt_init(struct pmap *pmap) 70{ 71 struct pmap_vnode_mgmt *m = &pmap->m; 72 /* special case init of own pmap vnode mgmt */ 73 if (get_current_pmap() == pmap) { 74 /* use core state buffers */ 75 slab_init(&m->slab, sizeof(struct vnode), NULL); 76 slab_grow(&m->slab, m->slab_buffer, INIT_SLAB_BUFFER_SIZE); 77 78 /* Initialize slab allocator for child arrays */ 79 slab_init(&m->ptslab, PTSLAB_SLABSIZE, NULL); 80 slab_grow(&m->ptslab, m->ptslab_buffer, INIT_PTSLAB_BUFFER_SIZE); 81 } else { 82 /*initialize slab allocator for vnodes */ 83 slab_init(&m->slab, sizeof(struct vnode), NULL); 84 uint8_t *buf = malloc(INIT_SLAB_BUFFER_SIZE); 85 if (!buf) { 86 return LIB_ERR_MALLOC_FAIL; 87 } 88 slab_grow(&m->slab, buf, INIT_SLAB_BUFFER_SIZE); 89 90 /* Initialize slab allocator for child arrays */ 91 slab_init(&m->ptslab, PTSLAB_SLABSIZE, NULL); 92 buf = malloc(INIT_PTSLAB_BUFFER_SIZE); 93 if (!buf) { 94 return LIB_ERR_MALLOC_FAIL; 95 } 96 slab_grow(&m->ptslab, buf, INIT_PTSLAB_BUFFER_SIZE); 97 } 98 99 return SYS_ERR_OK; 100} 101 102void pmap_vnode_init(struct pmap *p, struct vnode *v) 103{ 104 v->v.u.vnode.children = slab_alloc(&p->m.ptslab); 105 assert(v->v.u.vnode.children); 106 memset(v->v.u.vnode.children, 0, PTSLAB_SLABSIZE); 107} 108 109void pmap_vnode_insert_child(struct vnode *root, struct vnode *newvnode) 110{ 111 size_t pte_count = newvnode->v.is_vnode ? 1 : newvnode->v.u.frame.pte_count; 112 // check that we don't overflow children buffer 113 assert(newvnode->v.entry + pte_count <= PTABLE_ENTRIES); 114 for (int i = 0; i < pte_count; i++) { 115 root->v.u.vnode.children[newvnode->v.entry+i] = newvnode; 116 } 117} 118 119void pmap_vnode_free(struct pmap *pmap, struct vnode *n) 120{ 121 slab_free(&pmap->m.ptslab, n->v.u.vnode.children); 122 slab_free(&pmap->m.slab, n); 123} 124 125errval_t pmap_refill_slabs(struct pmap *pmap, size_t max_slabs) 126{ 127 errval_t err; 128 err = pmap_slab_refill(pmap, &pmap->m.slab, max_slabs); 129 if (err_is_fail(err)) { 130 return err; 131 } 132 err = pmap_slab_refill(pmap, &pmap->m.ptslab, max_slabs); 133 if (err_is_fail(err)) { 134 return err; 135 } 136 /* for pmap_array, after refilling ptslabs, we need to make sure that we 137 * actually still have enough vnode slabs. */ 138 err = pmap_slab_refill(pmap, &pmap->m.slab, max_slabs); 139 if (err_is_fail(err)) { 140 return err; 141 } 142 return SYS_ERR_OK; 143} 144