Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/genarch/src/mm/page_pt.c

    r235e6c7 rcaed0279  
    3939#include <mm/page.h>
    4040#include <mm/frame.h>
     41#include <mm/km.h>
    4142#include <mm/as.h>
    4243#include <arch/mm/page.h>
     
    4546#include <arch/asm.h>
    4647#include <memstr.h>
     48#include <align.h>
     49#include <macros.h>
     50#include <bitops.h>
    4751
    4852static void pt_mapping_insert(as_t *, uintptr_t, uintptr_t, unsigned int);
    4953static void pt_mapping_remove(as_t *, uintptr_t);
    5054static pte_t *pt_mapping_find(as_t *, uintptr_t, bool);
     55static void pt_mapping_make_global(uintptr_t, size_t);
    5156
    5257page_mapping_operations_t pt_mapping_operations = {
    5358        .mapping_insert = pt_mapping_insert,
    5459        .mapping_remove = pt_mapping_remove,
    55         .mapping_find = pt_mapping_find
     60        .mapping_find = pt_mapping_find,
     61        .mapping_make_global = pt_mapping_make_global
    5662};
    5763
     
    7581       
    7682        if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) {
    77                 pte_t *newpt = (pte_t *) frame_alloc(PTL1_SIZE, FRAME_KA);
     83                pte_t *newpt = (pte_t *) frame_alloc(PTL1_SIZE,
     84                    FRAME_LOWMEM | FRAME_KA);
    7885                memsetb(newpt, FRAME_SIZE << PTL1_SIZE, 0);
    7986                SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page), KA2PA(newpt));
    80                 SET_PTL1_FLAGS(ptl0, PTL0_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE);
     87                SET_PTL1_FLAGS(ptl0, PTL0_INDEX(page),
     88                    PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
     89                    PAGE_WRITE);
    8190        }
    8291       
     
    8493       
    8594        if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) {
    86                 pte_t *newpt = (pte_t *) frame_alloc(PTL2_SIZE, FRAME_KA);
     95                pte_t *newpt = (pte_t *) frame_alloc(PTL2_SIZE,
     96                    FRAME_LOWMEM | FRAME_KA);
    8797                memsetb(newpt, FRAME_SIZE << PTL2_SIZE, 0);
    8898                SET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page), KA2PA(newpt));
    89                 SET_PTL2_FLAGS(ptl1, PTL1_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE);
     99                SET_PTL2_FLAGS(ptl1, PTL1_INDEX(page),
     100                    PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
     101                    PAGE_WRITE);
    90102        }
    91103       
     
    93105       
    94106        if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) {
    95                 pte_t *newpt = (pte_t *) frame_alloc(PTL3_SIZE, FRAME_KA);
     107                pte_t *newpt = (pte_t *) frame_alloc(PTL3_SIZE,
     108                    FRAME_LOWMEM | FRAME_KA);
    96109                memsetb(newpt, FRAME_SIZE << PTL3_SIZE, 0);
    97110                SET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page), KA2PA(newpt));
    98                 SET_PTL3_FLAGS(ptl2, PTL2_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE);
     111                SET_PTL3_FLAGS(ptl2, PTL2_INDEX(page),
     112                    PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
     113                    PAGE_WRITE);
    99114        }
    100115       
     
    123138        /*
    124139         * First, remove the mapping, if it exists.
    125          *
    126140         */
    127141       
     
    140154        pte_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
    141155       
    142         /* Destroy the mapping. Setting to PAGE_NOT_PRESENT is not sufficient. */
     156        /*
     157         * Destroy the mapping.
     158         * Setting to PAGE_NOT_PRESENT is not sufficient.
     159         */
    143160        memsetb(&ptl3[PTL3_INDEX(page)], sizeof(pte_t), 0);
    144161       
    145162        /*
    146          * Second, free all empty tables along the way from PTL3 down to PTL0.
    147          *
     163         * Second, free all empty tables along the way from PTL3 down to PTL0
     164         * except those needed for sharing the kernel non-identity mappings.
    148165         */
    149166       
     
    162179                /*
    163180                 * PTL3 is empty.
    164                  * Release the frame and remove PTL3 pointer from preceding table.
    165                  *
    166                  */
    167                 frame_free(KA2PA((uintptr_t) ptl3));
     181                 * Release the frame and remove PTL3 pointer from the parent
     182                 * table.
     183                 */
    168184#if (PTL2_ENTRIES != 0)
    169185                memsetb(&ptl2[PTL2_INDEX(page)], sizeof(pte_t), 0);
     
    171187                memsetb(&ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0);
    172188#else
     189                if (km_is_non_identity(page))
     190                        return;
     191
    173192                memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
    174193#endif
     194                frame_free(KA2PA((uintptr_t) ptl3));
    175195        } else {
    176196                /*
     
    195215                /*
    196216                 * PTL2 is empty.
    197                  * Release the frame and remove PTL2 pointer from preceding table.
    198                  *
    199                  */
    200                 frame_free(KA2PA((uintptr_t) ptl2));
     217                 * Release the frame and remove PTL2 pointer from the parent
     218                 * table.
     219                 */
    201220#if (PTL1_ENTRIES != 0)
    202221                memsetb(&ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0);
    203222#else
     223                if (km_is_non_identity(page))
     224                        return;
     225
    204226                memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
    205227#endif
     228                frame_free(KA2PA((uintptr_t) ptl2));
    206229        } else {
    207230                /*
     
    227250                /*
    228251                 * PTL1 is empty.
    229                  * Release the frame and remove PTL1 pointer from preceding table.
    230                  *
    231                  */
     252                 * Release the frame and remove PTL1 pointer from the parent
     253                 * table.
     254                 */
     255                if (km_is_non_identity(page))
     256                        return;
     257
     258                memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
    232259                frame_free(KA2PA((uintptr_t) ptl1));
    233                 memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
    234260        }
    235261#endif /* PTL1_ENTRIES != 0 */
     
    267293}
    268294
     295/** Return the size of the region mapped by a single PTL0 entry.
     296 *
     297 * @return Size of the region mapped by a single PTL0 entry.
     298 */
     299static uintptr_t ptl0_step_get(void)
     300{
     301        size_t va_bits;
     302
     303        va_bits = fnzb(PTL0_ENTRIES) + fnzb(PTL1_ENTRIES) + fnzb(PTL2_ENTRIES) +
     304            fnzb(PTL3_ENTRIES) + PAGE_WIDTH;
     305
     306        return 1UL << (va_bits - fnzb(PTL0_ENTRIES));
     307}
     308
     309/** Make the mappings in the given range global accross all address spaces.
     310 *
     311 * All PTL0 entries in the given range will be mapped to a next level page
     312 * table. The next level page table will be allocated and cleared.
     313 *
     314 * pt_mapping_remove() will never deallocate these page tables even when there
     315 * are no PTEs in them.
     316 *
     317 * @param as   Address space.
     318 * @param base Base address corresponding to the first PTL0 entry that will be
     319 *             altered by this function.
     320 * @param size Size in bytes defining the range of PTL0 entries that will be
     321 *             altered by this function.
     322 */
     323void pt_mapping_make_global(uintptr_t base, size_t size)
     324{
     325        uintptr_t ptl0 = PA2KA((uintptr_t) AS_KERNEL->genarch.page_table);
     326        uintptr_t ptl0_step = ptl0_step_get();
     327        size_t order;
     328        uintptr_t addr;
     329
     330#if (PTL1_ENTRIES != 0)
     331        order = PTL1_SIZE;
     332#elif (PTL2_ENTRIES != 0)
     333        order = PTL2_SIZE;
     334#else
     335        order = PTL3_SIZE;
     336#endif
     337
     338        ASSERT(size > 0);
     339
     340        for (addr = ALIGN_DOWN(base, ptl0_step); addr - 1 < base + size - 1;
     341            addr += ptl0_step) {
     342                uintptr_t l1;
     343
     344                l1 = (uintptr_t) frame_alloc(order, FRAME_KA | FRAME_LOWMEM);
     345                memsetb((void *) l1, FRAME_SIZE << order, 0);
     346                SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(addr), KA2PA(l1));
     347                SET_PTL1_FLAGS(ptl0, PTL0_INDEX(addr),
     348                    PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
     349                    PAGE_WRITE);
     350        }
     351}
     352
    269353/** @}
    270354 */
Note: See TracChangeset for help on using the changeset viewer.