MIPS: Fix race condition with FPU thread task flag during context switch.
authorLeonid Yegoshin <yegoshin@mips.com>
Thu, 19 Jul 2012 07:11:14 +0000 (09:11 +0200)
committerRalf Baechle <ralf@linux-mips.org>
Thu, 19 Jul 2012 09:23:43 +0000 (11:23 +0200)
[ralf@linux-mips.org: Cosmetic changes; also fixed up r2300_switch.S and
octeon_switch.S which needed similar modifications.]

Signed-off-by: Leonid Yegoshin <yegoshin@mips.com>
Signed-off-by: Steven J. Hill <sjhill@mips.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/3784/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/include/asm/switch_to.h
arch/mips/kernel/octeon_switch.S
arch/mips/kernel/r2300_switch.S
arch/mips/kernel/r4k_switch.S

index 5d33621b5658f9c46314f4fcc1d2d123eaaf83d5..4f8ddba8c360050703d6d760b5909e92944e8b23 100644 (file)
@@ -22,7 +22,7 @@ struct task_struct;
  * switch_to(n) should switch tasks to task nr n, first
  * checking that n isn't the current task, in which case it does nothing.
  */
-extern asmlinkage void *resume(void *last, void *next, void *next_ti);
+extern asmlinkage void *resume(void *last, void *next, void *next_ti, u32 __usedfpu);
 
 extern unsigned int ll_bit;
 extern struct task_struct *ll_task;
@@ -66,11 +66,13 @@ do {                                                                        \
 
 #define switch_to(prev, next, last)                                    \
 do {                                                                   \
+       u32 __usedfpu;                                                  \
        __mips_mt_fpaff_switch_to(prev);                                \
        if (cpu_has_dsp)                                                \
                __save_dsp(prev);                                       \
        __clear_software_ll_bit();                                      \
-       (last) = resume(prev, next, task_thread_info(next));            \
+       __usedfpu = test_and_clear_tsk_thread_flag(prev, TIF_USEDFPU);  \
+       (last) = resume(prev, next, task_thread_info(next), __usedfpu); \
 } while (0)
 
 #define finish_arch_switch(prev)                                       \
index ce89c806170846a1ea2bbcf027598fae11028648..0441f54b2a6acc9ab27a0d229c1465a8e0fa5975 100644 (file)
@@ -31,7 +31,7 @@
 
 /*
  * task_struct *resume(task_struct *prev, task_struct *next,
- *                     struct thread_info *next_ti)
+ *                     struct thread_info *next_ti, int usedfpu)
  */
        .align  7
        LEAF(resume)
index 293898391e674bd0979f87918a019b3a377d575d..9c51be5a163a9249efa3bd74f12be62b64eba923 100644 (file)
@@ -43,7 +43,7 @@
 
 /*
  * task_struct *resume(task_struct *prev, task_struct *next,
- *                     struct thread_info *next_ti)
+ *                     struct thread_info *next_ti, int usedfpu)
  */
 LEAF(resume)
        mfc0    t1, CP0_STATUS
@@ -51,18 +51,9 @@ LEAF(resume)
        cpu_save_nonscratch a0
        sw      ra, THREAD_REG31(a0)
 
-       /*
-        * check if we need to save FPU registers
-        */
-       lw      t3, TASK_THREAD_INFO(a0)
-       lw      t0, TI_FLAGS(t3)
-       li      t1, _TIF_USEDFPU
-       and     t2, t0, t1
-       beqz    t2, 1f
-       nor     t1, zero, t1
+       beqz    a3, 1f
 
-       and     t0, t0, t1
-       sw      t0, TI_FLAGS(t3)
+       PTR_L   t3, TASK_THREAD_INFO(a0)
 
        /*
         * clear saved user stack CU1 bit
index 9414f935446968069ec4f22daed1ae19b0799fb7..42d2a3938420df28e64d1f016459529b13991b7e 100644 (file)
@@ -41,7 +41,7 @@
 
 /*
  * task_struct *resume(task_struct *prev, task_struct *next,
- *                     struct thread_info *next_ti)
+ *                     struct thread_info *next_ti, int usedfpu)
  */
        .align  5
        LEAF(resume)
        /*
         * check if we need to save FPU registers
         */
-       PTR_L   t3, TASK_THREAD_INFO(a0)
-       LONG_L  t0, TI_FLAGS(t3)
-       li      t1, _TIF_USEDFPU
-       and     t2, t0, t1
-       beqz    t2, 1f
-       nor     t1, zero, t1
 
-       and     t0, t0, t1
-       LONG_S  t0, TI_FLAGS(t3)
+       beqz    a3, 1f
 
+       PTR_L   t3, TASK_THREAD_INFO(a0)
        /*
         * clear saved user stack CU1 bit
         */