Ignore:
File:
1 edited

Legend:

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

    re731b0d r7e752b2  
    3838#include <interrupt.h>
    3939#include <mm/as.h>
     40#include <mm/page.h>
    4041#include <arch.h>
    4142#include <print.h>
     
    4445
    4546static unsigned int seed = 10;
    46 static unsigned int seed_real __attribute__ ((section("K_UNMAPPED_DATA_START"))) = 42;
    47 
     47static unsigned int seed_real
     48    __attribute__ ((section("K_UNMAPPED_DATA_START"))) = 42;
    4849
    4950/** Try to find PTE for faulting address
    5051 *
    51  * Try to find PTE for faulting address.
    52  * The as->lock must be held on entry to this function
    53  * if lock is true.
    54  *
    55  * @param as            Address space.
    56  * @param lock          Lock/unlock the address space.
    57  * @param badvaddr      Faulting virtual address.
    58  * @param access        Access mode that caused the fault.
    59  * @param istate        Pointer to interrupted state.
    60  * @param pfrc          Pointer to variable where as_page_fault() return code
    61  *                      will be stored.
    62  * @return              PTE on success, NULL otherwise.
    63  *
    64  */
    65 static pte_t *
    66 find_mapping_and_check(as_t *as, bool lock, uintptr_t badvaddr, int access,
     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 */
     63static pte_t *find_mapping_and_check(as_t *as, uintptr_t badvaddr, int access,
    6764    istate_t *istate, int *pfrc)
    6865{
     66        ASSERT(mutex_locked(&as->lock));
     67
    6968        /*
    7069         * Check if the mapping exists in page tables.
    71          */     
     70         */
    7271        pte_t *pte = page_mapping_find(as, badvaddr);
    7372        if ((pte) && (pte->present)) {
     
    7877                return pte;
    7978        } else {
    80                 int rc;
    81        
    8279                /*
    8380                 * Mapping not found in page tables.
    8481                 * Resort to higher-level page fault handler.
    8582                 */
    86                 page_table_unlock(as, lock);
    87                 switch (rc = as_page_fault(badvaddr, access, istate)) {
     83                page_table_unlock(as, true);
     84               
     85                int rc = as_page_fault(badvaddr, access, istate);
     86                switch (rc) {
    8887                case AS_PF_OK:
    8988                        /*
     
    9190                         * The mapping ought to be in place.
    9291                         */
    93                         page_table_lock(as, lock);
     92                        page_table_lock(as, true);
    9493                        pte = page_mapping_find(as, badvaddr);
    9594                        ASSERT((pte) && (pte->present));
     
    9796                        return pte;
    9897                case AS_PF_DEFER:
    99                         page_table_lock(as, lock);
     98                        page_table_lock(as, true);
    10099                        *pfrc = rc;
    101100                        return NULL;
    102101                case AS_PF_FAULT:
    103                         page_table_lock(as, lock);
     102                        page_table_lock(as, true);
    104103                        *pfrc = rc;
    105104                        return NULL;
    106105                default:
    107106                        panic("Unexpected rc (%d).", rc);
    108                 }       
    109         }
    110 }
    111 
     107                }
     108        }
     109}
    112110
    113111static void pht_refill_fail(uintptr_t badvaddr, istate_t *istate)
    114112{
    115         char *symbol;
    116         char *sym2;
    117 
    118         symbol = symtab_fmt_name_lookup(istate->pc);
    119         sym2 = symtab_fmt_name_lookup(istate->lr);
    120 
    121         fault_if_from_uspace(istate,
    122             "PHT Refill Exception on %p.", badvaddr);
    123         panic("%p: PHT Refill Exception at %p (%s<-%s).", badvaddr,
    124             istate->pc, symbol, sym2);
    125 }
    126 
     113        fault_if_from_uspace(istate, "PHT Refill Exception on %p.",
     114            (void *) badvaddr);
     115        panic_memtrap(istate, PF_ACCESS_UNKNOWN, badvaddr,
     116            "PHT Refill Exception.");
     117}
    127118
    128119static void pht_insert(const uintptr_t vaddr, const pte_t *pte)
     
    131122        uint32_t api = (vaddr >> 22) & 0x3f;
    132123       
    133         uint32_t vsid;
    134         asm volatile (
    135                 "mfsrin %0, %1\n"
    136                 : "=r" (vsid)
    137                 : "r" (vaddr)
    138         );
    139        
    140         uint32_t sdr1;
    141         asm volatile (
    142                 "mfsdr1 %0\n"
    143                 : "=r" (sdr1)
    144         );
     124        uint32_t vsid = sr_get(vaddr);
     125        uint32_t sdr1 = sdr1_get();
     126       
     127        // FIXME: compute size of PHT exactly
    145128        phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000);
    146129       
     
    217200}
    218201
    219 
    220202/** Process Instruction/Data Storage Exception
    221203 *
     
    224206 *
    225207 */
    226 void pht_refill(int n, istate_t *istate)
    227 {
     208void pht_refill(unsigned int n, istate_t *istate)
     209{
     210        as_t *as = (AS == NULL) ? AS_KERNEL : AS;
    228211        uintptr_t badvaddr;
    229         pte_t *pte;
    230         int pfrc;
    231         as_t *as;
    232         bool lock;
    233        
    234         if (AS == NULL) {
    235                 as = AS_KERNEL;
    236                 lock = false;
    237         } else {
    238                 as = AS;
    239                 lock = true;
    240         }
    241212       
    242213        if (n == VECTOR_DATA_STORAGE)
     
    244215        else
    245216                badvaddr = istate->pc;
    246                
    247         page_table_lock(as, lock);
    248        
    249         pte = find_mapping_and_check(as, lock, badvaddr,
     217       
     218        page_table_lock(as, true);
     219       
     220        int pfrc;
     221        pte_t *pte = find_mapping_and_check(as, badvaddr,
    250222            PF_ACCESS_READ /* FIXME */, istate, &pfrc);
     223       
    251224        if (!pte) {
    252225                switch (pfrc) {
     
    259232                         * or copy_to_uspace().
    260233                         */
    261                         page_table_unlock(as, lock);
     234                        page_table_unlock(as, true);
    262235                        return;
    263236                default:
     
    266239        }
    267240       
    268         pte->accessed = 1; /* Record access to PTE */
     241        /* Record access to PTE */
     242        pte->accessed = 1;
    269243        pht_insert(badvaddr, pte);
    270244       
    271         page_table_unlock(as, lock);
     245        page_table_unlock(as, true);
    272246        return;
    273247       
    274248fail:
    275         page_table_unlock(as, lock);
     249        page_table_unlock(as, true);
    276250        pht_refill_fail(badvaddr, istate);
    277251}
    278 
    279252
    280253/** Process Instruction/Data Storage Exception in Real Mode
     
    284257 *
    285258 */
    286 bool pht_refill_real(int n, istate_t *istate)
     259bool pht_refill_real(unsigned int n, istate_t *istate)
    287260{
    288261        uintptr_t badvaddr;
     
    293266                badvaddr = istate->pc;
    294267       
    295         uint32_t physmem;
    296         asm volatile (
    297                 "mfsprg3 %0\n"
    298                 : "=r" (physmem)
    299         );
     268        uint32_t physmem = physmem_top();
    300269       
    301270        if ((badvaddr < PA2KA(0)) || (badvaddr >= PA2KA(physmem)))
     
    305274        uint32_t api = (badvaddr >> 22) & 0x3f;
    306275       
    307         uint32_t vsid;
    308         asm volatile (
    309                 "mfsrin %0, %1\n"
    310                 : "=r" (vsid)
    311                 : "r" (badvaddr)
    312         );
    313        
    314         uint32_t sdr1;
    315         asm volatile (
    316                 "mfsdr1 %0\n"
    317                 : "=r" (sdr1)
    318         );
     276        uint32_t vsid = sr_get(badvaddr);
     277        uint32_t sdr1 = sdr1_get();
     278       
     279        // FIXME: compute size of PHT exactly
    319280        phte_t *phte_real = (phte_t *) (sdr1 & 0xffff0000);
    320281       
     
    398359}
    399360
    400 
    401361/** Process ITLB/DTLB Miss Exception in Real Mode
    402362 *
    403363 *
    404364 */
    405 void tlb_refill_real(int n, uint32_t tlbmiss, ptehi_t ptehi, ptelo_t ptelo, istate_t *istate)
     365void tlb_refill_real(unsigned int n, uint32_t tlbmiss, ptehi_t ptehi,
     366    ptelo_t ptelo, istate_t *istate)
    406367{
    407368        uint32_t badvaddr = tlbmiss & 0xfffffffc;
    408        
    409         uint32_t physmem;
    410         asm volatile (
    411                 "mfsprg3 %0\n"
    412                 : "=r" (physmem)
    413         );
     369        uint32_t physmem = physmem_top();
    414370       
    415371        if ((badvaddr < PA2KA(0)) || (badvaddr >= PA2KA(physmem)))
     
    422378        uint32_t index = 0;
    423379        asm volatile (
    424                 "mtspr 981, %0\n"
    425                 "mtspr 982, %1\n"
    426                 "tlbld %2\n"
    427                 "tlbli %2\n"
    428                 : "=r" (index)
    429                 : "r" (ptehi),
    430                   "r" (ptelo)
     380                "mtspr 981, %[ptehi]\n"
     381                "mtspr 982, %[ptelo]\n"
     382                "tlbld %[index]\n"
     383                "tlbli %[index]\n"
     384                : [index] "=r" (index)
     385                : [ptehi] "r" (ptehi),
     386                  [ptelo] "r" (ptelo)
    431387        );
    432388}
    433389
    434 
    435390void tlb_arch_init(void)
    436391{
     
    438393}
    439394
    440 
    441395void tlb_invalidate_all(void)
    442396{
    443397        uint32_t index;
     398       
    444399        asm volatile (
    445                 "li %0, 0\n"
     400                "li %[index], 0\n"
    446401                "sync\n"
    447402               
    448403                ".rept 64\n"
    449                 "tlbie %0\n"
    450                 "addi %0, %0, 0x1000\n"
     404                "       tlbie %[index]\n"
     405                "       addi %[index], %[index], 0x1000\n"
    451406                ".endr\n"
    452407               
     
    454409                "tlbsync\n"
    455410                "sync\n"
    456                 : "=r" (index)
     411                : [index] "=r" (index)
    457412        );
    458413}
    459414
    460 
    461415void tlb_invalidate_asid(asid_t asid)
    462416{
    463         uint32_t sdr1;
    464         asm volatile (
    465                 "mfsdr1 %0\n"
    466                 : "=r" (sdr1)
    467         );
     417        uint32_t sdr1 = sdr1_get();
     418       
     419        // FIXME: compute size of PHT exactly
    468420        phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000);
    469421       
    470         uint32_t i;
     422        size_t i;
    471423        for (i = 0; i < 8192; i++) {
    472424                if ((phte[i].v) && (phte[i].vsid >= (asid << 4)) &&
     
    474426                        phte[i].v = 0;
    475427        }
     428       
    476429        tlb_invalidate_all();
    477430}
    478 
    479431
    480432void tlb_invalidate_pages(asid_t asid, uintptr_t page, size_t cnt)
     
    484436}
    485437
    486 
    487438#define PRINT_BAT(name, ureg, lreg) \
    488439        asm volatile ( \
    489                 "mfspr %0," #ureg "\n" \
    490                 "mfspr %1," #lreg "\n" \
    491                 : "=r" (upper), "=r" (lower) \
     440                "mfspr %[upper], " #ureg "\n" \
     441                "mfspr %[lower], " #lreg "\n" \
     442                : [upper] "=r" (upper), \
     443                  [lower] "=r" (lower) \
    492444        ); \
     445        \
    493446        mask = (upper & 0x1ffc) >> 2; \
    494447        if (upper & 3) { \
    495448                uint32_t tmp = mask; \
    496449                length = 128; \
     450                \
    497451                while (tmp) { \
    498452                        if ((tmp & 1) == 0) { \
     
    505459        } else \
    506460                length = 0; \
    507         printf(name ": page=%.*p frame=%.*p length=%d KB (mask=%#x)%s%s\n", \
    508             sizeof(upper) * 2, upper & 0xffff0000, sizeof(lower) * 2, \
    509             lower & 0xffff0000, length, mask, \
     461        \
     462        printf(name ": page=%#0" PRIx32 " frame=%#0" PRIx32 \
     463            " length=%#0" PRIx32 " KB (mask=%#0" PRIx32 ")%s%s\n", \
     464            upper & UINT32_C(0xffff0000), lower & UINT32_C(0xffff0000), \
     465            length, mask, \
    510466            ((upper >> 1) & 1) ? " supervisor" : "", \
    511467            (upper & 1) ? " user" : "");
    512468
    513 
    514469void tlb_print(void)
    515470{
     
    517472       
    518473        for (sr = 0; sr < 16; sr++) {
    519                 uint32_t vsid;
    520                 asm volatile (
    521                         "mfsrin %0, %1\n"
    522                         : "=r" (vsid)
    523                         : "r" (sr << 28)
    524                 );
    525                 printf("sr[%02u]: vsid=%.*p (asid=%u)%s%s\n", sr,
    526                     sizeof(vsid) * 2, vsid & 0xffffff, (vsid & 0xffffff) >> 4,
     474                uint32_t vsid = sr_get(sr << 28);
     475               
     476                printf("sr[%02" PRIu32 "]: vsid=%#0" PRIx32 " (asid=%" PRIu32 ")"
     477                    "%s%s\n", sr, vsid & UINT32_C(0x00ffffff),
     478                    (vsid & UINT32_C(0x00ffffff)) >> 4,
    527479                    ((vsid >> 30) & 1) ? " supervisor" : "",
    528480                    ((vsid >> 29) & 1) ? " user" : "");
Note: See TracChangeset for help on using the changeset viewer.