Ignore:
File:
1 edited

Legend:

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

    rc99693a r655f70b  
    3333 */
    3434
    35 #include <mm/tlb.h>
    3635#include <arch/mm/tlb.h>
    37 #include <arch/interrupt.h>
    3836#include <interrupt.h>
    39 #include <mm/as.h>
    40 #include <mm/page.h>
    41 #include <arch.h>
    42 #include <print.h>
    43 #include <macros.h>
    44 #include <symtab.h>
    45 
    46 static unsigned int seed = 42;
    47 
    48 /** Try to find PTE for faulting address
    49  *
    50  * @param as       Address space.
    51  * @param badvaddr Faulting virtual address.
    52  * @param access   Access mode that caused the fault.
    53  * @param istate   Pointer to interrupted state.
    54  * @param pfrc     Pointer to variable where as_page_fault() return code
    55  *                 will be stored.
    56  *
    57  * @return PTE on success, NULL otherwise.
    58  *
    59  */
    60 static pte_t *find_mapping_and_check(as_t *as, uintptr_t badvaddr, int access,
    61     istate_t *istate, int *pfrc)
    62 {
    63         /*
    64          * Check if the mapping exists in page tables.
    65          */
    66         pte_t *pte = page_mapping_find(as, badvaddr, true);
    67         if ((pte) && (pte->present)) {
    68                 /*
    69                  * Mapping found in page tables.
    70                  * Immediately succeed.
    71                  */
    72                 return pte;
    73         } else {
    74                 /*
    75                  * Mapping not found in page tables.
    76                  * Resort to higher-level page fault handler.
    77                  */
    78                 int rc = as_page_fault(badvaddr, access, istate);
    79                 switch (rc) {
    80                 case AS_PF_OK:
    81                         /*
    82                          * The higher-level page fault handler succeeded,
    83                          * The mapping ought to be in place.
    84                          */
    85                         pte = page_mapping_find(as, badvaddr, true);
    86                         ASSERT((pte) && (pte->present));
    87                         *pfrc = 0;
    88                         return pte;
    89                 case AS_PF_DEFER:
    90                         *pfrc = rc;
    91                         return NULL;
    92                 case AS_PF_FAULT:
    93                         *pfrc = rc;
    94                         return NULL;
    95                 default:
    96                         panic("Unexpected rc (%d).", rc);
    97                 }
    98         }
    99 }
    100 
    101 static void pht_refill_fail(uintptr_t badvaddr, istate_t *istate)
    102 {
    103         fault_if_from_uspace(istate, "PHT Refill Exception on %p.",
    104             (void *) badvaddr);
    105         panic_memtrap(istate, PF_ACCESS_UNKNOWN, badvaddr,
    106             "PHT Refill Exception.");
    107 }
    108 
    109 static void pht_insert(const uintptr_t vaddr, const pte_t *pte)
    110 {
    111         uint32_t page = (vaddr >> 12) & 0xffff;
    112         uint32_t api = (vaddr >> 22) & 0x3f;
    113        
    114         uint32_t vsid = sr_get(vaddr);
    115         uint32_t sdr1 = sdr1_get();
    116        
    117         // FIXME: compute size of PHT exactly
    118         phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000);
    119        
    120         /* Primary hash (xor) */
    121         uint32_t h = 0;
    122         uint32_t hash = vsid ^ page;
    123         uint32_t base = (hash & 0x3ff) << 3;
    124         uint32_t i;
    125         bool found = false;
    126        
    127         /* Find colliding PTE in PTEG */
    128         for (i = 0; i < 8; i++) {
    129                 if ((phte[base + i].v)
    130                     && (phte[base + i].vsid == vsid)
    131                     && (phte[base + i].api == api)
    132                     && (phte[base + i].h == 0)) {
    133                         found = true;
    134                         break;
    135                 }
    136         }
    137        
    138         if (!found) {
    139                 /* Find unused PTE in PTEG */
    140                 for (i = 0; i < 8; i++) {
    141                         if (!phte[base + i].v) {
    142                                 found = true;
    143                                 break;
    144                         }
    145                 }
    146         }
    147        
    148         if (!found) {
    149                 /* Secondary hash (not) */
    150                 uint32_t base2 = (~hash & 0x3ff) << 3;
    151                
    152                 /* Find colliding PTE in PTEG */
    153                 for (i = 0; i < 8; i++) {
    154                         if ((phte[base2 + i].v)
    155                             && (phte[base2 + i].vsid == vsid)
    156                             && (phte[base2 + i].api == api)
    157                             && (phte[base2 + i].h == 1)) {
    158                                 found = true;
    159                                 base = base2;
    160                                 h = 1;
    161                                 break;
    162                         }
    163                 }
    164                
    165                 if (!found) {
    166                         /* Find unused PTE in PTEG */
    167                         for (i = 0; i < 8; i++) {
    168                                 if (!phte[base2 + i].v) {
    169                                         found = true;
    170                                         base = base2;
    171                                         h = 1;
    172                                         break;
    173                                 }
    174                         }
    175                 }
    176                
    177                 if (!found)
    178                         i = RANDI(seed) % 8;
    179         }
    180        
    181         phte[base + i].v = 1;
    182         phte[base + i].vsid = vsid;
    183         phte[base + i].h = h;
    184         phte[base + i].api = api;
    185         phte[base + i].rpn = pte->pfn;
    186         phte[base + i].r = 0;
    187         phte[base + i].c = 0;
    188         phte[base + i].wimg = (pte->page_cache_disable ? WIMG_NO_CACHE : 0);
    189         phte[base + i].pp = 2; // FIXME
    190 }
    191 
    192 /** Process Instruction/Data Storage Exception
    193  *
    194  * @param n      Exception vector number.
    195  * @param istate Interrupted register context.
    196  *
    197  */
    198 void pht_refill(unsigned int n, istate_t *istate)
    199 {
    200         as_t *as = (AS == NULL) ? AS_KERNEL : AS;
    201         uintptr_t badvaddr;
    202        
    203         if (n == VECTOR_DATA_STORAGE)
    204                 badvaddr = istate->dar;
    205         else
    206                 badvaddr = istate->pc;
    207        
    208         int pfrc;
    209         pte_t *pte = find_mapping_and_check(as, badvaddr,
    210             PF_ACCESS_READ /* FIXME */, istate, &pfrc);
    211        
    212         if (!pte) {
    213                 switch (pfrc) {
    214                 case AS_PF_FAULT:
    215                         pht_refill_fail(badvaddr, istate);
    216                         return;
    217                 case AS_PF_DEFER:
    218                         /*
    219                          * The page fault came during copy_from_uspace()
    220                          * or copy_to_uspace().
    221                          */
    222                         return;
    223                 default:
    224                         panic("Unexpected pfrc (%d).", pfrc);
    225                 }
    226         }
    227        
    228         /* Record access to PTE */
    229         pte->accessed = 1;
    230         pht_insert(badvaddr, pte);
    231 }
     37#include <typedefs.h>
    23238
    23339void tlb_refill(unsigned int n, istate_t *istate)
     
    27581void tlb_invalidate_all(void)
    27682{
    277         uint32_t index;
     83        asm volatile (
     84                "sync\n"
     85        );
     86       
     87        for (unsigned int i = 0; i < 0x00040000; i += 0x00001000) {
     88                asm volatile (
     89                        "tlbie %[i]\n"
     90                        :: [i] "r" (i)
     91                );
     92        }
    27893       
    27994        asm volatile (
    280                 "li %[index], 0\n"
    281                 "sync\n"
    282                
    283                 ".rept 64\n"
    284                 "       tlbie %[index]\n"
    285                 "       addi %[index], %[index], 0x1000\n"
    286                 ".endr\n"
    287                
    28895                "eieio\n"
    28996                "tlbsync\n"
    29097                "sync\n"
    291                 : [index] "=r" (index)
    29298        );
    29399}
     
    295101void tlb_invalidate_asid(asid_t asid)
    296102{
    297         uint32_t sdr1 = sdr1_get();
    298        
    299         // FIXME: compute size of PHT exactly
    300         phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000);
    301        
    302         size_t i;
    303         for (i = 0; i < 8192; i++) {
    304                 if ((phte[i].v) && (phte[i].vsid >= (asid << 4)) &&
    305                     (phte[i].vsid < ((asid << 4) + 16)))
    306                         phte[i].v = 0;
    307         }
    308        
    309103        tlb_invalidate_all();
    310104}
     
    312106void tlb_invalidate_pages(asid_t asid, uintptr_t page, size_t cnt)
    313107{
    314         // TODO
    315108        tlb_invalidate_all();
    316109}
Note: See TracChangeset for help on using the changeset viewer.