Changeset 976c434 in mainline


Ignore:
Timestamp:
2013-02-17T17:45:53Z (11 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
2b95d13
Parents:
192a23f0
Message:

Streamline TLB miss handling.

  • Do one thing at a time.
  • If the page is mapped in the page tables, insert it into TLB.
  • If the page is not mapped in the page tables, call as_page_fault() and return.
File:
1 edited

Legend:

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

    r192a23f0 r976c434  
    5757       
    5858
    59 static pte_t *find_mapping_and_check(uintptr_t, int, istate_t *);
    60 
    6159/** Initialize TLB.
    6260 *
     
    8684}
    8785
    88 /** Verify the TLB still contains / does not contain a given entry after the
    89  * current thread possibly blocked.
    90  *
    91  * @param hi           Remembered contents of the EntryHi register.
    92  * @param should_exist Flag saying whether the caller expect the entry to exist
    93  *                     or not to exist.
    94  * @returns            True if the TLB contains or does not contain the mapping
    95  *                     according to the caller's expectation.
    96  * @returns            False otherwise.
    97  */
    98 static bool tlb_recheck_entry(entry_hi_t hi, bool should_exist)
    99 {
    100         tlb_index_t index;
    101 
    102         cp0_entry_hi_write(hi.value);
    103         tlbp();
    104         index.value = cp0_index_read();
    105 
    106         if (!(should_exist ^ index.p)) {
    107                 /* The old entry disappeared or the new entry already exists. */
    108                 return false;
    109         }
    110 
    111         return true;
    112 }
    113 
    11486/** Process TLB Refill Exception.
    11587 *
     
    11890void tlb_refill(istate_t *istate)
    11991{
    120         entry_hi_t hi;
    12192        entry_lo_t lo;
    12293        uintptr_t badvaddr;
     
    12495       
    12596        badvaddr = cp0_badvaddr_read();
    126         hi.value = cp0_entry_hi_read();
    127 
    128         /* We may block in find_mapping_and_check(). */
    129         pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ, istate);
    130         if (pte) {
    131                 if (!tlb_recheck_entry(hi, false))
    132                         return;
    133 
     97
     98        pte = page_mapping_find(AS, badvaddr, true);
     99        if (pte && pte->p) {
    134100                /*
    135101                 * Record access to PTE.
     
    152118                cp0_pagemask_write(TLB_PAGE_MASK_16K);
    153119                tlbwr();
    154         }
     120                return;
     121        }
     122
     123        (void) as_page_fault(badvaddr, PF_ACCESS_READ, istate);
    155124}
    156125
     
    161130void tlb_invalid(istate_t *istate)
    162131{
    163         entry_hi_t hi;
    164132        entry_lo_t lo;
    165133        tlb_index_t index;
     
    188156
    189157        badvaddr = cp0_badvaddr_read();
    190         hi.value = cp0_entry_hi_read();
    191 
    192         /* We may block in find_mapping_and_check(). */
    193         pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ, istate);
    194         if (pte) {
    195                 if (!tlb_recheck_entry(hi, true))
    196                         return;
    197 
     158
     159        pte = page_mapping_find(AS, badvaddr, true);
     160        if (pte && pte->p) {
    198161                /*
    199162                 * Read the faulting TLB entry.
     
    217180                        cp0_entry_lo1_write(lo.value);
    218181                tlbwi();
    219         }
     182                return;
     183        }
     184
     185        (void) as_page_fault(badvaddr, PF_ACCESS_READ, istate);
    220186}
    221187
     
    226192void tlb_modified(istate_t *istate)
    227193{
    228         entry_hi_t hi;
    229194        entry_lo_t lo;
    230195        tlb_index_t index;
     
    244209
    245210        badvaddr = cp0_badvaddr_read();
    246         hi.value = cp0_entry_hi_read();
    247 
    248         /* We may block in find_mapping_and_check(). */
    249         pte = find_mapping_and_check(badvaddr, PF_ACCESS_WRITE, istate);
    250         if (pte) {
    251                 if (!tlb_recheck_entry(hi, true))
    252                         return;
    253 
     211
     212        pte = page_mapping_find(AS, badvaddr, true);
     213        if (pte && pte->p && pte->w) {
    254214                /*
    255215                 * Read the faulting TLB entry.
     
    274234                        cp0_entry_lo1_write(lo.value);
    275235                tlbwi();
    276         }
    277 }
    278 
    279 /** Try to find PTE for faulting address.
    280  *
    281  * @param badvaddr      Faulting virtual address.
    282  * @param access        Access mode that caused the fault.
    283  * @param istate        Pointer to interrupted state.
    284  *
    285  * @return              PTE on success, NULL otherwise.
    286  */
    287 pte_t *find_mapping_and_check(uintptr_t badvaddr, int access, istate_t *istate)
    288 {
    289         entry_hi_t hi;
    290         pte_t *pte;
    291 
    292         hi.value = cp0_entry_hi_read();
    293 
    294         ASSERT(hi.asid == AS->asid);
    295 
    296         /*
    297          * Check if the mapping exists in page tables.
    298          */     
    299         pte = page_mapping_find(AS, badvaddr, true);
    300         if (pte && pte->p && (pte->w || access != PF_ACCESS_WRITE)) {
    301                 /*
    302                  * Mapping found in page tables.
    303                  * Immediately succeed.
    304                  */
    305                 return pte;
    306         }
    307 
    308         /*
    309          * Mapping not found in page tables.
    310          * Resort to higher-level page fault handler.
    311          */
    312         if (as_page_fault(badvaddr, access, istate) == AS_PF_OK) {
    313                 pte = page_mapping_find(AS, badvaddr, true);
    314                 ASSERT(pte && pte->p);
    315                 ASSERT(pte->w || access != PF_ACCESS_WRITE);
    316                 return pte;
    317         }
    318 
    319         return NULL;
     236                return;
     237        }
     238
     239        (void) as_page_fault(badvaddr, PF_ACCESS_WRITE, istate);
    320240}
    321241
Note: See TracChangeset for help on using the changeset viewer.