On Mon, Sep 23, 2013 at 12:30 AM, Maciej W. Rozycki <macro@xxxxxxxxxxxxxx> wrote: > There is no reliable way to tell R4000/R4400 SC and MC variations apart, > however simple heuristic should give good results. Only the MC version > supports coherent caching so we can rely on such a mode having been set > for KSEG0 by the power-on firmware to reliably indicate an MC processor. > SC processors reportedly hang on coherent cached memory accesses and Linux > is linked to a cached load address so the firmware has to use the correct > caching mode to download the kernel image in a cached mode successfully. > > OTOH if the firmware chooses to use either the non-coherent cached or the > uncached mode for KSEG0 on an MC processor, then the SC variant will be > reported, just as we currently do, so no regression here. > > Signed-off-by: Maciej W. Rozycki <macro@xxxxxxxxxxxxxx> > --- > Ralf, > > I believe we discussed this once long ago and you had some concerns about > such an approach although I don't recall exactly what they were. I > maintain that this heuristic is reasonable, has no drawbacks and has a > potential to make some optimisations or errata workarounds easier. Also > we can collect data about systems affected to see what their firmware does > -- R4000SC/R4400SC DECstations definitely get CP0.Config.K0 right. > > Maciej > > linux-mips-r4k-mc.patch > Index: linux/arch/mips/kernel/cpu-probe.c > =================================================================== > --- linux.orig/arch/mips/kernel/cpu-probe.c > +++ linux/arch/mips/kernel/cpu-probe.c > @@ -362,13 +362,33 @@ static inline void cpu_probe_legacy(stru > __cpu_name[cpu] = "R4000PC"; > } > } else { > + int cca = read_c0_config() & CONF_CM_CMASK; > + int mc; > + > + /* > + * SC and MC versions can't be reliably told apart, > + * but only the latter support coherent caching > + * modes so assume the firmware has set the KSEG0 > + * coherency attribute reasonably (if uncached, we > + * assume SC). > + */ > + switch (cca) { > + case CONF_CM_CACHABLE_CE: > + case CONF_CM_CACHABLE_COW: > + case CONF_CM_CACHABLE_CUW: > + mc = 1; > + break; > + default: > + mc = 0; > + break; > + } > if ((c->processor_id & PRID_REV_MASK) >= > PRID_REV_R4400) { > - c->cputype = CPU_R4400SC; > - __cpu_name[cpu] = "R4400SC"; > + c->cputype = mc ? CPU_R4400MC : CPU_R4400SC; > + __cpu_name[cpu] = mc ? "R4400MC" : "R4400SC"; > } else { > - c->cputype = CPU_R4000SC; > - __cpu_name[cpu] = "R4000SC"; > + c->cputype = mc ? CPU_R4000MC : CPU_R4000SC; > + __cpu_name[cpu] = mc ? "R4400SC" : "R4000SC"; I guess the first one should be "R4000MC", not "R4400SC". Regards Jonas