1/** 2 * \file 3 * \brief memory object of type single frame 4 */ 5 6/* 7 * Copyright (c) 2009, 2010, ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <barrelfish/barrelfish.h> 16#include "vspace_internal.h" 17 18/** 19 * \brief Map the memory object into a region 20 * 21 * \param memobj The memory object 22 * \param region The region to add 23 */ 24static errval_t map_region(struct memobj *memobj, struct vregion *vregion) 25{ 26 struct memobj_one_frame *one_frame = (struct memobj_one_frame*)memobj; 27 28 // Allocate and insert 29 struct vregion_list *data = malloc(sizeof(struct vregion_list)); 30 if (!data) { 31 return LIB_ERR_MALLOC_FAIL; 32 } 33 data->region = vregion; 34 struct vregion_list *walk = one_frame->vregion_list; 35 one_frame->vregion_list = data; 36 data->next = walk; 37 38 return SYS_ERR_OK; 39} 40 41/** 42 * \brief Unmap the memory object from a region 43 * 44 * \param memobj The memory object 45 * \param region The region to remove 46 * 47 * Will delete self using free if no more vregions are mapped in 48 */ 49static errval_t unmap_region(struct memobj *memobj, struct vregion *vregion) 50{ 51 errval_t err; 52 struct memobj_one_frame *one_frame = (struct memobj_one_frame*)memobj; 53 54 /* Unmap the affected area in the pmap */ 55 // XXX: assuming that area is mapped in pmap, i.e. pagefault was called 56 struct vspace *vspace = vregion_get_vspace(vregion); 57 struct pmap *pmap = vspace_get_pmap(vspace); 58 genvaddr_t vregion_base = vregion_get_base_addr(vregion); 59 genvaddr_t vregion_off = vregion_get_offset(vregion); 60 61 err = pmap->f.unmap(pmap, vregion_base + vregion_off, memobj->size, NULL); 62 if (err_is_fail(err)) { 63 return err_push(err, LIB_ERR_PMAP_UNMAP); 64 } 65 66 /* Remove the vregion from the list */ 67 struct vregion_list *walk = one_frame->vregion_list; 68 struct vregion_list *prev = NULL; 69 while (walk) { 70 if (walk->region == vregion) { 71 if (prev) { 72 prev->next = walk->next; 73 free(walk); 74 return SYS_ERR_OK; 75 } else { 76 one_frame->vregion_list = walk->next; 77 free(walk); 78 free(memobj); 79 return SYS_ERR_OK; 80 } 81 } 82 prev = walk; 83 walk = walk->next; 84 } 85 86 return LIB_ERR_VREGION_NOT_FOUND; 87} 88 89/** 90 * \brief Set the protection on a range 91 * 92 * \param memobj The memory object 93 * \param region The vregion to modify the mappings on 94 * \param offset Offset into the memory object 95 * \param range The range of space to set the protection for 96 * \param flags The protection flags 97 */ 98static errval_t protect(struct memobj *memobj, struct vregion *vregion, 99 genvaddr_t offset, size_t range, vs_prot_flags_t flags) 100{ 101 struct vspace *vspace = vregion_get_vspace(vregion); 102 struct pmap *pmap = vspace_get_pmap(vspace); 103 genvaddr_t base = vregion_get_base_addr(vregion); 104 genvaddr_t vregion_offset = vregion_get_offset(vregion); 105 errval_t err; 106 size_t ret_size; 107 err = pmap->f.modify_flags(pmap, base + offset + vregion_offset, range, 108 flags, &ret_size); 109 if (err_is_fail(err)) { 110 return err_push(err, LIB_ERR_PMAP_MODIFY_FLAGS); 111 } 112 113 return SYS_ERR_OK; 114} 115 116/** 117 * \brief Pin a range 118 * 119 * \param memobj The memory object 120 * \param region The vregion to modify the state on 121 * \param offset Offset into the memory object 122 * \param range The range of space to pin 123 */ 124static errval_t pin(struct memobj *memobj, struct vregion *vregion, 125 genvaddr_t offset, size_t range) 126{ 127 USER_PANIC("NYI"); 128} 129 130/** 131 * \brief Unpin a range 132 * 133 * \param memobj The memory object 134 * \param region The vregion to modify the state on 135 * \param offset Offset into the memory object 136 * \param range The range of space to unpin 137 */ 138static errval_t unpin(struct memobj *memobj, struct vregion *vregion, 139 genvaddr_t offset, size_t range) 140{ 141 USER_PANIC("NYI"); 142} 143 144/** 145 * \brief Set a frame for an offset into the memobj 146 * 147 * \param memobj The memory object 148 * \param offset Offset into the memory object 149 * \param frame The frame cap for the offset 150 * \param size The size of frame cap 151 */ 152static errval_t fill(struct memobj *memobj, genvaddr_t offset, struct capref frame, 153 size_t size) 154{ 155 struct memobj_one_frame *one_frame = (struct memobj_one_frame*)memobj; 156 157 assert(size == memobj->size); 158 one_frame->frame = frame; 159 one_frame->offset = offset; 160 161 return SYS_ERR_OK; 162} 163 164/** 165 * \brief Page fault handler 166 * 167 * \param memobj The memory object 168 * \param region The associated vregion 169 * \param offset Offset into memory object of the page fault 170 * \param type The fault type 171 */ 172static errval_t pagefault(struct memobj *memobj, struct vregion *vregion, 173 genvaddr_t offset, vm_fault_type_t type) 174{ 175 errval_t err; 176 struct memobj_one_frame *one_frame = (struct memobj_one_frame*)memobj; 177 if (offset < one_frame->offset || 178 offset > one_frame->offset + memobj->size) { 179 return LIB_ERR_MEMOBJ_WRONG_OFFSET; 180 } 181 182 // Map the single frame 183 struct vspace *vspace = vregion_get_vspace(vregion); 184 struct pmap *pmap = vspace_get_pmap(vspace); 185 genvaddr_t vregion_base = vregion_get_base_addr(vregion); 186 genvaddr_t vregion_off = vregion_get_offset(vregion); 187 vregion_flags_t flags = vregion_get_flags(vregion); 188 189 err = pmap->f.map(pmap, vregion_base + vregion_off, one_frame->frame, 190 one_frame->offset, memobj->size, flags, NULL, NULL); 191 if (err_is_fail(err)) { 192 return err_push(err, LIB_ERR_PMAP_MAP); 193 } 194 195 return SYS_ERR_OK; 196} 197 198/** 199 * \brief Free up some pages by placing them in the backing storage 200 * 201 * \param memobj The memory object 202 * \param size The amount of space to free up 203 * \param frames An array of capref frames to return the freed pages 204 * \param num_frames The number of frames returned 205 * 206 * This will affect all the vregions that are associated with the object 207 */ 208static errval_t pager_free(struct memobj *memobj, size_t size, 209 struct capref *frames, size_t num_frames) 210{ 211 USER_PANIC("NYI"); 212} 213 214/** 215 * \brief Initialize a memory object of type one frame 216 * 217 * \param memobj The memory object 218 * \param size Size of the memory region 219 * \param flags Memory object specific flags 220 * \param frame The frame to use 221 * \param offset Offset into the frame 222 */ 223errval_t memobj_create_one_frame(struct memobj_one_frame *one_frame, 224 size_t size, memobj_flags_t flags) 225{ 226 struct memobj *memobj = &one_frame->m; 227 228 /* Generic portion */ 229 memobj->f.map_region = map_region; 230 memobj->f.unmap_region = unmap_region; 231 memobj->f.protect = protect; 232 memobj->f.pin = pin; 233 memobj->f.unpin = unpin; 234 memobj->f.fill = fill; 235 memobj->f.pagefault = pagefault; 236 memobj->f.pager_free = pager_free; 237 238 memobj->size = size; 239 memobj->flags = flags; 240 241 memobj->type = ONE_FRAME; 242 243 /* one_frame specific portion */ 244 one_frame->vregion_list = NULL; 245 return SYS_ERR_OK; 246} 247 248/** 249 * \brief Destroy the object 250 * 251 * \bug NYI 252 */ 253errval_t memobj_destroy_one_frame(struct memobj *memobj) 254{ 255 return SYS_ERR_OK; 256} 257