Ejemplo n.º 1
0
/** 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;
}
Ejemplo n.º 3
0
/** 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();
	}
}