Hello,
Being an early implementation of a CPU family, R4000 contains a number of
interesting "features". One of them is a problem that affects a few
variations of shift operations (both 32-bit and 64-bit ones) that are
executed after multiply or divide instructions. Under certain
circumstances the shifts produce incorrect results. This is documented as
erratum #28 in "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0"
which is available at the MIPS site (I can't quote it here, sorry, as it's
copyrighted material and I failed to get permission from MIPS).
There is a partial workaround for the problem implemented in gcc which
gets activated if the "-mcpu=r4000" option is passed to the compiler.
Recent problems with the kernel when run on an affected CPU led me to
complete the multiplication part of the workaround (I'm also working on
the division part that is less biting). A suitable patch for 2.95.x is
available in mipsel-linux and mips64el-linux cross-gcc packages at my
site.
But to let gcc activate the workaround, kernel Makefiles must pass the
mentioned option. Here is a suitable patch. OK to apply?
I would like to express my gratitude to Karsten, who patiently tested on
his R4000 system a seemingly endless stream of kernels I fed him until I
discovered the reason of a mysterious misbehaviour. Without his help I
wouldn't be able to resolve the problem.
Maciej
--
+ Maciej W. Rozycki, Technical University of Gdansk, Poland +
+--------------------------------------------------------------+
+ e-mail: macro@ds2.pg.gda.pl, PGP key available +
patch-mips-2.4.19-rc1-20020807-r4000-0
diff -up --recursive --new-file
linux-mips-2.4.19-rc1-20020807.macro/Documentation/Configure.help
linux-mips-2.4.19-rc1-20020807/Documentation/Configure.help
--- linux-mips-2.4.19-rc1-20020807.macro/Documentation/Configure.help
2002-06-27 02:56:15.000000000 +0000
+++ linux-mips-2.4.19-rc1-20020807/Documentation/Configure.help 2002-09-02
18:32:45.000000000 +0000
@@ -2196,9 +2196,9 @@ CONFIG_PCMCIA_FDOMAIN
# Choice: mipstype
CPU type
-CONFIG_CPU_R3000
+CONFIG_CPU_MIPS32
Please make sure to pick the right CPU type. Linux/MIPS is not
- designed to be generic, i.e. Kernels compiled for R3000 CPUs will
+ designed to be generic, i.e. kernels compiled for R3000 CPUs will
*not* work on R4000 machines and vice versa. However, since most
of the supported machines have an R4000 (or similar) CPU, R4x00
might be a safe bet. If the resulting kernel does not work,
@@ -2210,10 +2210,12 @@ CONFIG_CPU_R3000
R6000 MIPS Technologies R6000-series processors,
including the 64474, 64475, 64574 and 64575.
+ R4000 MIPS Technologies R4000-series processors.
+
R4300 MIPS Technologies R4300-series processors.
- R4x00 MIPS Technologies R4000-series processors other than 4300,
- including the 4640, 4650, and 4700.
+ R4x00 MIPS Technologies R4xxx-series processors other than 4000
+ and 4300, including the 4640, 4650, and 4700.
R5000 MIPS Technologies R5000-series processors other than the
Nevada.
@@ -2227,14 +2229,18 @@ CONFIG_CPU_R6000
MIPS Technologies R6000-series processors, including the 64474,
64475, 64574 and 64575.
+R4000
+CONFIG_CPU_R4000
+ MIPS Technologies R4000-series processors.
+
R4300
CONFIG_CPU_R4300
MIPS Technologies R4300-series processors.
R4x00
CONFIG_CPU_R4X00
- MIPS Technologies R4000-series processors other than 4300, including
- the 4640, 4650, and 4700.
+ MIPS Technologies R4xxx-series processors other than 4000 and 4300,
+ including the 4640, 4650, and 4700.
R5000
CONFIG_CPU_R5000
diff -up --recursive --new-file
linux-mips-2.4.19-rc1-20020807.macro/arch/mips/Makefile
linux-mips-2.4.19-rc1-20020807/arch/mips/Makefile
--- linux-mips-2.4.19-rc1-20020807.macro/arch/mips/Makefile 2002-08-07
02:58:14.000000000 +0000
+++ linux-mips-2.4.19-rc1-20020807/arch/mips/Makefile 2002-09-02
18:34:52.000000000 +0000
@@ -57,6 +57,9 @@ endif
ifdef CONFIG_CPU_R6000
GCCFLAGS += -mcpu=r6000 -mips2 -Wa,--trap
endif
+ifdef CONFIG_CPU_R4000
+GCCFLAGS += -mcpu=r4000 -mips2 -Wa,--trap
+endif
ifdef CONFIG_CPU_R4300
GCCFLAGS += -mcpu=r4300 -mips2 -Wa,--trap
endif
diff -up --recursive --new-file
linux-mips-2.4.19-rc1-20020807.macro/arch/mips/config-shared.in
linux-mips-2.4.19-rc1-20020807/arch/mips/config-shared.in
--- linux-mips-2.4.19-rc1-20020807.macro/arch/mips/config-shared.in
2002-08-07 02:58:14.000000000 +0000
+++ linux-mips-2.4.19-rc1-20020807/arch/mips/config-shared.in 2002-09-02
18:59:33.000000000 +0000
@@ -413,6 +413,7 @@ choice 'CPU type' \
MIPS64 CONFIG_CPU_MIPS64 \
R3000 CONFIG_CPU_R3000 \
R39XX CONFIG_CPU_TX39XX \
+ R4000 CONFIG_CPU_R4000 \
R41xx CONFIG_CPU_VR41XX \
R4300 CONFIG_CPU_R4300 \
R4x00 CONFIG_CPU_R4X00 \
@@ -447,7 +448,8 @@ if [ "$CONFIG_CPU_SB1" = "y" ]; then
define_bool CONFIG_CPU_HAS_PREFETCH y
fi
-if [ "$CONFIG_CPU_R4X00" = "y" -o \
+if [ "$CONFIG_CPU_R4000" = "y" -o \
+ "$CONFIG_CPU_R4X00" = "y" -o \
"$CONFIG_CPU_R5000" = "y" -o \
"$CONFIG_CPU_RM7000" = "y" -o \
"$CONFIG_CPU_R10000" = "y" -o \
diff -up --recursive --new-file
linux-mips-2.4.19-rc1-20020807.macro/arch/mips/dec/prom/init.c
linux-mips-2.4.19-rc1-20020807/arch/mips/dec/prom/init.c
--- linux-mips-2.4.19-rc1-20020807.macro/arch/mips/dec/prom/init.c
2002-08-06 02:57:08.000000000 +0000
+++ linux-mips-2.4.19-rc1-20020807/arch/mips/dec/prom/init.c 2002-09-02
18:38:37.000000000 +0000
@@ -100,7 +100,7 @@ int __init prom_init(int argc, char **ar
}
#endif
-#if defined(CONFIG_CPU_R4X00)
+#if defined(CONFIG_CPU_R4000) || defined(CONFIG_CPU_R4X00)
if ((mips_cpu.cputype == CPU_R3000) ||
(mips_cpu.cputype == CPU_R3000A)) {
prom_printf("Sorry, this kernel is compiled for the wrong CPU
type!\n");
diff -up --recursive --new-file
linux-mips-2.4.19-rc1-20020807.macro/arch/mips/mm/Makefile
linux-mips-2.4.19-rc1-20020807/arch/mips/mm/Makefile
--- linux-mips-2.4.19-rc1-20020807.macro/arch/mips/mm/Makefile 2002-06-26
03:04:37.000000000 +0000
+++ linux-mips-2.4.19-rc1-20020807/arch/mips/mm/Makefile 2002-09-02
18:41:00.000000000 +0000
@@ -17,6 +17,7 @@ obj-$(CONFIG_CPU_R3000) += pg-r3k.o c-r
tlbex-r3k.o
obj-$(CONFIG_CPU_TX39XX) += pg-r3k.o c-tx39.o tlb-r3k.o tlbex-r3k.o
obj-$(CONFIG_CPU_TX49XX) += pg-r4k.o c-tx49.o tlb-r4k.o tlbex-r4k.o
+obj-$(CONFIG_CPU_R4000) += pg-r4k.o c-r4k.o tlb-r4k.o
tlbex-r4k.o
obj-$(CONFIG_CPU_R4300) += pg-r4k.o c-r4k.o tlb-r4k.o
tlbex-r4k.o
obj-$(CONFIG_CPU_R4X00) += pg-r4k.o c-r4k.o tlb-r4k.o
tlbex-r4k.o
obj-$(CONFIG_CPU_VR41XX) += pg-r4k.o c-r4k.o tlb-r4k.o tlbex-r4k.o
diff -up --recursive --new-file
linux-mips-2.4.19-rc1-20020807.macro/arch/mips/mm/loadmmu.c
linux-mips-2.4.19-rc1-20020807/arch/mips/mm/loadmmu.c
--- linux-mips-2.4.19-rc1-20020807.macro/arch/mips/mm/loadmmu.c 2002-08-06
02:57:32.000000000 +0000
+++ linux-mips-2.4.19-rc1-20020807/arch/mips/mm/loadmmu.c 2002-09-02
18:42:30.000000000 +0000
@@ -68,9 +68,9 @@ extern void sb1_tlb_init(void);
void __init loadmmu(void)
{
if (mips_cpu.options & MIPS_CPU_4KTLB) {
-#if defined(CONFIG_CPU_R4X00) || defined(CONFIG_CPU_VR41XX) || \
- defined(CONFIG_CPU_R4300) || defined(CONFIG_CPU_R5000) || \
- defined(CONFIG_CPU_NEVADA)
+#if defined(CONFIG_CPU_R4000) || defined(CONFIG_CPU_VR41XX) || \
+ defined(CONFIG_CPU_R4300) || defined(CONFIG_CPU_R4X00) || \
+ defined(CONFIG_CPU_R5000) || defined(CONFIG_CPU_NEVADA)
ld_mmu_r4xx0();
r4k_tlb_init();
#endif
diff -up --recursive --new-file
linux-mips-2.4.19-rc1-20020807.macro/arch/mips64/Makefile
linux-mips-2.4.19-rc1-20020807/arch/mips64/Makefile
--- linux-mips-2.4.19-rc1-20020807.macro/arch/mips64/Makefile 2002-08-07
02:58:22.000000000 +0000
+++ linux-mips-2.4.19-rc1-20020807/arch/mips64/Makefile 2002-09-02
18:45:02.000000000 +0000
@@ -46,6 +46,9 @@ endif
#
# CPU-dependent compiler/assembler options for optimization.
#
+ifdef CONFIG_CPU_R4000
+GCCFLAGS += -mcpu=r4000 -mips3
+endif
ifdef CONFIG_CPU_R4300
GCCFLAGS += -mcpu=r4300 -mips3
endif
diff -up --recursive --new-file
linux-mips-2.4.19-rc1-20020807.macro/arch/mips64/mm/Makefile
linux-mips-2.4.19-rc1-20020807/arch/mips64/mm/Makefile
--- linux-mips-2.4.19-rc1-20020807.macro/arch/mips64/mm/Makefile
2002-07-25 02:57:02.000000000 +0000
+++ linux-mips-2.4.19-rc1-20020807/arch/mips64/mm/Makefile 2002-09-02
18:45:30.000000000 +0000
@@ -9,6 +9,7 @@ O_TARGET := mm.o
export-objs += umap.o
obj-y := extable.o init.o fault.o loadmmu.o
+obj-$(CONFIG_CPU_R4000) += r4xx0.o tlbex-r4k.o tlb-glue-r4k.o
obj-$(CONFIG_CPU_R4300) += r4xx0.o tlbex-r4k.o tlb-glue-r4k.o
obj-$(CONFIG_CPU_R4X00) += r4xx0.o tlbex-r4k.o tlb-glue-r4k.o
obj-$(CONFIG_CPU_R5000) += r4xx0.o tlbex-r4k.o tlb-glue-r4k.o
diff -up --recursive --new-file
linux-mips-2.4.19-rc1-20020807.macro/arch/mips64/mm/loadmmu.c
linux-mips-2.4.19-rc1-20020807/arch/mips64/mm/loadmmu.c
--- linux-mips-2.4.19-rc1-20020807.macro/arch/mips64/mm/loadmmu.c
2002-08-06 02:57:39.000000000 +0000
+++ linux-mips-2.4.19-rc1-20020807/arch/mips64/mm/loadmmu.c 2002-09-02
18:46:37.000000000 +0000
@@ -60,7 +60,8 @@ extern void r4k_tlb_init(void);
void __init load_mmu(void)
{
if (mips_cpu.options & MIPS_CPU_4KTLB) {
-#if defined (CONFIG_CPU_R4300) \
+#if defined (CONFIG_CPU_R4000) \
+ || defined (CONFIG_CPU_R4300) \
|| defined (CONFIG_CPU_R4X00) \
|| defined (CONFIG_CPU_R5000) \
|| defined (CONFIG_CPU_NEVADA)
diff -up --recursive --new-file
linux-mips-2.4.19-rc1-20020807.macro/include/asm-mips64/addrspace.h
linux-mips-2.4.19-rc1-20020807/include/asm-mips64/addrspace.h
--- linux-mips-2.4.19-rc1-20020807.macro/include/asm-mips64/addrspace.h
2002-08-22 06:18:02.000000000 +0000
+++ linux-mips-2.4.19-rc1-20020807/include/asm-mips64/addrspace.h
2002-09-02 19:00:37.000000000 +0000
@@ -82,7 +82,8 @@
#define CKSSEG 0xffffffffc0000000
#define CKSEG3 0xffffffffe0000000
-#if defined (CONFIG_CPU_R4300) \
+#if defined (CONFIG_CPU_R4000) \
+ || defined (CONFIG_CPU_R4300) \
|| defined (CONFIG_CPU_R4X00) \
|| defined (CONFIG_CPU_R5000) \
|| defined (CONFIG_CPU_NEVADA) \
|