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 /include/asm-mips/war.h | |
parent | 2b22c034d04d3632a339d14d5803c8f94e412608 (diff) | |
download | lwn-20d60d9973c3b441902b0a3f4f6f7e7ade08f77d.tar.gz lwn-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 'include/asm-mips/war.h')
-rw-r--r-- | include/asm-mips/war.h | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/include/asm-mips/war.h b/include/asm-mips/war.h index d2808edfd4e9..22361d5e3bf0 100644 --- a/include/asm-mips/war.h +++ b/include/asm-mips/war.h @@ -4,6 +4,7 @@ * for more details. * * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + * Copyright (C) 2007 Maciej W. Rozycki */ #ifndef _ASM_WAR_H #define _ASM_WAR_H @@ -11,6 +12,67 @@ #include <war.h> /* + * Work around certain R4000 CPU errata (as implemented by GCC): + * + * - A double-word or a variable shift may give an incorrect result + * if executed immediately after starting an integer division: + * "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0", + * erratum #28 + * "MIPS R4000MC Errata, Processor Revision 2.2 and 3.0", erratum + * #19 + * + * - A double-word or a variable shift may give an incorrect result + * if executed while an integer multiplication is in progress: + * "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0", + * errata #16 & #28 + * + * - An integer division may give an incorrect result if started in + * a delay slot of a taken branch or a jump: + * "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0", + * erratum #52 + */ +#ifdef CONFIG_CPU_R4000_WORKAROUNDS +#define R4000_WAR 1 +#else +#define R4000_WAR 0 +#endif + +/* + * Work around certain R4400 CPU errata (as implemented by GCC): + * + * - A double-word or a variable shift may give an incorrect result + * if executed immediately after starting an integer division: + * "MIPS R4400MC Errata, Processor Revision 1.0", erratum #10 + * "MIPS R4400MC Errata, Processor Revision 2.0 & 3.0", erratum #4 + */ +#ifdef CONFIG_CPU_R4400_WORKAROUNDS +#define R4400_WAR 1 +#else +#define R4400_WAR 0 +#endif + +/* + * Work around the "daddi" and "daddiu" CPU errata: + * + * - The `daddi' instruction fails to trap on overflow. + * "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0", + * erratum #23 + * + * - The `daddiu' instruction can produce an incorrect result. + * "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0", + * erratum #41 + * "MIPS R4000MC Errata, Processor Revision 2.2 and 3.0", erratum + * #15 + * "MIPS R4400PC/SC Errata, Processor Revision 1.0", erratum #7 + * "MIPS R4400MC Errata, Processor Revision 1.0", erratum #5 + */ +#ifdef CONFIG_CPU_DADDI_WORKAROUNDS +#define DADDI_WAR 1 +#else +#define DADDI_WAR 0 +#endif + +/* * Another R4600 erratum. Due to the lack of errata information the exact * technical details aren't known. I've experimentally found that disabling * interrupts during indexed I-cache flushes seems to be sufficient to deal |