Ignore:
File:
1 edited

Legend:

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

    re943ecf r17af882  
    8282       
    8383        if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) {
    84                 pte_t *newpt = (pte_t *) frame_alloc(PTL1_SIZE,
    85                     FRAME_LOWMEM | FRAME_KA);
    86                 memsetb(newpt, FRAME_SIZE << PTL1_SIZE, 0);
     84                pte_t *newpt = (pte_t *)
     85                    PA2KA(frame_alloc(PTL1_FRAMES, FRAME_LOWMEM, PTL1_SIZE - 1));
     86                memsetb(newpt, PTL1_SIZE, 0);
    8787                SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page), KA2PA(newpt));
    8888                SET_PTL1_FLAGS(ptl0, PTL0_INDEX(page),
    8989                    PAGE_NOT_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
    9090                    PAGE_WRITE);
     91                /*
     92                 * Make sure that a concurrent hardware page table walk or
     93                 * pt_mapping_find() will see the new PTL1 only after it is
     94                 * fully initialized.
     95                 */
    9196                write_barrier();
    9297                SET_PTL1_PRESENT(ptl0, PTL0_INDEX(page));
     
    96101       
    97102        if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) {
    98                 pte_t *newpt = (pte_t *) frame_alloc(PTL2_SIZE,
    99                     FRAME_LOWMEM | FRAME_KA);
    100                 memsetb(newpt, FRAME_SIZE << PTL2_SIZE, 0);
     103                pte_t *newpt = (pte_t *)
     104                    PA2KA(frame_alloc(PTL2_FRAMES, FRAME_LOWMEM, PTL2_SIZE - 1));
     105                memsetb(newpt, PTL2_SIZE, 0);
    101106                SET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page), KA2PA(newpt));
    102107                SET_PTL2_FLAGS(ptl1, PTL1_INDEX(page),
    103108                    PAGE_NOT_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
    104109                    PAGE_WRITE);
     110                /*
     111                 * Make the new PTL2 visible only after it is fully initialized.
     112                 */
    105113                write_barrier();
    106                 SET_PTL2_PRESENT(ptl1, PTL1_INDEX(page));       
     114                SET_PTL2_PRESENT(ptl1, PTL1_INDEX(page));
    107115        }
    108116       
     
    110118       
    111119        if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) {
    112                 pte_t *newpt = (pte_t *) frame_alloc(PTL3_SIZE,
    113                     FRAME_LOWMEM | FRAME_KA);
    114                 memsetb(newpt, FRAME_SIZE << PTL3_SIZE, 0);
     120                pte_t *newpt = (pte_t *)
     121                    PA2KA(frame_alloc(PTL3_FRAMES, FRAME_LOWMEM, PTL2_SIZE - 1));
     122                memsetb(newpt, PTL2_SIZE, 0);
    115123                SET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page), KA2PA(newpt));
    116124                SET_PTL3_FLAGS(ptl2, PTL2_INDEX(page),
    117125                    PAGE_NOT_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
    118126                    PAGE_WRITE);
     127                /*
     128                 * Make the new PTL3 visible only after it is fully initialized.
     129                 */
    119130                write_barrier();
    120131                SET_PTL3_PRESENT(ptl2, PTL2_INDEX(page));
     
    125136        SET_FRAME_ADDRESS(ptl3, PTL3_INDEX(page), frame);
    126137        SET_FRAME_FLAGS(ptl3, PTL3_INDEX(page), flags | PAGE_NOT_PRESENT);
     138        /*
     139         * Make the new mapping visible only after it is fully initialized.
     140         */
    127141        write_barrier();
    128142        SET_FRAME_PRESENT(ptl3, PTL3_INDEX(page));
     
    166180         * Destroy the mapping.
    167181         * Setting to PAGE_NOT_PRESENT is not sufficient.
    168          */
     182         * But we need SET_FRAME for possible PT coherence maintenance.
     183         * At least on ARM.
     184         */
     185        //TODO: Fix this inconsistency
     186        SET_FRAME_FLAGS(ptl3, PTL3_INDEX(page), PAGE_NOT_PRESENT);
    169187        memsetb(&ptl3[PTL3_INDEX(page)], sizeof(pte_t), 0);
    170188       
     
    201219                memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
    202220#endif
    203                 frame_free(KA2PA((uintptr_t) ptl3));
     221                frame_free(KA2PA((uintptr_t) ptl3), PTL3_FRAMES);
    204222        } else {
    205223                /*
     
    235253                memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
    236254#endif
    237                 frame_free(KA2PA((uintptr_t) ptl2));
     255                frame_free(KA2PA((uintptr_t) ptl2), PTL2_FRAMES);
    238256        } else {
    239257                /*
     
    266284
    267285                memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
    268                 frame_free(KA2PA((uintptr_t) ptl1));
     286                frame_free(KA2PA((uintptr_t) ptl1), PTL1_FRAMES);
    269287        }
    270288#endif /* PTL1_ENTRIES != 0 */
     
    296314
    297315#if (PTL1_ENTRIES != 0)
     316        /*
     317         * Always read ptl2 only after we are sure it is present.
     318         */
    298319        read_barrier();
    299320#endif
     
    304325
    305326#if (PTL2_ENTRIES != 0)
     327        /*
     328         * Always read ptl3 only after we are sure it is present.
     329         */
    306330        read_barrier();
    307331#endif
     
    339363 * @param size Size in bytes defining the range of PTL0 entries that will be
    340364 *             altered by this function.
     365 *
    341366 */
    342367void pt_mapping_make_global(uintptr_t base, size_t size)
    343368{
     369        ASSERT(size > 0);
     370       
    344371        uintptr_t ptl0 = PA2KA((uintptr_t) AS_KERNEL->genarch.page_table);
    345372        uintptr_t ptl0_step = ptl0_step_get();
    346         size_t order;
    347         uintptr_t addr;
    348 
     373        size_t frames;
     374       
    349375#if (PTL1_ENTRIES != 0)
    350         order = PTL1_SIZE;
     376        frames = PTL1_FRAMES;
    351377#elif (PTL2_ENTRIES != 0)
    352         order = PTL2_SIZE;
     378        frames = PTL2_FRAMES;
    353379#else
    354         order = PTL3_SIZE;
     380        frames = PTL3_FRAMES;
    355381#endif
    356 
    357         ASSERT(size > 0);
    358 
    359         for (addr = ALIGN_DOWN(base, ptl0_step); addr - 1 < base + size - 1;
     382       
     383        for (uintptr_t addr = ALIGN_DOWN(base, ptl0_step);
     384            addr - 1 < base + size - 1;
    360385            addr += ptl0_step) {
    361                 uintptr_t l1;
    362 
    363                 l1 = (uintptr_t) frame_alloc(order, FRAME_KA | FRAME_LOWMEM);
    364                 memsetb((void *) l1, FRAME_SIZE << order, 0);
     386                if (GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(addr))) {
     387                        ASSERT(overlaps(addr, ptl0_step,
     388                            config.identity_base, config.identity_size));
     389
     390                        /*
     391                         * This PTL0 entry also maps the kernel identity region,
     392                         * so it is already global and initialized.
     393                         */
     394                        continue;
     395                }
     396
     397                uintptr_t l1 = PA2KA(frame_alloc(frames, FRAME_LOWMEM, 0));
     398                memsetb((void *) l1, FRAMES2SIZE(frames), 0);
    365399                SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(addr), KA2PA(l1));
    366400                SET_PTL1_FLAGS(ptl0, PTL0_INDEX(addr),
Note: See TracChangeset for help on using the changeset viewer.