Ignore:
File:
1 edited

Legend:

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

    r94795812 rf97f1e51  
    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 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.
    292291 *
    293292 * @return True if there is no conflict, false otherwise.
     
    295294 */
    296295NO_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)
    298297{
    299298        ASSERT((addr % PAGE_SIZE) == 0);
    300299        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;
    308300       
    309301        /*
     
    312304        if (overlaps(addr, P2SZ(count), (uintptr_t) NULL, PAGE_SIZE))
    313305                return false;
    314 
     306       
    315307        /*
    316308         * The leaf node is found in O(log n), where n is proportional to
     
    336328                if (area != avoid) {
    337329                        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                       
    354331                        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,
    385332                            P2SZ(area->pages))) {
    386333                                mutex_unlock(&area->lock);
     
    392339        }
    393340       
     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       
    394358        /* Second, check the leaf node. */
    395359        btree_key_t i;
    396360        for (i = 0; i < leaf->keys; i++) {
    397361                area = (as_area_t *) leaf->value[i];
    398                 int agp;
    399                 int gp;
    400362               
    401363                if (area == avoid)
     
    403365               
    404366                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))) {
    419370                        mutex_unlock(&area->lock);
    420371                        return false;
     
    441392 * this function.
    442393 *
    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.
    447397 *
    448398 * @return Address of the beginning of unmapped address space area.
     
    451401 */
    452402NO_TRACE static uintptr_t as_get_unmapped_area(as_t *as, uintptr_t bound,
    453     size_t size, bool guarded)
     403    size_t size)
    454404{
    455405        ASSERT(mutex_locked(&as->lock));
     
    473423        /* First check the bound address itself */
    474424        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;
    486428       
    487429        /* Eventually check the addresses behind each area */
     
    497439                        addr =
    498440                            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 
    507441                        bool avail =
    508442                            ((addr >= bound) && (addr >= area->base) &&
    509                             (check_area_conflicts(as, addr, pages, guarded, area)));
     443                            (check_area_conflicts(as, addr, pages, area)));
    510444                       
    511445                        mutex_unlock(&area->lock);
     
    547481        if (size == 0)
    548482                return NULL;
    549 
     483       
    550484        size_t pages = SIZE2FRAMES(size);
    551485       
     
    553487        if ((flags & AS_AREA_EXEC) && (flags & AS_AREA_WRITE))
    554488                return NULL;
    555 
    556         bool const guarded = flags & AS_AREA_GUARD;
    557489       
    558490        mutex_lock(&as->lock);
    559491       
    560492        if (*base == (uintptr_t) -1) {
    561                 *base = as_get_unmapped_area(as, bound, size, guarded);
     493                *base = as_get_unmapped_area(as, bound, size);
    562494                if (*base == (uintptr_t) -1) {
    563495                        mutex_unlock(&as->lock);
     
    565497                }
    566498        }
    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)) {
    572501                mutex_unlock(&as->lock);
    573502                return NULL;
     
    736665               
    737666                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);
    738673               
    739674                /*
     
    791726                                }
    792727                               
    793                                 /*
    794                                  * Start TLB shootdown sequence.
    795                                  *
    796                                  * The sequence is rather short and can be
    797                                  * repeated multiple times. The reason is that
    798                                  * we don't want to have used_space_remove()
    799                                  * inside the sequence as it may use a blocking
    800                                  * memory allocation for its B+tree. Blocking
    801                                  * while holding the tlblock spinlock is
    802                                  * 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                
    809728                                for (; i < size; i++) {
    810729                                        pte_t *pte = page_mapping_find(as,
     
    824743                                        page_mapping_remove(as, ptr + P2SZ(i));
    825744                                }
    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 caches
    837                                  * (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);
    843745                        }
    844746                }
     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               
    845763                page_table_unlock(as, false);
    846764        } else {
    847765                /*
    848766                 * Growing the area.
    849                  */
    850 
    851                 if (overflows_into_positive(address, P2SZ(pages)))
    852                         return EINVAL;
    853 
    854                 /*
    855767                 * Check for overlaps with other address space areas.
    856768                 */
    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)) {
    859770                        mutex_unlock(&area->lock);
    860771                        mutex_unlock(&as->lock);
Note: See TracChangeset for help on using the changeset viewer.