Orabug14038272

based on Chander's patch in bug7708133, 
also port 15d8791cae75dca27bfda8ecfe87dca9379d6bb0
diff -up --new-file ./arch/x86_64/kernel/i387.c.orig ./arch/x86_64/kernel/i387.c
--- ./arch/x86_64/kernel/i387.c.orig	2012-06-14 19:38:25.000000000 +0800
+++ ./arch/x86_64/kernel/i387.c	2012-06-14 19:41:52.000000000 +0800
@@ -96,7 +96,10 @@ int save_i387(struct _fpstate __user *bu
 	if (task_thread_info(tsk)->status & TS_USEDFPU) {
 		err = save_i387_checking((struct i387_fxsave_struct __user *)buf);
 		if (err) return err;
+	preempt_disable();
+	task_thread_info(tsk)->status &= ~TS_USEDFPU;
 		stts();
+	preempt_enable();
 	} else {
 		if (__copy_to_user(buf, &tsk->thread.i387.fxsave, 
 				   sizeof(struct i387_fxsave_struct)))
diff -up --new-file ./arch/x86_64/kernel/signal.c.orig ./arch/x86_64/kernel/signal.c
--- ./arch/x86_64/kernel/signal.c.orig	2012-06-14 19:34:32.000000000 +0800
+++ ./arch/x86_64/kernel/signal.c	2012-06-14 19:38:04.000000000 +0800
@@ -95,14 +95,24 @@ restore_sigcontext(struct pt_regs *regs,
 
 	{
 		struct _fpstate __user * buf;
+		struct task_struct *me = current;
+
 		err |= __get_user(buf, &sc->fpstate);
 
 		if (buf) {
 			if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))
 				goto badframe;
+			if (!used_math()) {
+				init_fpu(me);
+			}
+			preempt_disable();
+			if (!(task_thread_info(current)->status & TS_USEDFPU)) {
+				clts();
+				task_thread_info(current)->status |= TS_USEDFPU;
+			}
+			preempt_enable();
 			err |= restore_i387(buf);
 		} else {
-			struct task_struct *me = current;
 			if (used_math()) {
 				clear_fpu(me);
 				clear_used_math();
