diff options
author | Atsushi Nemoto <anemo@mba.ocn.ne.jp> | 2006-03-13 12:23:03 +0300 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2006-03-18 19:59:27 +0300 |
commit | de62893bc0725f8b5f0445250577cd7a10b2d8f8 (patch) | |
tree | 3a5d77b8e8aa66113431ebe287c552749c2e8fee | |
parent | a3c4946db4fe64cb21b66a09e89890678aac6d65 (diff) | |
download | linux-de62893bc0725f8b5f0445250577cd7a10b2d8f8.tar.xz |
[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>
-rw-r--r-- | arch/mips/mm/c-r4k.c | 13 | ||||
-rw-r--r-- | arch/mips/mm/c-tx39.c | 1 | ||||
-rw-r--r-- | include/asm-mips/cpu-features.h | 3 | ||||
-rw-r--r-- | include/asm-mips/cpu-info.h | 1 | ||||
-rw-r--r-- | include/asm-mips/r4kcache.h | 3 |
5 files changed, 15 insertions, 6 deletions
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 0668e9bfce41..9572ed44f0d5 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -375,6 +375,7 @@ static void r4k_flush_cache_mm(struct mm_struct *mm) struct flush_cache_page_args { struct vm_area_struct *vma; unsigned long addr; + unsigned long pfn; }; static inline void local_r4k_flush_cache_page(void *args) @@ -382,6 +383,7 @@ static inline void local_r4k_flush_cache_page(void *args) struct flush_cache_page_args *fcp_args = args; struct vm_area_struct *vma = fcp_args->vma; unsigned long addr = fcp_args->addr; + unsigned long paddr = fcp_args->pfn << PAGE_SHIFT; int exec = vma->vm_flags & VM_EXEC; struct mm_struct *mm = vma->vm_mm; pgd_t *pgdp; @@ -431,11 +433,12 @@ static inline void local_r4k_flush_cache_page(void *args) * Do indexed flush, too much work to get the (possible) TLB refills * to work correctly. */ - addr = INDEX_BASE + (addr & (dcache_size - 1)); if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) { - r4k_blast_dcache_page_indexed(addr); - if (exec && !cpu_icache_snoops_remote_store) - r4k_blast_scache_page_indexed(addr); + r4k_blast_dcache_page_indexed(cpu_has_pindexed_dcache ? + paddr : addr); + if (exec && !cpu_icache_snoops_remote_store) { + r4k_blast_scache_page_indexed(paddr); + } } if (exec) { if (cpu_has_vtag_icache) { @@ -455,6 +458,7 @@ static void r4k_flush_cache_page(struct vm_area_struct *vma, args.vma = vma; args.addr = addr; + args.pfn = pfn; on_each_cpu(local_r4k_flush_cache_page, &args, 1, 1); } @@ -956,6 +960,7 @@ static void __init probe_pcache(void) switch (c->cputype) { case CPU_20KC: case CPU_25KF: + c->dcache.flags |= MIPS_CACHE_PINDEX; case CPU_R10000: case CPU_R12000: case CPU_SB1: diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c index 7c572bea4a98..fe232e3988e3 100644 --- a/arch/mips/mm/c-tx39.c +++ b/arch/mips/mm/c-tx39.c @@ -210,7 +210,6 @@ static void tx39_flush_cache_page(struct vm_area_struct *vma, unsigned long page * Do indexed flush, too much work to get the (possible) TLB refills * to work correctly. */ - page = (KSEG0 + (page & (dcache_size - 1))); if (cpu_has_dc_aliases || exec) tx39_blast_dcache_page_indexed(page); if (exec) diff --git a/include/asm-mips/cpu-features.h b/include/asm-mips/cpu-features.h index 78c9cc2735d5..3f2b6d9ac45e 100644 --- a/include/asm-mips/cpu-features.h +++ b/include/asm-mips/cpu-features.h @@ -96,6 +96,9 @@ #ifndef cpu_has_ic_fills_f_dc #define cpu_has_ic_fills_f_dc (cpu_data[0].icache.flags & MIPS_CACHE_IC_F_DC) #endif +#ifndef cpu_has_pindexed_dcache +#define cpu_has_pindexed_dcache (cpu_data[0].dcache.flags & MIPS_CACHE_PINDEX) +#endif /* * I-Cache snoops remote store. This only matters on SMP. Some multiprocessors diff --git a/include/asm-mips/cpu-info.h b/include/asm-mips/cpu-info.h index d5cf519f8fcc..140be1c67da7 100644 --- a/include/asm-mips/cpu-info.h +++ b/include/asm-mips/cpu-info.h @@ -39,6 +39,7 @@ struct cache_desc { #define MIPS_CACHE_ALIASES 0x00000004 /* Cache could have aliases */ #define MIPS_CACHE_IC_F_DC 0x00000008 /* Ic can refill from D-cache */ #define MIPS_IC_SNOOPS_REMOTE 0x00000010 /* Ic snoops remote stores */ +#define MIPS_CACHE_PINDEX 0x00000020 /* Physically indexed cache */ struct cpuinfo_mips { unsigned long udelay_val; diff --git a/include/asm-mips/r4kcache.h b/include/asm-mips/r4kcache.h index 9632c27dad15..0bcb79a58ee9 100644 --- a/include/asm-mips/r4kcache.h +++ b/include/asm-mips/r4kcache.h @@ -257,7 +257,8 @@ static inline void blast_##pfx##cache##lsize##_page(unsigned long page) \ \ static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \ { \ - unsigned long start = page; \ + unsigned long indexmask = current_cpu_data.desc.waysize - 1; \ + unsigned long start = INDEX_BASE + (page & indexmask); \ unsigned long end = start + PAGE_SIZE; \ unsigned long ws_inc = 1UL << current_cpu_data.desc.waybit; \ unsigned long ws_end = current_cpu_data.desc.ways << \ |