MIPS: c-r4k.c: Fix the 74K D-cache alias erratum workaround

Fix the 74K D-cache alias erratum workaround so that it actually works.
Our current code sets MIPS_CACHE_VTAG for the D-cache, but that flag
only has any effect for the I-cache.  Additionally MIPS_CACHE_PINDEX is
set for the D-cache if CP0.Config7.AR is also set for an affected
processor, leading to confusing information in the bootstrap log (the
flag isn't used beyond that).

So delete the setting of MIPS_CACHE_VTAG and rely on MIPS_CACHE_ALIASES,
set in a common place, removing I-cache coherency issues seen in GDB
testing with software breakpoints, gdbserver and ptrace(2), on affected
systems.

While at it add a little piece of explanation of what CP0.Config6.SYND
is so that people do not have to chase documentation.

Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/8507/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
Maciej W. Rozycki 2014-11-16 01:02:29 +00:00 committed by Ralf Baechle
parent 12a8471de9
commit e2e7f29af8
1 changed files with 15 additions and 8 deletions

View File

@ -889,33 +889,39 @@ static inline void rm7k_erratum31(void)
} }
} }
static inline void alias_74k_erratum(struct cpuinfo_mips *c) static inline int alias_74k_erratum(struct cpuinfo_mips *c)
{ {
unsigned int imp = c->processor_id & PRID_IMP_MASK; unsigned int imp = c->processor_id & PRID_IMP_MASK;
unsigned int rev = c->processor_id & PRID_REV_MASK; unsigned int rev = c->processor_id & PRID_REV_MASK;
int present = 0;
/* /*
* Early versions of the 74K do not update the cache tags on a * Early versions of the 74K do not update the cache tags on a
* vtag miss/ptag hit which can occur in the case of KSEG0/KUSEG * vtag miss/ptag hit which can occur in the case of KSEG0/KUSEG
* aliases. In this case it is better to treat the cache as always * aliases. In this case it is better to treat the cache as always
* having aliases. * having aliases. Also disable the synonym tag update feature
* where available. In this case no opportunistic tag update will
* happen where a load causes a virtual address miss but a physical
* address hit during a D-cache look-up.
*/ */
switch (imp) { switch (imp) {
case PRID_IMP_74K: case PRID_IMP_74K:
if (rev <= PRID_REV_ENCODE_332(2, 4, 0)) if (rev <= PRID_REV_ENCODE_332(2, 4, 0))
c->dcache.flags |= MIPS_CACHE_VTAG; present = 1;
if (rev == PRID_REV_ENCODE_332(2, 4, 0)) if (rev == PRID_REV_ENCODE_332(2, 4, 0))
write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND); write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND);
break; break;
case PRID_IMP_1074K: case PRID_IMP_1074K:
if (rev <= PRID_REV_ENCODE_332(1, 1, 0)) { if (rev <= PRID_REV_ENCODE_332(1, 1, 0)) {
c->dcache.flags |= MIPS_CACHE_VTAG; present = 1;
write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND); write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND);
} }
break; break;
default: default:
BUG(); BUG();
} }
return present;
} }
static void b5k_instruction_hazard(void) static void b5k_instruction_hazard(void)
@ -939,6 +945,7 @@ static void probe_pcache(void)
struct cpuinfo_mips *c = &current_cpu_data; struct cpuinfo_mips *c = &current_cpu_data;
unsigned int config = read_c0_config(); unsigned int config = read_c0_config();
unsigned int prid = read_c0_prid(); unsigned int prid = read_c0_prid();
int has_74k_erratum = 0;
unsigned long config1; unsigned long config1;
unsigned int lsize; unsigned int lsize;
@ -1247,7 +1254,7 @@ static void probe_pcache(void)
case CPU_74K: case CPU_74K:
case CPU_1074K: case CPU_1074K:
alias_74k_erratum(c); has_74k_erratum = alias_74k_erratum(c);
/* Fall through. */ /* Fall through. */
case CPU_M14KC: case CPU_M14KC:
case CPU_M14KEC: case CPU_M14KEC:
@ -1262,7 +1269,7 @@ static void probe_pcache(void)
if (!(read_c0_config7() & MIPS_CONF7_IAR) && if (!(read_c0_config7() & MIPS_CONF7_IAR) &&
(c->icache.waysize > PAGE_SIZE)) (c->icache.waysize > PAGE_SIZE))
c->icache.flags |= MIPS_CACHE_ALIASES; c->icache.flags |= MIPS_CACHE_ALIASES;
if (read_c0_config7() & MIPS_CONF7_AR) { if (!has_74k_erratum && (read_c0_config7() & MIPS_CONF7_AR)) {
/* /*
* Effectively physically indexed dcache, * Effectively physically indexed dcache,
* thus no virtual aliases. * thus no virtual aliases.
@ -1271,7 +1278,7 @@ static void probe_pcache(void)
break; break;
} }
default: default:
if (c->dcache.waysize > PAGE_SIZE) if (has_74k_erratum || c->dcache.waysize > PAGE_SIZE)
c->dcache.flags |= MIPS_CACHE_ALIASES; c->dcache.flags |= MIPS_CACHE_ALIASES;
} }