Subject: fpu, preempt, ptrace

From: Atsushi Nemoto <[email-masked]>
Date: Tue, 10 May 2005 12:10:38 +0900 (JST)

Here is a (revised) patch to fix some preempt issues around fpu and ptrace.

For now, get_fpu_regs() is used in ptrace code only and the condition
'tsk == current' should always be false.  So we can just remove
_save_fp() call instead of disabling preemption.

diff -ur linux-mips/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c
--- linux-mips/arch/mips/kernel/ptrace.c	2005-04-18 11:42:47.000000000 +0900
+++ linux/arch/mips/kernel/ptrace.c	2005-05-10 11:41:35.000000000 +0900
@@ -169,10 +169,12 @@
 			if (!cpu_has_fpu)
 				break;
 
+			preempt_disable();
 			flags = read_c0_status();
 			__enable_fpu();
 			__asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
 			write_c0_status(flags);
+			preempt_enable();
 			break;
 		}
 		default:
diff -ur linux-mips/arch/mips/kernel/ptrace32.c linux/arch/mips/kernel/ptrace32.c
--- linux-mips/arch/mips/kernel/ptrace32.c	2005-04-18 11:42:47.000000000 +0900
+++ linux/arch/mips/kernel/ptrace32.c	2005-05-10 11:38:51.000000000 +0900
@@ -155,10 +155,12 @@
 			if (!cpu_has_fpu)
 				break;
 
+			preempt_disable();
 			flags = read_c0_status();
 			__enable_fpu();
 			__asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
 			write_c0_status(flags);
+			preempt_enable();
 			break;
 		}
 		default:
diff -ur linux-mips/include/asm-mips/fpu.h linux/include/asm-mips/fpu.h
--- linux-mips/include/asm-mips/fpu.h	2005-05-10 10:21:31.000000000 +0900
+++ linux/include/asm-mips/fpu.h	2005-05-10 11:38:38.000000000 +0900
@@ -132,8 +132,10 @@
 static inline fpureg_t *get_fpu_regs(struct task_struct *tsk)
 {
 	if (cpu_has_fpu) {
+		preempt_disable();
 		if ((tsk == current) && __is_fpu_owner()) 
 			_save_fp(current);
+		preempt_enable();
 		return tsk->thread.fpu.hard.fpr;
 	}
 
---
Atsushi Nemoto

---

From: Atsushi Nemoto <[email-masked]>
Date: Wed, 11 May 2005 00:06:20 +0900 (JST)

>>>>> On Tue, 10 May 2005 12:10:38 +0900 (JST), Atsushi Nemoto <[email-masked]> said:

anemo> For now, get_fpu_regs() is used in ptrace code only and the
anemo> condition 'tsk == current' should always be false.  So we can
anemo> just remove _save_fp() call instead of disabling preemption.

The get_fpu_regs() fix was insufficient.  The caller of the function
should disable preemption.  And while the caller (sys_ptrace) never
pass 'current' to the function, it should be preempt-safe anyway.
Please ignore that part of my patch.

---
Atsushi Nemoto