Changeset efdfebc in mainline for kernel/generic/src/mm/as.c


Ignore:
Timestamp:
2012-11-06T21:03:44Z (11 years ago)
Author:
Jakub Jermar <jakub@…>
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.
Message:

Merge mainline changes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/mm/as.c

    rde73242 refdfebc  
    285285/** Check area conflicts with other areas.
    286286 *
    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.
    291292 *
    292293 * @return True if there is no conflict, false otherwise.
     
    294295 */
    295296NO_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)
    297298{
    298299        ASSERT((addr % PAGE_SIZE) == 0);
    299300        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;
    300308       
    301309        /*
     
    304312        if (overlaps(addr, P2SZ(count), (uintptr_t) NULL, PAGE_SIZE))
    305313                return false;
    306        
     314
    307315        /*
    308316         * The leaf node is found in O(log n), where n is proportional to
     
    328336                if (area != avoid) {
    329337                        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                         */
    331354                        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,
    332385                            P2SZ(area->pages))) {
    333386                                mutex_unlock(&area->lock);
     
    339392        }
    340393       
    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        
    358394        /* Second, check the leaf node. */
    359395        btree_key_t i;
    360396        for (i = 0; i < leaf->keys; i++) {
    361397                area = (as_area_t *) leaf->value[i];
     398                int agp;
     399                int gp;
    362400               
    363401                if (area == avoid)
     
    365403               
    366404                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))) {
    370419                        mutex_unlock(&area->lock);
    371420                        return false;
     
    392441 * this function.
    393442 *
    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.
    397447 *
    398448 * @return Address of the beginning of unmapped address space area.
     
    401451 */
    402452NO_TRACE static uintptr_t as_get_unmapped_area(as_t *as, uintptr_t bound,
    403     size_t size)
     453    size_t size, bool guarded)
    404454{
    405455        ASSERT(mutex_locked(&as->lock));
     
    423473        /* First check the bound address itself */
    424474        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        }
    428486       
    429487        /* Eventually check the addresses behind each area */
     
    439497                        addr =
    440498                            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
    441507                        bool avail =
    442508                            ((addr >= bound) && (addr >= area->base) &&
    443                             (check_area_conflicts(as, addr, pages, area)));
     509                            (check_area_conflicts(as, addr, pages, guarded, area)));
    444510                       
    445511                        mutex_unlock(&area->lock);
     
    481547        if (size == 0)
    482548                return NULL;
    483        
     549
    484550        size_t pages = SIZE2FRAMES(size);
    485551       
     
    487553        if ((flags & AS_AREA_EXEC) && (flags & AS_AREA_WRITE))
    488554                return NULL;
     555
     556        bool const guarded = flags & AS_AREA_GUARD;
    489557       
    490558        mutex_lock(&as->lock);
    491559       
    492560        if (*base == (uintptr_t) -1) {
    493                 *base = as_get_unmapped_area(as, bound, size);
     561                *base = as_get_unmapped_area(as, bound, size, guarded);
    494562                if (*base == (uintptr_t) -1) {
    495563                        mutex_unlock(&as->lock);
     
    497565                }
    498566        }
    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)) {
    501572                mutex_unlock(&as->lock);
    502573                return NULL;
     
    776847                /*
    777848                 * Growing the area.
     849                 */
     850
     851                if (overflows_into_positive(address, P2SZ(pages)))
     852                        return EINVAL;
     853
     854                /*
    778855                 * Check for overlaps with other address space areas.
    779856                 */
    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)) {
    781859                        mutex_unlock(&area->lock);
    782860                        mutex_unlock(&as->lock);
Note: See TracChangeset for help on using the changeset viewer.