1/** 2 * \file 3 * \brief Helpful utility functions 4 */ 5 6/* 7 * Copyright (c) 2009, 2010, 2011, ETH Zurich. 8 * Copyright (c) 2014, HP Labs. 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, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group. 14 */ 15 16#include <barrelfish/barrelfish.h> 17 18/** 19 * \brief Translate a lvaddr_t to genvaddr_t 20 */ 21genvaddr_t vspace_lvaddr_to_genvaddr(lvaddr_t lvaddr) 22{ 23 struct vspace *vspace = get_current_vspace(); 24 return vspace_layout_lvaddr_to_genvaddr(&vspace->layout, lvaddr); 25} 26 27/** 28 * \brief Translate a genvaddr_t to lvaddr_t 29 */ 30lvaddr_t vspace_genvaddr_to_lvaddr(genvaddr_t genvaddr) 31{ 32 struct vspace *vspace = get_current_vspace(); 33 return vspace_layout_genvaddr_to_lvaddr(&vspace->layout, genvaddr); 34} 35 36errval_t vspace_unmap(const void *buf) 37{ 38 errval_t err; 39 40 struct vregion *vregion = vspace_get_region(get_current_vspace(), buf); 41 assert(vregion); 42 43 err = vregion_destroy(vregion); 44 if (err_is_fail(err)) { 45 return err_push(err, LIB_ERR_VREGION_DESTROY); 46 } 47 48 return SYS_ERR_OK; 49} 50 51/// Map with an alignment constraint 52errval_t vspace_map_anon_nomalloc(void **retaddr, struct memobj_anon *memobj, 53 struct vregion *vregion, size_t size, 54 size_t *retsize, vregion_flags_t flags, 55 size_t alignment) 56{ 57 errval_t err1, err2; 58 size = ROUND_UP(size, BASE_PAGE_SIZE); 59 if (retsize) { 60 *retsize = size; 61 } 62 63 // Create a memobj and vregion 64 err1 = memobj_create_anon(memobj, size, 0); 65 if (err_is_fail(err1)) { 66 err1 = err_push(err1, LIB_ERR_MEMOBJ_CREATE_ANON); 67 goto error; 68 } 69 err1 = vregion_map_aligned(vregion, get_current_vspace(), 70 (struct memobj *)memobj, 0, size, 71 flags, alignment); 72 if (err_is_fail(err1)) { 73 err1 = err_push(err1, LIB_ERR_VREGION_MAP); 74 goto error; 75 } 76 77 *retaddr = (void*)vspace_genvaddr_to_lvaddr(vregion_get_base_addr(vregion)); 78 79 return SYS_ERR_OK; 80 81 error: 82 if (err_no(err1) != LIB_ERR_MEMOBJ_CREATE_ANON) { 83 err2 = memobj_destroy_anon((struct memobj *)memobj, true); 84 if (err_is_fail(err2)) { 85 DEBUG_ERR(err2, "memobj_destroy_anon failed"); 86 } 87 } 88 return err1; 89} 90 91/** 92 * \brief Wrapper for creating and mapping a memory object of type anonymous. 93 * 94 * The memory object and vregion are returned so the user can call fill and 95 * pagefault on it to create actual mappings. 96 */ 97errval_t vspace_map_anon_aligned(void **retaddr, struct memobj **ret_memobj, 98 struct vregion **ret_vregion, size_t size, 99 size_t *retsize, vregion_flags_t flags, 100 size_t alignment) 101{ 102 errval_t err; 103 struct memobj_anon *memobj = NULL; 104 struct vregion *vregion = NULL; 105 106 // Allocate space 107 memobj = malloc(sizeof(struct memobj_anon)); 108 assert(memobj != NULL); 109 110 vregion = malloc(sizeof(struct vregion)); 111 assert(vregion != NULL); 112 113 err = vspace_map_anon_nomalloc(retaddr, memobj, vregion, size, 114 retsize, flags, alignment); 115 if (err_is_fail(err)) { 116 free(memobj); 117 free(vregion); 118 } else { 119 *ret_memobj = (struct memobj *)memobj; 120 *ret_vregion = vregion; 121 } 122 123 return err; 124} 125 126/** 127 * \brief Wrapper for creating and mapping a memory object of type anonymous. 128 * 129 * The memory object and vregion are returned so the user can call fill and 130 * pagefault on it to create actual mappings. 131 */ 132errval_t vspace_map_anon_attr(void **retaddr, struct memobj **ret_memobj, 133 struct vregion **ret_vregion, size_t size, 134 size_t *retsize, vregion_flags_t flags) 135{ 136 errval_t err; 137 138 struct memobj_anon *memobj = NULL; 139 struct vregion *vregion = NULL; 140 141 // Allocate space 142 memobj = malloc(sizeof(struct memobj_anon)); 143 assert(memobj != NULL); 144 145 vregion = malloc(sizeof(struct vregion)); 146 assert(vregion != NULL); 147 148 err = vspace_map_anon_nomalloc(retaddr, memobj, vregion, size, 149 retsize, flags, 0); 150 if (err_is_fail(err)) { 151 free(memobj); 152 free(vregion); 153 } else { 154 *ret_memobj = (struct memobj *)memobj; 155 *ret_vregion = vregion; 156 } 157 158 return err; 159} 160 161/** 162 * \brief Wrapper to create and map an anonymous memory object at a fixed address. 163 * 164 * The memory object and vregion are returned so the user can call fill and 165 * pagefault on it to create actual mappings. 166 */ 167errval_t vspace_map_anon_fixed(genvaddr_t base, size_t size, 168 vregion_flags_t flags, 169 struct vregion **ret_vregion, 170 struct memobj **ret_memobj) 171{ 172 errval_t err1, err2; 173 struct memobj *memobj = NULL; 174 struct vregion *vregion = NULL; 175 176 // Allocate space 177 memobj = malloc(sizeof(struct memobj_anon)); 178 if (!memobj) { 179 err1 = LIB_ERR_MALLOC_FAIL; 180 goto error; 181 } 182 vregion = malloc(sizeof(struct vregion)); 183 if (!vregion) { 184 err1 = LIB_ERR_MALLOC_FAIL; 185 goto error; 186 } 187 188 // Create a memobj and vregion 189 err1 = memobj_create_anon((struct memobj_anon*)memobj, size, 0); 190 if (err_is_fail(err1)) { 191 err1 = err_push(err1, LIB_ERR_MEMOBJ_CREATE_ANON); 192 goto error; 193 } 194 err1 = vregion_map_fixed(vregion, get_current_vspace(), memobj, 0, size, 195 base, flags); 196 if (err_is_fail(err1)) { 197 err1 = err_push(err1, LIB_ERR_VREGION_MAP); 198 goto error; 199 } 200 201 *ret_vregion = vregion; 202 *ret_memobj = memobj; 203 204 return SYS_ERR_OK; 205 206error: 207 if (memobj) { 208 err2 = memobj_destroy_anon(memobj, true); 209 if (err_is_fail(err2)) { 210 DEBUG_ERR(err2, "memobj_destroy_anon failed"); 211 } 212 free(memobj); 213 } 214 if (vregion) { 215 err2 = vregion_destroy(vregion); 216 if (err_is_fail(err2)) { 217 DEBUG_ERR(err2, "vregion_destroy failed"); 218 } 219 free(vregion); 220 } 221 return err1; 222} 223 224/** 225 * \brief Wrapper for creating and mapping a memory object of type one frame 226 */ 227errval_t vspace_map_one_frame(void **retaddr, size_t size, struct capref frame, 228 struct memobj **retmemobj, 229 struct vregion **retvregion) 230{ 231 return vspace_map_one_frame_attr(retaddr, size, frame, 232 VREGION_FLAGS_READ_WRITE, retmemobj, 233 retvregion); 234} 235 236errval_t vspace_map_one_frame_fixed(lvaddr_t addr, size_t size, 237 struct capref frame, 238 struct memobj **retmemobj, 239 struct vregion **retvregion) 240{ 241 return vspace_map_one_frame_fixed_attr(addr, size, frame, 242 VREGION_FLAGS_READ_WRITE, retmemobj, 243 retvregion); 244} 245 246errval_t vspace_map_one_frame_fixed_attr(lvaddr_t addr, size_t size, 247 struct capref frame, vregion_flags_t flags, 248 struct memobj **retmemobj, 249 struct vregion **retvregion) 250{ 251 errval_t err1, err2; 252 struct memobj *memobj = NULL; 253 struct vregion *vregion = NULL; 254 255 size = ROUND_UP(size, BASE_PAGE_SIZE); 256 257 // Allocate space 258 memobj = malloc(sizeof(struct memobj_one_frame)); 259 if (!memobj) { 260 err1 = LIB_ERR_MALLOC_FAIL; 261 goto error; 262 } 263 vregion = malloc(sizeof(struct vregion)); 264 if (!vregion) { 265 err1 = LIB_ERR_MALLOC_FAIL; 266 goto error; 267 } 268 269 // Create mappings 270 err1 = memobj_create_one_frame((struct memobj_one_frame*)memobj, size, 0); 271 if (err_is_fail(err1)) { 272 err1 = err_push(err1, LIB_ERR_MEMOBJ_CREATE_ONE_FRAME); 273 goto error; 274 } 275 276 err1 = memobj->f.fill(memobj, 0, frame, size); 277 if (err_is_fail(err1)) { 278 err1 = err_push(err1, LIB_ERR_MEMOBJ_FILL); 279 goto error; 280 } 281 282 err1 = vregion_map_fixed(vregion, get_current_vspace(), memobj, 0, size, addr, flags); 283 if (err_is_fail(err1)) { 284 err1 = err_push(err1, LIB_ERR_VREGION_MAP); 285 goto error; 286 } 287 288 err1 = memobj->f.pagefault(memobj, vregion, 0, 0); 289 if (err_is_fail(err1)) { 290 err1 = err_push(err1, LIB_ERR_MEMOBJ_PAGEFAULT_HANDLER); 291 goto error; 292 } 293 294 if (retmemobj) { 295 *retmemobj = memobj; 296 } 297 if (retvregion) { 298 *retvregion = vregion; 299 } 300 return SYS_ERR_OK; 301 302 error: 303 if (memobj) { 304 err2 = memobj_destroy_one_frame(memobj); 305 if (err_is_fail(err2)) { 306 DEBUG_ERR(err2, "memobj_destroy_anon failed"); 307 } 308 } 309 if (vregion) { 310 err2 = vregion_destroy(vregion); 311 if (err_is_fail(err2)) { 312 DEBUG_ERR(err2, "vregion_destroy failed"); 313 } 314 } 315 return err1; 316} 317 318/** 319 * \brief Wrapper for creating and mapping a memory object 320 * of type one frame with specific flags 321 */ 322errval_t vspace_map_one_frame_attr(void **retaddr, size_t size, 323 struct capref frame, vregion_flags_t flags, 324 struct memobj **retmemobj, 325 struct vregion **retvregion) 326{ 327 return vspace_map_one_frame_attr_aligned(retaddr, size, 328 frame, flags, 0, retmemobj, retvregion); 329} 330 331/** 332 * \brief Wrapper for creating and mapping a memory object 333 * of type one frame with specific flags and a specific alignment 334 */ 335errval_t vspace_map_one_frame_attr_aligned(void **retaddr, size_t size, 336 struct capref frame, vregion_flags_t flags, 337 size_t alignment, 338 struct memobj **retmemobj, 339 struct vregion **retvregion) 340{ 341 errval_t err1, err2; 342 struct memobj *memobj = NULL; 343 struct vregion *vregion = NULL; 344 345 size = ROUND_UP(size, BASE_PAGE_SIZE); 346 347 // Allocate space 348 memobj = calloc(1, sizeof(struct memobj_one_frame)); 349 if (!memobj) { 350 err1 = LIB_ERR_MALLOC_FAIL; 351 goto error; 352 } 353 vregion = calloc(1, sizeof(struct vregion)); 354 if (!vregion) { 355 err1 = LIB_ERR_MALLOC_FAIL; 356 goto error; 357 } 358 359 // Create mappings 360 err1 = memobj_create_one_frame((struct memobj_one_frame*)memobj, size, 0); 361 if (err_is_fail(err1)) { 362 err1 = err_push(err1, LIB_ERR_MEMOBJ_CREATE_ONE_FRAME); 363 goto error; 364 } 365 366 err1 = memobj->f.fill(memobj, 0, frame, size); 367 if (err_is_fail(err1)) { 368 err1 = err_push(err1, LIB_ERR_MEMOBJ_FILL); 369 goto error; 370 } 371 372 err1 = vregion_map_aligned(vregion, get_current_vspace(), memobj, 0, size, 373 flags, alignment); 374 if (err_is_fail(err1)) { 375 err1 = err_push(err1, LIB_ERR_VREGION_MAP); 376 goto error; 377 } 378 379 err1 = memobj->f.pagefault(memobj, vregion, 0, 0); 380 if (err_is_fail(err1)) { 381 err1 = err_push(err1, LIB_ERR_MEMOBJ_PAGEFAULT_HANDLER); 382 goto error; 383 } 384 385 *retaddr = (void*)vspace_genvaddr_to_lvaddr(vregion_get_base_addr(vregion)); 386 if (retmemobj) { 387 *retmemobj = memobj; 388 } 389 if (retvregion) { 390 *retvregion = vregion; 391 } 392 return SYS_ERR_OK; 393 394 error: 395 if (memobj) { 396 err2 = memobj_destroy_one_frame(memobj); 397 if (err_is_fail(err2)) { 398 DEBUG_ERR(err2, "memobj_destroy_anon failed"); 399 } 400 } 401 if (vregion) { 402 err2 = vregion_destroy(vregion); 403 if (err_is_fail(err2)) { 404 DEBUG_ERR(err2, "vregion_destroy failed"); 405 } 406 } 407 return err1; 408} 409 410errval_t vspace_map_one_frame_one_map(struct memobj_one_frame_one_map *memobj, 411 struct vregion *vregion, size_t size, 412 struct capref frame) 413{ 414 errval_t err; 415 416 err = memobj_create_one_frame_one_map(memobj, size, 0); 417 if (err_is_fail(err)) { 418 return err_push(err, LIB_ERR_MEMOBJ_CREATE_ONE_FRAME_ONE_MAP); 419 } 420 err = memobj->m.f.fill(&memobj->m, 0, frame, size); 421 if (err_is_fail(err)) { 422 return err_push(err, LIB_ERR_MEMOBJ_FILL); 423 } 424 err = vregion_map(vregion, get_current_vspace(), &memobj->m, 0, size, 425 VREGION_FLAGS_READ_WRITE); 426 if (err_is_fail(err)) { 427 return err_push(err, LIB_ERR_VREGION_MAP); 428 } 429 err = memobj->m.f.pagefault(&memobj->m, vregion, 0, 0); 430 if (err_is_fail(err)) { 431 return err_push(err, LIB_ERR_MEMOBJ_PAGEFAULT_HANDLER); 432 } 433 434 return SYS_ERR_OK; 435} 436