diff options
author | Leonid Yegoshin <Leonid.Yegoshin@imgtec.com> | 2013-11-14 20:12:31 +0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2014-01-22 23:19:00 +0400 |
commit | 75b5b5e0a262790fa11043fe45700499c7e3d818 (patch) | |
tree | 3c5af9caa9c5478668159ff34db0ab34b51d7511 /arch/mips/mm/tlb-r4k.c | |
parent | 601cfa7b6fb657cff9e8f77bbcce79f75dd7ab74 (diff) | |
download | linux-75b5b5e0a262790fa11043fe45700499c7e3d818.tar.xz |
MIPS: Add support for FTLBs
The Fixed Page Size TLB (FTLB) is a set-associative dual entry TLB. Its
purpose is to reduce the number of TLB misses by increasing the effective
TLB size and keep the implementation complexity to minimum levels.
A supported core can have both VTLB and FTLB.
Reviewed-by: James Hogan <james.hogan@imgtec.com>
Reviewed-by: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
Signed-off-by: John Crispin <blogic@openwrt.org>
Patchwork: http://patchwork.linux-mips.org/patch/6139/
Diffstat (limited to 'arch/mips/mm/tlb-r4k.c')
-rw-r--r-- | arch/mips/mm/tlb-r4k.c | 29 |
1 files changed, 22 insertions, 7 deletions
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index 427dcacca586..ae4ca2450707 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -72,7 +72,7 @@ void local_flush_tlb_all(void) { unsigned long flags; unsigned long old_ctx; - int entry; + int entry, ftlbhighset; ENTER_CRITICAL(flags); /* Save old context and create impossible VPN2 value */ @@ -83,10 +83,21 @@ void local_flush_tlb_all(void) entry = read_c0_wired(); /* Blast 'em all away. */ - if (cpu_has_tlbinv && current_cpu_data.tlbsize) { - write_c0_index(0); - mtc0_tlbw_hazard(); - tlbinvf(); /* invalidate VTLB */ + if (cpu_has_tlbinv) { + 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. */ @@ -134,7 +145,9 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, 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.tlbsize/2) { + 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); @@ -173,7 +186,9 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) ENTER_CRITICAL(flags); size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; size = (size + 1) >> 1; - if (size <= current_cpu_data.tlbsize / 2) { + if (size <= (current_cpu_data.tlbsizeftlbsets ? + current_cpu_data.tlbsize / 8 : + current_cpu_data.tlbsize / 2)) { int pid = read_c0_entryhi(); start &= (PAGE_MASK << 1); |