diff options
author | Leonid Yegoshin <yegoshin@mips.com> | 2012-07-19 03:11:14 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2012-07-19 05:23:43 -0400 |
commit | 2dd17030c940ef1199a07b095ec79c4660fa8734 (patch) | |
tree | 34261c3c27f418a785ef127afe6a1f0109310a53 | |
parent | dc34b05fea0cc9a869863b929f37f1e8ce30edf4 (diff) |
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>
-rw-r--r-- | arch/mips/include/asm/switch_to.h | 6 | ||||
-rw-r--r-- | arch/mips/kernel/octeon_switch.S | 2 | ||||
-rw-r--r-- | arch/mips/kernel/r2300_switch.S | 15 | ||||
-rw-r--r-- | arch/mips/kernel/r4k_switch.S | 12 |
4 files changed, 11 insertions, 24 deletions
diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h index 5d33621b565..4f8ddba8c36 100644 --- a/arch/mips/include/asm/switch_to.h +++ b/arch/mips/include/asm/switch_to.h | |||
@@ -22,7 +22,7 @@ struct task_struct; | |||
22 | * switch_to(n) should switch tasks to task nr n, first | 22 | * switch_to(n) should switch tasks to task nr n, first |
23 | * checking that n isn't the current task, in which case it does nothing. | 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 | extern unsigned int ll_bit; | 27 | extern unsigned int ll_bit; |
28 | extern struct task_struct *ll_task; | 28 | extern struct task_struct *ll_task; |
@@ -66,11 +66,13 @@ do { \ | |||
66 | 66 | ||
67 | #define switch_to(prev, next, last) \ | 67 | #define switch_to(prev, next, last) \ |
68 | do { \ | 68 | do { \ |
69 | u32 __usedfpu; \ | ||
69 | __mips_mt_fpaff_switch_to(prev); \ | 70 | __mips_mt_fpaff_switch_to(prev); \ |
70 | if (cpu_has_dsp) \ | 71 | if (cpu_has_dsp) \ |
71 | __save_dsp(prev); \ | 72 | __save_dsp(prev); \ |
72 | __clear_software_ll_bit(); \ | 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 | } while (0) | 76 | } while (0) |
75 | 77 | ||
76 | #define finish_arch_switch(prev) \ | 78 | #define finish_arch_switch(prev) \ |
diff --git a/arch/mips/kernel/octeon_switch.S b/arch/mips/kernel/octeon_switch.S index ce89c806170..0441f54b2a6 100644 --- a/arch/mips/kernel/octeon_switch.S +++ b/arch/mips/kernel/octeon_switch.S | |||
@@ -31,7 +31,7 @@ | |||
31 | 31 | ||
32 | /* | 32 | /* |
33 | * task_struct *resume(task_struct *prev, task_struct *next, | 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 | .align 7 | 36 | .align 7 |
37 | LEAF(resume) | 37 | LEAF(resume) |
diff --git a/arch/mips/kernel/r2300_switch.S b/arch/mips/kernel/r2300_switch.S index 293898391e6..9c51be5a163 100644 --- a/arch/mips/kernel/r2300_switch.S +++ b/arch/mips/kernel/r2300_switch.S | |||
@@ -43,7 +43,7 @@ | |||
43 | 43 | ||
44 | /* | 44 | /* |
45 | * task_struct *resume(task_struct *prev, task_struct *next, | 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 | LEAF(resume) | 48 | LEAF(resume) |
49 | mfc0 t1, CP0_STATUS | 49 | mfc0 t1, CP0_STATUS |
@@ -51,18 +51,9 @@ LEAF(resume) | |||
51 | cpu_save_nonscratch a0 | 51 | cpu_save_nonscratch a0 |
52 | sw ra, THREAD_REG31(a0) | 52 | sw ra, THREAD_REG31(a0) |
53 | 53 | ||
54 | /* | 54 | beqz a3, 1f |
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 | ||
63 | 55 | ||
64 | and t0, t0, t1 | 56 | PTR_L t3, TASK_THREAD_INFO(a0) |
65 | sw t0, TI_FLAGS(t3) | ||
66 | 57 | ||
67 | /* | 58 | /* |
68 | * clear saved user stack CU1 bit | 59 | * clear saved user stack CU1 bit |
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S index 9414f935446..42d2a393842 100644 --- a/arch/mips/kernel/r4k_switch.S +++ b/arch/mips/kernel/r4k_switch.S | |||
@@ -41,7 +41,7 @@ | |||
41 | 41 | ||
42 | /* | 42 | /* |
43 | * task_struct *resume(task_struct *prev, task_struct *next, | 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 | .align 5 | 46 | .align 5 |
47 | LEAF(resume) | 47 | LEAF(resume) |
@@ -53,16 +53,10 @@ | |||
53 | /* | 53 | /* |
54 | * check if we need to save FPU registers | 54 | * check if we need to save FPU registers |
55 | */ | 55 | */ |
56 | 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 | 56 | ||
63 | and t0, t0, t1 | 57 | beqz a3, 1f |
64 | LONG_S t0, TI_FLAGS(t3) | ||
65 | 58 | ||
59 | PTR_L t3, TASK_THREAD_INFO(a0) | ||
66 | /* | 60 | /* |
67 | * clear saved user stack CU1 bit | 61 | * clear saved user stack CU1 bit |
68 | */ | 62 | */ |