Ignore:
File:
1 edited

Legend:

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

    rc15b374 ra000878c  
    4545
    4646static unsigned int seed = 10;
    47 static unsigned int seed_real
    48     __attribute__ ((section("K_UNMAPPED_DATA_START"))) = 42;
     47static unsigned int seed_real __attribute__ ((section("K_UNMAPPED_DATA_START"))) = 42;
     48
    4949
    5050/** Try to find PTE for faulting address
    5151 *
    52  * @param as       Address space.
    53  * @param lock     Lock/unlock the address space.
    54  * @param badvaddr Faulting virtual address.
    55  * @param access   Access mode that caused the fault.
    56  * @param istate   Pointer to interrupted state.
    57  * @param pfrc     Pointer to variable where as_page_fault() return code
    58  *                 will be stored.
    59  *
    60  * @return PTE on success, NULL otherwise.
    61  *
    62  */
    63 static pte_t *find_mapping_and_check(as_t *as, uintptr_t badvaddr, int access,
     52 * Try to find PTE for faulting address.
     53 * The as->lock must be held on entry to this function
     54 * if lock is true.
     55 *
     56 * @param as            Address space.
     57 * @param lock          Lock/unlock the address space.
     58 * @param badvaddr      Faulting virtual address.
     59 * @param access        Access mode that caused the fault.
     60 * @param istate        Pointer to interrupted state.
     61 * @param pfrc          Pointer to variable where as_page_fault() return code
     62 *                      will be stored.
     63 * @return              PTE on success, NULL otherwise.
     64 *
     65 */
     66static pte_t *
     67find_mapping_and_check(as_t *as, bool lock, uintptr_t badvaddr, int access,
    6468    istate_t *istate, int *pfrc)
    6569{
    66         ASSERT(mutex_locked(&as->lock));
    67 
    6870        /*
    6971         * Check if the mapping exists in page tables.
    70          */
     72         */     
    7173        pte_t *pte = page_mapping_find(as, badvaddr);
    7274        if ((pte) && (pte->present)) {
     
    7779                return pte;
    7880        } else {
     81                int rc;
     82       
    7983                /*
    8084                 * Mapping not found in page tables.
    8185                 * Resort to higher-level page fault handler.
    8286                 */
    83                 page_table_unlock(as, true);
    84                
    85                 int rc = as_page_fault(badvaddr, access, istate);
    86                 switch (rc) {
     87                page_table_unlock(as, lock);
     88                switch (rc = as_page_fault(badvaddr, access, istate)) {
    8789                case AS_PF_OK:
    8890                        /*
     
    9092                         * The mapping ought to be in place.
    9193                         */
    92                         page_table_lock(as, true);
     94                        page_table_lock(as, lock);
    9395                        pte = page_mapping_find(as, badvaddr);
    9496                        ASSERT((pte) && (pte->present));
     
    9698                        return pte;
    9799                case AS_PF_DEFER:
    98                         page_table_lock(as, true);
     100                        page_table_lock(as, lock);
    99101                        *pfrc = rc;
    100102                        return NULL;
    101103                case AS_PF_FAULT:
    102                         page_table_lock(as, true);
     104                        page_table_lock(as, lock);
    103105                        *pfrc = rc;
    104106                        return NULL;
    105107                default:
    106108                        panic("Unexpected rc (%d).", rc);
    107                 }
    108         }
    109 }
     109                }       
     110        }
     111}
     112
    110113
    111114static void pht_refill_fail(uintptr_t badvaddr, istate_t *istate)
    112115{
    113         fault_if_from_uspace(istate, "PHT Refill Exception on %p.", badvaddr);
    114         panic_memtrap(istate, PF_ACCESS_UNKNOWN, badvaddr,
    115             "PHT Refill Exception.");
    116 }
     116        const char *symbol = symtab_fmt_name_lookup(istate->pc);
     117        const char *sym2 = symtab_fmt_name_lookup(istate->lr);
     118       
     119        fault_if_from_uspace(istate,
     120            "PHT Refill Exception on %p.", badvaddr);
     121        panic("%p: PHT Refill Exception at %p (%s<-%s).", badvaddr,
     122            istate->pc, symbol, sym2);
     123}
     124
    117125
    118126static void pht_insert(const uintptr_t vaddr, const pte_t *pte)
     
    121129        uint32_t api = (vaddr >> 22) & 0x3f;
    122130       
    123         uint32_t vsid = sr_get(vaddr);
    124         uint32_t sdr1 = sdr1_get();
    125        
    126         // FIXME: compute size of PHT exactly
     131        uint32_t vsid;
     132        asm volatile (
     133                "mfsrin %0, %1\n"
     134                : "=r" (vsid)
     135                : "r" (vaddr)
     136        );
     137       
     138        uint32_t sdr1;
     139        asm volatile (
     140                "mfsdr1 %0\n"
     141                : "=r" (sdr1)
     142        );
    127143        phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000);
    128144       
     
    199215}
    200216
     217
    201218/** Process Instruction/Data Storage Exception
    202219 *
     
    205222 *
    206223 */
    207 void pht_refill(unsigned int n, istate_t *istate)
    208 {
    209         as_t *as = (AS == NULL) ? AS_KERNEL : AS;
     224void pht_refill(int n, istate_t *istate)
     225{
    210226        uintptr_t badvaddr;
     227        pte_t *pte;
     228        int pfrc;
     229        as_t *as;
     230        bool lock;
     231       
     232        if (AS == NULL) {
     233                as = AS_KERNEL;
     234                lock = false;
     235        } else {
     236                as = AS;
     237                lock = true;
     238        }
    211239       
    212240        if (n == VECTOR_DATA_STORAGE)
     
    214242        else
    215243                badvaddr = istate->pc;
    216        
    217         page_table_lock(as, true);
    218        
    219         int pfrc;
    220         pte_t *pte = find_mapping_and_check(as, badvaddr,
     244               
     245        page_table_lock(as, lock);
     246       
     247        pte = find_mapping_and_check(as, lock, badvaddr,
    221248            PF_ACCESS_READ /* FIXME */, istate, &pfrc);
    222        
    223249        if (!pte) {
    224250                switch (pfrc) {
     
    231257                         * or copy_to_uspace().
    232258                         */
    233                         page_table_unlock(as, true);
     259                        page_table_unlock(as, lock);
    234260                        return;
    235261                default:
     
    238264        }
    239265       
    240         /* Record access to PTE */
    241         pte->accessed = 1;
     266        pte->accessed = 1; /* Record access to PTE */
    242267        pht_insert(badvaddr, pte);
    243268       
    244         page_table_unlock(as, true);
     269        page_table_unlock(as, lock);
    245270        return;
    246271       
    247272fail:
    248         page_table_unlock(as, true);
     273        page_table_unlock(as, lock);
    249274        pht_refill_fail(badvaddr, istate);
    250275}
     276
    251277
    252278/** Process Instruction/Data Storage Exception in Real Mode
     
    256282 *
    257283 */
    258 bool pht_refill_real(unsigned int n, istate_t *istate)
     284bool pht_refill_real(int n, istate_t *istate)
    259285{
    260286        uintptr_t badvaddr;
     
    265291                badvaddr = istate->pc;
    266292       
    267         uint32_t physmem = physmem_top();
     293        uint32_t physmem;
     294        asm volatile (
     295                "mfsprg3 %0\n"
     296                : "=r" (physmem)
     297        );
    268298       
    269299        if ((badvaddr < PA2KA(0)) || (badvaddr >= PA2KA(physmem)))
     
    273303        uint32_t api = (badvaddr >> 22) & 0x3f;
    274304       
    275         uint32_t vsid = sr_get(badvaddr);
    276         uint32_t sdr1 = sdr1_get();
    277        
    278         // FIXME: compute size of PHT exactly
     305        uint32_t vsid;
     306        asm volatile (
     307                "mfsrin %0, %1\n"
     308                : "=r" (vsid)
     309                : "r" (badvaddr)
     310        );
     311       
     312        uint32_t sdr1;
     313        asm volatile (
     314                "mfsdr1 %0\n"
     315                : "=r" (sdr1)
     316        );
    279317        phte_t *phte_real = (phte_t *) (sdr1 & 0xffff0000);
    280318       
     
    358396}
    359397
     398
    360399/** Process ITLB/DTLB Miss Exception in Real Mode
    361400 *
    362401 *
    363402 */
    364 void tlb_refill_real(unsigned int n, uint32_t tlbmiss, ptehi_t ptehi,
    365     ptelo_t ptelo, istate_t *istate)
     403void tlb_refill_real(int n, uint32_t tlbmiss, ptehi_t ptehi, ptelo_t ptelo, istate_t *istate)
    366404{
    367405        uint32_t badvaddr = tlbmiss & 0xfffffffc;
    368         uint32_t physmem = physmem_top();
     406       
     407        uint32_t physmem;
     408        asm volatile (
     409                "mfsprg3 %0\n"
     410                : "=r" (physmem)
     411        );
    369412       
    370413        if ((badvaddr < PA2KA(0)) || (badvaddr >= PA2KA(physmem)))
     
    377420        uint32_t index = 0;
    378421        asm volatile (
    379                 "mtspr 981, %[ptehi]\n"
    380                 "mtspr 982, %[ptelo]\n"
    381                 "tlbld %[index]\n"
    382                 "tlbli %[index]\n"
    383                 : [index] "=r" (index)
    384                 : [ptehi] "r" (ptehi),
    385                   [ptelo] "r" (ptelo)
    386         );
    387 }
     422                "mtspr 981, %0\n"
     423                "mtspr 982, %1\n"
     424                "tlbld %2\n"
     425                "tlbli %2\n"
     426                : "=r" (index)
     427                : "r" (ptehi),
     428                  "r" (ptelo)
     429        );
     430}
     431
    388432
    389433void tlb_arch_init(void)
     
    392436}
    393437
     438
    394439void tlb_invalidate_all(void)
    395440{
    396441        uint32_t index;
    397        
    398         asm volatile (
    399                 "li %[index], 0\n"
     442        asm volatile (
     443                "li %0, 0\n"
    400444                "sync\n"
    401445               
    402446                ".rept 64\n"
    403                 "       tlbie %[index]\n"
    404                 "       addi %[index], %[index], 0x1000\n"
     447                "tlbie %0\n"
     448                "addi %0, %0, 0x1000\n"
    405449                ".endr\n"
    406450               
     
    408452                "tlbsync\n"
    409453                "sync\n"
    410                 : [index] "=r" (index)
    411         );
    412 }
     454                : "=r" (index)
     455        );
     456}
     457
    413458
    414459void tlb_invalidate_asid(asid_t asid)
    415460{
    416         uint32_t sdr1 = sdr1_get();
    417        
    418         // FIXME: compute size of PHT exactly
     461        uint32_t sdr1;
     462        asm volatile (
     463                "mfsdr1 %0\n"
     464                : "=r" (sdr1)
     465        );
    419466        phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000);
    420467       
    421         size_t i;
     468        uint32_t i;
    422469        for (i = 0; i < 8192; i++) {
    423470                if ((phte[i].v) && (phte[i].vsid >= (asid << 4)) &&
     
    425472                        phte[i].v = 0;
    426473        }
    427        
    428474        tlb_invalidate_all();
    429475}
     476
    430477
    431478void tlb_invalidate_pages(asid_t asid, uintptr_t page, size_t cnt)
     
    435482}
    436483
     484
    437485#define PRINT_BAT(name, ureg, lreg) \
    438486        asm volatile ( \
    439                 "mfspr %[upper], " #ureg "\n" \
    440                 "mfspr %[lower], " #lreg "\n" \
    441                 : [upper] "=r" (upper), \
    442                   [lower] "=r" (lower) \
     487                "mfspr %0," #ureg "\n" \
     488                "mfspr %1," #lreg "\n" \
     489                : "=r" (upper), "=r" (lower) \
    443490        ); \
    444         \
    445491        mask = (upper & 0x1ffc) >> 2; \
    446492        if (upper & 3) { \
    447493                uint32_t tmp = mask; \
    448494                length = 128; \
    449                 \
    450495                while (tmp) { \
    451496                        if ((tmp & 1) == 0) { \
     
    458503        } else \
    459504                length = 0; \
    460         \
    461505        printf(name ": page=%.*p frame=%.*p length=%d KB (mask=%#x)%s%s\n", \
    462506            sizeof(upper) * 2, upper & 0xffff0000, sizeof(lower) * 2, \
     
    471515       
    472516        for (sr = 0; sr < 16; sr++) {
    473                 uint32_t vsid = sr_get(sr << 28);
    474                
     517                uint32_t vsid;
     518                asm volatile (
     519                        "mfsrin %0, %1\n"
     520                        : "=r" (vsid)
     521                        : "r" (sr << 28)
     522                );
    475523                printf("sr[%02u]: vsid=%.*p (asid=%u)%s%s\n", sr,
    476524                    sizeof(vsid) * 2, vsid & 0xffffff, (vsid & 0xffffff) >> 4,
Note: See TracChangeset for help on using the changeset viewer.