1130812Smarcel/** 2130812Smarcel * \file 3130812Smarcel * \brief memory object of type single frame 4130812Smarcel */ 5130812Smarcel 6130812Smarcel/* 7130812Smarcel * Copyright (c) 2009, 2010, ETH Zurich. 8130812Smarcel * All rights reserved. 9130812Smarcel * 10130812Smarcel * This file is distributed under the terms in the attached LICENSE file. 11130812Smarcel * If you do not find this file, copies can be found by writing to: 12130812Smarcel * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 13130812Smarcel */ 14130812Smarcel 15130812Smarcel#include <barrelfish/barrelfish.h> 16130812Smarcel#include "vspace_internal.h" 17130812Smarcel 18130812Smarcel/** 19130812Smarcel * \brief Map the memory object into a region 20130812Smarcel * 21130812Smarcel * \param memobj The memory object 22130812Smarcel * \param region The region to add 23130812Smarcel */ 24130812Smarcelstatic errval_t map_region(struct memobj *memobj, struct vregion *vregion) 25130812Smarcel{ 26130812Smarcel struct memobj_one_frame *one_frame = (struct memobj_one_frame*)memobj; 27130812Smarcel 28130812Smarcel // Allocate and insert 29130812Smarcel struct vregion_list *data = malloc(sizeof(struct vregion_list)); 30130812Smarcel if (!data) { 31130812Smarcel return LIB_ERR_MALLOC_FAIL; 32130812Smarcel } 33130812Smarcel data->region = vregion; 34130812Smarcel struct vregion_list *walk = one_frame->vregion_list; 35130812Smarcel one_frame->vregion_list = data; 36130812Smarcel data->next = walk; 37130812Smarcel 38130812Smarcel return SYS_ERR_OK; 39130812Smarcel} 40130812Smarcel 41130812Smarcel/** 42130812Smarcel * \brief Unmap the memory object from a region 43130812Smarcel * 44130812Smarcel * \param memobj The memory object 45130812Smarcel * \param region The region to remove 46130812Smarcel * 47130812Smarcel * Will delete self using free if no more vregions are mapped in 48130812Smarcel */ 49130812Smarcelstatic errval_t unmap_region(struct memobj *memobj, struct vregion *vregion) 50130812Smarcel{ 51130812Smarcel errval_t err; 52130812Smarcel struct memobj_one_frame *one_frame = (struct memobj_one_frame*)memobj; 53130812Smarcel 54130812Smarcel /* Unmap the affected area in the pmap */ 55130812Smarcel // XXX: assuming that area is mapped in pmap, i.e. pagefault was called 56130812Smarcel struct vspace *vspace = vregion_get_vspace(vregion); 57130812Smarcel struct pmap *pmap = vspace_get_pmap(vspace); 58130812Smarcel genvaddr_t vregion_base = vregion_get_base_addr(vregion); 59130812Smarcel genvaddr_t vregion_off = vregion_get_offset(vregion); 60130812Smarcel 61130812Smarcel err = pmap->f.unmap(pmap, vregion_base + vregion_off, memobj->size, NULL); 62130812Smarcel if (err_is_fail(err)) { 63130812Smarcel return err_push(err, LIB_ERR_PMAP_UNMAP); 64130812Smarcel } 65130812Smarcel 66130812Smarcel /* Remove the vregion from the list */ 67130812Smarcel struct vregion_list *walk = one_frame->vregion_list; 68130812Smarcel struct vregion_list *prev = NULL; 69130812Smarcel while (walk) { 70130812Smarcel if (walk->region == vregion) { 71130812Smarcel if (prev) { 72130812Smarcel prev->next = walk->next; 73130812Smarcel free(walk); 74130812Smarcel return SYS_ERR_OK; 75130812Smarcel } else { 76130812Smarcel one_frame->vregion_list = walk->next; 77130812Smarcel free(walk); 78130812Smarcel free(memobj); 79130812Smarcel return SYS_ERR_OK; 80130812Smarcel } 81130812Smarcel } 82130812Smarcel prev = walk; 83130812Smarcel walk = walk->next; 84130812Smarcel } 85130812Smarcel 86130812Smarcel return LIB_ERR_VREGION_NOT_FOUND; 87130812Smarcel} 88130812Smarcel 89130812Smarcel/** 90130812Smarcel * \brief Set the protection on a range 91130812Smarcel * 92130812Smarcel * \param memobj The memory object 93130812Smarcel * \param region The vregion to modify the mappings on 94130812Smarcel * \param offset Offset into the memory object 95130812Smarcel * \param range The range of space to set the protection for 96130812Smarcel * \param flags The protection flags 97130812Smarcel */ 98130812Smarcelstatic errval_t protect(struct memobj *memobj, struct vregion *vregion, 99130812Smarcel genvaddr_t offset, size_t range, vs_prot_flags_t flags) 100130812Smarcel{ 101130812Smarcel struct vspace *vspace = vregion_get_vspace(vregion); 102130812Smarcel struct pmap *pmap = vspace_get_pmap(vspace); 103130812Smarcel genvaddr_t base = vregion_get_base_addr(vregion); 104130812Smarcel genvaddr_t vregion_offset = vregion_get_offset(vregion); 105130812Smarcel errval_t err; 106130812Smarcel size_t ret_size; 107130812Smarcel err = pmap->f.modify_flags(pmap, base + offset + vregion_offset, range, 108130812Smarcel flags, &ret_size); 109130812Smarcel if (err_is_fail(err)) { 110130812Smarcel return err_push(err, LIB_ERR_PMAP_MODIFY_FLAGS); 111130812Smarcel } 112130812Smarcel 113130812Smarcel return SYS_ERR_OK; 114130812Smarcel} 115130812Smarcel 116130812Smarcel/** 117130812Smarcel * \brief Pin a range 118130812Smarcel * 119130812Smarcel * \param memobj The memory object 120130812Smarcel * \param region The vregion to modify the state on 121130812Smarcel * \param offset Offset into the memory object 122130812Smarcel * \param range The range of space to pin 123130812Smarcel */ 124130812Smarcelstatic errval_t pin(struct memobj *memobj, struct vregion *vregion, 125130812Smarcel genvaddr_t offset, size_t range) 126130812Smarcel{ 127130812Smarcel USER_PANIC("NYI"); 128130812Smarcel} 129130812Smarcel 130130812Smarcel/** 131130812Smarcel * \brief Unpin a range 132130812Smarcel * 133130812Smarcel * \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