Ignore:
File:
1 edited

Legend:

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

    r26aafe8 r7e752b2  
    4444#include <symtab.h>
    4545
    46 static unsigned int seed = 42;
     46static unsigned int seed = 10;
     47static unsigned int seed_real
     48    __attribute__ ((section("K_UNMAPPED_DATA_START"))) = 42;
    4749
    4850/** Try to find PTE for faulting address
     
    223225                switch (pfrc) {
    224226                case AS_PF_FAULT:
    225                         page_table_unlock(as, true);
    226                         pht_refill_fail(badvaddr, istate);
    227                         return;
     227                        goto fail;
     228                        break;
    228229                case AS_PF_DEFER:
    229230                        /*
     
    243244       
    244245        page_table_unlock(as, true);
    245 }
    246 
    247 void tlb_refill(unsigned int n, istate_t *istate)
    248 {
    249         uint32_t tlbmiss;
    250         ptehi_t ptehi;
    251         ptelo_t ptelo;
    252        
    253         asm volatile (
    254                 "mfspr %[tlbmiss], 980\n"
    255                 "mfspr %[ptehi], 981\n"
    256                 "mfspr %[ptelo], 982\n"
    257                 : [tlbmiss] "=r" (tlbmiss),
    258                   [ptehi] "=r" (ptehi),
    259                   [ptelo] "=r" (ptelo)
    260         );
    261        
     246        return;
     247       
     248fail:
     249        page_table_unlock(as, true);
     250        pht_refill_fail(badvaddr, istate);
     251}
     252
     253/** Process Instruction/Data Storage Exception in Real Mode
     254 *
     255 * @param n      Exception vector number.
     256 * @param istate Interrupted register context.
     257 *
     258 */
     259bool pht_refill_real(unsigned int n, istate_t *istate)
     260{
     261        uintptr_t badvaddr;
     262       
     263        if (n == VECTOR_DATA_STORAGE)
     264                badvaddr = istate->dar;
     265        else
     266                badvaddr = istate->pc;
     267       
     268        uint32_t physmem = physmem_top();
     269       
     270        if ((badvaddr < PA2KA(0)) || (badvaddr >= PA2KA(physmem)))
     271                return false;
     272       
     273        uint32_t page = (badvaddr >> 12) & 0xffff;
     274        uint32_t api = (badvaddr >> 22) & 0x3f;
     275       
     276        uint32_t vsid = sr_get(badvaddr);
     277        uint32_t sdr1 = sdr1_get();
     278       
     279        // FIXME: compute size of PHT exactly
     280        phte_t *phte_real = (phte_t *) (sdr1 & 0xffff0000);
     281       
     282        /* Primary hash (xor) */
     283        uint32_t h = 0;
     284        uint32_t hash = vsid ^ page;
     285        uint32_t base = (hash & 0x3ff) << 3;
     286        uint32_t i;
     287        bool found = false;
     288       
     289        /* Find colliding PTE in PTEG */
     290        for (i = 0; i < 8; i++) {
     291                if ((phte_real[base + i].v)
     292                    && (phte_real[base + i].vsid == vsid)
     293                    && (phte_real[base + i].api == api)
     294                    && (phte_real[base + i].h == 0)) {
     295                        found = true;
     296                        break;
     297                }
     298        }
     299       
     300        if (!found) {
     301                /* Find unused PTE in PTEG */
     302                for (i = 0; i < 8; i++) {
     303                        if (!phte_real[base + i].v) {
     304                                found = true;
     305                                break;
     306                        }
     307                }
     308        }
     309       
     310        if (!found) {
     311                /* Secondary hash (not) */
     312                uint32_t base2 = (~hash & 0x3ff) << 3;
     313               
     314                /* Find colliding PTE in PTEG */
     315                for (i = 0; i < 8; i++) {
     316                        if ((phte_real[base2 + i].v)
     317                            && (phte_real[base2 + i].vsid == vsid)
     318                            && (phte_real[base2 + i].api == api)
     319                            && (phte_real[base2 + i].h == 1)) {
     320                                found = true;
     321                                base = base2;
     322                                h = 1;
     323                                break;
     324                        }
     325                }
     326               
     327                if (!found) {
     328                        /* Find unused PTE in PTEG */
     329                        for (i = 0; i < 8; i++) {
     330                                if (!phte_real[base2 + i].v) {
     331                                        found = true;
     332                                        base = base2;
     333                                        h = 1;
     334                                        break;
     335                                }
     336                        }
     337                }
     338               
     339                if (!found) {
     340                        /* Use secondary hash to avoid collisions
     341                           with usual PHT refill handler. */
     342                        i = RANDI(seed_real) % 8;
     343                        base = base2;
     344                        h = 1;
     345                }
     346        }
     347       
     348        phte_real[base + i].v = 1;
     349        phte_real[base + i].vsid = vsid;
     350        phte_real[base + i].h = h;
     351        phte_real[base + i].api = api;
     352        phte_real[base + i].rpn = KA2PA(badvaddr) >> 12;
     353        phte_real[base + i].r = 0;
     354        phte_real[base + i].c = 0;
     355        phte_real[base + i].wimg = 0;
     356        phte_real[base + i].pp = 2; // FIXME
     357       
     358        return true;
     359}
     360
     361/** Process ITLB/DTLB Miss Exception in Real Mode
     362 *
     363 *
     364 */
     365void tlb_refill_real(unsigned int n, uint32_t tlbmiss, ptehi_t ptehi,
     366    ptelo_t ptelo, istate_t *istate)
     367{
    262368        uint32_t badvaddr = tlbmiss & 0xfffffffc;
    263369        uint32_t physmem = physmem_top();
Note: See TracChangeset for help on using the changeset viewer.