Commit de62893b authored by Atsushi Nemoto's avatar Atsushi Nemoto Committed by Ralf Baechle

[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: default avatarAtsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent a3c4946d
...@@ -375,6 +375,7 @@ static void r4k_flush_cache_mm(struct mm_struct *mm) ...@@ -375,6 +375,7 @@ static void r4k_flush_cache_mm(struct mm_struct *mm)
struct flush_cache_page_args { struct flush_cache_page_args {
struct vm_area_struct *vma; struct vm_area_struct *vma;
unsigned long addr; unsigned long addr;
unsigned long pfn;
}; };
static inline void local_r4k_flush_cache_page(void *args) static inline void local_r4k_flush_cache_page(void *args)
...@@ -382,6 +383,7 @@ 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 flush_cache_page_args *fcp_args = args;
struct vm_area_struct *vma = fcp_args->vma; struct vm_area_struct *vma = fcp_args->vma;
unsigned long addr = fcp_args->addr; unsigned long addr = fcp_args->addr;
unsigned long paddr = fcp_args->pfn << PAGE_SHIFT;
int exec = vma->vm_flags & VM_EXEC; int exec = vma->vm_flags & VM_EXEC;
struct mm_struct *mm = vma->vm_mm; struct mm_struct *mm = vma->vm_mm;
pgd_t *pgdp; pgd_t *pgdp;
...@@ -431,11 +433,12 @@ static inline void local_r4k_flush_cache_page(void *args) ...@@ -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 * Do indexed flush, too much work to get the (possible) TLB refills
* to work correctly. * to work correctly.
*/ */
addr = INDEX_BASE + (addr & (dcache_size - 1));
if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) { if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) {
r4k_blast_dcache_page_indexed(addr); r4k_blast_dcache_page_indexed(cpu_has_pindexed_dcache ?
if (exec && !cpu_icache_snoops_remote_store) paddr : addr);
r4k_blast_scache_page_indexed(addr); if (exec && !cpu_icache_snoops_remote_store) {
r4k_blast_scache_page_indexed(paddr);
}
} }
if (exec) { if (exec) {
if (cpu_has_vtag_icache) { if (cpu_has_vtag_icache) {
...@@ -455,6 +458,7 @@ static void r4k_flush_cache_page(struct vm_area_struct *vma, ...@@ -455,6 +458,7 @@ static void r4k_flush_cache_page(struct vm_area_struct *vma,
args.vma = vma; args.vma = vma;
args.addr = addr; args.addr = addr;
args.pfn = pfn;
on_each_cpu(local_r4k_flush_cache_page, &args, 1, 1); on_each_cpu(local_r4k_flush_cache_page, &args, 1, 1);
} }
...@@ -956,6 +960,7 @@ static void __init probe_pcache(void) ...@@ -956,6 +960,7 @@ static void __init probe_pcache(void)
switch (c->cputype) { switch (c->cputype) {
case CPU_20KC: case CPU_20KC:
case CPU_25KF: case CPU_25KF:
c->dcache.flags |= MIPS_CACHE_PINDEX;
case CPU_R10000: case CPU_R10000:
case CPU_R12000: case CPU_R12000:
case CPU_SB1: case CPU_SB1:
......
...@@ -210,7 +210,6 @@ static void tx39_flush_cache_page(struct vm_area_struct *vma, unsigned long page ...@@ -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 * Do indexed flush, too much work to get the (possible) TLB refills
* to work correctly. * to work correctly.
*/ */
page = (KSEG0 + (page & (dcache_size - 1)));
if (cpu_has_dc_aliases || exec) if (cpu_has_dc_aliases || exec)
tx39_blast_dcache_page_indexed(page); tx39_blast_dcache_page_indexed(page);
if (exec) if (exec)
......
...@@ -96,6 +96,9 @@ ...@@ -96,6 +96,9 @@
#ifndef cpu_has_ic_fills_f_dc #ifndef cpu_has_ic_fills_f_dc
#define cpu_has_ic_fills_f_dc (cpu_data[0].icache.flags & MIPS_CACHE_IC_F_DC) #define cpu_has_ic_fills_f_dc (cpu_data[0].icache.flags & MIPS_CACHE_IC_F_DC)
#endif #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 * I-Cache snoops remote store. This only matters on SMP. Some multiprocessors
......
...@@ -39,6 +39,7 @@ struct cache_desc { ...@@ -39,6 +39,7 @@ struct cache_desc {
#define MIPS_CACHE_ALIASES 0x00000004 /* Cache could have aliases */ #define MIPS_CACHE_ALIASES 0x00000004 /* Cache could have aliases */
#define MIPS_CACHE_IC_F_DC 0x00000008 /* Ic can refill from D-cache */ #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_IC_SNOOPS_REMOTE 0x00000010 /* Ic snoops remote stores */
#define MIPS_CACHE_PINDEX 0x00000020 /* Physically indexed cache */
struct cpuinfo_mips { struct cpuinfo_mips {
unsigned long udelay_val; unsigned long udelay_val;
......
...@@ -257,7 +257,8 @@ static inline void blast_##pfx##cache##lsize##_page(unsigned long page) \ ...@@ -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) \ 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 end = start + PAGE_SIZE; \
unsigned long ws_inc = 1UL << current_cpu_data.desc.waybit; \ unsigned long ws_inc = 1UL << current_cpu_data.desc.waybit; \
unsigned long ws_end = current_cpu_data.desc.ways << \ unsigned long ws_end = current_cpu_data.desc.ways << \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment