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, Universitaetstrasse 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 91errval_t vspace_map_append_nomalloc(void **retaddr, struct memobj_append *memobj, 92 struct vregion *vregion, size_t size, 93 size_t *retsize, vregion_flags_t flags, 94 size_t alignment) 95{ 96 errval_t err1, err2; 97 size = ROUND_UP(size, BASE_PAGE_SIZE); 98 if (retsize) { 99 *retsize = size; 100 } 101 102 // Create a memobj and vregion 103 err1 = memobj_create_append(memobj, size, 0); 104 if (err_is_fail(err1)) { 105 err1 = err_push(err1, LIB_ERR_MEMOBJ_CREATE_ANON); 106 goto error; 107 } 108 err1 = vregion_map_aligned(vregion, get_current_vspace(), 109 (struct memobj *)memobj, 0, size, 110 flags, alignment); 111 if (err_is_fail(err1)) { 112 err1 = err_push(err1, LIB_ERR_VREGION_MAP); 113 goto error; 114 } 115 116 *retaddr = (void*)vspace_genvaddr_to_lvaddr(vregion_get_base_addr(vregion)); 117 118 return SYS_ERR_OK; 119 120 error: 121 if (err_no(err1) != LIB_ERR_MEMOBJ_CREATE_ANON) { 122 err2 = memobj_destroy_append((struct memobj *)memobj); 123 if (err_is_fail(err2)) { 124 DEBUG_ERR(err2, "memobj_destroy_anon failed"); 125 } 126 } 127 return err1; 128} 129 130/** 131 * \brief Wrapper for creating and mapping a memory object of type anonymous. 132 * 133 * The memory object and vregion are returned so the user can call fill and 134 * pagefault on it to create actual mappings. 135 */ 136errval_t vspace_map_anon_aligned(void **retaddr, struct memobj **ret_memobj, 137 struct vregion **ret_vregion, size_t size, 138 size_t *retsize, vregion_flags_t flags, 139 size_t alignment) 140{ 141 errval_t err; 142 struct memobj_anon *memobj = NULL; 143 struct vregion *vregion = NULL; 144 145 // Allocate space 146 memobj = malloc(sizeof(struct memobj_anon)); 147 assert(memobj != NULL); 148 149 vregion = malloc(sizeof(struct vregion)); 150 assert(vregion != NULL); 151 152 err = vspace_map_anon_nomalloc(retaddr, memobj, vregion, size, 153 retsize, flags, alignment); 154 if (err_is_fail(err)) { 155 free(memobj); 156 free(vregion); 157 } else { 158 *ret_memobj = (struct memobj *)memobj; 159 *ret_vregion = vregion; 160 } 161 162 return err; 163} 164 165/** 166 * \brief Wrapper for creating and mapping a memory object of type anonymous. 167 * 168 * The memory object and vregion are returned so the user can call fill and 169 * pagefault on it to create actual mappings. 170 */ 171errval_t vspace_map_anon_attr(void **retaddr, struct memobj **ret_memobj, 172 struct vregion **ret_vregion, size_t size, 173 size_t *retsize, vregion_flags_t flags) 174{ 175 errval_t err; 176 177 struct memobj_anon *memobj = NULL; 178 struct vregion *vregion = NULL; 179 180 // Allocate space 181 memobj = malloc(sizeof(struct memobj_anon)); 182 assert(memobj != NULL); 183 184 vregion = malloc(sizeof(struct vregion)); 185 assert(vregion != NULL); 186 187 err = vspace_map_anon_nomalloc(retaddr, memobj, vregion, size, 188 retsize, flags, 0); 189 if (err_is_fail(err)) { 190 free(memobj); 191 free(vregion); 192 } else { 193 *ret_memobj = (struct memobj *)memobj; 194 *ret_vregion = vregion; 195 } 196 197 return err; 198} 199 200/** 201 * \brief Wrapper to create and map an anonymous memory object at a fixed address. 202 * 203 * The memory object and vregion are returned so the user can call fill and 204 * pagefault on it to create actual mappings. 205 */ 206errval_t vspace_map_anon_fixed(genvaddr_t base, size_t size, 207 vregion_flags_t flags, 208 struct vregion **ret_vregion, 209 struct memobj **ret_memobj) 210{ 211 errval_t err1, err2; 212 struct memobj *memobj = NULL; 213 struct vregion *vregion = NULL; 214 215 // Allocate space 216 memobj = malloc(sizeof(struct memobj_anon)); 217 if (!memobj) { 218 err1 = LIB_ERR_MALLOC_FAIL; 219 goto error; 220 } 221 vregion = malloc(sizeof(struct vregion)); 222 if (!vregion) { 223 err1 = LIB_ERR_MALLOC_FAIL; 224 goto error; 225 } 226 227 // Create a memobj and vregion 228 err1 = memobj_create_anon((struct memobj_anon*)memobj, size, 0); 229 if (err_is_fail(err1)) { 230 err1 = err_push(err1, LIB_ERR_MEMOBJ_CREATE_ANON); 231 goto error; 232 } 233 err1 = vregion_map_fixed(vregion, get_current_vspace(), memobj, 0, size, 234 base, flags); 235 if (err_is_fail(err1)) { 236 err1 = err_push(err1, LIB_ERR_VREGION_MAP); 237 goto error; 238 } 239 240 *ret_vregion = vregion; 241 *ret_memobj = memobj; 242 243 return SYS_ERR_OK; 244 245error: 246 if (memobj) { 247 err2 = memobj_destroy_anon(memobj, true); 248 if (err_is_fail(err2)) { 249 DEBUG_ERR(err2, "memobj_destroy_anon failed"); 250 } 251 free(memobj); 252 } 253 if (vregion) { 254 err2 = vregion_destroy(vregion); 255 if (err_is_fail(err2)) { 256 DEBUG_ERR(err2, "vregion_destroy failed"); 257 } 258 free(vregion); 259 } 260 return err1; 261} 262 263/** 264 * \brief Wrapper for creating and mapping a memory object of type one frame 265 */ 266errval_t vspace_map_one_frame(void **retaddr, size_t size, struct capref frame, 267 struct memobj **retmemobj, 268 struct vregion **retvregion) 269{ 270 return vspace_map_one_frame_attr(retaddr, size, frame, 271 VREGION_FLAGS_READ_WRITE, retmemobj, 272 retvregion); 273} 274 275errval_t vspace_map_one_frame_fixed(lvaddr_t addr, size_t size, 276 struct capref frame, 277 struct memobj **retmemobj, 278 struct vregion **retvregion) 279{ 280 return vspace_map_one_frame_fixed_attr(addr, size, frame, 281 VREGION_FLAGS_READ_WRITE, retmemobj, 282 retvregion); 283} 284 285errval_t vspace_map_one_frame_fixed_attr(lvaddr_t addr, size_t size, 286 struct capref frame, vregion_flags_t flags, 287 struct memobj **retmemobj, 288 struct vregion **retvregion) 289{ 290 errval_t err1, err2; 291 struct memobj *memobj = NULL; 292 struct vregion *vregion = NULL; 293 294 size = ROUND_UP(size, BASE_PAGE_SIZE); 295 296 // Allocate space 297 memobj = malloc(sizeof(struct memobj_one_frame)); 298 if (!memobj) { 299 err1 = LIB_ERR_MALLOC_FAIL; 300 goto error; 301 } 302 vregion = malloc(sizeof(struct vregion)); 303 if (!vregion) { 304 err1 = LIB_ERR_MALLOC_FAIL; 305 goto error; 306 } 307 308 // Create mappings 309 err1 = memobj_create_one_frame((struct memobj_one_frame*)memobj, size, 0); 310 if (err_is_fail(err1)) { 311 err1 = err_push(err1, LIB_ERR_MEMOBJ_CREATE_ONE_FRAME); 312 goto error; 313 } 314 315 err1 = memobj->f.fill(memobj, 0, frame, size); 316 if (err_is_fail(err1)) { 317 err1 = err_push(err1, LIB_ERR_MEMOBJ_FILL); 318 goto error; 319 } 320 321 err1 = vregion_map_fixed(vregion, get_current_vspace(), memobj, 0, size, addr, flags); 322 if (err_is_fail(err1)) { 323 err1 = err_push(err1, LIB_ERR_VREGION_MAP); 324 goto error; 325 } 326 327 err1 = memobj->f.pagefault(memobj, vregion, 0, 0); 328 if (err_is_fail(err1)) { 329 err1 = err_push(err1, LIB_ERR_MEMOBJ_PAGEFAULT_HANDLER); 330 goto error; 331 } 332 333 if (retmemobj) { 334 *retmemobj = memobj; 335 } 336 if (retvregion) { 337 *retvregion = vregion; 338 } 339 return SYS_ERR_OK; 340 341 error: 342 if (memobj) { 343 err2 = memobj_destroy_one_frame(memobj); 344 if (err_is_fail(err2)) { 345 DEBUG_ERR(err2, "memobj_destroy_anon failed"); 346 } 347 } 348 if (vregion) { 349 err2 = vregion_destroy(vregion); 350 if (err_is_fail(err2)) { 351 DEBUG_ERR(err2, "vregion_destroy failed"); 352 } 353 } 354 return err1; 355} 356 357/** 358 * \brief Wrapper for creating and mapping a memory object 359 * of type one frame with specific flags 360 */ 361errval_t vspace_map_one_frame_attr(void **retaddr, size_t size, 362 struct capref frame, vregion_flags_t flags, 363 struct memobj **retmemobj, 364 struct vregion **retvregion) 365{ 366 return vspace_map_one_frame_attr_aligned(retaddr, size, 367 frame, flags, 0, retmemobj, retvregion); 368} 369 370/** 371 * \brief Wrapper for creating and mapping a memory object 372 * of type one frame with specific flags and a specific alignment 373 */ 374errval_t vspace_map_one_frame_attr_aligned(void **retaddr, size_t size, 375 struct capref frame, vregion_flags_t flags, 376 size_t alignment, 377 struct memobj **retmemobj, 378 struct vregion **retvregion) 379{ 380 errval_t err1, err2; 381 struct memobj *memobj = NULL; 382 struct vregion *vregion = NULL; 383 384 size = ROUND_UP(size, BASE_PAGE_SIZE); 385 386 // Allocate space 387 memobj = calloc(1, sizeof(struct memobj_one_frame)); 388 if (!memobj) { 389 err1 = LIB_ERR_MALLOC_FAIL; 390 goto error; 391 } 392 vregion = calloc(1, sizeof(struct vregion)); 393 if (!vregion) { 394 err1 = LIB_ERR_MALLOC_FAIL; 395 goto error; 396 } 397 398 // Create mappings 399 err1 = memobj_create_one_frame((struct memobj_one_frame*)memobj, size, 0); 400 if (err_is_fail(err1)) { 401 err1 = err_push(err1, LIB_ERR_MEMOBJ_CREATE_ONE_FRAME); 402 goto error; 403 } 404 405 err1 = memobj->f.fill(memobj, 0, frame, size); 406 if (err_is_fail(err1)) { 407 err1 = err_push(err1, LIB_ERR_MEMOBJ_FILL); 408 goto error; 409 } 410 411 err1 = vregion_map_aligned(vregion, get_current_vspace(), memobj, 0, size, 412 flags, alignment); 413 if (err_is_fail(err1)) { 414 err1 = err_push(err1, LIB_ERR_VREGION_MAP); 415 goto error; 416 } 417 418 err1 = memobj->f.pagefault(memobj, vregion, 0, 0); 419 if (err_is_fail(err1)) { 420 err1 = err_push(err1, LIB_ERR_MEMOBJ_PAGEFAULT_HANDLER); 421 goto error; 422 } 423 424 *retaddr = (void*)vspace_genvaddr_to_lvaddr(vregion_get_base_addr(vregion)); 425 if (retmemobj) { 426 *retmemobj = memobj; 427 } 428 if (retvregion) { 429 *retvregion = vregion; 430 } 431 return SYS_ERR_OK; 432 433 error: 434 if (memobj) { 435 err2 = memobj_destroy_one_frame(memobj); 436 if (err_is_fail(err2)) { 437 DEBUG_ERR(err2, "memobj_destroy_anon failed"); 438 } 439 } 440 if (vregion) { 441 err2 = vregion_destroy(vregion); 442 if (err_is_fail(err2)) { 443 DEBUG_ERR(err2, "vregion_destroy failed"); 444 } 445 } 446 return err1; 447} 448 449errval_t vspace_map_one_frame_one_map(struct memobj_one_frame_one_map *memobj, 450 struct vregion *vregion, size_t size, 451 struct capref frame) 452{ 453 errval_t err; 454 455 err = memobj_create_one_frame_one_map(memobj, size, 0); 456 if (err_is_fail(err)) { 457 return err_push(err, LIB_ERR_MEMOBJ_CREATE_ONE_FRAME_ONE_MAP); 458 } 459 err = memobj->m.f.fill(&memobj->m, 0, frame, size); 460 if (err_is_fail(err)) { 461 return err_push(err, LIB_ERR_MEMOBJ_FILL); 462 } 463 err = vregion_map(vregion, get_current_vspace(), &memobj->m, 0, size, 464 VREGION_FLAGS_READ_WRITE); 465 if (err_is_fail(err)) { 466 return err_push(err, LIB_ERR_VREGION_MAP); 467 } 468 err = memobj->m.f.pagefault(&memobj->m, vregion, 0, 0); 469 if (err_is_fail(err)) { 470 return err_push(err, LIB_ERR_MEMOBJ_PAGEFAULT_HANDLER); 471 } 472 473 return SYS_ERR_OK; 474} 475