/** Process TLB Refill Exception. * * @param istate Interrupted register context. * */ void tlb_refill(istate_t *istate) { uintptr_t badvaddr = cp0_badvaddr_read(); mutex_lock(&AS->lock); asid_t asid = AS->asid; mutex_unlock(&AS->lock); int pfrc; pte_t *pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ, istate, &pfrc); if (!pte) { switch (pfrc) { case AS_PF_FAULT: goto fail; break; case AS_PF_DEFER: /* * The page fault came during copy_from_uspace() * or copy_to_uspace(). */ return; default: panic("Unexpected pfrc (%d).", pfrc); } } /* * Record access to PTE. */ pte->a = 1; entry_lo_t lo; entry_hi_t hi; tlb_prepare_entry_hi(&hi, asid, badvaddr); tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->c, pte->frame); /* * New entry is to be inserted into TLB */ cp0_entry_hi_write(hi.value); if ((badvaddr / PAGE_SIZE) % 2 == 0) { cp0_entry_lo0_write(lo.value); cp0_entry_lo1_write(0); } else { cp0_entry_lo0_write(0); cp0_entry_lo1_write(lo.value); } cp0_pagemask_write(TLB_PAGE_MASK_16K); tlbwr(); return; fail: tlb_refill_fail(istate); }
void handle_tlb_refill(struct trapframe *tf) { unsigned long entryhi=read_c0_entryhi(); unsigned long vpn=TLB_VPN(entryhi); unsigned long pfn=pt[ENTRYHI_ASID(entryhi)][vpn]; if(pfn) { unsigned long entrylo=( TLB_PFN(pfn, entryhi) | TLB_COHERENT | TLB_VALID | TLB_DIRTY | TLB_GLOBAL)^TLB_GLOBAL; write_c0_entrylo0(entrylo); write_c0_entrylo1(TLB_ELO0TO1(entrylo)); tlbwr(); } else { kprintf("Fatal error, invalied page: %x with ASID= %d, rebooting...\n",vpn, ENTRYHI_ASID(entryhi)); unsigned long* reg=(unsigned long*)tf; write_c0_status((read_c0_status()|ST_KSU)^ST_KSU); reg[ORD_STATUS]=(read_c0_status()|ST_KSU)^ST_KSU; reg[ORD_EPC]=__reset; } return; }
/** Process TLB Refill Exception. * * @param istate Interrupted register context. * */ void tlb_refill(istate_t *istate) { uintptr_t badvaddr = cp0_badvaddr_read(); mutex_lock(&AS->lock); asid_t asid = AS->asid; mutex_unlock(&AS->lock); pte_t *pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ, istate); if (pte) { /* * Record access to PTE. */ pte->a = 1; entry_lo_t lo; entry_hi_t hi; tlb_prepare_entry_hi(&hi, asid, badvaddr); tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->c, pte->frame); /* * New entry is to be inserted into TLB */ cp0_entry_hi_write(hi.value); if ((badvaddr / PAGE_SIZE) % 2 == 0) { cp0_entry_lo0_write(lo.value); cp0_entry_lo1_write(0); } else { cp0_entry_lo0_write(0); cp0_entry_lo1_write(lo.value); } cp0_pagemask_write(TLB_PAGE_MASK_16K); tlbwr(); } }