Subject: CFC1 instruction in compute_return_epc

From: Atsushi Nemoto <[email-masked]>
Date: Wed, 20 Apr 2005 16:53:20 +0900 (JST)

The __compute_return_epc() uses CFC1 instruction but it might cause a
coprocessor unusable exception since the process can lose its fpu
context by preemption.  The coprocessor unusable exception is not
allowed in kernel context.

Here is a patch.  Please review.  Thank you.

--- linux-mips/arch/mips/kernel/branch.c	2004-08-14 19:55:32.000000000 +0900
+++ linux/arch/mips/kernel/branch.c	2005-04-20 16:33:24.662914765 +0900
@@ -12,6 +12,7 @@
 #include <asm/branch.h>
 #include <asm/cpu.h>
 #include <asm/cpu-features.h>
+#include <asm/fpu.h>
 #include <asm/inst.h>
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
@@ -163,8 +164,14 @@
 	case cop1_op:
 		if (!cpu_has_fpu)
 			fcr31 = current->thread.fpu.soft.fcr31;
-		else
-			asm volatile("cfc1\t%0,$31" : "=r" (fcr31));
+		else {
+			preempt_disable();
+			if (is_fpu_owner())
+				asm volatile("cfc1\t%0,$31" : "=r" (fcr31));
+			else
+				fcr31 = current->thread.fpu.hard.fcr31;
+			preempt_enable();
+		}
 		bit = (insn.i_format.rt >> 2);
 		bit += (bit != 0);
 		bit += 23;

---
Atsushi Nemoto