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 rev = c->processor_id & PRID_REV_MASK;
int present = 0;
/*
* 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
* aliases. In this case it is better to treat the cache as always
* having aliases.
* aliases. In this case it is better to treat the cache as always
* 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) {
case PRID_IMP_74K:
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))
write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND);
break;
case PRID_IMP_1074K:
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);
}
break;
default:
BUG();
}
return present;
}
static void b5k_instruction_hazard(void)
@ -939,6 +945,7 @@ static void probe_pcache(void)
struct cpuinfo_mips *c = &current_cpu_data;
unsigned int config = read_c0_config();
unsigned int prid = read_c0_prid();
int has_74k_erratum = 0;
unsigned long config1;
unsigned int lsize;
@ -1247,7 +1254,7 @@ static void probe_pcache(void)
case CPU_74K:
case CPU_1074K:
alias_74k_erratum(c);
has_74k_erratum = alias_74k_erratum(c);
/* Fall through. */
case CPU_M14KC:
case CPU_M14KEC:
@ -1262,7 +1269,7 @@ static void probe_pcache(void)
if (!(read_c0_config7() & MIPS_CONF7_IAR) &&
(c->icache.waysize > PAGE_SIZE))
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,
* thus no virtual aliases.
@ -1271,7 +1278,7 @@ static void probe_pcache(void)
break;
}
default:
if (c->dcache.waysize > PAGE_SIZE)
if (has_74k_erratum || c->dcache.waysize > PAGE_SIZE)
c->dcache.flags |= MIPS_CACHE_ALIASES;
}