MIPS: Handle COP3 Unusable exception as COP1X for FP emulation
authorMaciej W. Rozycki <macro@codesourcery.com>
Tue, 6 Mar 2012 20:28:54 +0000 (20:28 +0000)
committerRalf Baechle <ralf@linux-mips.org>
Thu, 13 Dec 2012 17:15:27 +0000 (18:15 +0100)
 Our FP emulator is hardcoded for the MIPS IV FP instruction set and does
not match the FP ISA with the general ISA.  However for the few MIPS IV FP
instructions that use the COP1X major opcode it relies on the Coprocessor
Unusable exception to be delivered as a COP1 rather than COP3 exception.
This includes indexed transfer (LDXC1, etc.) and FP multiply-accumulate
(MADD.D, etc.) instructions.

 All the MIPS I, II, III and IV processors and some newer chips that do not
implement the FPU use the COP3 exception however.  Therefore I believe the
kernel should follow and redirect any COP3 Unusable traps to the emulator
unless an actual FPU part or core is present.

 This is a change that implements it.  Any minor opcode encodings that are
not recognised as valid FP instructions are rejected by the emulator and
will result in a SIGILL signal being delivered as they currently do.  We
do not support vendor-specific coprocessor 3 implementations supported
with MIPS I and MIPS II ISA processors; we never set CP0.Status.CU3.

[Ralf: On MIPS IV processors the kernel always enables the XX bit which
replaces the CU3 bit off earlier architecture revisions.]

 If matching between the CPU and the FPU ISA is considered required one
day, this can still be done in the emulator itself.  I think the CpU
exception dispatcher is not the right place to do this anyway, as there
are further differences between MIPS I, MIPS II, MIPS III, MIPS IV and
MIPS32 FP ISAs.

 Corresponding explanation of this implementation is included within the
change itself.

Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/project/linux-mips/list/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/kernel/traps.c

index da0c29422cf2a6b44e1b2fa35d1f03b97c2a0d1a..cf7ac5483f5398e8f91b05c1615a7aab6efa6349 100644 (file)
@@ -1025,6 +1025,24 @@ asmlinkage void do_cpu(struct pt_regs *regs)
 
                return;
 
+       case 3:
+               /*
+                * Old (MIPS I and MIPS II) processors will set this code
+                * for COP1X opcode instructions that replaced the original
+                * COP3 space.  We don't limit COP1 space instructions in
+                * the emulator according to the CPU ISA, so we want to
+                * treat COP1X instructions consistently regardless of which
+                * code the CPU chose.  Therefore we redirect this trap to
+                * the FP emulator too.
+                *
+                * Then some newer FPU-less processors use this code
+                * erroneously too, so they are covered by this choice
+                * as well.
+                */
+               if (raw_cpu_has_fpu)
+                       break;
+               /* Fall through.  */
+
        case 1:
                if (used_math())        /* Using the FPU again.  */
                        own_fpu(1);
@@ -1048,9 +1066,6 @@ asmlinkage void do_cpu(struct pt_regs *regs)
        case 2:
                raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs);
                return;
-
-       case 3:
-               break;
        }
 
        force_sig(SIGILL, current);