Ignore:
File:
1 edited

Legend:

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

    r7e752b2 re731b0d  
    3838#include <interrupt.h>
    3939#include <mm/as.h>
    40 #include <mm/page.h>
    4140#include <arch.h>
    4241#include <print.h>
     
    4544
    4645static unsigned int seed = 10;
    47 static unsigned int seed_real
    48     __attribute__ ((section("K_UNMAPPED_DATA_START"))) = 42;
     46static unsigned int seed_real __attribute__ ((section("K_UNMAPPED_DATA_START"))) = 42;
     47
    4948
    5049/** Try to find PTE for faulting address
    5150 *
    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,
     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 */
     65static pte_t *
     66find_mapping_and_check(as_t *as, bool lock, uintptr_t badvaddr, int access,
    6467    istate_t *istate, int *pfrc)
    6568{
    66         ASSERT(mutex_locked(&as->lock));
    67 
    6869        /*
    6970         * Check if the mapping exists in page tables.
    70          */
     71         */     
    7172        pte_t *pte = page_mapping_find(as, badvaddr);
    7273        if ((pte) && (pte->present)) {
     
    7778                return pte;
    7879        } else {
     80                int rc;
     81       
    7982                /*
    8083                 * Mapping not found in page tables.
    8184                 * Resort to higher-level page fault handler.
    8285                 */
    83                 page_table_unlock(as, true);
    84                
    85                 int rc = as_page_fault(badvaddr, access, istate);
    86                 switch (rc) {
     86                page_table_unlock(as, lock);
     87                switch (rc = as_page_fault(badvaddr, access, istate)) {
    8788                case AS_PF_OK:
    8889                        /*
     
    9091                         * The mapping ought to be in place.
    9192                         */
    92                         page_table_lock(as, true);
     93                        page_table_lock(as, lock);
    9394                        pte = page_mapping_find(as, badvaddr);
    9495                        ASSERT((pte) && (pte->present));
     
    9697                        return pte;
    9798                case AS_PF_DEFER:
    98                         page_table_lock(as, true);
     99                        page_table_lock(as, lock);
    99100                        *pfrc = rc;
    100101                        return NULL;
    101102                case AS_PF_FAULT:
    102                         page_table_lock(as, true);
     103                        page_table_lock(as, lock);
    103104                        *pfrc = rc;
    104105                        return NULL;
    105106                default:
    106107                        panic("Unexpected rc (%d).", rc);
    107                 }
    108         }
    109 }
     108                }       
     109        }
     110}
     111
    110112
    111113static void pht_refill_fail(uintptr_t badvaddr, istate_t *istate)
    112114{
    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 }
     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
    118127
    119128static void pht_insert(const uintptr_t vaddr, const pte_t *pte)
     
    122131        uint32_t api = (vaddr >> 22) & 0x3f;
    123132       
    124         uint32_t vsid = sr_get(vaddr);
    125         uint32_t sdr1 = sdr1_get();
    126        
    127         // FIXME: compute size of PHT exactly
     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        );
    128145        phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000);
    129146       
     
    200217}
    201218
     219
    202220/** Process Instruction/Data Storage Exception
    203221 *
     
    206224 *
    207225 */
    208 void pht_refill(unsigned int n, istate_t *istate)
    209 {
    210         as_t *as = (AS == NULL) ? AS_KERNEL : AS;
     226void pht_refill(int n, istate_t *istate)
     227{
    211228        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        }
    212241       
    213242        if (n == VECTOR_DATA_STORAGE)
     
    215244        else
    216245                badvaddr = istate->pc;
    217        
    218         page_table_lock(as, true);
    219        
    220         int pfrc;
    221         pte_t *pte = find_mapping_and_check(as, badvaddr,
     246               
     247        page_table_lock(as, lock);
     248       
     249        pte = find_mapping_and_check(as, lock, badvaddr,
    222250            PF_ACCESS_READ /* FIXME */, istate, &pfrc);
    223        
    224251        if (!pte) {
    225252                switch (pfrc) {
     
    232259                         * or copy_to_uspace().
    233260                         */
    234                         page_table_unlock(as, true);
     261                        page_table_unlock(as, lock);
    235262                        return;
    236263                default:
     
    239266        }
    240267       
    241         /* Record access to PTE */
    242         pte->accessed = 1;
     268        pte->accessed = 1; /* Record access to PTE */
    243269        pht_insert(badvaddr, pte);
    244270       
    245         page_table_unlock(as, true);
     271        page_table_unlock(as, lock);
    246272        return;
    247273       
    248274fail:
    249         page_table_unlock(as, true);
     275        page_table_unlock(as, lock);
    250276        pht_refill_fail(badvaddr, istate);
    251277}
     278
    252279
    253280/** Process Instruction/Data Storage Exception in Real Mode
     
    257284 *
    258285 */
    259 bool pht_refill_real(unsigned int n, istate_t *istate)
     286bool pht_refill_real(int n, istate_t *istate)
    260287{
    261288        uintptr_t badvaddr;
     
    266293                badvaddr = istate->pc;
    267294       
    268         uint32_t physmem = physmem_top();
     295        uint32_t physmem;
     296        asm volatile (
     297                "mfsprg3 %0\n"
     298                : "=r" (physmem)
     299        );
    269300       
    270301        if ((badvaddr < PA2KA(0)) || (badvaddr >= PA2KA(physmem)))
     
    274305        uint32_t api = (badvaddr >> 22) & 0x3f;
    275306       
    276         uint32_t vsid = sr_get(badvaddr);
    277         uint32_t sdr1 = sdr1_get();
    278        
    279         // FIXME: compute size of PHT exactly
     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        );
    280319        phte_t *phte_real = (phte_t *) (sdr1 & 0xffff0000);
    281320       
     
    359398}
    360399
     400
    361401/** Process ITLB/DTLB Miss Exception in Real Mode
    362402 *
    363403 *
    364404 */
    365 void tlb_refill_real(unsigned int n, uint32_t tlbmiss, ptehi_t ptehi,
    366     ptelo_t ptelo, istate_t *istate)
     405void tlb_refill_real(int n, uint32_t tlbmiss, ptehi_t ptehi, ptelo_t ptelo, istate_t *istate)
    367406{
    368407        uint32_t badvaddr = tlbmiss & 0xfffffffc;
    369         uint32_t physmem = physmem_top();
     408       
     409        uint32_t physmem;
     410        asm volatile (
     411                "mfsprg3 %0\n"
     412                : "=r" (physmem)
     413        );
    370414       
    371415        if ((badvaddr < PA2KA(0)) || (badvaddr >= PA2KA(physmem)))
     
    378422        uint32_t index = 0;
    379423        asm volatile (
    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)
    387         );
    388 }
     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)
     431        );
     432}
     433
    389434
    390435void tlb_arch_init(void)
     
    393438}
    394439
     440
    395441void tlb_invalidate_all(void)
    396442{
    397443        uint32_t index;
    398        
    399         asm volatile (
    400                 "li %[index], 0\n"
     444        asm volatile (
     445                "li %0, 0\n"
    401446                "sync\n"
    402447               
    403448                ".rept 64\n"
    404                 "       tlbie %[index]\n"
    405                 "       addi %[index], %[index], 0x1000\n"
     449                "tlbie %0\n"
     450                "addi %0, %0, 0x1000\n"
    406451                ".endr\n"
    407452               
     
    409454                "tlbsync\n"
    410455                "sync\n"
    411                 : [index] "=r" (index)
    412         );
    413 }
     456                : "=r" (index)
     457        );
     458}
     459
    414460
    415461void tlb_invalidate_asid(asid_t asid)
    416462{
    417         uint32_t sdr1 = sdr1_get();
    418        
    419         // FIXME: compute size of PHT exactly
     463        uint32_t sdr1;
     464        asm volatile (
     465                "mfsdr1 %0\n"
     466                : "=r" (sdr1)
     467        );
    420468        phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000);
    421469       
    422         size_t i;
     470        uint32_t i;
    423471        for (i = 0; i < 8192; i++) {
    424472                if ((phte[i].v) && (phte[i].vsid >= (asid << 4)) &&
     
    426474                        phte[i].v = 0;
    427475        }
    428        
    429476        tlb_invalidate_all();
    430477}
     478
    431479
    432480void tlb_invalidate_pages(asid_t asid, uintptr_t page, size_t cnt)
     
    436484}
    437485
     486
    438487#define PRINT_BAT(name, ureg, lreg) \
    439488        asm volatile ( \
    440                 "mfspr %[upper], " #ureg "\n" \
    441                 "mfspr %[lower], " #lreg "\n" \
    442                 : [upper] "=r" (upper), \
    443                   [lower] "=r" (lower) \
     489                "mfspr %0," #ureg "\n" \
     490                "mfspr %1," #lreg "\n" \
     491                : "=r" (upper), "=r" (lower) \
    444492        ); \
    445         \
    446493        mask = (upper & 0x1ffc) >> 2; \
    447494        if (upper & 3) { \
    448495                uint32_t tmp = mask; \
    449496                length = 128; \
    450                 \
    451497                while (tmp) { \
    452498                        if ((tmp & 1) == 0) { \
     
    459505        } else \
    460506                length = 0; \
    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, \
     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, \
    466510            ((upper >> 1) & 1) ? " supervisor" : "", \
    467511            (upper & 1) ? " user" : "");
    468512
     513
    469514void tlb_print(void)
    470515{
     
    472517       
    473518        for (sr = 0; sr < 16; sr++) {
    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,
     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,
    479527                    ((vsid >> 30) & 1) ? " supervisor" : "",
    480528                    ((vsid >> 29) & 1) ? " user" : "");
Note: See TracChangeset for help on using the changeset viewer.