diff options
author | Maciej W. Rozycki <macro@linux-mips.org> | 2007-10-23 12:43:11 +0100 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2008-01-29 10:14:54 +0000 |
commit | 20d60d9973c3b441902b0a3f4f6f7e7ade08f77d (patch) | |
tree | 2dbadcb5600fcb486612ec30d972e6c29195ee1d /arch/mips/kernel/cpu-bugs64.c | |
parent | 2b22c034d04d3632a339d14d5803c8f94e412608 (diff) | |
download | blackbird-op-linux-20d60d9973c3b441902b0a3f4f6f7e7ade08f77d.tar.gz blackbird-op-linux-20d60d9973c3b441902b0a3f4f6f7e7ade08f77d.zip |
[MIPS] R4000/R4400 errata workarounds
This is the gereric part of R4000/R4400 errata workarounds. They include
compiler and assembler support as well as some source code modifications
to address the problems with some combinations of multiply/divide+shift
instructions as well as the daddi and daddiu instructions.
Changes included are as follows:
1. New Kconfig options to select workarounds by platforms as necessary.
2. Arch top-level Makefile to pass necessary options to the compiler; also
incompatible configurations are detected (-mno-sym32 unsupported as
horribly intrusive for little gain).
3. Bug detection updated and shuffled -- the multiply/divide+shift problem
is lethal enough that if not worked around it makes the kernel crash in
time_init() because of a division by zero; the daddiu erratum might
also trigger early potentially, though I have not observed it. On the
other hand the daddi detection code requires the exception subsystem to
have been initialised (and is there mainly for information).
4. r4k_daddiu_bug() added so that the existence of the erratum can be
queried by code at the run time as necessary; useful for generated code
like TLB fault and copy/clear page handlers.
5. __udelay() updated as it uses multiplication in inline assembly.
Note that -mdaddi requires modified toolchain (which has been maintained
by myself and available from my site for ~4years now -- versions covered
are GCC 2.95.4 - 4.1.2 and binutils from 2.13 onwards). The -mfix-r4000
and -mfix-r4400 have been standard for a while though.
Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel/cpu-bugs64.c')
-rw-r--r-- | arch/mips/kernel/cpu-bugs64.c | 47 |
1 files changed, 23 insertions, 24 deletions
diff --git a/arch/mips/kernel/cpu-bugs64.c b/arch/mips/kernel/cpu-bugs64.c index af78456d4138..417bb3e336ac 100644 --- a/arch/mips/kernel/cpu-bugs64.c +++ b/arch/mips/kernel/cpu-bugs64.c @@ -18,6 +18,15 @@ #include <asm/mipsregs.h> #include <asm/system.h> +static char bug64hit[] __initdata = + "reliable operation impossible!\n%s"; +static char nowar[] __initdata = + "Please report to <linux-mips@linux-mips.org>."; +static char r4kwar[] __initdata = + "Enable CPU_R4000_WORKAROUNDS to rectify."; +static char daddiwar[] __initdata = + "Enable CPU_DADDI_WORKAROUNDS to rectify."; + static inline void align_mod(const int align, const int mod) { asm volatile( @@ -155,13 +164,7 @@ static inline void check_mult_sh(void) } printk("no.\n"); - panic("Reliable operation impossible!\n" -#ifndef CONFIG_CPU_R4000 - "Configure for R4000 to enable the workaround." -#else - "Please report to <linux-mips@linux-mips.org>." -#endif - ); + panic(bug64hit, !R4000_WAR ? r4kwar : nowar); } static volatile int daddi_ov __initdata = 0; @@ -233,15 +236,11 @@ static inline void check_daddi(void) } printk("no.\n"); - panic("Reliable operation impossible!\n" -#if !defined(CONFIG_CPU_R4000) && !defined(CONFIG_CPU_R4400) - "Configure for R4000 or R4400 to enable the workaround." -#else - "Please report to <linux-mips@linux-mips.org>." -#endif - ); + panic(bug64hit, !DADDI_WAR ? daddiwar : nowar); } +int daddiu_bug __initdata = -1; + static inline void check_daddiu(void) { long v, w, tmp; @@ -281,7 +280,9 @@ static inline void check_daddiu(void) : "=&r" (v), "=&r" (w), "=&r" (tmp) : "I" (0xffffffffffffdb9aUL), "I" (0x1234)); - if (v == w) { + daddiu_bug = v != w; + + if (!daddiu_bug) { printk("no.\n"); return; } @@ -303,18 +304,16 @@ static inline void check_daddiu(void) } printk("no.\n"); - panic("Reliable operation impossible!\n" -#if !defined(CONFIG_CPU_R4000) && !defined(CONFIG_CPU_R4400) - "Configure for R4000 or R4400 to enable the workaround." -#else - "Please report to <linux-mips@linux-mips.org>." -#endif - ); + panic(bug64hit, !DADDI_WAR ? daddiwar : nowar); } -void __init check_bugs64(void) +void __init check_bugs64_early(void) { check_mult_sh(); - check_daddi(); check_daddiu(); } + +void __init check_bugs64(void) +{ + check_daddi(); +} |