Changes in kernel/generic/src/mm/as.c [94795812:f97f1e51] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/mm/as.c
r94795812 rf97f1e51 285 285 /** Check area conflicts with other areas. 286 286 * 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 guarded True if the area being tested is protected by guard pages. 291 * @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. 292 291 * 293 292 * @return True if there is no conflict, false otherwise. … … 295 294 */ 296 295 NO_TRACE static bool check_area_conflicts(as_t *as, uintptr_t addr, 297 size_t count, bool guarded,as_area_t *avoid)296 size_t count, as_area_t *avoid) 298 297 { 299 298 ASSERT((addr % PAGE_SIZE) == 0); 300 299 ASSERT(mutex_locked(&as->lock)); 301 302 /*303 * If the addition of the supposed area address and size overflows,304 * report conflict.305 */306 if (overflows_into_positive(addr, P2SZ(count)))307 return false;308 300 309 301 /* … … 312 304 if (overlaps(addr, P2SZ(count), (uintptr_t) NULL, PAGE_SIZE)) 313 305 return false; 314 306 315 307 /* 316 308 * The leaf node is found in O(log n), where n is proportional to … … 336 328 if (area != avoid) { 337 329 mutex_lock(&area->lock); 338 339 /* 340 * If at least one of the two areas are protected 341 * by the AS_AREA_GUARD flag then we must be sure 342 * that they are separated by at least one unmapped 343 * page. 344 */ 345 int const gp = (guarded || 346 (area->flags & AS_AREA_GUARD)) ? 1 : 0; 347 348 /* 349 * The area comes from the left neighbour node, which 350 * means that there already are some areas in the leaf 351 * node, which in turn means that adding gp is safe and 352 * will not cause an integer overflow. 353 */ 330 354 331 if (overlaps(addr, P2SZ(count), area->base, 355 P2SZ(area->pages + gp))) {356 mutex_unlock(&area->lock);357 return false;358 }359 360 mutex_unlock(&area->lock);361 }362 }363 364 node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf);365 if (node) {366 area = (as_area_t *) node->value[0];367 368 if (area != avoid) {369 int gp;370 371 mutex_lock(&area->lock);372 373 gp = (guarded || (area->flags & AS_AREA_GUARD)) ? 1 : 0;374 if (gp && overflows(addr, P2SZ(count))) {375 /*376 * Guard page not needed if the supposed area377 * is adjacent to the end of the address space.378 * We already know that the following test is379 * going to fail...380 */381 gp--;382 }383 384 if (overlaps(addr, P2SZ(count + gp), area->base,385 332 P2SZ(area->pages))) { 386 333 mutex_unlock(&area->lock); … … 392 339 } 393 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 394 358 /* Second, check the leaf node. */ 395 359 btree_key_t i; 396 360 for (i = 0; i < leaf->keys; i++) { 397 361 area = (as_area_t *) leaf->value[i]; 398 int agp;399 int gp;400 362 401 363 if (area == avoid) … … 403 365 404 366 mutex_lock(&area->lock); 405 406 gp = (guarded || (area->flags & AS_AREA_GUARD)) ? 1 : 0; 407 agp = gp; 408 409 /* 410 * Sanitize the two possible unsigned integer overflows. 411 */ 412 if (gp && overflows(addr, P2SZ(count))) 413 gp--; 414 if (agp && overflows(area->base, P2SZ(area->pages))) 415 agp--; 416 417 if (overlaps(addr, P2SZ(count + gp), area->base, 418 P2SZ(area->pages + agp))) { 367 368 if (overlaps(addr, P2SZ(count), area->base, 369 P2SZ(area->pages))) { 419 370 mutex_unlock(&area->lock); 420 371 return false; … … 441 392 * this function. 442 393 * 443 * @param as Address space. 444 * @param bound Lowest address bound. 445 * @param size Requested size of the allocation. 446 * @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. 447 397 * 448 398 * @return Address of the beginning of unmapped address space area. … … 451 401 */ 452 402 NO_TRACE static uintptr_t as_get_unmapped_area(as_t *as, uintptr_t bound, 453 size_t size , bool guarded)403 size_t size) 454 404 { 455 405 ASSERT(mutex_locked(&as->lock)); … … 473 423 /* First check the bound address itself */ 474 424 uintptr_t addr = ALIGN_UP(bound, PAGE_SIZE); 475 if (addr >= bound) { 476 if (guarded) { 477 /* Leave an unmapped page between the lower 478 * bound and the area's start address. 479 */ 480 addr += P2SZ(1); 481 } 482 483 if (check_area_conflicts(as, addr, pages, guarded, NULL)) 484 return addr; 485 } 425 if ((addr >= bound) && 426 (check_area_conflicts(as, addr, pages, NULL))) 427 return addr; 486 428 487 429 /* Eventually check the addresses behind each area */ … … 497 439 addr = 498 440 ALIGN_UP(area->base + P2SZ(area->pages), PAGE_SIZE); 499 500 if (guarded || area->flags & AS_AREA_GUARD) {501 /* We must leave an unmapped page502 * between the two areas.503 */504 addr += P2SZ(1);505 }506 507 441 bool avail = 508 442 ((addr >= bound) && (addr >= area->base) && 509 (check_area_conflicts(as, addr, pages, guarded,area)));443 (check_area_conflicts(as, addr, pages, area))); 510 444 511 445 mutex_unlock(&area->lock); … … 547 481 if (size == 0) 548 482 return NULL; 549 483 550 484 size_t pages = SIZE2FRAMES(size); 551 485 … … 553 487 if ((flags & AS_AREA_EXEC) && (flags & AS_AREA_WRITE)) 554 488 return NULL; 555 556 bool const guarded = flags & AS_AREA_GUARD;557 489 558 490 mutex_lock(&as->lock); 559 491 560 492 if (*base == (uintptr_t) -1) { 561 *base = as_get_unmapped_area(as, bound, size , guarded);493 *base = as_get_unmapped_area(as, bound, size); 562 494 if (*base == (uintptr_t) -1) { 563 495 mutex_unlock(&as->lock); … … 565 497 } 566 498 } 567 568 if (overflows_into_positive(*base, size)) 569 return NULL; 570 571 if (!check_area_conflicts(as, *base, pages, guarded, NULL)) { 499 500 if (!check_area_conflicts(as, *base, pages, NULL)) { 572 501 mutex_unlock(&as->lock); 573 502 return NULL; … … 736 665 737 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); 738 673 739 674 /* … … 791 726 } 792 727 793 /*794 * Start TLB shootdown sequence.795 *796 * The sequence is rather short and can be797 * repeated multiple times. The reason is that798 * we don't want to have used_space_remove()799 * inside the sequence as it may use a blocking800 * memory allocation for its B+tree. Blocking801 * while holding the tlblock spinlock is802 * forbidden and would hit a kernel assertion.803 */804 805 ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES,806 as->asid, area->base + P2SZ(pages),807 area->pages - pages);808 809 728 for (; i < size; i++) { 810 729 pte_t *pte = page_mapping_find(as, … … 824 743 page_mapping_remove(as, ptr + P2SZ(i)); 825 744 } 826 827 /*828 * Finish TLB shootdown sequence.829 */830 831 tlb_invalidate_pages(as->asid,832 area->base + P2SZ(pages),833 area->pages - pages);834 835 /*836 * Invalidate software translation caches837 * (e.g. TSB on sparc64, PHT on ppc32).838 */839 as_invalidate_translation_cache(as,840 area->base + P2SZ(pages),841 area->pages - pages);842 tlb_shootdown_finalize(ipl);843 745 } 844 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 845 763 page_table_unlock(as, false); 846 764 } else { 847 765 /* 848 766 * Growing the area. 849 */850 851 if (overflows_into_positive(address, P2SZ(pages)))852 return EINVAL;853 854 /*855 767 * Check for overlaps with other address space areas. 856 768 */ 857 bool const guarded = area->flags & AS_AREA_GUARD; 858 if (!check_area_conflicts(as, address, pages, guarded, area)) { 769 if (!check_area_conflicts(as, address, pages, area)) { 859 770 mutex_unlock(&area->lock); 860 771 mutex_unlock(&as->lock);
Note:
See TracChangeset
for help on using the changeset viewer.