1/* 2 * Copyright 2016, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(D61_BSD) 11 */ 12 13#include "../../common.h" 14#include "../../state.h" 15#include "vspace.h" 16#include "../memserv/window.h" 17#include "../process/pid.h" 18#include "../process/process.h" 19#include <autoconf.h> 20#include <refos/refos.h> 21#include <sel4utils/vspace.h> 22 23/*! @file 24 @brief Client address space objects. */ 25 26#define VSPACE_WINDOW_VERBOSE_DEBUG true 27 28/* -------------------- VSpace Helper Library Callback Functions ---------------------------------*/ 29 30static void 31vs_vspace_allocated_object_bookkeeping_callback(void *allocated_object_cookie, vka_object_t object) 32{ 33 struct vs_vspace *vs = (struct vs_vspace *) allocated_object_cookie; 34 assert(vs && vs->magic == REFOS_VSPACE_MAGIC); 35 36 /* Create our own copy of this allocated object struct. */ 37 vka_object_t *kobj = kmalloc(sizeof(vka_object_t)); 38 if (!kobj) { 39 ROS_WARNING("Could not allocate new vka_object_t to book keep vspace allocated object."); 40 ROS_WARNING("Object will be LEAKED."); 41 return; 42 } 43 memcpy(kobj, &object, sizeof(vka_object_t)); 44 45 /* Add to end of free list. */ 46 cvector_add(&vs->kobjVSpaceAllocatedFreelist, (cvector_item_t) kobj); 47} 48 49 50/* ---------------------------------- VSpace struct ----------------------------------------------*/ 51 52int 53vs_initialise(struct vs_vspace *vs, uint32_t pid) 54{ 55 assert(vs); 56 dvprintf(" Initialising a vspace...\n"); 57 memset(vs, 0, sizeof(*vs)); 58 int error = ESUCCESS; 59 60 vs->magic = REFOS_VSPACE_MAGIC; 61 vs->ref = 1; 62 vs->pid = pid; 63 64 /* Initialise the free list vector. */ 65 cvector_init(&vs->kobjVSpaceAllocatedFreelist); 66 67 /* Initialise window association list. */ 68 w_associate_init(&vs->windows); 69 70 /* Assign a kernel page directory. */ 71 dvprintf(" Assigning new kernel page directory objects...\n"); 72 struct pd_info pdi = pd_assign(&procServ.PDList); 73 if (!pdi.kpdObject | !pdi.kcnodeObject) { 74 ROS_ERROR("Failed to allocate page directory for new process."); 75 error = ENOMEM; 76 goto exit1; 77 } 78 vs->kpd = pdi.kpdObject; 79 80 /* Create the CSpace path associated with this address space's root CNode. */ 81 cspacepath_t pathTemp; 82 vs->cspaceUnguarded = pdi.kcnodeObject; 83 vs->cspaceSize = REFOS_CSPACE_RADIX; 84 vka_cspace_make_path(&procServ.vka, vs->cspaceUnguarded, &pathTemp); 85 86 /* Mint a guarded cspace from the created cspace. */ 87 dvprintf(" Allocating cslot for guarded cspace...\n"); 88 error = vka_cspace_alloc_path(&procServ.vka, &vs->cspace); 89 if (error) { 90 ROS_ERROR("Failed to allocate guarded cspace cslot: error %d\n", error); 91 error = ENOMEM; 92 goto exit2; 93 } 94 95 dvprintf(" Minting guarded cspace...\n"); 96 vs->cspaceGuardData = seL4_CapData_Guard_new(0, REFOS_CSPACE_GUARD); 97 error = vka_cnode_mint(&vs->cspace, &pathTemp, seL4_AllRights, vs->cspaceGuardData); 98 assert(error == seL4_NoError); 99 (void) error; 100 101 /* Self-reference so the thread knows about its own cspace. */ 102 dvprintf(" Copying self-reference cap into REFOS_CSPACE cslot...\n"); 103 error = seL4_CNode_Copy( 104 vs->cspace.capPtr, REFOS_CSPACE, REFOS_CDEPTH, 105 vs->cspace.root, vs->cspace.capPtr, vs->cspace.capDepth, 106 seL4_AllRights 107 ); 108 if (error) { 109 ROS_ERROR("Could not copy self reference cspace cap: error %d\n", error); 110 error = EINVALID; 111 goto exit3; 112 } 113 114 /* Create a vspace object to keep reservations book-keeping. */ 115 dvprintf(" Initialising child sel4utils vspace struct...\n"); 116 error = sel4utils_get_vspace ( 117 &procServ.vspace, &vs->vspace, &vs->vspaceData, 118 &procServ.vka, vs->kpd, 119 vs_vspace_allocated_object_bookkeeping_callback, (void*) vs 120 ); 121 if (error) { 122 ROS_ERROR("Failed to initialise sel4utils vspace struct: %d\n", error); 123 error = ENOMEM; 124 goto exit3; 125 } 126 127 dvprintf(" VSpace setup OK, new vspace is ready to go.\n"); 128 return ESUCCESS; 129 130 /* Exit stack. */ 131exit3: 132 vka_cnode_delete(&vs->cspace); 133 vka_cspace_free(&procServ.vka, vs->cspace.capPtr); 134exit2: 135 vka_cnode_revoke(&pathTemp); 136 pd_free(&procServ.PDList, vs->kpd); 137exit1: 138 return error; 139} 140 141static void 142vs_release(struct vs_vspace *vs) 143{ 144 assert(vs && vs->magic == REFOS_VSPACE_MAGIC); 145 assert(vs->magic == REFOS_VSPACE_MAGIC); 146 assert(vs->ref == 0); 147 dvprintf(" Releasing VSpace PID %d...\n", vs->pid); 148 cspacepath_t pathTemp; 149 150 /* Clear the associated windows list. */ 151 dvprintf(" Clearing VSpace associated window list...\n"); 152 for (int i = 0; i < vs->windows.numIndex; i++) { 153 vs_unmap_window(vs, vs->windows.associated[i].winID); 154 } 155 w_associate_release_associated_all_windows(&procServ.windowList, &vs->windows); 156 157 /* Free the allocated vspace book-keeping objects. */ 158 dvprintf(" Releasing VSpace list of vspace bookkeeping kobjs...\n"); 159 int c = cvector_count(&vs->kobjVSpaceAllocatedFreelist); 160 for (int i = 0; i < c; i++) { 161 vka_object_t *kobj = (vka_object_t *) cvector_get(&vs->kobjVSpaceAllocatedFreelist, i); 162 assert(kobj); 163 vka_cspace_make_path(&procServ.vka, kobj->cptr, &pathTemp); 164 vka_cnode_revoke(&pathTemp); 165 vka_cnode_delete(&pathTemp); 166 vka_free_object(&procServ.vka, kobj); 167 kfree(kobj); 168 cvector_set(&vs->kobjVSpaceAllocatedFreelist, i, (cvector_item_t) NULL); 169 } 170 cvector_reset(&vs->kobjVSpaceAllocatedFreelist); 171 172 /* Teardown the vspace. */ 173 vspace_tear_down(&vs->vspace, VSPACE_FREE); 174 175 /* Free the allocated kernel objects. */ 176 dvprintf(" Releasing VSpace kobjs...\n"); 177 vka_cnode_revoke(&vs->cspace); 178 vka_cnode_delete(&vs->cspace); 179 vka_cspace_free(&procServ.vka, vs->cspace.capPtr); 180 181 /* Note the unguarded original CNode capability belongs to the PD, we don't have ownership of 182 that. pd_free here will release it back into the pool to be reused. */ 183 dvprintf(" Releasing PD kobjs...\n"); 184 pd_free(&procServ.PDList, vs->kpd); 185 memset(vs, 0, sizeof(struct vs_vspace)); 186} 187 188void 189vs_ref(struct vs_vspace *vs) 190{ 191 assert(vs && vs->magic == REFOS_VSPACE_MAGIC); 192 vs->ref++; 193} 194 195void 196vs_unref(struct vs_vspace *vs) 197{ 198 assert(vs && vs->magic == REFOS_VSPACE_MAGIC); 199 vs->ref--; 200 if (vs->ref <= 0) { 201 /* Release this vspace. */ 202 vs_release(vs); 203 } 204} 205 206void 207vs_track_obj(struct vs_vspace *vs, vka_object_t object) 208{ 209 assert(vs && vs->magic == REFOS_VSPACE_MAGIC); 210 vs_vspace_allocated_object_bookkeeping_callback((void *)vs, object);; 211} 212/* ---------------------------------- VSpace windows ---------------------------------------------*/ 213 214int 215vs_create_window(struct vs_vspace *vs, vaddr_t vaddr, vaddr_t size, seL4_Word permissions, 216 bool cacheable, int *winID) 217{ 218 assert(vs && vs->magic == REFOS_VSPACE_MAGIC); 219 assert(winID != NULL); 220 *winID = W_INVALID_WINID; 221 int error = EINVALID; 222 223 /* Check the window segment with window association list for any conflicts. */ 224 if (w_associate_check(&vs->windows, vaddr, size) == false) { 225 dvprintf("memory window overlaps with another one.\n"); 226 227 #if VSPACE_WINDOW_VERBOSE_DEBUG 228 dvprintf("������������������������������������������������������������������������������ Detailed Report ������������������������������������������������������������������������\n"); 229 dvprintf("attempted to create window 0x%x ��������� 0x%x.\n", vaddr, vaddr + size); 230 w_associate_print(&vs->windows); 231 dvprintf("���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������\n"); 232 #endif 233 234 return EINVALIDWINDOW; 235 } 236 237 /* Create the seL4 vspace reservation. */ 238 reservation_t r = vspace_reserve_range_at(&vs->vspace, (void*) vaddr, (size_t) size, 239 w_convert_permission_to_caprights(permissions), cacheable); 240 if (r.res == NULL) { 241 dvprintf("vspace reservation failed.\n"); 242 return EINVALIDWINDOW; 243 } 244 245 /* Add to global window list. */ 246 struct w_window *window = w_create_window(&procServ.windowList, size, vs->pid, 247 permissions, &vs->vspace, r, cacheable); 248 if (!window) { 249 ROS_ERROR("window creation failed.\n"); 250 error = ENOMEM; 251 goto exit0; 252 } 253 assert(window->wID != W_INVALID_WINID); 254 255 /* Now associate the window. */ 256 error = w_associate(&vs->windows, window->wID, vaddr, size); 257 if (error) { 258 ROS_ERROR("Window associate failed."); 259 assert(!"Window associate failed even after check. This is likely a bug."); 260 error = EINVALID; 261 goto exit1; 262 } 263 264 *winID = window->wID; 265 return ESUCCESS; 266 267 /* Exit stack. */ 268exit1: 269 /* Note that ownership of reservation is transferred to window. */ 270 w_delete_window(&procServ.windowList, window->wID); 271 return error; 272exit0: 273 vspace_free_reservation(&vs->vspace, r); 274 return error; 275} 276 277void 278vs_delete_window(struct vs_vspace *vs, int wID) 279{ 280 assert(vs && vs->magic == REFOS_VSPACE_MAGIC); 281 282 /* Find the associated window. */ 283 struct w_associated_window *awindow = w_associate_find_winID(&vs->windows, wID); 284 if (!awindow || awindow->winID != wID) { 285 ROS_WARNING("vs_delete_window: no such window exists."); 286 return; 287 } 288 289 /* Unmap everything in the associated window. */ 290 vs_unmap_window(vs, wID); 291 292 /* Unassociate this window. */ 293 w_unassociate(&vs->windows, wID); 294 295 /* Delete the window from the global window list. */ 296 int error = w_delete_window(&procServ.windowList, wID); 297 assert(error == ESUCCESS); 298 (void) error; 299} 300 301int 302vs_resize_window(struct vs_vspace *vs, int wID, vaddr_t size) 303{ 304 assert(vs && vs->magic == REFOS_VSPACE_MAGIC); 305 if (!size) { 306 return EINVALIDPARAM; 307 } 308 309 /* Find the associated window. */ 310 struct w_associated_window *awindow = w_associate_find_winID(&vs->windows, wID); 311 if (!awindow || awindow->winID != wID) { 312 ROS_WARNING("vs_resize_window: no such window assoc exists."); 313 return EINVALIDWINDOW; 314 } 315 316 /* Find the global window structure. */ 317 struct w_window* window = w_get_window(&procServ.windowList, wID); 318 if (!window) { 319 ROS_WARNING("vs_resize_window: no such window exists."); 320 return EINVALIDWINDOW; 321 } 322 assert(awindow->offset == (vaddr_t) reservation_to_res(window->reservation)->start); 323 324 if (size > awindow->size) { 325 /* If the new size is larger, we need to check the new portion of the window. */ 326 vaddr_t sizeIncrease = size - awindow->size; 327 if (!w_associate_check(&vs->windows, awindow->offset + awindow->size, sizeIncrease)) { 328 dvprintf("memory window resize fail: overlaps another window.\n"); 329 330 #if VSPACE_WINDOW_VERBOSE_DEBUG 331 dvprintf("������������������������������������������������������������������������������ Detailed Report ������������������������������������������������������������������������\n"); 332 dvprintf("attempted to resize window 0x%x ��������� 0x%x to 0x%x.\n", awindow->offset, 333 awindow->offset + awindow->size, awindow->offset + size); 334 w_associate_print(&vs->windows); 335 dvprintf("���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������\n"); 336 #endif 337 338 return EINVALIDPARAM; 339 } 340 } else if (size < awindow->size) { 341 /* If new size is smaller, we need to unmap. */ 342 vaddr_t sizeDecrease = awindow->size - size; 343 int npages = (sizeDecrease / REFOS_PAGE_SIZE) + ((sizeDecrease % REFOS_PAGE_SIZE) ? 1 : 0); 344 int error = vs_unmap(vs, REFOS_PAGE_ALIGN(awindow->offset + size), npages); 345 if (error) { 346 ROS_WARNING("vs_resize_window: failed to map window."); 347 return error; 348 } 349 } 350 351 /* Actually perform the window resize. This will also update the vspace reservation. */ 352 int error = w_resize_window(window, awindow->offset, size); 353 if (error) { 354 ROS_WARNING("vs_resize_window: failed to resize window. Shouldn't happen."); 355 return error; 356 } 357 358 awindow->size = size; 359 return ESUCCESS; 360} 361 362/* ---------------------------------- VSpace mapping ---------------------------------------------*/ 363 364int 365vs_map(struct vs_vspace *vs, vaddr_t vaddr, seL4_CPtr frames[], int nFrames) 366{ 367 assert(vs && vs->magic == REFOS_VSPACE_MAGIC); 368 int error = EINVALID; 369 vaddr = REFOS_PAGE_ALIGN(vaddr); 370 371 /* Check the window association to make sure there exists a window there. */ 372 struct w_associated_window *awindow = w_associate_find_range(&vs->windows, vaddr, 373 nFrames * REFOS_PAGE_SIZE); 374 if (!awindow) { 375 dvprintf("could not find window association.\n"); 376 377 #if VSPACE_WINDOW_VERBOSE_DEBUG 378 dvprintf("������������������������������������������������������������������������������ Detailed Report ������������������������������������������������������������������������\n"); 379 dvprintf("attempted to map vaddr range 0x%x ��������� 0x%x.\n", vaddr, 380 vaddr + nFrames * REFOS_PAGE_SIZE); 381 w_associate_print(&vs->windows); 382 dvprintf("���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������\n"); 383 #endif 384 385 return EINVALIDWINDOW; 386 } 387 388 /* Retrieve the window structure. */ 389 struct w_window* window = w_get_window(&procServ.windowList, awindow->winID); 390 if (!window) { 391 dvprintf("could not find window.\n"); 392 assert(!"window book keeping bug. Should not happen."); 393 return EINVALIDWINDOW; 394 } 395 assert(window->vspace == &vs->vspace); 396 397 /* Check that every frame in the region is unmapped. */ 398 vaddr = REFOS_PAGE_ALIGN(vaddr); 399 for (vaddr_t va = 0; va < nFrames; va++) { 400 seL4_CPtr existingFrame = vspace_get_cap(&vs->vspace, 401 (void*) (vaddr + va * REFOS_PAGE_SIZE)); 402 if (existingFrame) { 403 /* There's already mapped frame here. */ 404 return EUNMAPFIRST; 405 } 406 } 407 408 /* Make a copy of every cap given. */ 409 seL4_CPtr* frameCopy = malloc(sizeof(seL4_CPtr) * nFrames); 410 if (!frameCopy) { 411 ROS_ERROR("Could not allocate frame copy array, procserv out of memory.\n"); 412 return ENOMEM; 413 } 414 memset(frameCopy, 0, sizeof(seL4_CPtr) * nFrames); 415 for (int i = 0; i < nFrames; i++) { 416 vka_cspace_alloc(&procServ.vka, &frameCopy[i]); 417 if (!frameCopy[i]) { 418 ROS_ERROR("Could not allocate cspace to copy array.\n"); 419 error = ENOMEM; 420 goto exit1; 421 } 422 cspacepath_t pathDest, pathSrc; 423 vka_cspace_make_path(&procServ.vka, frameCopy[i], &pathDest); 424 vka_cspace_make_path(&procServ.vka, frames[i], &pathSrc); 425 vka_cnode_copy(&pathDest, &pathSrc, seL4_AllRights); 426 } 427 428 /* Map pages at the vspace reservation. */ 429 error = vspace_map_pages_at_vaddr(&vs->vspace, frameCopy, NULL, (void*) vaddr, nFrames, 430 seL4_PageBits, window->reservation); 431 if (error) { 432 dvprintf("could not map pages into vaddr 0x%x. error: %d\n", (uint32_t) vaddr, error); 433 error = EUNMAPFIRST; 434 goto exit1; 435 } 436 437 /* Flush the page caches. */ 438 procserv_flush(frameCopy, nFrames); 439 440 dvprintf("mapping vaddr 0x%x OK.\n", (uint32_t) vaddr); 441 free(frameCopy); 442 return ESUCCESS; 443 444 /* Exit stack. */ 445exit1: 446 for (int i = 0; i < nFrames; i++) { 447 if (frameCopy[i]) { 448 cspacepath_t path; 449 vka_cspace_make_path(&procServ.vka, frameCopy[i], &path); 450 vka_cnode_revoke(&path); 451 vka_cnode_delete(&path); 452 vka_cspace_free(&procServ.vka, frameCopy[i]); 453 } 454 } 455 free(frameCopy); 456 return error; 457} 458 459int 460vs_map_across_vspace(struct vs_vspace *vsSrc, vaddr_t vaddrSrc, struct w_window *windowDest, 461 uint32_t windowDestOffset, struct proc_pcb **outClientPCB) 462{ 463 assert(vsSrc && vsSrc->magic == REFOS_VSPACE_MAGIC); 464 assert(windowDest && windowDest->magic == W_MAGIC); 465 466 /* Find the cap in the source vspace's pagetable. */ 467 seL4_CPtr frameCap = vspace_get_cap(&vsSrc->vspace, (void*) vaddrSrc); 468 if (!frameCap) { 469 dvprintf("vs_map_across_vspace could not find source frame.\n"); 470 return EINVALIDPARAM; 471 } 472 473 /* Verify that the offset is within the window limits. */ 474 if (windowDestOffset >= windowDest->size) { 475 ROS_ERROR("invalid window offset address!\n"); 476 return EINVALIDPARAM; 477 } 478 479 /* Find the client which this window lives in. */ 480 struct proc_pcb *clientPCB = pid_get_pcb(&procServ.PIDList, windowDest->clientOwnerPID); 481 if (!clientPCB) { 482 ROS_ERROR("could not find window's corresponding client.\n"); 483 return EINVALIDWINDOW; 484 } 485 if (outClientPCB) { 486 (*outClientPCB) = clientPCB; 487 } 488 489 /* Check that this client actually has its own window mapped. */ 490 struct w_associated_window *wa = w_associate_find_winID(&clientPCB->vspace.windows, 491 windowDest->wID); 492 if (!wa) { 493 ROS_ERROR("client did not map its window, so invalid map call.\n"); 494 return EINVALIDWINDOW; 495 } 496 497 return vs_map(&clientPCB->vspace, wa->offset + windowDestOffset, &frameCap, 1); 498} 499 500int 501vs_map_device(struct vs_vspace *vs, struct w_window *window, uint32_t windowOffset, 502 uint32_t paddr , uint32_t size, bool cached) 503{ 504 assert(vs && vs->magic == REFOS_VSPACE_MAGIC); 505 assert(window && window->magic == W_MAGIC); 506 507 if (size != REFOS_PAGE_SIZE) { 508 ROS_WARNING("Large device frames not supported yet."); 509 assert(!"Large device frames not implemented."); 510 return EUNIMPLEMENTED; 511 } 512 513 /* Verify that the offset is within the window limits. */ 514 if (windowOffset + size > window->size) { 515 ROS_ERROR("invalid window offset address!\n"); 516 return EINVALIDPARAM; 517 } 518 519 /* Check that this client actually has its own window mapped. */ 520 struct proc_pcb* clientPCB = pid_get_pcb(&procServ.PIDList, window->clientOwnerPID); 521 if (!clientPCB) { 522 ROS_ERROR("invalid window owner!\n"); 523 return EINVALID; 524 } 525 assert(clientPCB->magic == REFOS_PCB_MAGIC); 526 if (&clientPCB->vspace != vs) { 527 return EACCESSDENIED; 528 } 529 struct w_associated_window *wa = w_associate_find_winID(&clientPCB->vspace.windows, 530 window->wID); 531 if (!wa) { 532 ROS_ERROR("client did not map its window, so invalid map call.\n"); 533 return EINVALIDWINDOW; 534 } 535 536 /* Check window cacheable state matches with requested cached state. */ 537 if (cached != window->cacheable) { 538 ROS_WARNING("Window cachable and frame cache request mismatch. Access denied."); 539 return EACCESSDENIED; 540 } 541 542 /* Find the device cap. */ 543 cspacepath_t deviceFrame = procserv_find_device((void*) paddr, size); 544 if (deviceFrame.capPtr == 0) { 545 ROS_WARNING("No such device."); 546 return EFILENOTFOUND; 547 } 548 dvprintf("Device 0x%x found at cslot 0x%x...\n", paddr, deviceFrame.capPtr); 549 550 /* Map the device frame. */ 551 vaddr_t vaddr = wa->offset + windowOffset; 552 int error = vs_map(vs, vaddr, &deviceFrame.capPtr, 1); 553 if (error != ESUCCESS) { 554 ROS_WARNING("Failed to map device."); 555 return error; 556 } 557 558 vka_cnode_delete(&deviceFrame); 559 vka_cspace_free(&procServ.vka, deviceFrame.capPtr); 560 return ESUCCESS; 561} 562 563static void 564vs_unmap_frame(struct vs_vspace *vs, vaddr_t vaddr) 565{ 566 assert(vs && vs->magic == REFOS_VSPACE_MAGIC); 567 568 /* Find the cap in the vspace's pagetable. */ 569 seL4_CPtr frameCap = vspace_get_cap(&vs->vspace, (void*) vaddr); 570 if (!frameCap) { 571 return; 572 } 573 574 /* Unmap the page & clear the pagetable entries. */ 575 vspace_unmap_pages(&vs->vspace, (void*) vaddr, 1, seL4_PageBits, VSPACE_PRESERVE); 576 577 /* Revoke and delete the cap. */ 578 cspacepath_t path; 579 vka_cspace_make_path(&procServ.vka, frameCap, &path); 580 vka_cnode_revoke(&path); 581 vka_cnode_delete(&path); 582 vka_cspace_free(&procServ.vka, frameCap); 583 584 dvprintf("vs_unmap_frame 0x%x OK.\n", (uint32_t) vaddr); 585} 586 587int 588vs_unmap(struct vs_vspace *vs, vaddr_t vaddr, int nFrames) 589{ 590 assert(vs && vs->magic == REFOS_VSPACE_MAGIC); 591 592 /* Check the window association to make sure there exists a window there. */ 593 struct w_associated_window *awindow = w_associate_find_range(&vs->windows, vaddr, 594 nFrames * REFOS_PAGE_SIZE); 595 if (!awindow) { 596 dvprintf("could not find window association for vaddr 0x%x.\n", (uint32_t) vaddr); 597 return EINVALIDWINDOW; 598 } 599 600 /* Retrieve the window structure. */ 601 struct w_window* window = w_get_window(&procServ.windowList, awindow->winID); 602 if (!window) { 603 dvprintf("could not find window.\n"); 604 assert(!"window book keeping bug. Should not happen."); 605 return EINVALIDWINDOW; 606 } 607 assert(window->vspace == &vs->vspace); 608 609 /* Unmap pages in vspace. */ 610 for (vaddr_t va = 0; va < nFrames; va++) { 611 vs_unmap_frame(vs, vaddr + va * REFOS_PAGE_SIZE); 612 } 613 return ESUCCESS; 614} 615 616void 617vs_unmap_window(struct vs_vspace *vs, int wID) 618{ 619 assert(vs && vs->magic == REFOS_VSPACE_MAGIC); 620 621 /* Find the associated window. */ 622 struct w_associated_window *awindow = w_associate_find_winID(&vs->windows, wID); 623 if (!awindow || awindow->winID != wID) { 624 return; 625 } 626 627 /* Retrieve the window structure. */ 628 struct w_window* window = w_get_window(&procServ.windowList, awindow->winID); 629 if (!window) { 630 dvprintf("could not find window.\n"); 631 assert(!"window book keeping bug. Should not happen."); 632 return; 633 } 634 assert(window->vspace == &vs->vspace); 635 636 /* Unmap everything in the associated window. */ 637 int nFrames = (awindow->size / REFOS_PAGE_SIZE) + ((awindow->size % REFOS_PAGE_SIZE) ? 1 : 0); 638 for (vaddr_t va = 0; va < nFrames; va++) { 639 vs_unmap_frame(vs, awindow->offset + va * REFOS_PAGE_SIZE); 640 } 641} 642 643cspacepath_t 644vs_get_frame(struct vs_vspace *vs, vaddr_t vaddr) 645{ 646 assert(vs && vs->magic == REFOS_VSPACE_MAGIC); 647 cspacepath_t path; 648 memset(&path, 0, sizeof(cspacepath_t)); 649 seL4_CPtr frameCap = vspace_get_cap(&vs->vspace, (void*) vaddr); 650 vka_cspace_make_path(&procServ.vka, frameCap, &path); 651 return path; 652} 653