Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e2e7f29a authored by Maciej W. Rozycki's avatar Maciej W. Rozycki Committed by Ralf Baechle
Browse files

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: default avatarMaciej W. Rozycki <macro@codesourcery.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/8507/


Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 12a8471d
Loading
Loading
Loading
Loading
+15 −8
Original line number Original line Diff line number Diff line
@@ -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;
	}
	}