Changeset efdfebc in mainline for kernel/generic/src/mm/as.c
- Timestamp:
- 2012-11-06T21:03:44Z (11 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 338810f
- Parents:
- de73242 (diff), 94795812 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/mm/as.c
rde73242 refdfebc 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 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 guarded True if the area being tested is protected by guard pages. 291 * @param avoid Do not touch this area. 291 292 * 292 293 * @return True if there is no conflict, false otherwise. … … 294 295 */ 295 296 NO_TRACE static bool check_area_conflicts(as_t *as, uintptr_t addr, 296 size_t count, as_area_t *avoid)297 size_t count, bool guarded, as_area_t *avoid) 297 298 { 298 299 ASSERT((addr % PAGE_SIZE) == 0); 299 300 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; 300 308 301 309 /* … … 304 312 if (overlaps(addr, P2SZ(count), (uintptr_t) NULL, PAGE_SIZE)) 305 313 return false; 306 314 307 315 /* 308 316 * The leaf node is found in O(log n), where n is proportional to … … 328 336 if (area != avoid) { 329 337 mutex_lock(&area->lock); 330 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 */ 331 354 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 area 377 * is adjacent to the end of the address space. 378 * We already know that the following test is 379 * going to fail... 380 */ 381 gp--; 382 } 383 384 if (overlaps(addr, P2SZ(count + gp), area->base, 332 385 P2SZ(area->pages))) { 333 386 mutex_unlock(&area->lock); … … 339 392 } 340 393 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 358 394 /* Second, check the leaf node. */ 359 395 btree_key_t i; 360 396 for (i = 0; i < leaf->keys; i++) { 361 397 area = (as_area_t *) leaf->value[i]; 398 int agp; 399 int gp; 362 400 363 401 if (area == avoid) … … 365 403 366 404 mutex_lock(&area->lock); 367 368 if (overlaps(addr, P2SZ(count), area->base, 369 P2SZ(area->pages))) { 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))) { 370 419 mutex_unlock(&area->lock); 371 420 return false; … … 392 441 * this function. 393 442 * 394 * @param as Address space. 395 * @param bound Lowest address bound. 396 * @param size Requested size of the allocation. 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. 397 447 * 398 448 * @return Address of the beginning of unmapped address space area. … … 401 451 */ 402 452 NO_TRACE static uintptr_t as_get_unmapped_area(as_t *as, uintptr_t bound, 403 size_t size )453 size_t size, bool guarded) 404 454 { 405 455 ASSERT(mutex_locked(&as->lock)); … … 423 473 /* First check the bound address itself */ 424 474 uintptr_t addr = ALIGN_UP(bound, PAGE_SIZE); 425 if ((addr >= bound) && 426 (check_area_conflicts(as, addr, pages, NULL))) 427 return addr; 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 } 428 486 429 487 /* Eventually check the addresses behind each area */ … … 439 497 addr = 440 498 ALIGN_UP(area->base + P2SZ(area->pages), PAGE_SIZE); 499 500 if (guarded || area->flags & AS_AREA_GUARD) { 501 /* We must leave an unmapped page 502 * between the two areas. 503 */ 504 addr += P2SZ(1); 505 } 506 441 507 bool avail = 442 508 ((addr >= bound) && (addr >= area->base) && 443 (check_area_conflicts(as, addr, pages, area)));509 (check_area_conflicts(as, addr, pages, guarded, area))); 444 510 445 511 mutex_unlock(&area->lock); … … 481 547 if (size == 0) 482 548 return NULL; 483 549 484 550 size_t pages = SIZE2FRAMES(size); 485 551 … … 487 553 if ((flags & AS_AREA_EXEC) && (flags & AS_AREA_WRITE)) 488 554 return NULL; 555 556 bool const guarded = flags & AS_AREA_GUARD; 489 557 490 558 mutex_lock(&as->lock); 491 559 492 560 if (*base == (uintptr_t) -1) { 493 *base = as_get_unmapped_area(as, bound, size );561 *base = as_get_unmapped_area(as, bound, size, guarded); 494 562 if (*base == (uintptr_t) -1) { 495 563 mutex_unlock(&as->lock); … … 497 565 } 498 566 } 499 500 if (!check_area_conflicts(as, *base, pages, NULL)) { 567 568 if (overflows_into_positive(*base, size)) 569 return NULL; 570 571 if (!check_area_conflicts(as, *base, pages, guarded, NULL)) { 501 572 mutex_unlock(&as->lock); 502 573 return NULL; … … 776 847 /* 777 848 * Growing the area. 849 */ 850 851 if (overflows_into_positive(address, P2SZ(pages))) 852 return EINVAL; 853 854 /* 778 855 * Check for overlaps with other address space areas. 779 856 */ 780 if (!check_area_conflicts(as, address, pages, area)) { 857 bool const guarded = area->flags & AS_AREA_GUARD; 858 if (!check_area_conflicts(as, address, pages, guarded, area)) { 781 859 mutex_unlock(&area->lock); 782 860 mutex_unlock(&as->lock);
Note:
See TracChangeset
for help on using the changeset viewer.