aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHuacai Chen <chenhc@lemote.com>2016-03-02 20:45:11 -0500
committerRalf Baechle <ralf@linux-mips.org>2016-05-13 08:02:14 -0400
commit06e4814eec988f7ee01c29762f945b3ff59355fb (patch)
treed23c5f9cf1b096b3bc67f458a6b0984b664d7cbf
parent37fbe8faa94fa8cae889a3a793fd7b32508b26ab (diff)
MIPS: Loongson: Invalidate special TLBs when needed
Loongson-2 has a 4 entry itlb which is a subset of jtlb, Loongson-3 has a 4 entry itlb and a 4 entry dtlb which are subsets of jtlb. We should write diag register to invalidate itlb/dtlb when flushing jtlb because itlb/dtlb are not totally transparent to software. For Loongson-3A R2 (and newer), we should invalidate ITLB, DTLB, VTLB and FTLB before we enable/disable FTLB. Signed-off-by: Huacai Chen <chenhc@lemote.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: Steven J . Hill <sjhill@realitydiluted.com> Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12753/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/include/asm/mipsregs.h9
-rw-r--r--arch/mips/kernel/cpu-probe.c3
-rw-r--r--arch/mips/mm/tlb-r4k.c27
3 files changed, 27 insertions, 12 deletions
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 28ded49d25c6..0d0bd161fc10 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -780,6 +780,15 @@
780/* Disable Branch Return Cache */ 780/* Disable Branch Return Cache */
781#define R10K_DIAG_D_BRC (_ULCAST_(1) << 22) 781#define R10K_DIAG_D_BRC (_ULCAST_(1) << 22)
782 782
783/* Flush ITLB */
784#define LOONGSON_DIAG_ITLB (_ULCAST_(1) << 2)
785/* Flush DTLB */
786#define LOONGSON_DIAG_DTLB (_ULCAST_(1) << 3)
787/* Flush VTLB */
788#define LOONGSON_DIAG_VTLB (_ULCAST_(1) << 12)
789/* Flush FTLB */
790#define LOONGSON_DIAG_FTLB (_ULCAST_(1) << 13)
791
783/* 792/*
784 * Coprocessor 1 (FPU) register names 793 * Coprocessor 1 (FPU) register names
785 */ 794 */
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 2bfd48375b46..515dd1f8901e 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -563,6 +563,9 @@ static int set_ftlb_enable(struct cpuinfo_mips *c, int enable)
563 << MIPS_CONF7_FTLBP_SHIFT)); 563 << MIPS_CONF7_FTLBP_SHIFT));
564 break; 564 break;
565 case CPU_LOONGSON3: 565 case CPU_LOONGSON3:
566 /* Flush ITLB, DTLB, VTLB and FTLB */
567 write_c0_diag(LOONGSON_DIAG_ITLB | LOONGSON_DIAG_DTLB |
568 LOONGSON_DIAG_VTLB | LOONGSON_DIAG_FTLB);
566 /* Loongson-3 cores use Config6 to enable the FTLB */ 569 /* Loongson-3 cores use Config6 to enable the FTLB */
567 config = read_c0_config6(); 570 config = read_c0_config6();
568 if (enable) 571 if (enable)
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index c17d7627f872..4c3362b46066 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -28,25 +28,28 @@
28extern void build_tlb_refill_handler(void); 28extern void build_tlb_refill_handler(void);
29 29
30/* 30/*
31 * LOONGSON2/3 has a 4 entry itlb which is a subset of dtlb, 31 * LOONGSON-2 has a 4 entry itlb which is a subset of jtlb, LOONGSON-3 has
32 * unfortunately, itlb is not totally transparent to software. 32 * a 4 entry itlb and a 4 entry dtlb which are subsets of jtlb. Unfortunately,
33 * itlb/dtlb are not totally transparent to software.
33 */ 34 */
34static inline void flush_itlb(void) 35static inline void flush_micro_tlb(void)
35{ 36{
36 switch (current_cpu_type()) { 37 switch (current_cpu_type()) {
37 case CPU_LOONGSON2: 38 case CPU_LOONGSON2:
39 write_c0_diag(LOONGSON_DIAG_ITLB);
40 break;
38 case CPU_LOONGSON3: 41 case CPU_LOONGSON3:
39 write_c0_diag(4); 42 write_c0_diag(LOONGSON_DIAG_ITLB | LOONGSON_DIAG_DTLB);
40 break; 43 break;
41 default: 44 default:
42 break; 45 break;
43 } 46 }
44} 47}
45 48
46static inline void flush_itlb_vm(struct vm_area_struct *vma) 49static inline void flush_micro_tlb_vm(struct vm_area_struct *vma)
47{ 50{
48 if (vma->vm_flags & VM_EXEC) 51 if (vma->vm_flags & VM_EXEC)
49 flush_itlb(); 52 flush_micro_tlb();
50} 53}
51 54
52void local_flush_tlb_all(void) 55void local_flush_tlb_all(void)
@@ -93,7 +96,7 @@ void local_flush_tlb_all(void)
93 tlbw_use_hazard(); 96 tlbw_use_hazard();
94 write_c0_entryhi(old_ctx); 97 write_c0_entryhi(old_ctx);
95 htw_start(); 98 htw_start();
96 flush_itlb(); 99 flush_micro_tlb();
97 local_irq_restore(flags); 100 local_irq_restore(flags);
98} 101}
99EXPORT_SYMBOL(local_flush_tlb_all); 102EXPORT_SYMBOL(local_flush_tlb_all);
@@ -159,7 +162,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
159 } else { 162 } else {
160 drop_mmu_context(mm, cpu); 163 drop_mmu_context(mm, cpu);
161 } 164 }
162 flush_itlb(); 165 flush_micro_tlb();
163 local_irq_restore(flags); 166 local_irq_restore(flags);
164 } 167 }
165} 168}
@@ -205,7 +208,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
205 } else { 208 } else {
206 local_flush_tlb_all(); 209 local_flush_tlb_all();
207 } 210 }
208 flush_itlb(); 211 flush_micro_tlb();
209 local_irq_restore(flags); 212 local_irq_restore(flags);
210} 213}
211 214
@@ -240,7 +243,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
240 finish: 243 finish:
241 write_c0_entryhi(oldpid); 244 write_c0_entryhi(oldpid);
242 htw_start(); 245 htw_start();
243 flush_itlb_vm(vma); 246 flush_micro_tlb_vm(vma);
244 local_irq_restore(flags); 247 local_irq_restore(flags);
245 } 248 }
246} 249}
@@ -274,7 +277,7 @@ void local_flush_tlb_one(unsigned long page)
274 } 277 }
275 write_c0_entryhi(oldpid); 278 write_c0_entryhi(oldpid);
276 htw_start(); 279 htw_start();
277 flush_itlb(); 280 flush_micro_tlb();
278 local_irq_restore(flags); 281 local_irq_restore(flags);
279} 282}
280 283
@@ -357,7 +360,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
357 } 360 }
358 tlbw_use_hazard(); 361 tlbw_use_hazard();
359 htw_start(); 362 htw_start();
360 flush_itlb_vm(vma); 363 flush_micro_tlb_vm(vma);
361 local_irq_restore(flags); 364 local_irq_restore(flags);
362} 365}
363 366