1/** 2 * \file 3 * \brief memory object that maintains a single frame and can be mapped once 4 */ 5 6/* 7 * Copyright (c) 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_map *state = 27 (struct memobj_one_frame_one_map*)memobj; 28 29 if (state->vregion) { 30 return LIB_ERR_MEMOBJ_VREGION_ALREADY_MAPPED; 31 } 32 33 state->vregion = vregion; 34 return SYS_ERR_OK; 35} 36 37/** 38 * \brief Unmap the memory object from a region 39 * 40 * \param memobj The memory object 41 * \param region The region to remove 42 */ 43static errval_t unmap_region(struct memobj *memobj, struct vregion *vregion) 44{ 45 errval_t err; 46 struct memobj_one_frame_one_map *one_frame = (struct memobj_one_frame_one_map*)memobj; 47 48 if (one_frame->vregion != vregion) { 49 return LIB_ERR_VREGION_NOT_FOUND; 50 } 51 52 struct vspace *vspace = vregion_get_vspace(vregion); 53 struct pmap *pmap = vspace_get_pmap(vspace); 54 genvaddr_t vregion_base = vregion_get_base_addr(vregion); 55 genvaddr_t vregion_off = vregion_get_offset(vregion); 56 57 err = pmap->f.unmap(pmap, vregion_base + vregion_off, memobj->size, NULL); 58 if (err_is_fail(err)) { 59 return err_push(err, LIB_ERR_PMAP_UNMAP); 60 } 61 62 one_frame->vregion = NULL; 63 64 return SYS_ERR_OK; 65} 66 67 68static errval_t protect(struct memobj *memobj, struct vregion *vregion, 69 genvaddr_t offset, size_t range, vs_prot_flags_t flags) 70{ 71 struct vspace *vspace = vregion_get_vspace(vregion); 72 struct pmap *pmap = vspace_get_pmap(vspace); 73 genvaddr_t base = vregion_get_base_addr(vregion); 74 genvaddr_t vregion_offset = vregion_get_offset(vregion); 75 errval_t err; 76 size_t ret_size; 77 err = pmap->f.modify_flags(pmap, base + offset + vregion_offset, range, 78 flags, &ret_size); 79 if (err_is_fail(err)) { 80 return err_push(err, LIB_ERR_PMAP_MODIFY_FLAGS); 81 } 82 83 return SYS_ERR_OK; 84} 85 86/** 87 * \brief Pin a range 88 * 89 * \param memobj The memory object 90 * \param region The vregion to modify the state on 91 * \param offset Offset into the memory object 92 * \param range The range of space to pin 93 */ 94static errval_t pin(struct memobj *memobj, struct vregion *vregion, 95 genvaddr_t offset, size_t range) 96{ 97 USER_PANIC("NYI"); 98 return SYS_ERR_OK; 99} 100 101/** 102 * \brief Unpin a range 103 * 104 * \param memobj The memory object 105 * \param region The vregion to modify the state on 106 * \param offset Offset into the memory object 107 * \param range The range of space to unpin 108 */ 109static errval_t unpin(struct memobj *memobj, struct vregion *vregion, 110 genvaddr_t offset, size_t range) 111{ 112 USER_PANIC("NYI"); 113 return SYS_ERR_OK; 114} 115 116/** 117 * \brief Set a frame for an offset into the memobj 118 * 119 * \param memobj The memory object 120 * \param offset Offset into the memory object 121 * \param frame The frame cap for the offset 122 * \param size The size of frame cap 123 */ 124static errval_t fill(struct memobj *memobj, genvaddr_t offset, struct capref frame, 125 size_t size) 126{ 127 struct memobj_one_frame_one_map *state = 128 (struct memobj_one_frame_one_map*)memobj; 129 130 assert(size == memobj->size); 131 state->frame = frame; 132 state->offset = offset; 133 134 return SYS_ERR_OK; 135} 136 137/** 138 * \brief Page fault handler 139 * 140 * \param memobj The memory object 141 * \param region The associated vregion 142 * \param offset Offset into memory object of the page fault 143 * \param type The fault type 144 */ 145static errval_t pagefault(struct memobj *memobj, struct vregion *vregion, 146 genvaddr_t offset, vm_fault_type_t type) 147{ 148 errval_t err; 149 struct memobj_one_frame_one_map *state = 150 (struct memobj_one_frame_one_map*)memobj; 151 if (offset < state->offset || 152 offset > state->offset + memobj->size) { 153 return LIB_ERR_MEMOBJ_WRONG_OFFSET; 154 } 155 156 // Map the single frame 157 struct vspace *vspace = vregion_get_vspace(vregion); 158 struct pmap *pmap = vspace_get_pmap(vspace); 159 genvaddr_t vregion_base = vregion_get_base_addr(vregion); 160 genvaddr_t vregion_off = vregion_get_offset(vregion); 161 vregion_flags_t flags = vregion_get_flags(vregion); 162 163 err = pmap->f.map(pmap, vregion_base + vregion_off, state->frame, 164 state->offset, memobj->size, flags, NULL, NULL); 165 if (err_is_fail(err)) { 166 return err_push(err, LIB_ERR_PMAP_MAP); 167 } 168 169 return SYS_ERR_OK; 170} 171 172/** 173 * \brief Free up some pages by placing them in the backing storage 174 * 175 * \param memobj The memory object 176 * \param size The amount of space to free up 177 * \param frames An array of capref frames to return the freed pages 178 * \param num_frames The number of frames returned 179 * 180 * This will affect all the vregions that are associated with the object 181 */ 182static errval_t pager_free(struct memobj *memobj, size_t size, 183 struct capref *frames, size_t num_frames) 184{ 185 USER_PANIC("NYI"); 186 return SYS_ERR_OK; 187} 188 189/** 190 * \brief Initialize a memory object of type one frame 191 * 192 * \param memobj The memory object 193 * \param size Size of the memory region 194 * \param flags Memory object specific flags 195 * \param frame The frame to use 196 * \param offset Offset into the frame 197 */ 198errval_t memobj_create_one_frame_one_map(struct memobj_one_frame_one_map *state, 199 size_t size, memobj_flags_t flags) 200{ 201 struct memobj *memobj = &state->m; 202 203 /* Generic portion */ 204 memobj->f.map_region = map_region; 205 memobj->f.unmap_region = unmap_region; 206 memobj->f.protect = protect; 207 memobj->f.pin = pin; 208 memobj->f.unpin = unpin; 209 memobj->f.fill = fill; 210 memobj->f.pagefault = pagefault; 211 memobj->f.pager_free = pager_free; 212 213 memobj->size = size; 214 memobj->flags = flags; 215 216 memobj->type = ONE_FRAME_ONE_MAP; 217 218 /* one_frame_one_map specific portion */ 219 state->vregion = NULL; 220 return SYS_ERR_OK; 221} 222