Changes in kernel/generic/src/mm/as.c [59fb782:fbcdeb8] in mainline
- File:
-
- 1 edited
-
kernel/generic/src/mm/as.c (modified) (29 diffs)
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/mm/as.c
r59fb782 rfbcdeb8 79 79 #include <syscall/copy.h> 80 80 #include <arch/interrupt.h> 81 #include <interrupt.h>82 81 83 82 /** … … 131 130 as_arch_init(); 132 131 133 as_slab = slab_cache_create("as_ t", sizeof(as_t), 0,132 as_slab = slab_cache_create("as_slab", sizeof(as_t), 0, 134 133 as_constructor, as_destructor, SLAB_CACHE_MAGDEFERRED); 135 134 … … 286 285 /** Check area conflicts with other areas. 287 286 * 288 * @param as Address space. 289 * @param addr Starting virtual address of the area being tested. 290 * @param count Number of pages in the area being tested. 291 * @param guarded True if the area being tested is protected by guard pages. 292 * @param avoid Do not touch this area. 287 * @param as Address space. 288 * @param addr Starting virtual address of the area being tested. 289 * @param count Number of pages in the area being tested. 290 * @param avoid Do not touch this area. 293 291 * 294 292 * @return True if there is no conflict, false otherwise. … … 296 294 */ 297 295 NO_TRACE static bool check_area_conflicts(as_t *as, uintptr_t addr, 298 size_t count, bool guarded,as_area_t *avoid)296 size_t count, as_area_t *avoid) 299 297 { 300 298 ASSERT((addr % PAGE_SIZE) == 0); 301 299 ASSERT(mutex_locked(&as->lock)); 302 303 /*304 * If the addition of the supposed area address and size overflows,305 * report conflict.306 */307 if (overflows_into_positive(addr, P2SZ(count)))308 return false;309 300 310 301 /* … … 313 304 if (overlaps(addr, P2SZ(count), (uintptr_t) NULL, PAGE_SIZE)) 314 305 return false; 315 306 316 307 /* 317 308 * The leaf node is found in O(log n), where n is proportional to … … 337 328 if (area != avoid) { 338 329 mutex_lock(&area->lock); 339 340 /* 341 * If at least one of the two areas are protected 342 * by the AS_AREA_GUARD flag then we must be sure 343 * that they are separated by at least one unmapped 344 * page. 345 */ 346 int const gp = (guarded || 347 (area->flags & AS_AREA_GUARD)) ? 1 : 0; 348 349 /* 350 * The area comes from the left neighbour node, which 351 * means that there already are some areas in the leaf 352 * node, which in turn means that adding gp is safe and 353 * will not cause an integer overflow. 354 */ 330 355 331 if (overlaps(addr, P2SZ(count), area->base, 356 P2SZ(area->pages + gp))) {357 mutex_unlock(&area->lock);358 return false;359 }360 361 mutex_unlock(&area->lock);362 }363 }364 365 node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf);366 if (node) {367 area = (as_area_t *) node->value[0];368 369 if (area != avoid) {370 int gp;371 372 mutex_lock(&area->lock);373 374 gp = (guarded || (area->flags & AS_AREA_GUARD)) ? 1 : 0;375 if (gp && overflows(addr, P2SZ(count))) {376 /*377 * Guard page not needed if the supposed area378 * is adjacent to the end of the address space.379 * We already know that the following test is380 * going to fail...381 */382 gp--;383 }384 385 if (overlaps(addr, P2SZ(count + gp), area->base,386 332 P2SZ(area->pages))) { 387 333 mutex_unlock(&area->lock); … … 393 339 } 394 340 341 node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf); 342 if (node) { 343 area = (as_area_t *) node->value[0]; 344 345 if (area != avoid) { 346 mutex_lock(&area->lock); 347 348 if (overlaps(addr, P2SZ(count), area->base, 349 P2SZ(area->pages))) { 350 mutex_unlock(&area->lock); 351 return false; 352 } 353 354 mutex_unlock(&area->lock); 355 } 356 } 357 395 358 /* Second, check the leaf node. */ 396 359 btree_key_t i; 397 360 for (i = 0; i < leaf->keys; i++) { 398 361 area = (as_area_t *) leaf->value[i]; 399 int agp;400 int gp;401 362 402 363 if (area == avoid) … … 404 365 405 366 mutex_lock(&area->lock); 406 407 gp = (guarded || (area->flags & AS_AREA_GUARD)) ? 1 : 0; 408 agp = gp; 409 410 /* 411 * Sanitize the two possible unsigned integer overflows. 412 */ 413 if (gp && overflows(addr, P2SZ(count))) 414 gp--; 415 if (agp && overflows(area->base, P2SZ(area->pages))) 416 agp--; 417 418 if (overlaps(addr, P2SZ(count + gp), area->base, 419 P2SZ(area->pages + agp))) { 367 368 if (overlaps(addr, P2SZ(count), area->base, 369 P2SZ(area->pages))) { 420 370 mutex_unlock(&area->lock); 421 371 return false; … … 427 377 /* 428 378 * So far, the area does not conflict with other areas. 429 * Check if it is contained in the useraddress space.379 * Check if it doesn't conflict with kernel address space. 430 380 */ 431 381 if (!KERNEL_ADDRESS_SPACE_SHADOWED) { 432 return iswithin(USER_ADDRESS_SPACE_START, 433 (USER_ADDRESS_SPACE_END - USER_ADDRESS_SPACE_START) + 1, 434 addr, P2SZ(count)); 382 return !overlaps(addr, P2SZ(count), KERNEL_ADDRESS_SPACE_START, 383 KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START); 435 384 } 436 385 … … 443 392 * this function. 444 393 * 445 * @param as Address space. 446 * @param bound Lowest address bound. 447 * @param size Requested size of the allocation. 448 * @param guarded True if the allocation must be protected by guard pages. 394 * @param as Address space. 395 * @param bound Lowest address bound. 396 * @param size Requested size of the allocation. 449 397 * 450 398 * @return Address of the beginning of unmapped address space area. … … 453 401 */ 454 402 NO_TRACE static uintptr_t as_get_unmapped_area(as_t *as, uintptr_t bound, 455 size_t size , bool guarded)403 size_t size) 456 404 { 457 405 ASSERT(mutex_locked(&as->lock)); … … 475 423 /* First check the bound address itself */ 476 424 uintptr_t addr = ALIGN_UP(bound, PAGE_SIZE); 477 if (addr >= bound) { 478 if (guarded) { 479 /* Leave an unmapped page between the lower 480 * bound and the area's start address. 481 */ 482 addr += P2SZ(1); 483 } 484 485 if (check_area_conflicts(as, addr, pages, guarded, NULL)) 486 return addr; 487 } 425 if ((addr >= bound) && 426 (check_area_conflicts(as, addr, pages, NULL))) 427 return addr; 488 428 489 429 /* Eventually check the addresses behind each area */ … … 499 439 addr = 500 440 ALIGN_UP(area->base + P2SZ(area->pages), PAGE_SIZE); 501 502 if (guarded || area->flags & AS_AREA_GUARD) {503 /* We must leave an unmapped page504 * between the two areas.505 */506 addr += P2SZ(1);507 }508 509 441 bool avail = 510 442 ((addr >= bound) && (addr >= area->base) && 511 (check_area_conflicts(as, addr, pages, guarded,area)));443 (check_area_conflicts(as, addr, pages, area))); 512 444 513 445 mutex_unlock(&area->lock); … … 544 476 mem_backend_data_t *backend_data, uintptr_t *base, uintptr_t bound) 545 477 { 546 if ((*base != (uintptr_t) -1) && !IS_ALIGNED(*base, PAGE_SIZE))478 if ((*base != (uintptr_t) -1) && ((*base % PAGE_SIZE) != 0)) 547 479 return NULL; 548 480 549 481 if (size == 0) 550 482 return NULL; 551 483 552 484 size_t pages = SIZE2FRAMES(size); 553 485 … … 555 487 if ((flags & AS_AREA_EXEC) && (flags & AS_AREA_WRITE)) 556 488 return NULL; 557 558 bool const guarded = flags & AS_AREA_GUARD;559 489 560 490 mutex_lock(&as->lock); 561 491 562 492 if (*base == (uintptr_t) -1) { 563 *base = as_get_unmapped_area(as, bound, size , guarded);493 *base = as_get_unmapped_area(as, bound, size); 564 494 if (*base == (uintptr_t) -1) { 565 495 mutex_unlock(&as->lock); … … 567 497 } 568 498 } 569 570 if (overflows_into_positive(*base, size)) 571 return NULL; 572 573 if (!check_area_conflicts(as, *base, pages, guarded, NULL)) { 499 500 if (!check_area_conflicts(as, *base, pages, NULL)) { 574 501 mutex_unlock(&as->lock); 575 502 return NULL; … … 688 615 int as_area_resize(as_t *as, uintptr_t address, size_t size, unsigned int flags) 689 616 { 690 if (!IS_ALIGNED(address, PAGE_SIZE))691 return EINVAL;692 693 617 mutex_lock(&as->lock); 694 618 … … 701 625 return ENOENT; 702 626 } 703 704 if (!area->backend->is_resizable(area)) { 705 /* 706 * The backend does not support resizing for this area. 627 628 if (area->backend == &phys_backend) { 629 /* 630 * Remapping of address space areas associated 631 * with memory mapped devices is not supported. 707 632 */ 708 633 mutex_unlock(&area->lock); … … 740 665 741 666 page_table_lock(as, false); 667 668 /* 669 * Start TLB shootdown sequence. 670 */ 671 ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid, 672 area->base + P2SZ(pages), area->pages - pages); 742 673 743 674 /* … … 795 726 } 796 727 797 /*798 * Start TLB shootdown sequence.799 *800 * The sequence is rather short and can be801 * repeated multiple times. The reason is that802 * we don't want to have used_space_remove()803 * inside the sequence as it may use a blocking804 * memory allocation for its B+tree. Blocking805 * while holding the tlblock spinlock is806 * forbidden and would hit a kernel assertion.807 */808 809 ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES,810 as->asid, area->base + P2SZ(pages),811 area->pages - pages);812 813 728 for (; i < size; i++) { 814 729 pte_t *pte = page_mapping_find(as, … … 828 743 page_mapping_remove(as, ptr + P2SZ(i)); 829 744 } 830 831 /*832 * Finish TLB shootdown sequence.833 */834 835 tlb_invalidate_pages(as->asid,836 area->base + P2SZ(pages),837 area->pages - pages);838 839 /*840 * Invalidate software translation caches841 * (e.g. TSB on sparc64, PHT on ppc32).842 */843 as_invalidate_translation_cache(as,844 area->base + P2SZ(pages),845 area->pages - pages);846 tlb_shootdown_finalize(ipl);847 745 } 848 746 } 747 748 /* 749 * Finish TLB shootdown sequence. 750 */ 751 752 tlb_invalidate_pages(as->asid, area->base + P2SZ(pages), 753 area->pages - pages); 754 755 /* 756 * Invalidate software translation caches 757 * (e.g. TSB on sparc64, PHT on ppc32). 758 */ 759 as_invalidate_translation_cache(as, area->base + P2SZ(pages), 760 area->pages - pages); 761 tlb_shootdown_finalize(ipl); 762 849 763 page_table_unlock(as, false); 850 764 } else { 851 765 /* 852 766 * Growing the area. 853 */854 855 if (overflows_into_positive(address, P2SZ(pages)))856 return EINVAL;857 858 /*859 767 * Check for overlaps with other address space areas. 860 768 */ 861 bool const guarded = area->flags & AS_AREA_GUARD; 862 if (!check_area_conflicts(as, address, pages, guarded, area)) { 769 if (!check_area_conflicts(as, address, pages, area)) { 863 770 mutex_unlock(&area->lock); 864 771 mutex_unlock(&as->lock); … … 1061 968 } 1062 969 1063 if (!src_area->backend->is_shareable(src_area)) { 1064 /* 1065 * The backend does not permit sharing of this area. 970 if ((!src_area->backend) || (!src_area->backend->share)) { 971 /* 972 * There is no backend or the backend does not 973 * know how to share the area. 1066 974 */ 1067 975 mutex_unlock(&src_area->lock); … … 1353 1261 * Interrupts are assumed disabled. 1354 1262 * 1355 * @param address Faulting address.1356 * @param access Access mode that caused the page fault (i.e.1357 * read/write/exec).1358 * @param istate Pointer to the interrupted state.1263 * @param page Faulting page. 1264 * @param access Access mode that caused the page fault (i.e. 1265 * read/write/exec). 1266 * @param istate Pointer to the interrupted state. 1359 1267 * 1360 1268 * @return AS_PF_FAULT on page fault. … … 1364 1272 * 1365 1273 */ 1366 int as_page_fault(uintptr_t address, pf_access_t access, istate_t *istate) 1367 { 1368 uintptr_t page = ALIGN_DOWN(address, PAGE_SIZE); 1369 int rc = AS_PF_FAULT; 1370 1274 int as_page_fault(uintptr_t page, pf_access_t access, istate_t *istate) 1275 { 1371 1276 if (!THREAD) 1372 goto page_fault;1277 return AS_PF_FAULT; 1373 1278 1374 1279 if (!AS) 1375 goto page_fault;1280 return AS_PF_FAULT; 1376 1281 1377 1282 mutex_lock(&AS->lock); … … 1429 1334 * Resort to the backend page fault handler. 1430 1335 */ 1431 rc = area->backend->page_fault(area, page, access); 1432 if (rc != AS_PF_OK) { 1336 if (area->backend->page_fault(area, page, access) != AS_PF_OK) { 1433 1337 page_table_unlock(AS, false); 1434 1338 mutex_unlock(&area->lock); … … 1451 1355 istate_set_retaddr(istate, 1452 1356 (uintptr_t) &memcpy_to_uspace_failover_address); 1453 } else if (rc == AS_PF_SILENT) {1454 printf("Killing task %" PRIu64 " due to a "1455 "failed late reservation request.\n", TASK->taskid);1456 task_kill_self(true);1457 1357 } else { 1458 fault_if_from_uspace(istate, "Page fault: %p.", (void *) address); 1459 panic_memtrap(istate, access, address, NULL); 1358 return AS_PF_FAULT; 1460 1359 } 1461 1360 … … 1683 1582 { 1684 1583 ASSERT(mutex_locked(&area->lock)); 1685 ASSERT( IS_ALIGNED(page, PAGE_SIZE));1584 ASSERT(page == ALIGN_DOWN(page, PAGE_SIZE)); 1686 1585 ASSERT(count); 1687 1586 … … 1967 1866 { 1968 1867 ASSERT(mutex_locked(&area->lock)); 1969 ASSERT( IS_ALIGNED(page, PAGE_SIZE));1868 ASSERT(page == ALIGN_DOWN(page, PAGE_SIZE)); 1970 1869 ASSERT(count); 1971 1870 … … 2144 2043 { 2145 2044 uintptr_t virt = base; 2146 as_area_t *area = as_area_create(AS, flags , size,2045 as_area_t *area = as_area_create(AS, flags | AS_AREA_CACHEABLE, size, 2147 2046 AS_AREA_ATTR_NONE, &anon_backend, NULL, &virt, bound); 2148 2047 if (area == NULL)
Note:
See TracChangeset
for help on using the changeset viewer.
