Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

MIPS: Fix race condition with FPU thread task flag during context switch.

[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>

authored by

Leonid Yegoshin and committed by
Ralf Baechle
2dd17030 dc34b05f

+12 -25
+4 -2
arch/mips/include/asm/switch_to.h
··· 22 22 * switch_to(n) should switch tasks to task nr n, first 23 23 * checking that n isn't the current task, in which case it does nothing. 24 24 */ 25 - extern asmlinkage void *resume(void *last, void *next, void *next_ti); 25 + extern asmlinkage void *resume(void *last, void *next, void *next_ti, u32 __usedfpu); 26 26 27 27 extern unsigned int ll_bit; 28 28 extern struct task_struct *ll_task; ··· 66 66 67 67 #define switch_to(prev, next, last) \ 68 68 do { \ 69 + u32 __usedfpu; \ 69 70 __mips_mt_fpaff_switch_to(prev); \ 70 71 if (cpu_has_dsp) \ 71 72 __save_dsp(prev); \ 72 73 __clear_software_ll_bit(); \ 73 - (last) = resume(prev, next, task_thread_info(next)); \ 74 + __usedfpu = test_and_clear_tsk_thread_flag(prev, TIF_USEDFPU); \ 75 + (last) = resume(prev, next, task_thread_info(next), __usedfpu); \ 74 76 } while (0) 75 77 76 78 #define finish_arch_switch(prev) \
+1 -1
arch/mips/kernel/octeon_switch.S
··· 31 31 32 32 /* 33 33 * task_struct *resume(task_struct *prev, task_struct *next, 34 - * struct thread_info *next_ti) 34 + * struct thread_info *next_ti, int usedfpu) 35 35 */ 36 36 .align 7 37 37 LEAF(resume)
+3 -12
arch/mips/kernel/r2300_switch.S
··· 43 43 44 44 /* 45 45 * task_struct *resume(task_struct *prev, task_struct *next, 46 - * struct thread_info *next_ti) ) 46 + * struct thread_info *next_ti, int usedfpu) 47 47 */ 48 48 LEAF(resume) 49 49 mfc0 t1, CP0_STATUS ··· 51 51 cpu_save_nonscratch a0 52 52 sw ra, THREAD_REG31(a0) 53 53 54 - /* 55 - * check if we need to save FPU registers 56 - */ 57 - lw t3, TASK_THREAD_INFO(a0) 58 - lw t0, TI_FLAGS(t3) 59 - li t1, _TIF_USEDFPU 60 - and t2, t0, t1 61 - beqz t2, 1f 62 - nor t1, zero, t1 54 + beqz a3, 1f 63 55 64 - and t0, t0, t1 65 - sw t0, TI_FLAGS(t3) 56 + PTR_L t3, TASK_THREAD_INFO(a0) 66 57 67 58 /* 68 59 * clear saved user stack CU1 bit
+4 -10
arch/mips/kernel/r4k_switch.S
··· 41 41 42 42 /* 43 43 * task_struct *resume(task_struct *prev, task_struct *next, 44 - * struct thread_info *next_ti) 44 + * struct thread_info *next_ti, int usedfpu) 45 45 */ 46 46 .align 5 47 47 LEAF(resume) ··· 53 53 /* 54 54 * check if we need to save FPU registers 55 55 */ 56 + 57 + beqz a3, 1f 58 + 56 59 PTR_L t3, TASK_THREAD_INFO(a0) 57 - LONG_L t0, TI_FLAGS(t3) 58 - li t1, _TIF_USEDFPU 59 - and t2, t0, t1 60 - beqz t2, 1f 61 - nor t1, zero, t1 62 - 63 - and t0, t0, t1 64 - LONG_S t0, TI_FLAGS(t3) 65 - 66 60 /* 67 61 * clear saved user stack CU1 bit 68 62 */