Changeset df3c6f02 in mainline for kernel/generic/src/mm


Ignore:
Timestamp:
2011-05-31T22:58:56Z (15 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/fix-logger-deadlock, topic/msim-upgrade, topic/simplify-dev-export
Children:
d362410
Parents:
82582e4 (diff), 4ce90544 (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.

Location:
kernel/generic/src/mm
Files:
1 added
6 edited

Legend:

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

    r82582e4 rdf3c6f02  
    8080#include <arch/interrupt.h>
    8181
    82 #ifdef CONFIG_VIRT_IDX_DCACHE
    83 #include <arch/mm/cache.h>
    84 #endif /* CONFIG_VIRT_IDX_DCACHE */
    85 
    8682/**
    8783 * Each architecture decides what functions will be used to carry out
     
    306302         * We don't want any area to have conflicts with NULL page.
    307303         */
    308         if (overlaps(addr, count << PAGE_WIDTH, (uintptr_t) NULL, PAGE_SIZE))
     304        if (overlaps(addr, P2SZ(count), (uintptr_t) NULL, PAGE_SIZE))
    309305                return false;
    310306       
     
    333329                        mutex_lock(&area->lock);
    334330                       
    335                         if (overlaps(addr, count << PAGE_WIDTH,
    336                             area->base, area->pages << PAGE_WIDTH)) {
     331                        if (overlaps(addr, P2SZ(count), area->base,
     332                            P2SZ(area->pages))) {
    337333                                mutex_unlock(&area->lock);
    338334                                return false;
     
    350346                        mutex_lock(&area->lock);
    351347                       
    352                         if (overlaps(addr, count << PAGE_WIDTH,
    353                             area->base, area->pages << PAGE_WIDTH)) {
     348                        if (overlaps(addr, P2SZ(count), area->base,
     349                            P2SZ(area->pages))) {
    354350                                mutex_unlock(&area->lock);
    355351                                return false;
     
    370366                mutex_lock(&area->lock);
    371367               
    372                 if (overlaps(addr, count << PAGE_WIDTH,
    373                     area->base, area->pages << PAGE_WIDTH)) {
     368                if (overlaps(addr, P2SZ(count), area->base,
     369                    P2SZ(area->pages))) {
    374370                        mutex_unlock(&area->lock);
    375371                        return false;
     
    384380         */
    385381        if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
    386                 return !overlaps(addr, count << PAGE_WIDTH,
    387                     KERNEL_ADDRESS_SPACE_START,
     382                return !overlaps(addr, P2SZ(count), KERNEL_ADDRESS_SPACE_START,
    388383                    KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START);
    389384        }
     
    448443                memsetb(&area->backend_data, sizeof(area->backend_data), 0);
    449444       
     445        if (area->backend && area->backend->create) {
     446                if (!area->backend->create(area)) {
     447                        free(area);
     448                        mutex_unlock(&as->lock);
     449                        return NULL;
     450                }
     451        }
     452       
    450453        btree_create(&area->used_space);
    451454        btree_insert(&as->as_area_btree, base, (void *) area, NULL);
     
    470473       
    471474        btree_node_t *leaf;
    472         as_area_t *area = (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
     475        as_area_t *area = (as_area_t *) btree_search(&as->as_area_btree, va,
     476            &leaf);
    473477        if (area) {
    474478                /* va is the base address of an address space area */
     
    478482       
    479483        /*
    480          * Search the leaf node and the righmost record of its left neighbour
     484         * Search the leaf node and the rightmost record of its left neighbour
    481485         * to find out whether this is a miss or va belongs to an address
    482486         * space area found there.
     
    490494               
    491495                mutex_lock(&area->lock);
    492                
     496
    493497                if ((area->base <= va) &&
    494                     (va < area->base + (area->pages << PAGE_WIDTH)))
     498                    (va <= area->base + (P2SZ(area->pages) - 1)))
    495499                        return area;
    496500               
     
    502506         * Because of its position in the B+tree, it must have base < va.
    503507         */
    504         btree_node_t *lnode = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);
     508        btree_node_t *lnode = btree_leaf_node_left_neighbour(&as->as_area_btree,
     509            leaf);
    505510        if (lnode) {
    506511                area = (as_area_t *) lnode->value[lnode->keys - 1];
     
    508513                mutex_lock(&area->lock);
    509514               
    510                 if (va < area->base + (area->pages << PAGE_WIDTH))
     515                if (va <= area->base + (P2SZ(area->pages) - 1))
    511516                        return area;
    512517               
     
    573578       
    574579        if (pages < area->pages) {
    575                 uintptr_t start_free = area->base + (pages << PAGE_WIDTH);
     580                uintptr_t start_free = area->base + P2SZ(pages);
    576581               
    577582                /*
     
    586591                 */
    587592                ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid,
    588                     area->base + (pages << PAGE_WIDTH), area->pages - pages);
     593                    area->base + P2SZ(pages), area->pages - pages);
    589594               
    590595                /*
     
    609614                                size_t i = 0;
    610615                               
    611                                 if (overlaps(ptr, size << PAGE_WIDTH, area->base,
    612                                     pages << PAGE_WIDTH)) {
     616                                if (overlaps(ptr, P2SZ(size), area->base,
     617                                    P2SZ(pages))) {
    613618                                       
    614                                         if (ptr + (size << PAGE_WIDTH) <= start_free) {
     619                                        if (ptr + P2SZ(size) <= start_free) {
    615620                                                /*
    616621                                                 * The whole interval fits
     
    643648                               
    644649                                for (; i < size; i++) {
    645                                         pte_t *pte = page_mapping_find(as, ptr +
    646                                             (i << PAGE_WIDTH));
     650                                        pte_t *pte = page_mapping_find(as,
     651                                            ptr + P2SZ(i), false);
    647652                                       
    648653                                        ASSERT(pte);
     
    653658                                            (area->backend->frame_free)) {
    654659                                                area->backend->frame_free(area,
    655                                                     ptr + (i << PAGE_WIDTH),
     660                                                    ptr + P2SZ(i),
    656661                                                    PTE_GET_FRAME(pte));
    657662                                        }
    658663                                       
    659                                         page_mapping_remove(as, ptr +
    660                                             (i << PAGE_WIDTH));
     664                                        page_mapping_remove(as, ptr + P2SZ(i));
    661665                                }
    662666                        }
     
    667671                 */
    668672               
    669                 tlb_invalidate_pages(as->asid, area->base + (pages << PAGE_WIDTH),
     673                tlb_invalidate_pages(as->asid, area->base + P2SZ(pages),
    670674                    area->pages - pages);
    671675               
    672676                /*
    673                  * Invalidate software translation caches (e.g. TSB on sparc64).
    674                  */
    675                 as_invalidate_translation_cache(as, area->base +
    676                     (pages << PAGE_WIDTH), area->pages - pages);
     677                 * Invalidate software translation caches
     678                 * (e.g. TSB on sparc64, PHT on ppc32).
     679                 */
     680                as_invalidate_translation_cache(as, area->base + P2SZ(pages),
     681                    area->pages - pages);
    677682                tlb_shootdown_finalize(ipl);
    678683               
     
    687692                        mutex_unlock(&as->lock);
    688693                        return EADDRNOTAVAIL;
     694                }
     695        }
     696       
     697        if (area->backend && area->backend->resize) {
     698                if (!area->backend->resize(area, pages)) {
     699                        mutex_unlock(&area->lock);
     700                        mutex_unlock(&as->lock);
     701                        return ENOMEM;
    689702                }
    690703        }
     
    756769                return ENOENT;
    757770        }
     771
     772        if (area->backend && area->backend->destroy)
     773                area->backend->destroy(area);
    758774       
    759775        uintptr_t base = area->base;
     
    782798                       
    783799                        for (size = 0; size < (size_t) node->value[i]; size++) {
    784                                 pte_t *pte =
    785                                     page_mapping_find(as, ptr + (size << PAGE_WIDTH));
     800                                pte_t *pte = page_mapping_find(as,
     801                                     ptr + P2SZ(size), false);
    786802                               
    787803                                ASSERT(pte);
     
    792808                                    (area->backend->frame_free)) {
    793809                                        area->backend->frame_free(area,
    794                                             ptr + (size << PAGE_WIDTH), PTE_GET_FRAME(pte));
     810                                            ptr + P2SZ(size),
     811                                            PTE_GET_FRAME(pte));
    795812                                }
    796813                               
    797                                 page_mapping_remove(as, ptr + (size << PAGE_WIDTH));
     814                                page_mapping_remove(as, ptr + P2SZ(size));
    798815                        }
    799816                }
     
    807824       
    808825        /*
    809          * Invalidate potential software translation caches (e.g. TSB on
    810          * sparc64).
     826         * Invalidate potential software translation caches
     827         * (e.g. TSB on sparc64, PHT on ppc32).
    811828         */
    812829        as_invalidate_translation_cache(as, area->base, area->pages);
     
    882899        }
    883900       
    884         size_t src_size = src_area->pages << PAGE_WIDTH;
     901        size_t src_size = P2SZ(src_area->pages);
    885902        unsigned int src_flags = src_area->flags;
    886903        mem_backend_t *src_backend = src_area->backend;
     
    10791096        for (cur = area->used_space.leaf_head.next;
    10801097            cur != &area->used_space.leaf_head; cur = cur->next) {
    1081                 btree_node_t *node
    1082                     = list_get_instance(cur, btree_node_t, leaf_link);
     1098                btree_node_t *node = list_get_instance(cur, btree_node_t,
     1099                    leaf_link);
    10831100                btree_key_t i;
    10841101               
     
    10881105                       
    10891106                        for (size = 0; size < (size_t) node->value[i]; size++) {
    1090                                 pte_t *pte =
    1091                                     page_mapping_find(as, ptr + (size << PAGE_WIDTH));
     1107                                pte_t *pte = page_mapping_find(as,
     1108                                    ptr + P2SZ(size), false);
    10921109                               
    10931110                                ASSERT(pte);
     
    10981115                               
    10991116                                /* Remove old mapping */
    1100                                 page_mapping_remove(as, ptr + (size << PAGE_WIDTH));
     1117                                page_mapping_remove(as, ptr + P2SZ(size));
    11011118                        }
    11021119                }
     
    11101127       
    11111128        /*
    1112          * Invalidate potential software translation caches (e.g. TSB on
    1113          * sparc64).
     1129         * Invalidate potential software translation caches
     1130         * (e.g. TSB on sparc64, PHT on ppc32).
    11141131         */
    11151132        as_invalidate_translation_cache(as, area->base, area->pages);
     
    11441161                               
    11451162                                /* Insert the new mapping */
    1146                                 page_mapping_insert(as, ptr + (size << PAGE_WIDTH),
     1163                                page_mapping_insert(as, ptr + P2SZ(size),
    11471164                                    old_frame[frame_idx++], page_flags);
    11481165                               
     
    12251242         */
    12261243        pte_t *pte;
    1227         if ((pte = page_mapping_find(AS, page))) {
     1244        if ((pte = page_mapping_find(AS, page, false))) {
    12281245                if (PTE_PRESENT(pte)) {
    12291246                        if (((access == PF_ACCESS_READ) && PTE_READABLE(pte)) ||
     
    14661483       
    14671484        if (src_area) {
    1468                 size = src_area->pages << PAGE_WIDTH;
     1485                size = P2SZ(src_area->pages);
    14691486                mutex_unlock(&src_area->lock);
    14701487        } else
     
    15211538                if (page >= right_pg) {
    15221539                        /* Do nothing. */
    1523                 } else if (overlaps(page, count << PAGE_WIDTH, left_pg,
    1524                     left_cnt << PAGE_WIDTH)) {
     1540                } else if (overlaps(page, P2SZ(count), left_pg,
     1541                    P2SZ(left_cnt))) {
    15251542                        /* The interval intersects with the left interval. */
    15261543                        return false;
    1527                 } else if (overlaps(page, count << PAGE_WIDTH, right_pg,
    1528                     right_cnt << PAGE_WIDTH)) {
     1544                } else if (overlaps(page, P2SZ(count), right_pg,
     1545                    P2SZ(right_cnt))) {
    15291546                        /* The interval intersects with the right interval. */
    15301547                        return false;
    1531                 } else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
    1532                     (page + (count << PAGE_WIDTH) == right_pg)) {
     1548                } else if ((page == left_pg + P2SZ(left_cnt)) &&
     1549                    (page + P2SZ(count) == right_pg)) {
    15331550                        /*
    15341551                         * The interval can be added by merging the two already
     
    15381555                        btree_remove(&area->used_space, right_pg, leaf);
    15391556                        goto success;
    1540                 } else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
     1557                } else if (page == left_pg + P2SZ(left_cnt)) {
    15411558                        /*
    15421559                         * The interval can be added by simply growing the left
     
    15451562                        node->value[node->keys - 1] += count;
    15461563                        goto success;
    1547                 } else if (page + (count << PAGE_WIDTH) == right_pg) {
     1564                } else if (page + P2SZ(count) == right_pg) {
    15481565                        /*
    15491566                         * The interval can be addded by simply moving base of
     
    15721589                 */
    15731590               
    1574                 if (overlaps(page, count << PAGE_WIDTH, right_pg,
    1575                     right_cnt << PAGE_WIDTH)) {
     1591                if (overlaps(page, P2SZ(count), right_pg, P2SZ(right_cnt))) {
    15761592                        /* The interval intersects with the right interval. */
    15771593                        return false;
    1578                 } else if (page + (count << PAGE_WIDTH) == right_pg) {
     1594                } else if (page + P2SZ(count) == right_pg) {
    15791595                        /*
    15801596                         * The interval can be added by moving the base of the
     
    16111627                if (page < left_pg) {
    16121628                        /* Do nothing. */
    1613                 } else if (overlaps(page, count << PAGE_WIDTH, left_pg,
    1614                     left_cnt << PAGE_WIDTH)) {
     1629                } else if (overlaps(page, P2SZ(count), left_pg,
     1630                    P2SZ(left_cnt))) {
    16151631                        /* The interval intersects with the left interval. */
    16161632                        return false;
    1617                 } else if (overlaps(page, count << PAGE_WIDTH, right_pg,
    1618                     right_cnt << PAGE_WIDTH)) {
     1633                } else if (overlaps(page, P2SZ(count), right_pg,
     1634                    P2SZ(right_cnt))) {
    16191635                        /* The interval intersects with the right interval. */
    16201636                        return false;
    1621                 } else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
    1622                     (page + (count << PAGE_WIDTH) == right_pg)) {
     1637                } else if ((page == left_pg + P2SZ(left_cnt)) &&
     1638                    (page + P2SZ(count) == right_pg)) {
    16231639                        /*
    16241640                         * The interval can be added by merging the two already
     
    16281644                        btree_remove(&area->used_space, right_pg, node);
    16291645                        goto success;
    1630                 } else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
     1646                } else if (page == left_pg + P2SZ(left_cnt)) {
    16311647                        /*
    16321648                         * The interval can be added by simply growing the left
     
    16351651                        leaf->value[leaf->keys - 1] += count;
    16361652                        goto success;
    1637                 } else if (page + (count << PAGE_WIDTH) == right_pg) {
     1653                } else if (page + P2SZ(count) == right_pg) {
    16381654                        /*
    16391655                         * The interval can be addded by simply moving base of
     
    16621678                 */
    16631679               
    1664                 if (overlaps(page, count << PAGE_WIDTH, left_pg,
    1665                     left_cnt << PAGE_WIDTH)) {
     1680                if (overlaps(page, P2SZ(count), left_pg, P2SZ(left_cnt))) {
    16661681                        /* The interval intersects with the left interval. */
    16671682                        return false;
    1668                 } else if (left_pg + (left_cnt << PAGE_WIDTH) == page) {
     1683                } else if (left_pg + P2SZ(left_cnt) == page) {
    16691684                        /*
    16701685                         * The interval can be added by growing the left
     
    17011716                         */
    17021717                       
    1703                         if (overlaps(page, count << PAGE_WIDTH, left_pg,
    1704                             left_cnt << PAGE_WIDTH)) {
     1718                        if (overlaps(page, P2SZ(count), left_pg,
     1719                            P2SZ(left_cnt))) {
    17051720                                /*
    17061721                                 * The interval intersects with the left
     
    17081723                                 */
    17091724                                return false;
    1710                         } else if (overlaps(page, count << PAGE_WIDTH, right_pg,
    1711                             right_cnt << PAGE_WIDTH)) {
     1725                        } else if (overlaps(page, P2SZ(count), right_pg,
     1726                            P2SZ(right_cnt))) {
    17121727                                /*
    17131728                                 * The interval intersects with the right
     
    17151730                                 */
    17161731                                return false;
    1717                         } else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
    1718                             (page + (count << PAGE_WIDTH) == right_pg)) {
     1732                        } else if ((page == left_pg + P2SZ(left_cnt)) &&
     1733                            (page + P2SZ(count) == right_pg)) {
    17191734                                /*
    17201735                                 * The interval can be added by merging the two
     
    17241739                                btree_remove(&area->used_space, right_pg, leaf);
    17251740                                goto success;
    1726                         } else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
     1741                        } else if (page == left_pg + P2SZ(left_cnt)) {
    17271742                                /*
    17281743                                 * The interval can be added by simply growing
     
    17311746                                leaf->value[i - 1] += count;
    17321747                                goto success;
    1733                         } else if (page + (count << PAGE_WIDTH) == right_pg) {
     1748                        } else if (page + P2SZ(count) == right_pg) {
    17341749                                /*
    17351750                                 * The interval can be addded by simply moving
     
    17971812                        for (i = 0; i < leaf->keys; i++) {
    17981813                                if (leaf->key[i] == page) {
    1799                                         leaf->key[i] += count << PAGE_WIDTH;
     1814                                        leaf->key[i] += P2SZ(count);
    18001815                                        leaf->value[i] -= count;
    18011816                                        goto success;
     
    18071822        }
    18081823       
    1809         btree_node_t *node = btree_leaf_node_left_neighbour(&area->used_space, leaf);
     1824        btree_node_t *node = btree_leaf_node_left_neighbour(&area->used_space,
     1825            leaf);
    18101826        if ((node) && (page < leaf->key[0])) {
    18111827                uintptr_t left_pg = node->key[node->keys - 1];
    18121828                size_t left_cnt = (size_t) node->value[node->keys - 1];
    18131829               
    1814                 if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
    1815                     count << PAGE_WIDTH)) {
    1816                         if (page + (count << PAGE_WIDTH) ==
    1817                             left_pg + (left_cnt << PAGE_WIDTH)) {
     1830                if (overlaps(left_pg, P2SZ(left_cnt), page, P2SZ(count))) {
     1831                        if (page + P2SZ(count) == left_pg + P2SZ(left_cnt)) {
    18181832                                /*
    18191833                                 * The interval is contained in the rightmost
     
    18241838                                node->value[node->keys - 1] -= count;
    18251839                                goto success;
    1826                         } else if (page + (count << PAGE_WIDTH) <
    1827                             left_pg + (left_cnt << PAGE_WIDTH)) {
     1840                        } else if (page + P2SZ(count) <
     1841                            left_pg + P2SZ(left_cnt)) {
     1842                                size_t new_cnt;
     1843
    18281844                                /*
    18291845                                 * The interval is contained in the rightmost
     
    18331849                                 * new interval.
    18341850                                 */
    1835                                 size_t new_cnt = ((left_pg + (left_cnt << PAGE_WIDTH)) -
    1836                                     (page + (count << PAGE_WIDTH))) >> PAGE_WIDTH;
     1851                                new_cnt = ((left_pg + P2SZ(left_cnt)) -
     1852                                    (page + P2SZ(count))) >> PAGE_WIDTH;
    18371853                                node->value[node->keys - 1] -= count + new_cnt;
    18381854                                btree_insert(&area->used_space, page +
    1839                                     (count << PAGE_WIDTH), (void *) new_cnt, leaf);
     1855                                    P2SZ(count), (void *) new_cnt, leaf);
    18401856                                goto success;
    18411857                        }
     
    18501866                size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
    18511867               
    1852                 if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
    1853                     count << PAGE_WIDTH)) {
    1854                         if (page + (count << PAGE_WIDTH) ==
    1855                             left_pg + (left_cnt << PAGE_WIDTH)) {
     1868                if (overlaps(left_pg, P2SZ(left_cnt), page, P2SZ(count))) {
     1869                        if (page + P2SZ(count) == left_pg + P2SZ(left_cnt)) {
    18561870                                /*
    18571871                                 * The interval is contained in the rightmost
     
    18611875                                leaf->value[leaf->keys - 1] -= count;
    18621876                                goto success;
    1863                         } else if (page + (count << PAGE_WIDTH) < left_pg +
    1864                             (left_cnt << PAGE_WIDTH)) {
     1877                        } else if (page + P2SZ(count) < left_pg +
     1878                            P2SZ(left_cnt)) {
     1879                                size_t new_cnt;
     1880
    18651881                                /*
    18661882                                 * The interval is contained in the rightmost
     
    18701886                                 * interval.
    18711887                                 */
    1872                                 size_t new_cnt = ((left_pg + (left_cnt << PAGE_WIDTH)) -
    1873                                     (page + (count << PAGE_WIDTH))) >> PAGE_WIDTH;
     1888                                new_cnt = ((left_pg + P2SZ(left_cnt)) -
     1889                                    (page + P2SZ(count))) >> PAGE_WIDTH;
    18741890                                leaf->value[leaf->keys - 1] -= count + new_cnt;
    18751891                                btree_insert(&area->used_space, page +
    1876                                     (count << PAGE_WIDTH), (void *) new_cnt, leaf);
     1892                                    P2SZ(count), (void *) new_cnt, leaf);
    18771893                                goto success;
    18781894                        }
     
    18961912                         * to (i - 1) and i.
    18971913                         */
    1898                         if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
    1899                             count << PAGE_WIDTH)) {
    1900                                 if (page + (count << PAGE_WIDTH) ==
    1901                                     left_pg + (left_cnt << PAGE_WIDTH)) {
     1914                        if (overlaps(left_pg, P2SZ(left_cnt), page,
     1915                            P2SZ(count))) {
     1916                                if (page + P2SZ(count) ==
     1917                                    left_pg + P2SZ(left_cnt)) {
    19021918                                        /*
    19031919                                         * The interval is contained in the
     
    19081924                                        leaf->value[i - 1] -= count;
    19091925                                        goto success;
    1910                                 } else if (page + (count << PAGE_WIDTH) <
    1911                                     left_pg + (left_cnt << PAGE_WIDTH)) {
     1926                                } else if (page + P2SZ(count) <
     1927                                    left_pg + P2SZ(left_cnt)) {
     1928                                        size_t new_cnt;
     1929
    19121930                                        /*
    19131931                                         * The interval is contained in the
     
    19171935                                         * also inserting a new interval.
    19181936                                         */
    1919                                         size_t new_cnt = ((left_pg +
    1920                                             (left_cnt << PAGE_WIDTH)) -
    1921                                             (page + (count << PAGE_WIDTH))) >>
     1937                                        new_cnt = ((left_pg + P2SZ(left_cnt)) -
     1938                                            (page + P2SZ(count))) >>
    19221939                                            PAGE_WIDTH;
    19231940                                        leaf->value[i - 1] -= count + new_cnt;
    19241941                                        btree_insert(&area->used_space, page +
    1925                                             (count << PAGE_WIDTH), (void *) new_cnt,
     1942                                            P2SZ(count), (void *) new_cnt,
    19261943                                            leaf);
    19271944                                        goto success;
     
    20192036                btree_key_t i;
    20202037                for (i = 0; (ret == 0) && (i < node->keys); i++) {
     2038                        uintptr_t addr;
     2039
    20212040                        as_area_t *area = (as_area_t *) node->value[i];
    20222041                       
    20232042                        mutex_lock(&area->lock);
    20242043                       
    2025                         uintptr_t addr =
    2026                             ALIGN_UP(area->base + (area->pages << PAGE_WIDTH),
     2044                        addr = ALIGN_UP(area->base + P2SZ(area->pages),
    20272045                            PAGE_SIZE);
    20282046                       
     
    20832101                       
    20842102                        info[area_idx].start_addr = area->base;
    2085                         info[area_idx].size = FRAMES2SIZE(area->pages);
     2103                        info[area_idx].size = P2SZ(area->pages);
    20862104                        info[area_idx].flags = area->flags;
    20872105                        ++area_idx;
     
    21212139                            " (%p - %p)\n", area, (void *) area->base,
    21222140                            area->pages, (void *) area->base,
    2123                             (void *) (area->base + FRAMES2SIZE(area->pages)));
     2141                            (void *) (area->base + P2SZ(area->pages)));
    21242142                        mutex_unlock(&area->lock);
    21252143                }
  • kernel/generic/src/mm/backend_anon.c

    r82582e4 rdf3c6f02  
    3939#include <mm/as.h>
    4040#include <mm/page.h>
     41#include <mm/reserve.h>
    4142#include <genarch/mm/page_pt.h>
    4243#include <genarch/mm/page_ht.h>
     
    4950#include <typedefs.h>
    5051#include <align.h>
     52#include <memstr.h>
    5153#include <arch.h>
    5254
    53 #ifdef CONFIG_VIRT_IDX_DCACHE
    54 #include <arch/mm/cache.h>
    55 #endif
    56 
    57 static int anon_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access);
    58 static void anon_frame_free(as_area_t *area, uintptr_t page, uintptr_t frame);
    59 static void anon_share(as_area_t *area);
     55static bool anon_create(as_area_t *);
     56static bool anon_resize(as_area_t *, size_t);
     57static void anon_share(as_area_t *);
     58static void anon_destroy(as_area_t *);
     59
     60static int anon_page_fault(as_area_t *, uintptr_t, pf_access_t);
     61static void anon_frame_free(as_area_t *, uintptr_t, uintptr_t);
    6062
    6163mem_backend_t anon_backend = {
     64        .create = anon_create,
     65        .resize = anon_resize,
     66        .share = anon_share,
     67        .destroy = anon_destroy,
     68
    6269        .page_fault = anon_page_fault,
    6370        .frame_free = anon_frame_free,
    64         .share = anon_share
    6571};
     72
     73bool anon_create(as_area_t *area)
     74{
     75        return reserve_try_alloc(area->pages);
     76}
     77
     78bool anon_resize(as_area_t *area, size_t new_pages)
     79{
     80        if (new_pages > area->pages)
     81                return reserve_try_alloc(new_pages - area->pages);
     82        else if (new_pages < area->pages)
     83                reserve_free(area->pages - new_pages);
     84
     85        return true;
     86}
     87
     88/** Share the anonymous address space area.
     89 *
     90 * Sharing of anonymous area is done by duplicating its entire mapping
     91 * to the pagemap. Page faults will primarily search for frames there.
     92 *
     93 * The address space and address space area must be already locked.
     94 *
     95 * @param area Address space area to be shared.
     96 */
     97void anon_share(as_area_t *area)
     98{
     99        link_t *cur;
     100
     101        ASSERT(mutex_locked(&area->as->lock));
     102        ASSERT(mutex_locked(&area->lock));
     103
     104        /*
     105         * Copy used portions of the area to sh_info's page map.
     106         */
     107        mutex_lock(&area->sh_info->lock);
     108        for (cur = area->used_space.leaf_head.next;
     109            cur != &area->used_space.leaf_head; cur = cur->next) {
     110                btree_node_t *node;
     111                unsigned int i;
     112               
     113                node = list_get_instance(cur, btree_node_t, leaf_link);
     114                for (i = 0; i < node->keys; i++) {
     115                        uintptr_t base = node->key[i];
     116                        size_t count = (size_t) node->value[i];
     117                        unsigned int j;
     118                       
     119                        for (j = 0; j < count; j++) {
     120                                pte_t *pte;
     121                       
     122                                page_table_lock(area->as, false);
     123                                pte = page_mapping_find(area->as,
     124                                    base + P2SZ(j), false);
     125                                ASSERT(pte && PTE_VALID(pte) &&
     126                                    PTE_PRESENT(pte));
     127                                btree_insert(&area->sh_info->pagemap,
     128                                    (base + P2SZ(j)) - area->base,
     129                                    (void *) PTE_GET_FRAME(pte), NULL);
     130                                page_table_unlock(area->as, false);
     131
     132                                pfn_t pfn = ADDR2PFN(PTE_GET_FRAME(pte));
     133                                frame_reference_add(pfn);
     134                        }
     135
     136                }
     137        }
     138        mutex_unlock(&area->sh_info->lock);
     139}
     140
     141void anon_destroy(as_area_t *area)
     142{
     143        reserve_free(area->pages);
     144}
     145
    66146
    67147/** Service a page fault in the anonymous memory address space area.
     
    115195                        }
    116196                        if (allocate) {
    117                                 frame = (uintptr_t) frame_alloc(ONE_FRAME, 0);
     197                                frame = (uintptr_t) frame_alloc_noreserve(
     198                                    ONE_FRAME, 0);
    118199                                memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
    119200                               
     
    145226                 *   the different causes
    146227                 */
    147                 frame = (uintptr_t) frame_alloc(ONE_FRAME, 0);
     228                frame = (uintptr_t) frame_alloc_noreserve(ONE_FRAME, 0);
    148229                memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
    149230        }
     
    174255        ASSERT(mutex_locked(&area->lock));
    175256
    176         frame_free(frame);
    177 }
    178 
    179 /** Share the anonymous address space area.
    180  *
    181  * Sharing of anonymous area is done by duplicating its entire mapping
    182  * to the pagemap. Page faults will primarily search for frames there.
    183  *
    184  * The address space and address space area must be already locked.
    185  *
    186  * @param area Address space area to be shared.
    187  */
    188 void anon_share(as_area_t *area)
    189 {
    190         link_t *cur;
    191 
    192         ASSERT(mutex_locked(&area->as->lock));
    193         ASSERT(mutex_locked(&area->lock));
    194 
    195         /*
    196          * Copy used portions of the area to sh_info's page map.
    197          */
    198         mutex_lock(&area->sh_info->lock);
    199         for (cur = area->used_space.leaf_head.next;
    200             cur != &area->used_space.leaf_head; cur = cur->next) {
    201                 btree_node_t *node;
    202                 unsigned int i;
    203                
    204                 node = list_get_instance(cur, btree_node_t, leaf_link);
    205                 for (i = 0; i < node->keys; i++) {
    206                         uintptr_t base = node->key[i];
    207                         size_t count = (size_t) node->value[i];
    208                         unsigned int j;
    209                        
    210                         for (j = 0; j < count; j++) {
    211                                 pte_t *pte;
    212                        
    213                                 page_table_lock(area->as, false);
    214                                 pte = page_mapping_find(area->as,
    215                                     base + j * PAGE_SIZE);
    216                                 ASSERT(pte && PTE_VALID(pte) &&
    217                                     PTE_PRESENT(pte));
    218                                 btree_insert(&area->sh_info->pagemap,
    219                                     (base + j * PAGE_SIZE) - area->base,
    220                                     (void *) PTE_GET_FRAME(pte), NULL);
    221                                 page_table_unlock(area->as, false);
    222 
    223                                 pfn_t pfn = ADDR2PFN(PTE_GET_FRAME(pte));
    224                                 frame_reference_add(pfn);
    225                         }
    226 
    227                 }
    228         }
    229         mutex_unlock(&area->sh_info->lock);
     257        frame_free_noreserve(frame);
    230258}
    231259
  • kernel/generic/src/mm/backend_elf.c

    r82582e4 rdf3c6f02  
    4343#include <mm/slab.h>
    4444#include <mm/page.h>
     45#include <mm/reserve.h>
    4546#include <genarch/mm/page_pt.h>
    4647#include <genarch/mm/page_ht.h>
     
    5152#include <arch/barrier.h>
    5253
    53 #ifdef CONFIG_VIRT_IDX_DCACHE
    54 #include <arch/mm/cache.h>
    55 #endif
    56 
    57 static int elf_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access);
    58 static void elf_frame_free(as_area_t *area, uintptr_t page, uintptr_t frame);
    59 static void elf_share(as_area_t *area);
     54static bool elf_create(as_area_t *);
     55static bool elf_resize(as_area_t *, size_t);
     56static void elf_share(as_area_t *);
     57static void elf_destroy(as_area_t *);
     58
     59static int elf_page_fault(as_area_t *, uintptr_t, pf_access_t);
     60static void elf_frame_free(as_area_t *, uintptr_t, uintptr_t);
    6061
    6162mem_backend_t elf_backend = {
     63        .create = elf_create,
     64        .resize = elf_resize,
     65        .share = elf_share,
     66        .destroy = elf_destroy,
     67
    6268        .page_fault = elf_page_fault,
    6369        .frame_free = elf_frame_free,
    64         .share = elf_share
    6570};
    6671
    67 /** Service a page fault in the ELF backend address space area.
    68  *
    69  * The address space area and page tables must be already locked.
    70  *
    71  * @param area          Pointer to the address space area.
    72  * @param addr          Faulting virtual address.
    73  * @param access        Access mode that caused the fault (i.e.
    74  *                      read/write/exec).
    75  *
    76  * @return              AS_PF_FAULT on failure (i.e. page fault) or AS_PF_OK
    77  *                      on success (i.e. serviced).
    78  */
    79 int elf_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access)
    80 {
    81         elf_header_t *elf = area->backend_data.elf;
     72static size_t elf_nonanon_pages_get(as_area_t *area)
     73{
    8274        elf_segment_header_t *entry = area->backend_data.segment;
    83         btree_node_t *leaf;
    84         uintptr_t base, frame, page, start_anon;
    85         size_t i;
    86         bool dirty = false;
    87 
    88         ASSERT(page_table_locked(AS));
    89         ASSERT(mutex_locked(&area->lock));
    90 
    91         if (!as_area_check_access(area, access))
    92                 return AS_PF_FAULT;
     75        uintptr_t first = ALIGN_UP(entry->p_vaddr, PAGE_SIZE);
     76        uintptr_t last = ALIGN_DOWN(entry->p_vaddr + entry->p_filesz,
     77            PAGE_SIZE);
     78
     79        if (entry->p_flags & PF_W)
     80                return 0;
     81
     82        if (last < first)
     83                return 0;
     84
     85        return last - first;
     86}
     87
     88bool elf_create(as_area_t *area)
     89{
     90        size_t nonanon_pages = elf_nonanon_pages_get(area);
     91
     92        if (area->pages <= nonanon_pages)
     93                return true;
    9394       
    94         if (addr < ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE))
    95                 return AS_PF_FAULT;
     95        return reserve_try_alloc(area->pages - nonanon_pages);
     96}
     97
     98bool elf_resize(as_area_t *area, size_t new_pages)
     99{
     100        size_t nonanon_pages = elf_nonanon_pages_get(area);
     101
     102        if (new_pages > area->pages) {
     103                /* The area is growing. */
     104                if (area->pages >= nonanon_pages)
     105                        return reserve_try_alloc(new_pages - area->pages);
     106                else if (new_pages > nonanon_pages)
     107                        return reserve_try_alloc(new_pages - nonanon_pages);
     108        } else if (new_pages < area->pages) {
     109                /* The area is shrinking. */
     110                if (new_pages >= nonanon_pages)
     111                        reserve_free(area->pages - new_pages);
     112                else if (area->pages > nonanon_pages)
     113                        reserve_free(nonanon_pages - new_pages);
     114        }
    96115       
    97         if (addr >= entry->p_vaddr + entry->p_memsz)
    98                 return AS_PF_FAULT;
    99        
    100         i = (addr - ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE)) >> PAGE_WIDTH;
    101         base = (uintptr_t)
    102             (((void *) elf) + ALIGN_DOWN(entry->p_offset, PAGE_SIZE));
    103 
    104         /* Virtual address of faulting page*/
    105         page = ALIGN_DOWN(addr, PAGE_SIZE);
    106 
    107         /* Virtual address of the end of initialized part of segment */
    108         start_anon = entry->p_vaddr + entry->p_filesz;
    109 
    110         if (area->sh_info) {
    111                 bool found = false;
    112 
    113                 /*
    114                  * The address space area is shared.
    115                  */
    116                
    117                 mutex_lock(&area->sh_info->lock);
    118                 frame = (uintptr_t) btree_search(&area->sh_info->pagemap,
    119                     page - area->base, &leaf);
    120                 if (!frame) {
    121                         unsigned int i;
    122 
    123                         /*
    124                          * Workaround for valid NULL address.
    125                          */
    126 
    127                         for (i = 0; i < leaf->keys; i++) {
    128                                 if (leaf->key[i] == page - area->base) {
    129                                         found = true;
    130                                         break;
    131                                 }
    132                         }
    133                 }
    134                 if (frame || found) {
    135                         frame_reference_add(ADDR2PFN(frame));
    136                         page_mapping_insert(AS, addr, frame,
    137                             as_area_get_flags(area));
    138                         if (!used_space_insert(area, page, 1))
    139                                 panic("Cannot insert used space.");
    140                         mutex_unlock(&area->sh_info->lock);
    141                         return AS_PF_OK;
    142                 }
    143         }
    144 
    145         /*
    146          * The area is either not shared or the pagemap does not contain the
    147          * mapping.
    148          */
    149         if (page >= entry->p_vaddr && page + PAGE_SIZE <= start_anon) {
    150                 /*
    151                  * Initialized portion of the segment. The memory is backed
    152                  * directly by the content of the ELF image. Pages are
    153                  * only copied if the segment is writable so that there
    154                  * can be more instantions of the same memory ELF image
    155                  * used at a time. Note that this could be later done
    156                  * as COW.
    157                  */
    158                 if (entry->p_flags & PF_W) {
    159                         frame = (uintptr_t)frame_alloc(ONE_FRAME, 0);
    160                         memcpy((void *) PA2KA(frame),
    161                             (void *) (base + i * FRAME_SIZE), FRAME_SIZE);
    162                         if (entry->p_flags & PF_X) {
    163                                 smc_coherence_block((void *) PA2KA(frame),
    164                                     FRAME_SIZE);
    165                         }
    166                         dirty = true;
    167                 } else {
    168                         frame = KA2PA(base + i * FRAME_SIZE);
    169                 }       
    170         } else if (page >= start_anon) {
    171                 /*
    172                  * This is the uninitialized portion of the segment.
    173                  * It is not physically present in the ELF image.
    174                  * To resolve the situation, a frame must be allocated
    175                  * and cleared.
    176                  */
    177                 frame = (uintptr_t)frame_alloc(ONE_FRAME, 0);
    178                 memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
    179                 dirty = true;
    180         } else {
    181                 size_t pad_lo, pad_hi;
    182                 /*
    183                  * The mixed case.
    184                  *
    185                  * The middle part is backed by the ELF image and
    186                  * the lower and upper parts are anonymous memory.
    187                  * (The segment can be and often is shorter than 1 page).
    188                  */
    189                 if (page < entry->p_vaddr)
    190                         pad_lo = entry->p_vaddr - page;
    191                 else
    192                         pad_lo = 0;
    193 
    194                 if (start_anon < page + PAGE_SIZE)
    195                         pad_hi = page + PAGE_SIZE - start_anon;
    196                 else
    197                         pad_hi = 0;
    198 
    199                 frame = (uintptr_t)frame_alloc(ONE_FRAME, 0);
    200                 memcpy((void *) (PA2KA(frame) + pad_lo),
    201                     (void *) (base + i * FRAME_SIZE + pad_lo),
    202                     FRAME_SIZE - pad_lo - pad_hi);
    203                 if (entry->p_flags & PF_X) {
    204                         smc_coherence_block((void *) (PA2KA(frame) + pad_lo),
    205                             FRAME_SIZE - pad_lo - pad_hi);
    206                 }
    207                 memsetb((void *) PA2KA(frame), pad_lo, 0);
    208                 memsetb((void *) (PA2KA(frame) + FRAME_SIZE - pad_hi), pad_hi,
    209                     0);
    210                 dirty = true;
    211         }
    212 
    213         if (dirty && area->sh_info) {
    214                 frame_reference_add(ADDR2PFN(frame));
    215                 btree_insert(&area->sh_info->pagemap, page - area->base,
    216                     (void *) frame, leaf);
    217         }
    218 
    219         if (area->sh_info)
    220                 mutex_unlock(&area->sh_info->lock);
    221 
    222         page_mapping_insert(AS, addr, frame, as_area_get_flags(area));
    223         if (!used_space_insert(area, page, 1))
    224                 panic("Cannot insert used space.");
    225 
    226         return AS_PF_OK;
    227 }
    228 
    229 /** Free a frame that is backed by the ELF backend.
    230  *
    231  * The address space area and page tables must be already locked.
    232  *
    233  * @param area          Pointer to the address space area.
    234  * @param page          Page that is mapped to frame. Must be aligned to
    235  *                      PAGE_SIZE.
    236  * @param frame         Frame to be released.
    237  *
    238  */
    239 void elf_frame_free(as_area_t *area, uintptr_t page, uintptr_t frame)
    240 {
    241         elf_segment_header_t *entry = area->backend_data.segment;
    242         uintptr_t start_anon;
    243 
    244         ASSERT(page_table_locked(area->as));
    245         ASSERT(mutex_locked(&area->lock));
    246 
    247         ASSERT(page >= ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE));
    248         ASSERT(page < entry->p_vaddr + entry->p_memsz);
    249 
    250         start_anon = entry->p_vaddr + entry->p_filesz;
    251 
    252         if (page >= entry->p_vaddr && page + PAGE_SIZE <= start_anon) {
    253                 if (entry->p_flags & PF_W) {
    254                         /*
    255                          * Free the frame with the copy of writable segment
    256                          * data.
    257                          */
    258                         frame_free(frame);
    259                 }
    260         } else {
    261                 /*
    262                  * The frame is either anonymous memory or the mixed case (i.e.
    263                  * lower part is backed by the ELF image and the upper is
    264                  * anonymous). In any case, a frame needs to be freed.
    265                  */
    266                 frame_free(frame);
    267         }
     116        return true;
    268117}
    269118
     
    321170                        if (!(area->flags & AS_AREA_WRITE))
    322171                                if (base >= entry->p_vaddr &&
    323                                     base + count * PAGE_SIZE <= start_anon)
     172                                    base + P2SZ(count) <= start_anon)
    324173                                        continue;
    325174                       
     
    333182                                if (!(area->flags & AS_AREA_WRITE))
    334183                                        if (base >= entry->p_vaddr &&
    335                                             base + (j + 1) * PAGE_SIZE <=
    336                                             start_anon)
     184                                            base + P2SZ(j + 1) <= start_anon)
    337185                                                continue;
    338186                               
    339187                                page_table_lock(area->as, false);
    340188                                pte = page_mapping_find(area->as,
    341                                     base + j * PAGE_SIZE);
     189                                    base + P2SZ(j), false);
    342190                                ASSERT(pte && PTE_VALID(pte) &&
    343191                                    PTE_PRESENT(pte));
    344192                                btree_insert(&area->sh_info->pagemap,
    345                                     (base + j * PAGE_SIZE) - area->base,
     193                                    (base + P2SZ(j)) - area->base,
    346194                                    (void *) PTE_GET_FRAME(pte), NULL);
    347195                                page_table_unlock(area->as, false);
     
    356204}
    357205
     206void elf_destroy(as_area_t *area)
     207{
     208        size_t nonanon_pages = elf_nonanon_pages_get(area);
     209
     210        if (area->pages > nonanon_pages)
     211                reserve_free(area->pages - nonanon_pages);
     212}
     213
     214/** Service a page fault in the ELF backend address space area.
     215 *
     216 * The address space area and page tables must be already locked.
     217 *
     218 * @param area          Pointer to the address space area.
     219 * @param addr          Faulting virtual address.
     220 * @param access        Access mode that caused the fault (i.e.
     221 *                      read/write/exec).
     222 *
     223 * @return              AS_PF_FAULT on failure (i.e. page fault) or AS_PF_OK
     224 *                      on success (i.e. serviced).
     225 */
     226int elf_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access)
     227{
     228        elf_header_t *elf = area->backend_data.elf;
     229        elf_segment_header_t *entry = area->backend_data.segment;
     230        btree_node_t *leaf;
     231        uintptr_t base, frame, page, start_anon;
     232        size_t i;
     233        bool dirty = false;
     234
     235        ASSERT(page_table_locked(AS));
     236        ASSERT(mutex_locked(&area->lock));
     237
     238        if (!as_area_check_access(area, access))
     239                return AS_PF_FAULT;
     240       
     241        if (addr < ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE))
     242                return AS_PF_FAULT;
     243       
     244        if (addr >= entry->p_vaddr + entry->p_memsz)
     245                return AS_PF_FAULT;
     246       
     247        i = (addr - ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE)) >> PAGE_WIDTH;
     248        base = (uintptr_t)
     249            (((void *) elf) + ALIGN_DOWN(entry->p_offset, PAGE_SIZE));
     250
     251        /* Virtual address of faulting page*/
     252        page = ALIGN_DOWN(addr, PAGE_SIZE);
     253
     254        /* Virtual address of the end of initialized part of segment */
     255        start_anon = entry->p_vaddr + entry->p_filesz;
     256
     257        if (area->sh_info) {
     258                bool found = false;
     259
     260                /*
     261                 * The address space area is shared.
     262                 */
     263               
     264                mutex_lock(&area->sh_info->lock);
     265                frame = (uintptr_t) btree_search(&area->sh_info->pagemap,
     266                    page - area->base, &leaf);
     267                if (!frame) {
     268                        unsigned int i;
     269
     270                        /*
     271                         * Workaround for valid NULL address.
     272                         */
     273
     274                        for (i = 0; i < leaf->keys; i++) {
     275                                if (leaf->key[i] == page - area->base) {
     276                                        found = true;
     277                                        break;
     278                                }
     279                        }
     280                }
     281                if (frame || found) {
     282                        frame_reference_add(ADDR2PFN(frame));
     283                        page_mapping_insert(AS, addr, frame,
     284                            as_area_get_flags(area));
     285                        if (!used_space_insert(area, page, 1))
     286                                panic("Cannot insert used space.");
     287                        mutex_unlock(&area->sh_info->lock);
     288                        return AS_PF_OK;
     289                }
     290        }
     291
     292        /*
     293         * The area is either not shared or the pagemap does not contain the
     294         * mapping.
     295         */
     296        if (page >= entry->p_vaddr && page + PAGE_SIZE <= start_anon) {
     297                /*
     298                 * Initialized portion of the segment. The memory is backed
     299                 * directly by the content of the ELF image. Pages are
     300                 * only copied if the segment is writable so that there
     301                 * can be more instantions of the same memory ELF image
     302                 * used at a time. Note that this could be later done
     303                 * as COW.
     304                 */
     305                if (entry->p_flags & PF_W) {
     306                        frame = (uintptr_t)frame_alloc_noreserve(ONE_FRAME, 0);
     307                        memcpy((void *) PA2KA(frame),
     308                            (void *) (base + i * FRAME_SIZE), FRAME_SIZE);
     309                        if (entry->p_flags & PF_X) {
     310                                smc_coherence_block((void *) PA2KA(frame),
     311                                    FRAME_SIZE);
     312                        }
     313                        dirty = true;
     314                } else {
     315                        frame = KA2PA(base + i * FRAME_SIZE);
     316                }       
     317        } else if (page >= start_anon) {
     318                /*
     319                 * This is the uninitialized portion of the segment.
     320                 * It is not physically present in the ELF image.
     321                 * To resolve the situation, a frame must be allocated
     322                 * and cleared.
     323                 */
     324                frame = (uintptr_t) frame_alloc_noreserve(ONE_FRAME, 0);
     325                memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
     326                dirty = true;
     327        } else {
     328                size_t pad_lo, pad_hi;
     329                /*
     330                 * The mixed case.
     331                 *
     332                 * The middle part is backed by the ELF image and
     333                 * the lower and upper parts are anonymous memory.
     334                 * (The segment can be and often is shorter than 1 page).
     335                 */
     336                if (page < entry->p_vaddr)
     337                        pad_lo = entry->p_vaddr - page;
     338                else
     339                        pad_lo = 0;
     340
     341                if (start_anon < page + PAGE_SIZE)
     342                        pad_hi = page + PAGE_SIZE - start_anon;
     343                else
     344                        pad_hi = 0;
     345
     346                frame = (uintptr_t) frame_alloc_noreserve(ONE_FRAME, 0);
     347                memcpy((void *) (PA2KA(frame) + pad_lo),
     348                    (void *) (base + i * FRAME_SIZE + pad_lo),
     349                    FRAME_SIZE - pad_lo - pad_hi);
     350                if (entry->p_flags & PF_X) {
     351                        smc_coherence_block((void *) (PA2KA(frame) + pad_lo),
     352                            FRAME_SIZE - pad_lo - pad_hi);
     353                }
     354                memsetb((void *) PA2KA(frame), pad_lo, 0);
     355                memsetb((void *) (PA2KA(frame) + FRAME_SIZE - pad_hi), pad_hi,
     356                    0);
     357                dirty = true;
     358        }
     359
     360        if (dirty && area->sh_info) {
     361                frame_reference_add(ADDR2PFN(frame));
     362                btree_insert(&area->sh_info->pagemap, page - area->base,
     363                    (void *) frame, leaf);
     364        }
     365
     366        if (area->sh_info)
     367                mutex_unlock(&area->sh_info->lock);
     368
     369        page_mapping_insert(AS, addr, frame, as_area_get_flags(area));
     370        if (!used_space_insert(area, page, 1))
     371                panic("Cannot insert used space.");
     372
     373        return AS_PF_OK;
     374}
     375
     376/** Free a frame that is backed by the ELF backend.
     377 *
     378 * The address space area and page tables must be already locked.
     379 *
     380 * @param area          Pointer to the address space area.
     381 * @param page          Page that is mapped to frame. Must be aligned to
     382 *                      PAGE_SIZE.
     383 * @param frame         Frame to be released.
     384 *
     385 */
     386void elf_frame_free(as_area_t *area, uintptr_t page, uintptr_t frame)
     387{
     388        elf_segment_header_t *entry = area->backend_data.segment;
     389        uintptr_t start_anon;
     390
     391        ASSERT(page_table_locked(area->as));
     392        ASSERT(mutex_locked(&area->lock));
     393
     394        ASSERT(page >= ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE));
     395        ASSERT(page < entry->p_vaddr + entry->p_memsz);
     396
     397        start_anon = entry->p_vaddr + entry->p_filesz;
     398
     399        if (page >= entry->p_vaddr && page + PAGE_SIZE <= start_anon) {
     400                if (entry->p_flags & PF_W) {
     401                        /*
     402                         * Free the frame with the copy of writable segment
     403                         * data.
     404                         */
     405                        frame_free_noreserve(frame);
     406                }
     407        } else {
     408                /*
     409                 * The frame is either anonymous memory or the mixed case (i.e.
     410                 * lower part is backed by the ELF image and the upper is
     411                 * anonymous). In any case, a frame needs to be freed.
     412                 */
     413                frame_free_noreserve(frame);
     414        }
     415}
     416
    358417/** @}
    359418 */
  • kernel/generic/src/mm/backend_phys.c

    r82582e4 rdf3c6f02  
    4848#include <align.h>
    4949
    50 static int phys_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access);
    51 static void phys_share(as_area_t *area);
     50static bool phys_create(as_area_t *);
     51static void phys_share(as_area_t *);
     52static void phys_destroy(as_area_t *);
     53
     54static int phys_page_fault(as_area_t *, uintptr_t, pf_access_t);
    5255
    5356mem_backend_t phys_backend = {
     57        .create = phys_create,
     58        .resize = NULL,
     59        .share = phys_share,
     60        .destroy = phys_destroy,
     61
    5462        .page_fault = phys_page_fault,
    5563        .frame_free = NULL,
    56         .share = phys_share
    5764};
     65
     66bool phys_create(as_area_t *area)
     67{
     68        return true;
     69}
     70
     71/** Share address space area backed by physical memory.
     72 *
     73 * Do actually nothing as sharing of address space areas
     74 * that are backed up by physical memory is very easy.
     75 * Note that the function must be defined so that
     76 * as_area_share() will succeed.
     77 */
     78void phys_share(as_area_t *area)
     79{
     80        ASSERT(mutex_locked(&area->as->lock));
     81        ASSERT(mutex_locked(&area->lock));
     82}
     83
     84
     85void phys_destroy(as_area_t *area)
     86{
     87        /* Nothing to do. */
     88}
    5889
    5990/** Service a page fault in the address space area backed by physical memory.
     
    88119}
    89120
    90 /** Share address space area backed by physical memory.
    91  *
    92  * Do actually nothing as sharing of address space areas
    93  * that are backed up by physical memory is very easy.
    94  * Note that the function must be defined so that
    95  * as_area_share() will succeed.
    96  */
    97 void phys_share(as_area_t *area)
    98 {
    99         ASSERT(mutex_locked(&area->as->lock));
    100         ASSERT(mutex_locked(&area->lock));
    101 }
    102 
    103121/** @}
    104122 */
  • kernel/generic/src/mm/frame.c

    r82582e4 rdf3c6f02  
    4545#include <typedefs.h>
    4646#include <mm/frame.h>
     47#include <mm/reserve.h>
    4748#include <mm/as.h>
    4849#include <panic.h>
     
    5960#include <macros.h>
    6061#include <config.h>
     62#include <str.h>
    6163
    6264zones_t zones;
     
    180182 *
    181183 */
    182 #ifdef CONFIG_DEBUG
    183 NO_TRACE static size_t total_frames_free(void)
     184NO_TRACE static size_t frame_total_free_get_internal(void)
    184185{
    185186        size_t total = 0;
    186187        size_t i;
     188
    187189        for (i = 0; i < zones.count; i++)
    188190                total += zones.info[i].free_count;
     
    190192        return total;
    191193}
    192 #endif /* CONFIG_DEBUG */
     194
     195NO_TRACE size_t frame_total_free_get(void)
     196{
     197        size_t total;
     198
     199        irq_spinlock_lock(&zones.lock, true);
     200        total = frame_total_free_get_internal();
     201        irq_spinlock_unlock(&zones.lock, true);
     202
     203        return total;
     204}
     205
    193206
    194207/** Find a zone with a given frames.
     
    472485 * @param frame_idx Frame index relative to zone.
    473486 *
    474  */
    475 NO_TRACE static void zone_frame_free(zone_t *zone, size_t frame_idx)
     487 * @return          Number of freed frames.
     488 *
     489 */
     490NO_TRACE static size_t zone_frame_free(zone_t *zone, size_t frame_idx)
    476491{
    477492        ASSERT(zone_flags_available(zone->flags));
    478493       
    479494        frame_t *frame = &zone->frames[frame_idx];
    480        
    481         /* Remember frame order */
    482         uint8_t order = frame->buddy_order;
     495        size_t size = 0;
    483496       
    484497        ASSERT(frame->refcount);
    485498       
    486499        if (!--frame->refcount) {
    487                 buddy_system_free(zone->buddy_system, &frame->buddy_link);
    488                
     500                size = 1 << frame->buddy_order;
     501                buddy_system_free(zone->buddy_system, &frame->buddy_link);             
    489502                /* Update zone information. */
    490                 zone->free_count += (1 << order);
    491                 zone->busy_count -= (1 << order);
    492         }
     503                zone->free_count += size;
     504                zone->busy_count -= size;
     505        }
     506       
     507        return size;
    493508}
    494509
     
    516531        ASSERT(link);
    517532        zone->free_count--;
     533        reserve_force_alloc(1);
    518534}
    519535
     
    645661        for (i = 0; i < cframes; i++) {
    646662                zones.info[znum].busy_count++;
    647                 zone_frame_free(&zones.info[znum],
     663                (void) zone_frame_free(&zones.info[znum],
    648664                    pfn - zones.info[znum].base + i);
    649665        }
     
    683699        /* Free unneeded frames */
    684700        for (i = count; i < (size_t) (1 << order); i++)
    685                 zone_frame_free(&zones.info[znum], i + frame_idx);
     701                (void) zone_frame_free(&zones.info[znum], i + frame_idx);
    686702}
    687703
     
    695711 * not to be 2^order size. Once the allocator is running it is no longer
    696712 * possible, merged configuration data occupies more space :-/
    697  *
    698  * The function uses
    699713 *
    700714 */
     
    9991013        size_t hint = pzone ? (*pzone) : 0;
    10001014       
     1015        /*
     1016         * If not told otherwise, we must first reserve the memory.
     1017         */
     1018        if (!(flags & FRAME_NO_RESERVE))
     1019                reserve_force_alloc(size);
     1020
    10011021loop:
    10021022        irq_spinlock_lock(&zones.lock, true);
     
    10331053                if (flags & FRAME_ATOMIC) {
    10341054                        irq_spinlock_unlock(&zones.lock, true);
     1055                        if (!(flags & FRAME_NO_RESERVE))
     1056                                reserve_free(size);
    10351057                        return NULL;
    10361058                }
    10371059               
    10381060#ifdef CONFIG_DEBUG
    1039                 size_t avail = total_frames_free();
     1061                size_t avail = frame_total_free_get_internal();
    10401062#endif
    10411063               
     
    10881110}
    10891111
     1112void *frame_alloc(uint8_t order, frame_flags_t flags)
     1113{
     1114        return frame_alloc_generic(order, flags, NULL);
     1115}
     1116
     1117void *frame_alloc_noreserve(uint8_t order, frame_flags_t flags)
     1118{
     1119        return frame_alloc_generic(order, flags | FRAME_NO_RESERVE, NULL);
     1120}
     1121
    10901122/** Free a frame.
    10911123 *
     
    10951127 *
    10961128 * @param frame Physical Address of of the frame to be freed.
    1097  *
    1098  */
    1099 void frame_free(uintptr_t frame)
    1100 {
     1129 * @param flags Flags to control memory reservation.
     1130 *
     1131 */
     1132void frame_free_generic(uintptr_t frame, frame_flags_t flags)
     1133{
     1134        size_t size;
     1135       
    11011136        irq_spinlock_lock(&zones.lock, true);
    11021137       
     
    11061141        pfn_t pfn = ADDR2PFN(frame);
    11071142        size_t znum = find_zone(pfn, 1, 0);
     1143
    11081144       
    11091145        ASSERT(znum != (size_t) -1);
    11101146       
    1111         zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base);
     1147        size = zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base);
    11121148       
    11131149        irq_spinlock_unlock(&zones.lock, true);
     
    11181154        mutex_lock(&mem_avail_mtx);
    11191155        if (mem_avail_req > 0)
    1120                 mem_avail_req--;
     1156                mem_avail_req -= min(mem_avail_req, size);
    11211157       
    11221158        if (mem_avail_req == 0) {
     
    11251161        }
    11261162        mutex_unlock(&mem_avail_mtx);
     1163       
     1164        if (!(flags & FRAME_NO_RESERVE))
     1165                reserve_free(size);
     1166}
     1167
     1168void frame_free(uintptr_t frame)
     1169{
     1170        frame_free_generic(frame, 0);
     1171}
     1172
     1173void frame_free_noreserve(uintptr_t frame)
     1174{
     1175        frame_free_generic(frame, FRAME_NO_RESERVE);
    11271176}
    11281177
     
    13551404        bool available = zone_flags_available(flags);
    13561405       
     1406        uint64_t size;
     1407        const char *size_suffix;
     1408        bin_order_suffix(FRAMES2SIZE(count), &size, &size_suffix, false);
     1409       
    13571410        printf("Zone number:       %zu\n", znum);
    13581411        printf("Zone base address: %p\n", (void *) base);
    1359         printf("Zone size:         %zu frames (%zu KiB)\n", count,
    1360             SIZE2KB(FRAMES2SIZE(count)));
     1412        printf("Zone size:         %zu frames (%" PRIu64 " %s)\n", count,
     1413            size, size_suffix);
    13611414        printf("Zone flags:        %c%c%c\n",
    13621415            available ? 'A' : ' ',
     
    13651418       
    13661419        if (available) {
    1367                 printf("Allocated space:   %zu frames (%zu KiB)\n",
    1368                     busy_count, SIZE2KB(FRAMES2SIZE(busy_count)));
    1369                 printf("Available space:   %zu frames (%zu KiB)\n",
    1370                     free_count, SIZE2KB(FRAMES2SIZE(free_count)));
     1420                bin_order_suffix(FRAMES2SIZE(busy_count), &size, &size_suffix,
     1421                    false);
     1422                printf("Allocated space:   %zu frames (%" PRIu64 " %s)\n",
     1423                    busy_count, size, size_suffix);
     1424                bin_order_suffix(FRAMES2SIZE(free_count), &size, &size_suffix,
     1425                    false);
     1426                printf("Available space:   %zu frames (%" PRIu64 " %s)\n",
     1427                    free_count, size, size_suffix);
    13711428        }
    13721429}
  • kernel/generic/src/mm/page.c

    r82582e4 rdf3c6f02  
    108108 * using flags. Allocate and setup any missing page tables.
    109109 *
    110  * @param as    Address space to wich page belongs.
     110 * @param as    Address space to which page belongs.
    111111 * @param page  Virtual address of the page to be mapped.
    112112 * @param frame Physical address of memory frame to which the mapping is
     
    135135 * this call visible.
    136136 *
    137  * @param as   Address space to wich page belongs.
     137 * @param as   Address space to which page belongs.
    138138 * @param page Virtual address of the page to be demapped.
    139139 *
     
    152152}
    153153
    154 /** Find mapping for virtual page
     154/** Find mapping for virtual page.
    155155 *
    156  * Find mapping for virtual page.
    157  *
    158  * @param as   Address space to wich page belongs.
    159  * @param page Virtual page.
     156 * @param as     Address space to which page belongs.
     157 * @param page   Virtual page.
     158 * @param nolock True if the page tables need not be locked.
    160159 *
    161160 * @return NULL if there is no such mapping; requested mapping
     
    163162 *
    164163 */
    165 NO_TRACE pte_t *page_mapping_find(as_t *as, uintptr_t page)
     164NO_TRACE pte_t *page_mapping_find(as_t *as, uintptr_t page, bool nolock)
    166165{
    167         ASSERT(page_table_locked(as));
     166        ASSERT(nolock || page_table_locked(as));
    168167       
    169168        ASSERT(page_mapping_operations);
    170169        ASSERT(page_mapping_operations->mapping_find);
    171170       
    172         return page_mapping_operations->mapping_find(as, page);
     171        return page_mapping_operations->mapping_find(as, page, nolock);
    173172}
    174173
Note: See TracChangeset for help on using the changeset viewer.