Changeset 346b12a2 in mainline for kernel/genarch/src/mm/page_pt.c


Ignore:
Timestamp:
2016-08-31T17:51:04Z (9 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
fb63c06
Parents:
38dc82d
Message:

Add page_mapping_update()

page_mapping_update() can be used to safely update the accessed and dirty
bits of a PTE in the actual page tables.

File:
1 edited

Legend:

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

    r38dc82d r346b12a2  
    5454static void pt_mapping_remove(as_t *, uintptr_t);
    5555static bool pt_mapping_find(as_t *, uintptr_t, bool, pte_t *pte);
     56static void pt_mapping_update(as_t *, uintptr_t, bool, pte_t *pte);
    5657static void pt_mapping_make_global(uintptr_t, size_t);
    5758
     
    6061        .mapping_remove = pt_mapping_remove,
    6162        .mapping_find = pt_mapping_find,
     63        .mapping_update = pt_mapping_update,
    6264        .mapping_make_global = pt_mapping_make_global
    6365};
     
    289291}
    290292
     293static pte_t *pt_mapping_find_internal(as_t *as, uintptr_t page, bool nolock)
     294{
     295        ASSERT(nolock || page_table_locked(as));
     296
     297        pte_t *ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table);
     298        if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT)
     299                return NULL;
     300
     301        read_barrier();
     302       
     303        pte_t *ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
     304        if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT)
     305                return NULL;
     306
     307#if (PTL1_ENTRIES != 0)
     308        /*
     309         * Always read ptl2 only after we are sure it is present.
     310         */
     311        read_barrier();
     312#endif
     313       
     314        pte_t *ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
     315        if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT)
     316                return NULL;
     317
     318#if (PTL2_ENTRIES != 0)
     319        /*
     320         * Always read ptl3 only after we are sure it is present.
     321         */
     322        read_barrier();
     323#endif
     324       
     325        pte_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
     326       
     327        return &ptl3[PTL3_INDEX(page)];
     328}
     329
    291330/** Find mapping for virtual page in hierarchical page tables.
    292331 *
     
    300339bool pt_mapping_find(as_t *as, uintptr_t page, bool nolock, pte_t *pte)
    301340{
    302         ASSERT(nolock || page_table_locked(as));
    303 
    304         pte_t *ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table);
    305         if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT)
    306                 return false;
    307 
    308         read_barrier();
    309        
    310         pte_t *ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
    311         if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT)
    312                 return false;
    313 
    314 #if (PTL1_ENTRIES != 0)
    315         /*
    316          * Always read ptl2 only after we are sure it is present.
    317          */
    318         read_barrier();
    319 #endif
    320        
    321         pte_t *ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
    322         if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT)
    323                 return false;
    324 
    325 #if (PTL2_ENTRIES != 0)
    326         /*
    327          * Always read ptl3 only after we are sure it is present.
    328          */
    329         read_barrier();
    330 #endif
    331        
    332         pte_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
    333        
    334         *pte = ptl3[PTL3_INDEX(page)];
    335         return true;
     341        pte_t *t = pt_mapping_find_internal(as, page, nolock);
     342        if (t)
     343                *pte = *t;
     344        return t != NULL;
     345}
     346
     347/** Update mapping for virtual page in hierarchical page tables.
     348 *
     349 * @param as       Address space to which page belongs.
     350 * @param page     Virtual page.
     351 * @param nolock   True if the page tables need not be locked.
     352 * @param[in] pte  New PTE.
     353 */
     354void pt_mapping_update(as_t *as, uintptr_t page, bool nolock, pte_t *pte)
     355{
     356        pte_t *t = pt_mapping_find_internal(as, page, nolock);
     357        if (!t)
     358                panic("Updating non-existent PTE");     
     359
     360        ASSERT(PTE_VALID(t) == PTE_VALID(pte));
     361        ASSERT(PTE_PRESENT(t) == PTE_PRESENT(pte));
     362        ASSERT(PTE_GET_FRAME(t) == PTE_GET_FRAME(pte));
     363        ASSERT(PTE_WRITABLE(t) == PTE_WRITABLE(pte));
     364        ASSERT(PTE_EXECUTABLE(t) == PTE_EXECUTABLE(pte));
     365
     366        *t = *pte;
    336367}
    337368
Note: See TracChangeset for help on using the changeset viewer.