Ignore:
File:
1 edited

Legend:

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

    r908bb96 rf97f1e51  
    7979#include <syscall/copy.h>
    8080#include <arch/interrupt.h>
    81 #include <interrupt.h>
    8281
    8382/**
     
    286285/** Check area conflicts with other areas.
    287286 *
    288  * @param as      Address space.
    289  * @param addr    Starting virtual address of the area being tested.
    290  * @param count   Number of pages in the area being tested.
    291  * @param guarded True if the area being tested is protected by guard pages.
    292  * @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.
    293291 *
    294292 * @return True if there is no conflict, false otherwise.
     
    296294 */
    297295NO_TRACE static bool check_area_conflicts(as_t *as, uintptr_t addr,
    298     size_t count, bool guarded, as_area_t *avoid)
     296    size_t count, as_area_t *avoid)
    299297{
    300298        ASSERT((addr % PAGE_SIZE) == 0);
    301299        ASSERT(mutex_locked(&as->lock));
    302 
    303         /*
    304          * If the addition of the supposed area address and size overflows,
    305          * report conflict.
    306          */
    307         if (overflows_into_positive(addr, P2SZ(count)))
    308                 return false;
    309300       
    310301        /*
     
    313304        if (overlaps(addr, P2SZ(count), (uintptr_t) NULL, PAGE_SIZE))
    314305                return false;
    315 
     306       
    316307        /*
    317308         * The leaf node is found in O(log n), where n is proportional to
     
    337328                if (area != avoid) {
    338329                        mutex_lock(&area->lock);
    339 
    340                         /*
    341                          * If at least one of the two areas are protected
    342                          * by the AS_AREA_GUARD flag then we must be sure
    343                          * that they are separated by at least one unmapped
    344                          * page.
    345                          */
    346                         int const gp = (guarded ||
    347                             (area->flags & AS_AREA_GUARD)) ? 1 : 0;
    348                        
    349                         /*
    350                          * The area comes from the left neighbour node, which
    351                          * means that there already are some areas in the leaf
    352                          * node, which in turn means that adding gp is safe and
    353                          * will not cause an integer overflow.
    354                          */
     330                       
    355331                        if (overlaps(addr, P2SZ(count), area->base,
    356                             P2SZ(area->pages + gp))) {
    357                                 mutex_unlock(&area->lock);
    358                                 return false;
    359                         }
    360                        
    361                         mutex_unlock(&area->lock);
    362                 }
    363         }
    364        
    365         node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf);
    366         if (node) {
    367                 area = (as_area_t *) node->value[0];
    368                
    369                 if (area != avoid) {
    370                         int gp;
    371 
    372                         mutex_lock(&area->lock);
    373 
    374                         gp = (guarded || (area->flags & AS_AREA_GUARD)) ? 1 : 0;
    375                         if (gp && overflows(addr, P2SZ(count))) {
    376                                 /*
    377                                  * Guard page not needed if the supposed area
    378                                  * is adjacent to the end of the address space.
    379                                  * We already know that the following test is
    380                                  * going to fail...
    381                                  */
    382                                 gp--;
    383                         }
    384                        
    385                         if (overlaps(addr, P2SZ(count + gp), area->base,
    386332                            P2SZ(area->pages))) {
    387333                                mutex_unlock(&area->lock);
     
    393339        }
    394340       
     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       
    395358        /* Second, check the leaf node. */
    396359        btree_key_t i;
    397360        for (i = 0; i < leaf->keys; i++) {
    398361                area = (as_area_t *) leaf->value[i];
    399                 int agp;
    400                 int gp;
    401362               
    402363                if (area == avoid)
     
    404365               
    405366                mutex_lock(&area->lock);
    406 
    407                 gp = (guarded || (area->flags & AS_AREA_GUARD)) ? 1 : 0;
    408                 agp = gp;
    409 
    410                 /*
    411                  * Sanitize the two possible unsigned integer overflows.
    412                  */
    413                 if (gp && overflows(addr, P2SZ(count)))
    414                         gp--;
    415                 if (agp && overflows(area->base, P2SZ(area->pages)))
    416                         agp--;
    417 
    418                 if (overlaps(addr, P2SZ(count + gp), area->base,
    419                     P2SZ(area->pages + agp))) {
     367               
     368                if (overlaps(addr, P2SZ(count), area->base,
     369                    P2SZ(area->pages))) {
    420370                        mutex_unlock(&area->lock);
    421371                        return false;
     
    427377        /*
    428378         * So far, the area does not conflict with other areas.
    429          * Check if it is contained in the user address space.
     379         * Check if it doesn't conflict with kernel address space.
    430380         */
    431381        if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
    432                 return iswithin(USER_ADDRESS_SPACE_START,
    433                     (USER_ADDRESS_SPACE_END - USER_ADDRESS_SPACE_START) + 1,
    434                     addr, P2SZ(count));
     382                return !overlaps(addr, P2SZ(count), KERNEL_ADDRESS_SPACE_START,
     383                    KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START);
    435384        }
    436385       
     
    443392 * this function.
    444393 *
    445  * @param as      Address space.
    446  * @param bound   Lowest address bound.
    447  * @param size    Requested size of the allocation.
    448  * @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.
    449397 *
    450398 * @return Address of the beginning of unmapped address space area.
     
    453401 */
    454402NO_TRACE static uintptr_t as_get_unmapped_area(as_t *as, uintptr_t bound,
    455     size_t size, bool guarded)
     403    size_t size)
    456404{
    457405        ASSERT(mutex_locked(&as->lock));
     
    475423        /* First check the bound address itself */
    476424        uintptr_t addr = ALIGN_UP(bound, PAGE_SIZE);
    477         if (addr >= bound) {
    478                 if (guarded) {
    479                         /* Leave an unmapped page between the lower
    480                          * bound and the area's start address.
    481                          */
    482                         addr += P2SZ(1);
    483                 }
    484 
    485                 if (check_area_conflicts(as, addr, pages, guarded, NULL))
    486                         return addr;
    487         }
     425        if ((addr >= bound) &&
     426            (check_area_conflicts(as, addr, pages, NULL)))
     427                return addr;
    488428       
    489429        /* Eventually check the addresses behind each area */
     
    499439                        addr =
    500440                            ALIGN_UP(area->base + P2SZ(area->pages), PAGE_SIZE);
    501 
    502                         if (guarded || area->flags & AS_AREA_GUARD) {
    503                                 /* We must leave an unmapped page
    504                                  * between the two areas.
    505                                  */
    506                                 addr += P2SZ(1);
    507                         }
    508 
    509441                        bool avail =
    510442                            ((addr >= bound) && (addr >= area->base) &&
    511                             (check_area_conflicts(as, addr, pages, guarded, area)));
     443                            (check_area_conflicts(as, addr, pages, area)));
    512444                       
    513445                        mutex_unlock(&area->lock);
     
    549481        if (size == 0)
    550482                return NULL;
    551 
     483       
    552484        size_t pages = SIZE2FRAMES(size);
    553485       
     
    555487        if ((flags & AS_AREA_EXEC) && (flags & AS_AREA_WRITE))
    556488                return NULL;
    557 
    558         bool const guarded = flags & AS_AREA_GUARD;
    559489       
    560490        mutex_lock(&as->lock);
    561491       
    562492        if (*base == (uintptr_t) -1) {
    563                 *base = as_get_unmapped_area(as, bound, size, guarded);
     493                *base = as_get_unmapped_area(as, bound, size);
    564494                if (*base == (uintptr_t) -1) {
    565495                        mutex_unlock(&as->lock);
     
    567497                }
    568498        }
    569 
    570         if (overflows_into_positive(*base, size))
    571                 return NULL;
    572 
    573         if (!check_area_conflicts(as, *base, pages, guarded, NULL)) {
     499       
     500        if (!check_area_conflicts(as, *base, pages, NULL)) {
    574501                mutex_unlock(&as->lock);
    575502                return NULL;
     
    698625                return ENOENT;
    699626        }
    700 
    701         if (!area->backend->is_resizable(area)) {
    702                 /*
    703                  * The backend does not support resizing for this area.
     627       
     628        if (area->backend == &phys_backend) {
     629                /*
     630                 * Remapping of address space areas associated
     631                 * with memory mapped devices is not supported.
    704632                 */
    705633                mutex_unlock(&area->lock);
     
    737665               
    738666                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);
    739673               
    740674                /*
     
    792726                                }
    793727                               
    794                                 /*
    795                                  * Start TLB shootdown sequence.
    796                                  *
    797                                  * The sequence is rather short and can be
    798                                  * repeated multiple times. The reason is that
    799                                  * we don't want to have used_space_remove()
    800                                  * inside the sequence as it may use a blocking
    801                                  * memory allocation for its B+tree. Blocking
    802                                  * while holding the tlblock spinlock is
    803                                  * forbidden and would hit a kernel assertion.
    804                                  */
    805 
    806                                 ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES,
    807                                     as->asid, area->base + P2SZ(pages),
    808                                     area->pages - pages);
    809                
    810728                                for (; i < size; i++) {
    811729                                        pte_t *pte = page_mapping_find(as,
     
    825743                                        page_mapping_remove(as, ptr + P2SZ(i));
    826744                                }
    827                
    828                                 /*
    829                                  * Finish TLB shootdown sequence.
    830                                  */
    831                
    832                                 tlb_invalidate_pages(as->asid,
    833                                     area->base + P2SZ(pages),
    834                                     area->pages - pages);
    835                
    836                                 /*
    837                                  * Invalidate software translation caches
    838                                  * (e.g. TSB on sparc64, PHT on ppc32).
    839                                  */
    840                                 as_invalidate_translation_cache(as,
    841                                     area->base + P2SZ(pages),
    842                                     area->pages - pages);
    843                                 tlb_shootdown_finalize(ipl);
    844745                        }
    845746                }
     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               
    846763                page_table_unlock(as, false);
    847764        } else {
    848765                /*
    849766                 * Growing the area.
    850                  */
    851 
    852                 if (overflows_into_positive(address, P2SZ(pages)))
    853                         return EINVAL;
    854 
    855                 /*
    856767                 * Check for overlaps with other address space areas.
    857768                 */
    858                 bool const guarded = area->flags & AS_AREA_GUARD;
    859                 if (!check_area_conflicts(as, address, pages, guarded, area)) {
     769                if (!check_area_conflicts(as, address, pages, area)) {
    860770                        mutex_unlock(&area->lock);
    861771                        mutex_unlock(&as->lock);
     
    1058968        }
    1059969       
    1060         if (!src_area->backend->is_shareable(src_area)) {
    1061                 /*
    1062                  * The backend does not permit sharing of this area.
     970        if ((!src_area->backend) || (!src_area->backend->share)) {
     971                /*
     972                 * There is no backend or the backend does not
     973                 * know how to share the area.
    1063974                 */
    1064975                mutex_unlock(&src_area->lock);
     
    13631274int as_page_fault(uintptr_t page, pf_access_t access, istate_t *istate)
    13641275{
    1365         int rc = AS_PF_FAULT;
    1366 
    13671276        if (!THREAD)
    1368                 goto page_fault;
     1277                return AS_PF_FAULT;
    13691278       
    13701279        if (!AS)
    1371                 goto page_fault;
     1280                return AS_PF_FAULT;
    13721281       
    13731282        mutex_lock(&AS->lock);
     
    14251334         * Resort to the backend page fault handler.
    14261335         */
    1427         rc = area->backend->page_fault(area, page, access);
    1428         if (rc != AS_PF_OK) {
     1336        if (area->backend->page_fault(area, page, access) != AS_PF_OK) {
    14291337                page_table_unlock(AS, false);
    14301338                mutex_unlock(&area->lock);
     
    14471355                istate_set_retaddr(istate,
    14481356                    (uintptr_t) &memcpy_to_uspace_failover_address);
    1449         } else if (rc == AS_PF_SILENT) {
    1450                 printf("Killing task %" PRIu64 " due to a "
    1451                     "failed late reservation request.\n", TASK->taskid);
    1452                 task_kill_self(true);
    14531357        } else {
    1454                 fault_if_from_uspace(istate, "Page fault: %p.", (void *) page);
    1455                 panic_memtrap(istate, access, page, NULL);
     1358                return AS_PF_FAULT;
    14561359        }
    14571360       
Note: See TracChangeset for help on using the changeset viewer.