Ignore:
File:
1 edited

Legend:

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

    ra2789d2 rde73242  
    4343#include <arch/mm/page.h>
    4444#include <arch/mm/as.h>
     45#include <arch/barrier.h>
    4546#include <typedefs.h>
    4647#include <arch/asm.h>
     
    4849#include <align.h>
    4950#include <macros.h>
     51#include <bitops.h>
    5052
    5153static void pt_mapping_insert(as_t *, uintptr_t, uintptr_t, unsigned int);
     
    8587                SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page), KA2PA(newpt));
    8688                SET_PTL1_FLAGS(ptl0, PTL0_INDEX(page),
    87                     PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
     89                    PAGE_NOT_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
    8890                    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                 */
     96                write_barrier();
     97                SET_PTL1_PRESENT(ptl0, PTL0_INDEX(page));
    8998        }
    9099       
     
    97106                SET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page), KA2PA(newpt));
    98107                SET_PTL2_FLAGS(ptl1, PTL1_INDEX(page),
    99                     PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
     108                    PAGE_NOT_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
    100109                    PAGE_WRITE);
     110                /*
     111                 * Make the new PTL2 visible only after it is fully initialized.
     112                 */
     113                write_barrier();
     114                SET_PTL2_PRESENT(ptl1, PTL1_INDEX(page));       
    101115        }
    102116       
     
    109123                SET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page), KA2PA(newpt));
    110124                SET_PTL3_FLAGS(ptl2, PTL2_INDEX(page),
    111                     PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
     125                    PAGE_NOT_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
    112126                    PAGE_WRITE);
     127                /*
     128                 * Make the new PTL3 visible only after it is fully initialized.
     129                 */
     130                write_barrier();
     131                SET_PTL3_PRESENT(ptl2, PTL2_INDEX(page));
    113132        }
    114133       
     
    116135       
    117136        SET_FRAME_ADDRESS(ptl3, PTL3_INDEX(page), frame);
    118         SET_FRAME_FLAGS(ptl3, PTL3_INDEX(page), flags);
     137        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         */
     141        write_barrier();
     142        SET_FRAME_PRESENT(ptl3, PTL3_INDEX(page));
    119143}
    120144
     
    278302        if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT)
    279303                return NULL;
     304
     305        read_barrier();
    280306       
    281307        pte_t *ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
    282308        if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT)
    283309                return NULL;
     310
     311#if (PTL1_ENTRIES != 0)
     312        /*
     313         * Always read ptl2 only after we are sure it is present.
     314         */
     315        read_barrier();
     316#endif
    284317       
    285318        pte_t *ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
    286319        if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT)
    287320                return NULL;
     321
     322#if (PTL2_ENTRIES != 0)
     323        /*
     324         * Always read ptl3 only after we are sure it is present.
     325         */
     326        read_barrier();
     327#endif
    288328       
    289329        pte_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
    290330       
    291331        return &ptl3[PTL3_INDEX(page)];
     332}
     333
     334/** Return the size of the region mapped by a single PTL0 entry.
     335 *
     336 * @return Size of the region mapped by a single PTL0 entry.
     337 */
     338static uintptr_t ptl0_step_get(void)
     339{
     340        size_t va_bits;
     341
     342        va_bits = fnzb(PTL0_ENTRIES) + fnzb(PTL1_ENTRIES) + fnzb(PTL2_ENTRIES) +
     343            fnzb(PTL3_ENTRIES) + PAGE_WIDTH;
     344
     345        return 1UL << (va_bits - fnzb(PTL0_ENTRIES));
    292346}
    293347
     
    309363{
    310364        uintptr_t ptl0 = PA2KA((uintptr_t) AS_KERNEL->genarch.page_table);
    311         uintptr_t ptl0step = (((uintptr_t) -1) / PTL0_ENTRIES) + 1;
     365        uintptr_t ptl0_step = ptl0_step_get();
    312366        size_t order;
    313367        uintptr_t addr;
     
    321375#endif
    322376
    323         ASSERT(ispwr2(ptl0step));
    324377        ASSERT(size > 0);
    325378
    326         for (addr = ALIGN_DOWN(base, ptl0step); addr - 1 < base + size - 1;
    327             addr += ptl0step) {
     379        for (addr = ALIGN_DOWN(base, ptl0_step); addr - 1 < base + size - 1;
     380            addr += ptl0_step) {
    328381                uintptr_t l1;
    329382
     
    332385                SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(addr), KA2PA(l1));
    333386                SET_PTL1_FLAGS(ptl0, PTL0_INDEX(addr),
    334                     PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
    335                     PAGE_WRITE);
     387                    PAGE_PRESENT | PAGE_USER | PAGE_CACHEABLE |
     388                    PAGE_EXEC | PAGE_WRITE | PAGE_READ);
    336389        }
    337390}
Note: See TracChangeset for help on using the changeset viewer.