static void refill_tbl_to(struct km_walk_ctx * ctx, unsigned int asid, int write, int pos) { unsigned long entry, oldl1, oldl2; unsigned long G_FLAG; int idx; int oldpid; /* Just test ASID consistency: Current ASID must equal to Given ASID, kernel process do not obay this rule. */ oldpid = read_c0_entryhi(); /* Entry HI */ asid = asid & CPU_PAGE_FALG_ASID_MASK; entry = get_vpn2(ctx->current_virtual_address); entry |= asid; write_c0_entryhi(entry); mtc0_tlbw_hazard(); tlb_probe(); tlb_probe_hazard(); idx = read_c0_index(); oldl1 = read_c0_entrylo0(); oldl2 = read_c0_entrylo1(); /* Add the G_FLAG if ASID == 0, because the entry is from kernel and shared by all process */ G_FLAG = (ctx->mem == &kp_get_system()->mem_ctx)? 1 : 0; /* Entry Low0 and Low1 */ WRITE_LO; /* Write by type, the write is random if the TLB entry is flushed for R/W flags changing */ mtc0_tlbw_hazard(); if (unlikely(idx < 0)) tlb_write_random(); else { if (write == 2) { printk("Write is forced index for %x, pos %d, idx %d,asid %d, %x %x.\n", ctx->current_virtual_address, pos, idx, asid, oldl1, oldl2); } tlb_write_indexed(); } tlbw_use_hazard(); /* Sanity: Just test ASID consistency: Current ASID must equal to Given ASID, kernel process do not obey this rule. */ if ((oldpid & 0xff) != (asid & 0xff) && asid != 0/*kernel asid*/) printk("Why old = %x, asid = %x. ", oldpid, asid); }
asmlinkage void xtlb_refill_debug(struct pt_regs *regs) { unsigned long addr; pgd_t *pgd; pmd_t *pmd; pte_t *pte; addr = regs->cp0_badvaddr & ~((PAGE_SIZE << 1) - 1); pgd = pgd_offset(current->active_mm, addr); pmd = pmd_offset(pgd, addr); pte = pte_offset(pmd, addr); write_c0_entrylo0(pte_val(pte[0]) >> 6); write_c0_entrylo1(pte_val(pte[1]) >> 6); __asm__ __volatile__("nop;nop;nop"); tlb_write_random(); }
/** @brief Refill the TLB entry @note Have to in interrupt disabled */ static void refill_tbl(struct km_walk_ctx * ctx) { unsigned char asid; unsigned long entry; unsigned long G_FLAG; /* Entry HI */ asid = ctx->mem->asid & CPU_PAGE_FALG_ASID_MASK; entry = get_vpn2(ctx->current_virtual_address); entry |= asid; write_c0_entryhi(entry); /* Add the G_FLAG if ASID == 0, because the entry is from kernel and shared by all process */ G_FLAG = (ctx->mem == &kp_get_system()->mem_ctx)? 1 : 0; /* Entry Low0 and Low1 */ WRITE_LO; /* Write by type */ mtc0_tlbw_hazard(); tlb_write_random(); tlbw_use_hazard(); }