Changes in kernel/generic/src/mm/as.c [57355a40:c4c2406] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/mm/as.c
r57355a40 rc4c2406 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; … … 426 377 /* 427 378 * So far, the area does not conflict with other areas. 428 * Check if it is contained in the useraddress space.379 * Check if it doesn't conflict with kernel address space. 429 380 */ 430 381 if (!KERNEL_ADDRESS_SPACE_SHADOWED) { 431 return iswithin(USER_ADDRESS_SPACE_START, 432 (USER_ADDRESS_SPACE_END - USER_ADDRESS_SPACE_START) + 1, 433 addr, P2SZ(count)); 382 return !overlaps(addr, P2SZ(count), KERNEL_ADDRESS_SPACE_START, 383 KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START); 434 384 } 435 385 … … 442 392 * this function. 443 393 * 444 * @param as Address space. 445 * @param bound Lowest address bound. 446 * @param size Requested size of the allocation. 447 * @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. 448 397 * 449 398 * @return Address of the beginning of unmapped address space area. … … 452 401 */ 453 402 NO_TRACE static uintptr_t as_get_unmapped_area(as_t *as, uintptr_t bound, 454 size_t size , bool guarded)403 size_t size) 455 404 { 456 405 ASSERT(mutex_locked(&as->lock)); … … 474 423 /* First check the bound address itself */ 475 424 uintptr_t addr = ALIGN_UP(bound, PAGE_SIZE); 476 if (addr >= bound) { 477 if (guarded) { 478 /* Leave an unmapped page between the lower 479 * bound and the area's start address. 480 */ 481 addr += P2SZ(1); 482 } 483 484 if (check_area_conflicts(as, addr, pages, guarded, NULL)) 485 return addr; 486 } 425 if ((addr >= bound) && 426 (check_area_conflicts(as, addr, pages, NULL))) 427 return addr; 487 428 488 429 /* Eventually check the addresses behind each area */ … … 498 439 addr = 499 440 ALIGN_UP(area->base + P2SZ(area->pages), PAGE_SIZE); 500 501 if (guarded || area->flags & AS_AREA_GUARD) {502 /* We must leave an unmapped page503 * between the two areas.504 */505 addr += P2SZ(1);506 }507 508 441 bool avail = 509 442 ((addr >= bound) && (addr >= area->base) && 510 (check_area_conflicts(as, addr, pages, guarded,area)));443 (check_area_conflicts(as, addr, pages, area))); 511 444 512 445 mutex_unlock(&area->lock); … … 548 481 if (size == 0) 549 482 return NULL; 550 483 551 484 size_t pages = SIZE2FRAMES(size); 552 485 … … 554 487 if ((flags & AS_AREA_EXEC) && (flags & AS_AREA_WRITE)) 555 488 return NULL; 556 557 bool const guarded = flags & AS_AREA_GUARD;558 489 559 490 mutex_lock(&as->lock); 560 491 561 492 if (*base == (uintptr_t) -1) { 562 *base = as_get_unmapped_area(as, bound, size , guarded);493 *base = as_get_unmapped_area(as, bound, size); 563 494 if (*base == (uintptr_t) -1) { 564 495 mutex_unlock(&as->lock); … … 566 497 } 567 498 } 568 569 if (overflows_into_positive(*base, size)) 570 return NULL; 571 572 if (!check_area_conflicts(as, *base, pages, guarded, NULL)) { 499 500 if (!check_area_conflicts(as, *base, pages, NULL)) { 573 501 mutex_unlock(&as->lock); 574 502 return NULL; … … 697 625 return ENOENT; 698 626 } 699 700 if ( !area->backend->is_resizable(area)) {627 628 if (area->backend == &phys_backend) { 701 629 /* 702 * The backend does not support resizing for this area. 630 * Remapping of address space areas associated 631 * with memory mapped devices is not supported. 703 632 */ 704 633 mutex_unlock(&area->lock); … … 847 776 /* 848 777 * Growing the area. 849 */850 851 if (overflows_into_positive(address, P2SZ(pages)))852 return EINVAL;853 854 /*855 778 * Check for overlaps with other address space areas. 856 779 */ 857 bool const guarded = area->flags & AS_AREA_GUARD; 858 if (!check_area_conflicts(as, address, pages, guarded, area)) { 780 if (!check_area_conflicts(as, address, pages, area)) { 859 781 mutex_unlock(&area->lock); 860 782 mutex_unlock(&as->lock); … … 1057 979 } 1058 980 1059 if ( !src_area->backend->is_shareable(src_area)) {981 if ((!src_area->backend) || (!src_area->backend->share)) { 1060 982 /* 1061 * The backend does not permit sharing of this area. 983 * There is no backend or the backend does not 984 * know how to share the area. 1062 985 */ 1063 986 mutex_unlock(&src_area->lock); … … 2131 2054 { 2132 2055 uintptr_t virt = base; 2133 as_area_t *area = as_area_create(AS, flags | AS_AREA_CACHEABLE, size,2056 as_area_t *area = as_area_create(AS, flags, size, 2134 2057 AS_AREA_ATTR_NONE, &anon_backend, NULL, &virt, bound); 2135 2058 if (area == NULL)
Note:
See TracChangeset
for help on using the changeset viewer.