1/** 2 * \file 3 * \brief vregion management 4 * 5 * A vregion is backed by a memory object and a vspace. 6 * A vregion manages a range of virtual address space. 7 */ 8 9/* 10 * Copyright (c) 2009, 2010, ETH Zurich. 11 * Copyright (c) 2014, HP Labs. 12 * All rights reserved. 13 * 14 * This file is distributed under the terms in the attached LICENSE file. 15 * If you do not find this file, copies can be found by writing to: 16 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 17 */ 18 19#include <barrelfish/barrelfish.h> 20#include "vspace_internal.h" 21 22/** 23 * \brief Setup a new vregion with alignment constraints in an address space 24 * 25 * \param vregion The vregion 26 * \param vspace The vspace to associate with the vregion 27 * \param memobj The memory object to associate with the region 28 * \param offset Offset into the memory object 29 * \param size Size of the memory object to use 30 * \param flags Vregion specific flags 31 * \param alignment Minimum required alignment of mapping (may be increased) 32 */ 33errval_t vregion_map_aligned(struct vregion *vregion, struct vspace* vspace, 34 struct memobj *memobj, size_t offset, size_t size, 35 vregion_flags_t flags, size_t alignment) 36{ 37 errval_t err; 38 struct pmap *pmap = vspace_get_pmap(vspace); 39 40 // Allocate some virtual address space 41 genvaddr_t address; 42 err = pmap->f.determine_addr(pmap, memobj, alignment, &address); 43 if (err_is_fail(err)) { 44 return err_push(err, LIB_ERR_PMAP_DETERMINE_ADDR); 45 } 46 47 // Initialize 48 vregion->vspace = vspace; 49 vregion->memobj = memobj; 50 vregion->base = address; 51 vregion->offset = offset; 52 vregion->size = size; 53 vregion->flags = flags; 54 55 // Add to the vspace 56 err = vspace_add_vregion(vspace, vregion); 57 if (err_is_fail(err)) { 58 return err_push(err, LIB_ERR_VSPACE_ADD_REGION); 59 } 60 61 // Add to memobj 62 err = memobj->f.map_region(memobj, vregion); 63 if (err_is_fail(err)) { 64 // remove memobj from region if map fails, otherwise we'll get a 65 // follow up error if client code call vregion_destroy() on the 66 // region. 67 vregion->memobj = NULL; 68 return err_push(err, LIB_ERR_MEMOBJ_MAP_REGION); 69 } 70 71 return SYS_ERR_OK; 72} 73 74/** 75 * \brief Setup a new vregion anywhere in the address space 76 * 77 * \param vregion The vregion 78 * \param vspace The vspace to associate with the vregion 79 * \param memobj The memory object to associate with the region 80 * \param offset Offset into the memory object 81 * \param size Size of the memory object to use 82 * \param flags Vregion specific flags 83 */ 84errval_t vregion_map(struct vregion *vregion, struct vspace *vspace, 85 struct memobj *memobj, size_t offset, size_t size, 86 vregion_flags_t flags) 87{ 88 return vregion_map_aligned(vregion, vspace, memobj, offset, size, flags, 0); 89} 90 91/** 92 * \brief Setup a new vregion at a specified location 93 * 94 * \param vregion The region 95 * \param vspace The vspace to associate with the region 96 * \param memobj The memory object to associate with the region 97 * \param offset Offset into the memory object 98 * \param size Size of the memory object to use 99 * \param addr Address to create the vregion for 100 * \param flags Vregion specific flags 101 */ 102errval_t vregion_map_fixed(struct vregion *vregion, struct vspace *vspace, 103 struct memobj *memobj, size_t offset, size_t size, 104 genvaddr_t addr, vregion_flags_t flags) 105{ 106 errval_t err; 107 108 // FIXME: this check is arch-specific and should involve a call on the pmap 109 if (addr % BASE_PAGE_SIZE != 0) { 110 return LIB_ERR_VREGION_BAD_ALIGNMENT; 111 } 112 113 // Initialize 114 vregion->vspace = vspace; 115 vregion->memobj = memobj; 116 vregion->base = addr; 117 vregion->offset = offset; 118 vregion->size = size; 119 vregion->flags = flags; 120 121 // Add to vspace 122 err = vspace_add_vregion(vspace, vregion); 123 if (err_is_fail(err)) { 124 return err_push(err, LIB_ERR_VSPACE_ADD_REGION); 125 } 126 127 // Add to memobj 128 err = memobj->f.map_region(memobj, vregion); 129 if (err_is_fail(err)) { 130 return err_push(err, LIB_ERR_MEMOBJ_MAP_REGION); 131 } 132 133 return SYS_ERR_OK; 134} 135 136/** 137 * \brief Destroy the given region 138 * 139 * \return SYS_ERR_OK on success, error code on failure 140 * 141 * \bug This only works if the memobj type is memobj_one_frame. 142 */ 143errval_t vregion_destroy(struct vregion *vregion) 144{ 145 errval_t err; 146 147 if (!vregion) { 148 return SYS_ERR_OK; 149 } 150 151 struct vspace *vspace = vregion_get_vspace(vregion); 152 if (vspace != NULL) { 153 err = vspace_remove_vregion(vspace, vregion); 154 if (err_is_fail(err)) { 155 return err_push(err, LIB_ERR_VSPACE_REMOVE_REGION); 156 } 157 } 158 159 struct memobj *memobj = vregion_get_memobj(vregion); 160 if (memobj != NULL) { 161 err = memobj->f.unmap_region(memobj, vregion); 162 if (err_is_fail(err)) { 163 return err_push(err, LIB_ERR_MEMOBJ_UNMAP_REGION); 164 } 165 } 166 167 return SYS_ERR_OK; 168} 169 170/** 171 * \brief Page fault handler 172 * 173 * \param vregion The vregion the fault occured in 174 * \param addr The faulting address 175 * \param type The fault type 176 * 177 * Look up the appropriate memory object and forward the fault to it 178 */ 179errval_t vregion_pagefault_handler(struct vregion *vregion, genvaddr_t addr, 180 vm_fault_type_t type) 181{ 182 struct memobj *memobj = vregion->memobj; 183 genvaddr_t offset = addr - vregion->base; 184 185 return memobj->f.pagefault(memobj, vregion, offset, type); 186} 187