Merge branch 'x86-fpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[firefly-linux-kernel-4.4.55.git] / arch / x86 / kernel / process.c
index f2e8c0f951d632c9d675d6801940ebb406c6865e..735279e54e59a56d3f3ce97288f2d81fc98491d6 100644 (file)
@@ -56,10 +56,16 @@ EXPORT_SYMBOL_GPL(idle_notifier_unregister);
 struct kmem_cache *task_xstate_cachep;
 EXPORT_SYMBOL_GPL(task_xstate_cachep);
 
+/*
+ * this gets called so that we can store lazy state into memory and copy the
+ * current task into the new thread.
+ */
 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 {
        int ret;
 
+       unlazy_fpu(src);
+
        *dst = *src;
        if (fpu_allocated(&src->thread.fpu)) {
                memset(&dst->thread.fpu, 0, sizeof(dst->thread.fpu));
@@ -89,6 +95,16 @@ void arch_task_cache_init(void)
                                  SLAB_PANIC | SLAB_NOTRACK, NULL);
 }
 
+static inline void drop_fpu(struct task_struct *tsk)
+{
+       /*
+        * Forget coprocessor state..
+        */
+       tsk->fpu_counter = 0;
+       clear_fpu(tsk);
+       clear_used_math();
+}
+
 /*
  * Free current thread data structures etc..
  */
@@ -111,6 +127,8 @@ void exit_thread(void)
                put_cpu();
                kfree(bp);
        }
+
+       drop_fpu(me);
 }
 
 void show_regs_common(void)
@@ -145,12 +163,7 @@ void flush_thread(void)
 
        flush_ptrace_hw_breakpoint(tsk);
        memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
-       /*
-        * Forget coprocessor state..
-        */
-       tsk->fpu_counter = 0;
-       clear_fpu(tsk);
-       clear_used_math();
+       drop_fpu(tsk);
 }
 
 static void hard_disable_TSC(void)