Commit de62893bc0725f8b5f0445250577cd7a10b2d8f8
Committed by
Ralf Baechle
1 parent
a3c4946db4
Exists in
master
and in
7 other branches
[MIPS] local_r4k_flush_cache_page fix
If dcache_size != icache_size or dcache_size != scache_size, or set-associative cache, icache/scache does not flushed properly. Make blast_?cache_page_indexed() masks its index value correctly. Also, use physical address for physically indexed pcache/scache. Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Showing 5 changed files with 15 additions and 6 deletions Side-by-side Diff
arch/mips/mm/c-r4k.c
... | ... | @@ -375,6 +375,7 @@ |
375 | 375 | struct flush_cache_page_args { |
376 | 376 | struct vm_area_struct *vma; |
377 | 377 | unsigned long addr; |
378 | + unsigned long pfn; | |
378 | 379 | }; |
379 | 380 | |
380 | 381 | static inline void local_r4k_flush_cache_page(void *args) |
... | ... | @@ -382,6 +383,7 @@ |
382 | 383 | struct flush_cache_page_args *fcp_args = args; |
383 | 384 | struct vm_area_struct *vma = fcp_args->vma; |
384 | 385 | unsigned long addr = fcp_args->addr; |
386 | + unsigned long paddr = fcp_args->pfn << PAGE_SHIFT; | |
385 | 387 | int exec = vma->vm_flags & VM_EXEC; |
386 | 388 | struct mm_struct *mm = vma->vm_mm; |
387 | 389 | pgd_t *pgdp; |
388 | 390 | |
... | ... | @@ -431,11 +433,12 @@ |
431 | 433 | * Do indexed flush, too much work to get the (possible) TLB refills |
432 | 434 | * to work correctly. |
433 | 435 | */ |
434 | - addr = INDEX_BASE + (addr & (dcache_size - 1)); | |
435 | 436 | if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) { |
436 | - r4k_blast_dcache_page_indexed(addr); | |
437 | - if (exec && !cpu_icache_snoops_remote_store) | |
438 | - r4k_blast_scache_page_indexed(addr); | |
437 | + r4k_blast_dcache_page_indexed(cpu_has_pindexed_dcache ? | |
438 | + paddr : addr); | |
439 | + if (exec && !cpu_icache_snoops_remote_store) { | |
440 | + r4k_blast_scache_page_indexed(paddr); | |
441 | + } | |
439 | 442 | } |
440 | 443 | if (exec) { |
441 | 444 | if (cpu_has_vtag_icache) { |
... | ... | @@ -455,6 +458,7 @@ |
455 | 458 | |
456 | 459 | args.vma = vma; |
457 | 460 | args.addr = addr; |
461 | + args.pfn = pfn; | |
458 | 462 | |
459 | 463 | on_each_cpu(local_r4k_flush_cache_page, &args, 1, 1); |
460 | 464 | } |
... | ... | @@ -956,6 +960,7 @@ |
956 | 960 | switch (c->cputype) { |
957 | 961 | case CPU_20KC: |
958 | 962 | case CPU_25KF: |
963 | + c->dcache.flags |= MIPS_CACHE_PINDEX; | |
959 | 964 | case CPU_R10000: |
960 | 965 | case CPU_R12000: |
961 | 966 | case CPU_SB1: |
arch/mips/mm/c-tx39.c
include/asm-mips/cpu-features.h
... | ... | @@ -96,6 +96,9 @@ |
96 | 96 | #ifndef cpu_has_ic_fills_f_dc |
97 | 97 | #define cpu_has_ic_fills_f_dc (cpu_data[0].icache.flags & MIPS_CACHE_IC_F_DC) |
98 | 98 | #endif |
99 | +#ifndef cpu_has_pindexed_dcache | |
100 | +#define cpu_has_pindexed_dcache (cpu_data[0].dcache.flags & MIPS_CACHE_PINDEX) | |
101 | +#endif | |
99 | 102 | |
100 | 103 | /* |
101 | 104 | * I-Cache snoops remote store. This only matters on SMP. Some multiprocessors |
include/asm-mips/cpu-info.h
... | ... | @@ -39,6 +39,7 @@ |
39 | 39 | #define MIPS_CACHE_ALIASES 0x00000004 /* Cache could have aliases */ |
40 | 40 | #define MIPS_CACHE_IC_F_DC 0x00000008 /* Ic can refill from D-cache */ |
41 | 41 | #define MIPS_IC_SNOOPS_REMOTE 0x00000010 /* Ic snoops remote stores */ |
42 | +#define MIPS_CACHE_PINDEX 0x00000020 /* Physically indexed cache */ | |
42 | 43 | |
43 | 44 | struct cpuinfo_mips { |
44 | 45 | unsigned long udelay_val; |
include/asm-mips/r4kcache.h
... | ... | @@ -257,7 +257,8 @@ |
257 | 257 | \ |
258 | 258 | static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \ |
259 | 259 | { \ |
260 | - unsigned long start = page; \ | |
260 | + unsigned long indexmask = current_cpu_data.desc.waysize - 1; \ | |
261 | + unsigned long start = INDEX_BASE + (page & indexmask); \ | |
261 | 262 | unsigned long end = start + PAGE_SIZE; \ |
262 | 263 | unsigned long ws_inc = 1UL << current_cpu_data.desc.waybit; \ |
263 | 264 | unsigned long ws_end = current_cpu_data.desc.ways << \ |