void local_flush_tlb_all(void) { unsigned long flags; unsigned long old_ctx; int entry; ENTER_CRITICAL(flags); /* Save old context and create impossible VPN2 value */ old_ctx = read_c0_entryhi(); write_c0_entrylo0(0); write_c0_entrylo1(0); entry = read_c0_wired(); /* Blast 'em all away. */ while (entry < current_cpu_data.tlbsize) { /* Make sure all entries differ. */ write_c0_entryhi(UNIQUE_ENTRYHI(entry)); write_c0_index(entry); mtc0_tlbw_hazard(); tlb_write_indexed(); entry++; } tlbw_use_hazard(); write_c0_entryhi(old_ctx); FLUSH_ITLB; EXIT_CRITICAL(flags); }
/* Initialize the wired register and all tlb entries to * known good state. */ void __init early_tlb_init(void) { unsigned long index; struct cpuinfo_mips *c = ¤t_cpu_data; tmp_tlb_ent = c->tlbsize; /* printk(KERN_ALERT "%s: tlb size %ld\n", __FUNCTION__, c->tlbsize); */ /* * initialize entire TLB to uniqe virtual addresses * but with the PAGE_VALID bit not set */ write_c0_pagemask(PM_DEFAULT_MASK); write_c0_wired(0); write_c0_entrylo0(0); /* not _PAGE_VALID */ write_c0_entrylo1(0); for (index = 0; index < c->tlbsize; index++) { /* Make sure all entries differ. */ write_c0_entryhi(UNIQUE_ENTRYHI(index+32)); write_c0_index(index); mtc0_tlbw_hazard(); tlb_write_indexed(); } tlbw_use_hazard(); }
void local_flush_tlb_all(void) { unsigned long flags; unsigned long old_ctx; unsigned long entry; #ifdef DEBUG_TLB printk("[tlball]"); #endif local_irq_save(flags); /* Save old context and create impossible VPN2 value */ old_ctx = read_c0_entryhi() & ASID_MASK; write_c0_entryhi(CKSEG0); write_c0_entrylo0(0); write_c0_entrylo1(0); entry = read_c0_wired(); /* Blast 'em all away. */ while (entry < NTLB_ENTRIES) { write_c0_index(entry); tlb_write_indexed(); entry++; } write_c0_entryhi(old_ctx); local_irq_restore(flags); }
void local_flush_tlb_all(void) { unsigned long flags; unsigned long old_ctx; int entry; #ifdef DEBUG_TLB printk("[tlball]"); #endif local_irq_save(flags); /* Save old context and create impossible VPN2 value */ old_ctx = (read_c0_entryhi() & ASID_MASK); write_c0_entryhi(XKPHYS); write_c0_entrylo0(0); write_c0_entrylo1(0); BARRIER; entry = read_c0_wired(); /* Blast 'em all away. */ while(entry < current_cpu_data.tlbsize) { /* Make sure all entries differ. */ write_c0_entryhi(XKPHYS+entry*0x2000); write_c0_index(entry); BARRIER; tlb_write_indexed(); BARRIER; entry++; } BARRIER; write_c0_entryhi(old_ctx); local_irq_restore(flags); }
void write_one_tlb(int index, u32 pagemask, u32 hi, u32 low0, u32 low1) { write_c0_entrylo0(low0); write_c0_pagemask(pagemask); write_c0_entrylo1(low1); write_c0_entryhi(hi); write_c0_index(index); tlb_write_indexed(); }
void tlb_init() { int index; write_c0_entrylo0((DEFAULT_PHY_ADDR|TLB_COHERENT | TLB_VALID | TLB_DIRTY | TLB_GLOBAL)^TLB_GLOBAL); write_c0_entrylo1((TLB_ELO0TO1(DEFAULT_PHY_ADDR)|TLB_COHERENT | TLB_VALID | TLB_DIRTY | TLB_GLOBAL)^TLB_GLOBAL); for(index=0;index<TLB_SIZE;index++) { write_c0_index(index); write_c0_entryhi(IVLD_ASID|(index<<13)); tlbwi(); } write_c0_entryhi(0x0); }
static void ipu_add_wired_entry(unsigned long pid, unsigned long entrylo0, unsigned long entrylo1, unsigned long entryhi, unsigned long pagemask) { unsigned long flags; unsigned long wired; unsigned long old_pagemask; unsigned long old_ctx; struct task_struct *g, *p; /* We will lock an 4MB page size entry to map the 4MB reserved IPU memory */ wired = read_c0_wired(); if (wired) return; do_each_thread(g, p) { if (p->pid == pid ) g_asid = p->mm->context[0]; } while_each_thread(g, p); local_irq_save(flags); entrylo0 = entrylo0 >> 6; /* PFN */ entrylo0 |= 0x6 | (0 << 3); /* Write-through cacheable, dirty, valid */ /* Save old context and create impossible VPN2 value */ old_ctx = read_c0_entryhi() & 0xff; old_pagemask = read_c0_pagemask(); wired = read_c0_wired(); write_c0_wired(wired + 1); write_c0_index(wired); BARRIER; entryhi &= ~0xff; /* new add, 20070906 */ entryhi |= g_asid; /* new add, 20070906 */ // entryhi |= old_ctx; /* new add, 20070906 */ write_c0_pagemask(pagemask); write_c0_entryhi(entryhi); write_c0_entrylo0(entrylo0); write_c0_entrylo1(entrylo1); BARRIER; tlb_write_indexed(); BARRIER; write_c0_entryhi(old_ctx); BARRIER; write_c0_pagemask(old_pagemask); local_flush_tlb_all(); local_irq_restore(flags); #if defined(DEBUG) printk("\nold_ctx=%03d\n", old_ctx); show_tlb(); #endif }
void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { struct mm_struct *mm = vma->vm_mm; int cpu = smp_processor_id(); if (cpu_context(cpu, mm) != 0) { unsigned long size, flags; unsigned long config6_flags; ENTER_CRITICAL(flags); disable_pgwalker(config6_flags); size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; size = (size + 1) >> 1; if (size <= current_cpu_data.tlbsize/2) { int oldpid = read_c0_entryhi(); int newpid = cpu_asid(cpu, mm); start &= (PAGE_MASK << 1); end += ((PAGE_SIZE << 1) - 1); end &= (PAGE_MASK << 1); while (start < end) { int idx; write_c0_entryhi(start | newpid); start += (PAGE_SIZE << 1); mtc0_tlbw_hazard(); tlb_probe(); tlb_probe_hazard(); idx = read_c0_index(); write_c0_entrylo0(0); write_c0_entrylo1(0); if (idx < 0) continue; /* Make sure all entries differ. */ #ifndef CONFIG_NLM_VMIPS write_c0_entryhi(UNIQUE_ENTRYHI(idx)); #else __write_64bit_c0_register($10, 0, (UNIQUE_VMIPS_ENTRYHI(idx))); #endif mtc0_tlbw_hazard(); tlb_write_indexed(); } tlbw_use_hazard(); write_c0_entryhi(oldpid); } else { drop_mmu_context(mm, cpu); } FLUSH_ITLB; enable_pgwalker(config6_flags); EXIT_CRITICAL(flags); }
void local_flush_tlb_all(void) { unsigned long flags; unsigned long old_ctx; int entry, ftlbhighset; local_irq_save(flags); /* Save old context and create impossible VPN2 value */ old_ctx = read_c0_entryhi(); htw_stop(); write_c0_entrylo0(0); write_c0_entrylo1(0); entry = read_c0_wired(); /* * Blast 'em all away. * If there are any wired entries, fall back to iterating */ if (cpu_has_tlbinv && !entry) { if (current_cpu_data.tlbsizevtlb) { write_c0_index(0); mtc0_tlbw_hazard(); tlbinvf(); /* invalidate VTLB */ } ftlbhighset = current_cpu_data.tlbsizevtlb + current_cpu_data.tlbsizeftlbsets; for (entry = current_cpu_data.tlbsizevtlb; entry < ftlbhighset; entry++) { write_c0_index(entry); mtc0_tlbw_hazard(); tlbinvf(); /* invalidate one FTLB set */ } } else { while (entry < current_cpu_data.tlbsize) { /* Make sure all entries differ. */ write_c0_entryhi(UNIQUE_ENTRYHI(entry)); write_c0_index(entry); mtc0_tlbw_hazard(); tlb_write_indexed(); entry++; } } tlbw_use_hazard(); write_c0_entryhi(old_ctx); htw_start(); flush_micro_tlb(); local_irq_restore(flags); }
void __init add_tmptlb_entry(unsigned long entrylo0, unsigned long entrylo1, unsigned long entryhi, unsigned long pagemask) { /* write one tlb entry */ --tmp_tlb_ent; write_c0_index(tmp_tlb_ent); write_c0_pagemask(pagemask); write_c0_entryhi(entryhi); write_c0_entrylo0(entrylo0); write_c0_entrylo1(entrylo1); mtc0_tlbw_hazard(); tlb_write_indexed(); tlbw_use_hazard(); }
void local_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) { int cpu = smp_processor_id(); if (cpu_context(cpu, mm) != 0) { unsigned long flags; int size; #ifdef DEBUG_TLB printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & ASID_MASK), start, end); #endif local_irq_save(flags); size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; size = (size + 1) >> 1; if(size <= current_cpu_data.tlbsize/2) { int oldpid = read_c0_entryhi() & ASID_MASK; int newpid = cpu_asid(cpu, mm); start &= (PAGE_MASK << 1); end += ((PAGE_SIZE << 1) - 1); end &= (PAGE_MASK << 1); while(start < end) { int idx; write_c0_entryhi(start | newpid); start += (PAGE_SIZE << 1); BARRIER; tlb_probe(); BARRIER; idx = read_c0_index(); write_c0_entrylo0(0); write_c0_entrylo1(0); if(idx < 0) continue; /* Make sure all entries differ. */ write_c0_entryhi(XKPHYS+idx*0x2000); BARRIER; tlb_write_indexed(); BARRIER; } write_c0_entryhi(oldpid); } else { drop_mmu_context(mm, cpu); } local_irq_restore(flags); }
void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { struct mm_struct *mm = vma->vm_mm; int cpu = smp_processor_id(); if (cpu_context(cpu, mm) != 0) { unsigned long size, flags; local_irq_save(flags); start = round_down(start, PAGE_SIZE << 1); end = round_up(end, PAGE_SIZE << 1); size = (end - start) >> (PAGE_SHIFT + 1); if (size <= (current_cpu_data.tlbsizeftlbsets ? current_cpu_data.tlbsize / 8 : current_cpu_data.tlbsize / 2)) { int oldpid = read_c0_entryhi(); int newpid = cpu_asid(cpu, mm); htw_stop(); while (start < end) { int idx; write_c0_entryhi(start | newpid); start += (PAGE_SIZE << 1); mtc0_tlbw_hazard(); tlb_probe(); tlb_probe_hazard(); idx = read_c0_index(); write_c0_entrylo0(0); write_c0_entrylo1(0); if (idx < 0) continue; /* Make sure all entries differ. */ write_c0_entryhi(UNIQUE_ENTRYHI(idx)); mtc0_tlbw_hazard(); tlb_write_indexed(); } tlbw_use_hazard(); write_c0_entryhi(oldpid); htw_start(); } else { drop_mmu_context(mm, cpu); } flush_micro_tlb(); local_irq_restore(flags); }
void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { struct mm_struct *mm = vma->vm_mm; int cpu = smp_processor_id(); if (cpu_context(cpu, mm) != 0) { unsigned long flags; int size; ENTER_CRITICAL(flags); size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; size = (size + 1) >> 1; local_irq_save(flags); if (size <= current_cpu_data.tlbsize/2) { int oldpid = read_c0_entryhi(); int newpid = cpu_asid(cpu, mm); start &= (PAGE_MASK << 1); end += ((PAGE_SIZE << 1) - 1); end &= (PAGE_MASK << 1); while (start < end) { int idx; write_c0_entryhi(start | newpid); start += (PAGE_SIZE << 1); mtc0_tlbw_hazard(); tlb_probe(); tlb_probe_hazard(); idx = read_c0_index(); write_c0_entrylo0(0); write_c0_entrylo1(0); if (idx < 0) continue; /* Make sure all entries differ. */ write_c0_entryhi(UNIQUE_ENTRYHI(idx)); mtc0_tlbw_hazard(); tlb_write_indexed(); } tlbw_use_hazard(); write_c0_entryhi(oldpid); } else { drop_mmu_context(mm, cpu); } EXIT_CRITICAL(flags); }
static void ipu_add_wired_entry(unsigned long pid, unsigned long entrylo0, unsigned long entrylo1, unsigned long entryhi, unsigned long pagemask) { unsigned long flags; unsigned long wired; unsigned long old_pagemask; unsigned long old_ctx; struct task_struct *g, *p; do_each_thread(g, p) { if (p->pid == pid ) g_asid = p->mm->context[0]; } while_each_thread(g, p); local_irq_save(flags); /* Save old context and create impossible VPN2 value */ old_ctx = read_c0_entryhi() & 0xff; old_pagemask = read_c0_pagemask(); wired = read_c0_wired(); write_c0_wired(wired + 1); write_c0_index(wired); BARRIER; entryhi &= ~0xff; /* new add, 20070906 */ entryhi |= g_asid; /* new add, 20070906 */ // entryhi |= old_ctx; /* new add, 20070906 */ write_c0_pagemask(pagemask); write_c0_entryhi(entryhi); write_c0_entrylo0(entrylo0); write_c0_entrylo1(entrylo1); BARRIER; tlb_write_indexed(); BARRIER; write_c0_entryhi(old_ctx); BARRIER; write_c0_pagemask(old_pagemask); local_flush_tlb_all(); local_irq_restore(flags); #if defined(DEBUG) printk("\nold_ctx=%03d\n", old_ctx); show_tlb(); #endif }
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; }
void local_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) { int cpu = smp_processor_id(); if (cpu_context(cpu, mm) != 0) { unsigned long flags; int size; #ifdef DEBUG_TLB printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & ASID_MASK), start, end); #endif local_irq_save(flags); size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; size = (size + 1) >> 1; if (size <= NTLB_ENTRIES_HALF) { int oldpid = (read_c0_entryhi() & ASID_MASK); int newpid = (cpu_context(smp_processor_id(), mm) & ASID_MASK); start &= (PAGE_MASK << 1); end += ((PAGE_SIZE << 1) - 1); end &= (PAGE_MASK << 1); while(start < end) { int idx; write_c0_entryhi(start | newpid); start += (PAGE_SIZE << 1); tlb_probe(); idx = read_c0_index(); write_c0_entrylo0(0); write_c0_entrylo1(0); write_c0_entryhi(KSEG0); if(idx < 0) continue; tlb_write_indexed(); } write_c0_entryhi(oldpid); } else { drop_mmu_context(mm, cpu); } local_irq_restore(flags); }
/** @brief Flush memory range If the memory range is too big, we flush all entries with this ASID */ void local_flush_tlb_range(unsigned int asid, unsigned long start, unsigned long end) { unsigned long size, flags; ENTER_CRITICAL(flags); size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; size = (size + 1) >> 1; if (size <= current_cpu_data.tlbsize / 2) { int oldpid = read_c0_entryhi(); int newpid = asid; start &= (PAGE_MASK << 1); end += ((PAGE_SIZE << 1) - 1); end &= (PAGE_MASK << 1); while (start < end) { int idx; write_c0_entryhi(start | newpid); start += (PAGE_SIZE << 1); mtc0_tlbw_hazard(); tlb_probe(); tlb_probe_hazard(); idx = read_c0_index(); write_c0_entrylo0(0); write_c0_entrylo1(0); if (idx < 0) continue; /* Make sure all entries differ. */ write_c0_entryhi(UNIQUE_ENTRYHI(idx)); mtc0_tlbw_hazard(); tlb_write_indexed(); } tlbw_use_hazard(); write_c0_entryhi(oldpid); } else local_flush_asid(asid); FLUSH_ITLB; EXIT_CRITICAL(flags); }
void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { struct mm_struct *mm = vma->vm_mm; int cpu = smp_processor_id(); if (cpu_context(cpu, mm) != 0) { unsigned long flags; int size; #ifdef DEBUG_TLB printk("[tlbrange<%lu,0x%08lx,0x%08lx>]", cpu_context(cpu, mm) & ASID_MASK, start, end); #endif local_irq_save(flags); size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; if (size <= current_cpu_data.tlbsize) { int oldpid = read_c0_entryhi() & ASID_MASK; int newpid = cpu_context(cpu, mm) & ASID_MASK; start &= PAGE_MASK; end += PAGE_SIZE - 1; end &= PAGE_MASK; while (start < end) { int idx; write_c0_entryhi(start | newpid); start += PAGE_SIZE; /* BARRIER */ tlb_probe(); idx = read_c0_index(); write_c0_entrylo0(0); write_c0_entryhi(KSEG0); if (idx < 0) /* BARRIER */ continue; tlb_write_indexed(); } write_c0_entryhi(oldpid); } else { drop_mmu_context(mm, cpu); } local_irq_restore(flags); }
static int add_wired_tlb_entry(uint32_t entrylo0, uint32_t entrylo1, uint32_t entryhi, uint32_t pgsize) { uint32_t tlbindex; tlbindex = read_c0_wired(); if (tlbindex >= get_tlb_size() || tlbindex >= C0_WIRED_MASK) { printk(BIOS_ERR, "Ran out of TLB entries\n"); return -1; } write_c0_wired(tlbindex + 1); write_c0_index(tlbindex); write_c0_pagemask(((pgsize / MIN_PAGE_SIZE) - 1) << C0_PAGEMASK_SHIFT); write_c0_entryhi(entryhi); write_c0_entrylo0(entrylo0); write_c0_entrylo1(entrylo1); mtc0_tlbw_hazard(); tlb_write_indexed(); tlbw_use_hazard(); return 0; }
void local_flush_tlb_all(void) { unsigned long flags, config6_flags; unsigned long old_ctx; int entry; ENTER_CRITICAL(flags); disable_pgwalker(config6_flags); /* Save old context and create impossible VPN2 value */ old_ctx = read_c0_entryhi(); write_c0_entrylo0(0); write_c0_entrylo1(0); entry = read_c0_wired(); #if defined(CONFIG_MAPPED_KERNEL) if (!entry) printk("[%s] flushing entry=%d in MAPPED_KERNEL mode!\n", __FUNCTION__, entry); #endif /* Blast 'em all away. */ while (entry < current_cpu_data.tlbsize) { /* Make sure all entries differ. */ #ifndef CONFIG_NLM_VMIPS write_c0_entryhi(UNIQUE_ENTRYHI(entry)); #else __write_64bit_c0_register($10, 0, (UNIQUE_VMIPS_ENTRYHI(entry))); #endif write_c0_index(entry); mtc0_tlbw_hazard(); tlb_write_indexed(); entry++; } tlbw_use_hazard(); write_c0_entryhi(old_ctx); FLUSH_ITLB; enable_pgwalker(config6_flags); EXIT_CRITICAL(flags); }
/* TLB operations. */ void local_flush_tlb_all(void) { unsigned long flags; unsigned long old_ctx; int entry; #ifdef DEBUG_TLB printk("[tlball]"); #endif local_irq_save(flags); old_ctx = read_c0_entryhi() & ASID_MASK; write_c0_entrylo0(0); entry = r3k_have_wired_reg ? read_c0_wired() : 8; for (; entry < current_cpu_data.tlbsize; entry++) { write_c0_index(entry << 8); write_c0_entryhi((entry | 0x80000) << 12); BARRIER; tlb_write_indexed(); } write_c0_entryhi(old_ctx); local_irq_restore(flags); }