Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Maciej W. Rozycki and committed by
Ralf Baechle
e2e7f29a 12a8471d

+15 -8
+15 -8
arch/mips/mm/c-r4k.c
··· 889 889 } 890 890 } 891 891 892 - static inline void alias_74k_erratum(struct cpuinfo_mips *c) 892 + static inline int alias_74k_erratum(struct cpuinfo_mips *c) 893 893 { 894 894 unsigned int imp = c->processor_id & PRID_IMP_MASK; 895 895 unsigned int rev = c->processor_id & PRID_REV_MASK; 896 + int present = 0; 896 897 897 898 /* 898 899 * Early versions of the 74K do not update the cache tags on a 899 900 * vtag miss/ptag hit which can occur in the case of KSEG0/KUSEG 900 - * aliases. In this case it is better to treat the cache as always 901 - * having aliases. 901 + * aliases. In this case it is better to treat the cache as always 902 + * having aliases. Also disable the synonym tag update feature 903 + * where available. In this case no opportunistic tag update will 904 + * happen where a load causes a virtual address miss but a physical 905 + * address hit during a D-cache look-up. 902 906 */ 903 907 switch (imp) { 904 908 case PRID_IMP_74K: 905 909 if (rev <= PRID_REV_ENCODE_332(2, 4, 0)) 906 - c->dcache.flags |= MIPS_CACHE_VTAG; 910 + present = 1; 907 911 if (rev == PRID_REV_ENCODE_332(2, 4, 0)) 908 912 write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND); 909 913 break; 910 914 case PRID_IMP_1074K: 911 915 if (rev <= PRID_REV_ENCODE_332(1, 1, 0)) { 912 - c->dcache.flags |= MIPS_CACHE_VTAG; 916 + present = 1; 913 917 write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND); 914 918 } 915 919 break; 916 920 default: 917 921 BUG(); 918 922 } 923 + 924 + return present; 919 925 } 920 926 921 927 static void b5k_instruction_hazard(void) ··· 945 939 struct cpuinfo_mips *c = &current_cpu_data; 946 940 unsigned int config = read_c0_config(); 947 941 unsigned int prid = read_c0_prid(); 942 + int has_74k_erratum = 0; 948 943 unsigned long config1; 949 944 unsigned int lsize; 950 945 ··· 1254 1247 1255 1248 case CPU_74K: 1256 1249 case CPU_1074K: 1257 - alias_74k_erratum(c); 1250 + has_74k_erratum = alias_74k_erratum(c); 1258 1251 /* Fall through. */ 1259 1252 case CPU_M14KC: 1260 1253 case CPU_M14KEC: ··· 1269 1262 if (!(read_c0_config7() & MIPS_CONF7_IAR) && 1270 1263 (c->icache.waysize > PAGE_SIZE)) 1271 1264 c->icache.flags |= MIPS_CACHE_ALIASES; 1272 - if (read_c0_config7() & MIPS_CONF7_AR) { 1265 + if (!has_74k_erratum && (read_c0_config7() & MIPS_CONF7_AR)) { 1273 1266 /* 1274 1267 * Effectively physically indexed dcache, 1275 1268 * thus no virtual aliases. ··· 1278 1271 break; 1279 1272 } 1280 1273 default: 1281 - if (c->dcache.waysize > PAGE_SIZE) 1274 + if (has_74k_erratum || c->dcache.waysize > PAGE_SIZE) 1282 1275 c->dcache.flags |= MIPS_CACHE_ALIASES; 1283 1276 } 1284 1277