Changeset 346b12a2 in mainline


Ignore:
Timestamp:
2016-08-31T17:51:04Z (8 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.

Location:
kernel
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/ia64/src/mm/tlb.c

    r38dc82d r346b12a2  
    662662                t.d = true;
    663663                dtc_pte_copy(&t);
     664                page_mapping_update(as, va, true, &t);
    664665        } else {
    665666                as_page_fault(va, PF_ACCESS_WRITE, istate);
     
    694695                t.a = true;
    695696                itc_pte_copy(&t);
     697                page_mapping_update(AS, va, true, &t);
    696698        } else {
    697699                as_page_fault(va, PF_ACCESS_EXEC, istate);
     
    728730                t.a = true;
    729731                dtc_pte_copy(&t);
     732                page_mapping_update(as, va, true, &t);
    730733        } else {
    731734                if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
  • kernel/arch/mips32/src/mm/tlb.c

    r38dc82d r346b12a2  
    111111                    pte.cacheable, pte.pfn);
    112112
     113                page_mapping_update(AS, badvaddr, true, &pte);
     114
    113115                /*
    114116                 * New entry is to be inserted into TLB
     
    176178                tlb_prepare_entry_lo(&lo, pte.g, pte.p, pte.d,
    177179                    pte.cacheable, pte.pfn);
     180
     181                page_mapping_update(AS, badvaddr, true, &pte);
    178182
    179183                /*
     
    239243                tlb_prepare_entry_lo(&lo, pte.g, pte.p, pte.w,
    240244                    pte.cacheable, pte.pfn);
     245
     246                page_mapping_update(AS, badvaddr, true, &pte);
    241247
    242248                /*
  • kernel/arch/sparc64/src/mm/sun4u/tlb.c

    r38dc82d r346b12a2  
    210210                itsb_pte_copy(&t, index);
    211211#endif
     212                page_mapping_update(AS, istate->tpc, true, &t);
    212213        } else {
    213214                /*
     
    264265                dtsb_pte_copy(&t, index, true);
    265266#endif
     267                page_mapping_update(as, page_16k, true, &t);
    266268        } else {
    267269                /*
     
    308310                dtsb_pte_copy(&t, index, false);
    309311#endif
     312                page_mapping_update(as, page_16k, true, &t);
    310313        } else {
    311314                /*
  • kernel/arch/sparc64/src/mm/sun4v/tlb.c

    r38dc82d r346b12a2  
    224224                itsb_pte_copy(&t);
    225225#endif
     226                page_mapping_update(AS, va, true, &t);
    226227        } else {
    227228                /*
     
    271272                dtsb_pte_copy(&t, true);
    272273#endif
     274                page_mapping_update(as, va, true, &t);
    273275        } else {
    274276                /*
     
    309311                dtsb_pte_copy(&t, false);
    310312#endif
     313                page_mapping_update(as, va, true, &t);
    311314        } else {
    312315                /*
  • kernel/genarch/src/mm/page_ht.c

    r38dc82d r346b12a2  
    6060static void ht_mapping_remove(as_t *, uintptr_t);
    6161static bool ht_mapping_find(as_t *, uintptr_t, bool, pte_t *);
     62static void ht_mapping_update(as_t *, uintptr_t, bool, pte_t *);
    6263static void ht_mapping_make_global(uintptr_t, size_t);
    6364
     
    9192        .mapping_remove = ht_mapping_remove,
    9293        .mapping_find = ht_mapping_find,
     94        .mapping_update = ht_mapping_update,
    9395        .mapping_make_global = ht_mapping_make_global
    9496};
     
    245247}
    246248
     249static pte_t *ht_mapping_find_internal(as_t *as, uintptr_t page, bool nolock)
     250{
     251        sysarg_t key[2] = {
     252                (uintptr_t) as,
     253                page = ALIGN_DOWN(page, PAGE_SIZE)
     254        };
     255
     256        ASSERT(nolock || page_table_locked(as));
     257       
     258        link_t *cur = hash_table_find(&page_ht, key);
     259        if (cur)
     260                return hash_table_get_instance(cur, pte_t, link);
     261       
     262        return NULL;
     263}
    247264
    248265/** Find mapping for virtual page in page hash table.
     
    257274bool ht_mapping_find(as_t *as, uintptr_t page, bool nolock, pte_t *pte)
    258275{
    259         sysarg_t key[2] = {
    260                 (uintptr_t) as,
    261                 page = ALIGN_DOWN(page, PAGE_SIZE)
    262         };
    263 
    264         ASSERT(nolock || page_table_locked(as));
    265        
    266         link_t *cur = hash_table_find(&page_ht, key);
    267         if (cur)
    268                 *pte = *hash_table_get_instance(cur, pte_t, link);
    269        
    270         return cur != NULL;
     276        pte_t *t = ht_mapping_find_internal(as, page, nolock);
     277        if (t)
     278                *pte = *t;
     279       
     280        return t != NULL;
     281}
     282
     283/** Update mapping for virtual page in page hash table.
     284 *
     285 * @param as       Address space to which page belongs.
     286 * @param page     Virtual page.
     287 * @param nolock   True if the page tables need not be locked.
     288 * @param pte      New PTE.
     289 */
     290void ht_mapping_update(as_t *as, uintptr_t page, bool nolock, pte_t *pte)
     291{
     292        pte_t *t = ht_mapping_find_internal(as, page, nolock);
     293        if (!t)
     294                panic("Updating non-existent PTE");
     295       
     296        ASSERT(pte->as == t->as);
     297        ASSERT(pte->page == t->page);
     298        ASSERT(pte->frame == t->frame);
     299        ASSERT(pte->g == t->g);
     300        ASSERT(pte->x == t->x);
     301        ASSERT(pte->w == t->w);
     302        ASSERT(pte->k == t->k);
     303        ASSERT(pte->c == t->c);
     304        ASSERT(pte->p == t->p);
     305
     306        t->a = pte->a;
     307        t->d = pte->d;
    271308}
    272309
  • 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
  • kernel/generic/include/mm/page.h

    r38dc82d r346b12a2  
    4949        void (* mapping_remove)(as_t *, uintptr_t);
    5050        bool (* mapping_find)(as_t *, uintptr_t, bool, pte_t *);
     51        void (* mapping_update)(as_t *, uintptr_t, bool, pte_t *);
    5152        void (* mapping_make_global)(uintptr_t, size_t);
    5253} page_mapping_operations_t;
     
    6162extern void page_mapping_remove(as_t *, uintptr_t);
    6263extern bool page_mapping_find(as_t *, uintptr_t, bool, pte_t *);
     64extern void page_mapping_update(as_t *, uintptr_t, bool, pte_t *);
    6365extern void page_mapping_make_global(uintptr_t, size_t);
    6466extern pte_t *page_table_create(unsigned int);
  • kernel/generic/src/mm/page.c

    r38dc82d r346b12a2  
    156156}
    157157
     158/** Update mapping for virtual page.
     159 *
     160 * Use only to update accessed and modified/dirty bits.
     161 *
     162 * @param as       Address space to which page belongs.
     163 * @param page     Virtual page.
     164 * @param nolock   True if the page tables need not be locked.
     165 * @param pte      New PTE.
     166 */
     167NO_TRACE void page_mapping_update(as_t *as, uintptr_t page, bool nolock,
     168    pte_t *pte)
     169{
     170        ASSERT(nolock || page_table_locked(as));
     171       
     172        ASSERT(page_mapping_operations);
     173        ASSERT(page_mapping_operations->mapping_find);
     174       
     175        page_mapping_operations->mapping_update(as,
     176            ALIGN_DOWN(page, PAGE_SIZE), nolock, pte);
     177}
     178
    158179/** Make the mapping shared by all page tables (not address spaces).
    159180 *
Note: See TracChangeset for help on using the changeset viewer.