diff options
author | Huacai Chen <chenhc@lemote.com> | 2016-03-02 20:45:11 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2016-05-13 08:02:14 -0400 |
commit | 06e4814eec988f7ee01c29762f945b3ff59355fb (patch) | |
tree | d23c5f9cf1b096b3bc67f458a6b0984b664d7cbf | |
parent | 37fbe8faa94fa8cae889a3a793fd7b32508b26ab (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.h | 9 | ||||
-rw-r--r-- | arch/mips/kernel/cpu-probe.c | 3 | ||||
-rw-r--r-- | arch/mips/mm/tlb-r4k.c | 27 |
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 @@ | |||
28 | extern void build_tlb_refill_handler(void); | 28 | extern 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 | */ |
34 | static inline void flush_itlb(void) | 35 | static 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 | ||
46 | static inline void flush_itlb_vm(struct vm_area_struct *vma) | 49 | static 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 | ||
52 | void local_flush_tlb_all(void) | 55 | void 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 | } |
99 | EXPORT_SYMBOL(local_flush_tlb_all); | 102 | EXPORT_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 | ||