Rev 1409 | Rev 1413 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 1409 | Rev 1411 | ||
|---|---|---|---|
| Line 373... | Line 373... | ||
| 373 | int as_area_destroy(as_t *as, __address address) |
373 | int as_area_destroy(as_t *as, __address address) |
| 374 | { |
374 | { |
| 375 | as_area_t *area; |
375 | as_area_t *area; |
| 376 | __address base; |
376 | __address base; |
| 377 | ipl_t ipl; |
377 | ipl_t ipl; |
| - | 378 | bool cond; |
|
| 378 | 379 | ||
| 379 | ipl = interrupts_disable(); |
380 | ipl = interrupts_disable(); |
| 380 | mutex_lock(&as->lock); |
381 | mutex_lock(&as->lock); |
| 381 | 382 | ||
| 382 | area = find_area_and_lock(as, address); |
383 | area = find_area_and_lock(as, address); |
| Line 385... | Line 386... | ||
| 385 | interrupts_restore(ipl); |
386 | interrupts_restore(ipl); |
| 386 | return ENOENT; |
387 | return ENOENT; |
| 387 | } |
388 | } |
| 388 | 389 | ||
| 389 | base = area->base; |
390 | base = area->base; |
| 390 | if (!(area->flags & AS_AREA_DEVICE)) { |
- | |
| 391 | bool cond; |
- | |
| 392 | - | ||
| 393 | /* |
- | |
| 394 | * Releasing physical memory. |
- | |
| 395 | * Areas mapping memory-mapped devices are treated differently than |
- | |
| 396 | * areas backing frame_alloc()'ed memory. |
- | |
| 397 | */ |
- | |
| 398 | 391 | ||
| 399 | /* |
392 | /* |
| 400 | * Visit only the pages mapped by used_space B+tree. |
393 | * Visit only the pages mapped by used_space B+tree. |
| 401 | * Note that we must be very careful when walking the tree |
394 | * Note that we must be very careful when walking the tree |
| 402 | * leaf list and removing used space as the leaf list changes |
395 | * leaf list and removing used space as the leaf list changes |
| 403 | * unpredictibly after each remove. The solution is to actually |
396 | * unpredictibly after each remove. The solution is to actually |
| 404 | * not walk the tree at all, but to remove items from the head |
397 | * not walk the tree at all, but to remove items from the head |
| 405 | * of the leaf list until there are some keys left. |
398 | * of the leaf list until there are some keys left. |
| 406 | */ |
399 | */ |
| 407 | for (cond = true; cond;) { |
400 | for (cond = true; cond;) { |
| 408 | btree_node_t *node; |
401 | btree_node_t *node; |
| 409 | 402 | ||
| 410 | ASSERT(!list_empty(&area->used_space.leaf_head)); |
403 | ASSERT(!list_empty(&area->used_space.leaf_head)); |
| 411 | node = list_get_instance(area->used_space.leaf_head.next, btree_node_t, leaf_link); |
404 | node = list_get_instance(area->used_space.leaf_head.next, btree_node_t, leaf_link); |
| 412 | if ((cond = (bool) node->keys)) { |
405 | if ((cond = (bool) node->keys)) { |
| 413 | __address b = node->key[0]; |
406 | __address b = node->key[0]; |
| 414 | count_t i; |
407 | count_t i; |
| 415 | pte_t *pte; |
408 | pte_t *pte; |
| 416 | 409 | ||
| 417 | for (i = 0; i < (count_t) node->value[0]; i++) { |
410 | for (i = 0; i < (count_t) node->value[0]; i++) { |
| 418 | page_table_lock(as, false); |
411 | page_table_lock(as, false); |
| 419 | pte = page_mapping_find(as, b + i*PAGE_SIZE); |
412 | pte = page_mapping_find(as, b + i*PAGE_SIZE); |
| 420 | ASSERT(pte && PTE_VALID(pte) && PTE_PRESENT(pte)); |
413 | ASSERT(pte && PTE_VALID(pte) && PTE_PRESENT(pte)); |
| 421 | if (area->backend && area->backend->backend_frame_free) { |
414 | if (area->backend && area->backend->backend_frame_free) { |
| 422 | area->backend->backend_frame_free(area, |
415 | area->backend->backend_frame_free(area, |
| 423 | b + i*PAGE_SIZE, PTE_GET_FRAME(pte)); |
416 | b + i*PAGE_SIZE, PTE_GET_FRAME(pte)); |
| 424 | } |
- | |
| 425 | page_mapping_remove(as, b + i*PAGE_SIZE); |
- | |
| 426 | page_table_unlock(as, false); |
- | |
| 427 | } |
417 | } |
| 428 | if (!used_space_remove(area, b, i)) |
418 | page_mapping_remove(as, b + i*PAGE_SIZE); |
| 429 | panic("Could not remove used space.\n"); |
419 | page_table_unlock(as, false); |
| 430 | } |
420 | } |
| - | 421 | if (!used_space_remove(area, b, i)) |
|
| - | 422 | panic("Could not remove used space.\n"); |
|
| 431 | } |
423 | } |
| 432 | } |
424 | } |
| 433 | btree_destroy(&area->used_space); |
425 | btree_destroy(&area->used_space); |
| 434 | 426 | ||
| 435 | /* |
427 | /* |
| Line 621... | Line 613... | ||
| 621 | * fault. |
613 | * fault. |
| 622 | * |
614 | * |
| 623 | * Interrupts are assumed disabled. |
615 | * Interrupts are assumed disabled. |
| 624 | * |
616 | * |
| 625 | * @param page Faulting page. |
617 | * @param page Faulting page. |
| - | 618 | * @param access Access mode that caused the fault (i.e. read/write/exec). |
|
| 626 | * @param istate Pointer to interrupted state. |
619 | * @param istate Pointer to interrupted state. |
| 627 | * |
620 | * |
| 628 | * @return AS_PF_FAULT on page fault, AS_PF_OK on success or AS_PF_DEFER if the |
621 | * @return AS_PF_FAULT on page fault, AS_PF_OK on success or AS_PF_DEFER if the |
| 629 | * fault was caused by copy_to_uspace() or copy_from_uspace(). |
622 | * fault was caused by copy_to_uspace() or copy_from_uspace(). |
| 630 | */ |
623 | */ |
| 631 | int as_page_fault(__address page, istate_t *istate) |
624 | int as_page_fault(__address page, pf_access_t access, istate_t *istate) |
| 632 | { |
625 | { |
| 633 | pte_t *pte; |
626 | pte_t *pte; |
| 634 | as_area_t *area; |
627 | as_area_t *area; |
| 635 | 628 | ||
| 636 | if (!THREAD) |
629 | if (!THREAD) |
| Line 686... | Line 679... | ||
| 686 | } |
679 | } |
| 687 | 680 | ||
| 688 | /* |
681 | /* |
| 689 | * Resort to the backend page fault handler. |
682 | * Resort to the backend page fault handler. |
| 690 | */ |
683 | */ |
| 691 | if (area->backend->backend_page_fault(area, page) != AS_PF_OK) { |
684 | if (area->backend->backend_page_fault(area, page, access) != AS_PF_OK) { |
| 692 | page_table_unlock(AS, false); |
685 | page_table_unlock(AS, false); |
| 693 | mutex_unlock(&area->lock); |
686 | mutex_unlock(&area->lock); |
| 694 | mutex_unlock(&AS->lock); |
687 | mutex_unlock(&AS->lock); |
| 695 | goto page_fault; |
688 | goto page_fault; |
| 696 | } |
689 | } |
| Line 1448... | Line 1441... | ||
| 1448 | btree_destroy(&sh_info->pagemap); |
1441 | btree_destroy(&sh_info->pagemap); |
| 1449 | free(sh_info); |
1442 | free(sh_info); |
| 1450 | } |
1443 | } |
| 1451 | } |
1444 | } |
| 1452 | 1445 | ||
| 1453 | static int anon_page_fault(as_area_t *area, __address addr); |
1446 | static int anon_page_fault(as_area_t *area, __address addr, pf_access_t access); |
| 1454 | static void anon_frame_free(as_area_t *area, __address page, __address frame); |
1447 | static void anon_frame_free(as_area_t *area, __address page, __address frame); |
| 1455 | 1448 | ||
| 1456 | /* |
1449 | /* |
| 1457 | * Anonymous memory backend. |
1450 | * Anonymous memory backend. |
| 1458 | */ |
1451 | */ |
| Line 1465... | Line 1458... | ||
| 1465 | * |
1458 | * |
| 1466 | * The address space area and page tables must be already locked. |
1459 | * The address space area and page tables must be already locked. |
| 1467 | * |
1460 | * |
| 1468 | * @param area Pointer to the address space area. |
1461 | * @param area Pointer to the address space area. |
| 1469 | * @param addr Faulting virtual address. |
1462 | * @param addr Faulting virtual address. |
| - | 1463 | * @param access Access mode that caused the fault (i.e. read/write/exec). |
|
| 1470 | * |
1464 | * |
| 1471 | * @return AS_PF_FAULT on failure (i.e. page fault) or AS_PF_OK on success (i.e. serviced). |
1465 | * @return AS_PF_FAULT on failure (i.e. page fault) or AS_PF_OK on success (i.e. serviced). |
| 1472 | */ |
1466 | */ |
| 1473 | int anon_page_fault(as_area_t *area, __address addr) |
1467 | int anon_page_fault(as_area_t *area, __address addr, pf_access_t access) |
| 1474 | { |
1468 | { |
| 1475 | __address frame; |
1469 | __address frame; |
| 1476 | 1470 | ||
| 1477 | if (area->sh_info) { |
1471 | if (area->sh_info) { |
| 1478 | btree_node_t *leaf; |
1472 | btree_node_t *leaf; |