diff options
author | Maciej W. Rozycki <macro@codesourcery.com> | 2014-11-15 20:02:29 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2015-04-02 07:54:18 -0400 |
commit | e2e7f29af84aa59dd8191b9f6fee80aafa4e06cd (patch) | |
tree | d24402478d2956b93d2d881673d527f0a483eb11 | |
parent | 12a8471de9e8dc3c867e15bbf4a37152d2f690b8 (diff) |
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>
-rw-r--r-- | arch/mips/mm/c-r4k.c | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 58e2eeddc391..0dbb65a51ce5 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c | |||
@@ -889,33 +889,39 @@ static inline void rm7k_erratum31(void) | |||
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 | unsigned int imp = c->processor_id & PRID_IMP_MASK; | 894 | unsigned int imp = c->processor_id & PRID_IMP_MASK; |
895 | unsigned int rev = c->processor_id & PRID_REV_MASK; | 895 | unsigned int rev = c->processor_id & PRID_REV_MASK; |
896 | int present = 0; | ||
896 | 897 | ||
897 | /* | 898 | /* |
898 | * Early versions of the 74K do not update the cache tags on a | 899 | * Early versions of the 74K do not update the cache tags on a |
899 | * vtag miss/ptag hit which can occur in the case of KSEG0/KUSEG | 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 | * aliases. In this case it is better to treat the cache as always |
901 | * having aliases. | 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 | switch (imp) { | 907 | switch (imp) { |
904 | case PRID_IMP_74K: | 908 | case PRID_IMP_74K: |
905 | if (rev <= PRID_REV_ENCODE_332(2, 4, 0)) | 909 | if (rev <= PRID_REV_ENCODE_332(2, 4, 0)) |
906 | c->dcache.flags |= MIPS_CACHE_VTAG; | 910 | present = 1; |
907 | if (rev == PRID_REV_ENCODE_332(2, 4, 0)) | 911 | if (rev == PRID_REV_ENCODE_332(2, 4, 0)) |
908 | write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND); | 912 | write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND); |
909 | break; | 913 | break; |
910 | case PRID_IMP_1074K: | 914 | case PRID_IMP_1074K: |
911 | if (rev <= PRID_REV_ENCODE_332(1, 1, 0)) { | 915 | if (rev <= PRID_REV_ENCODE_332(1, 1, 0)) { |
912 | c->dcache.flags |= MIPS_CACHE_VTAG; | 916 | present = 1; |
913 | write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND); | 917 | write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND); |
914 | } | 918 | } |
915 | break; | 919 | break; |
916 | default: | 920 | default: |
917 | BUG(); | 921 | BUG(); |
918 | } | 922 | } |
923 | |||
924 | return present; | ||
919 | } | 925 | } |
920 | 926 | ||
921 | static void b5k_instruction_hazard(void) | 927 | static void b5k_instruction_hazard(void) |
@@ -939,6 +945,7 @@ static void probe_pcache(void) | |||
939 | struct cpuinfo_mips *c = ¤t_cpu_data; | 945 | struct cpuinfo_mips *c = ¤t_cpu_data; |
940 | unsigned int config = read_c0_config(); | 946 | unsigned int config = read_c0_config(); |
941 | unsigned int prid = read_c0_prid(); | 947 | unsigned int prid = read_c0_prid(); |
948 | int has_74k_erratum = 0; | ||
942 | unsigned long config1; | 949 | unsigned long config1; |
943 | unsigned int lsize; | 950 | unsigned int lsize; |
944 | 951 | ||
@@ -1247,7 +1254,7 @@ static void probe_pcache(void) | |||
1247 | 1254 | ||
1248 | case CPU_74K: | 1255 | case CPU_74K: |
1249 | case CPU_1074K: | 1256 | case CPU_1074K: |
1250 | alias_74k_erratum(c); | 1257 | has_74k_erratum = alias_74k_erratum(c); |
1251 | /* Fall through. */ | 1258 | /* Fall through. */ |
1252 | case CPU_M14KC: | 1259 | case CPU_M14KC: |
1253 | case CPU_M14KEC: | 1260 | case CPU_M14KEC: |
@@ -1262,7 +1269,7 @@ static void probe_pcache(void) | |||
1262 | if (!(read_c0_config7() & MIPS_CONF7_IAR) && | 1269 | if (!(read_c0_config7() & MIPS_CONF7_IAR) && |
1263 | (c->icache.waysize > PAGE_SIZE)) | 1270 | (c->icache.waysize > PAGE_SIZE)) |
1264 | c->icache.flags |= MIPS_CACHE_ALIASES; | 1271 | c->icache.flags |= MIPS_CACHE_ALIASES; |
1265 | if (read_c0_config7() & MIPS_CONF7_AR) { | 1272 | if (!has_74k_erratum && (read_c0_config7() & MIPS_CONF7_AR)) { |
1266 | /* | 1273 | /* |
1267 | * Effectively physically indexed dcache, | 1274 | * Effectively physically indexed dcache, |
1268 | * thus no virtual aliases. | 1275 | * thus no virtual aliases. |
@@ -1271,7 +1278,7 @@ static void probe_pcache(void) | |||
1271 | break; | 1278 | break; |
1272 | } | 1279 | } |
1273 | default: | 1280 | default: |
1274 | if (c->dcache.waysize > PAGE_SIZE) | 1281 | if (has_74k_erratum || c->dcache.waysize > PAGE_SIZE) |
1275 | c->dcache.flags |= MIPS_CACHE_ALIASES; | 1282 | c->dcache.flags |= MIPS_CACHE_ALIASES; |
1276 | } | 1283 | } |
1277 | 1284 | ||