diff options
author | Atsushi Nemoto <anemo@mba.ocn.ne.jp> | 2007-03-09 11:07:45 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2007-03-16 21:03:26 -0400 |
commit | 53dc80287da43b75df2fe2658651d3c5160dad8e (patch) | |
tree | 3c4c97534c379709cd2a1dae5b90df626349f21d /arch/mips/kernel/signal32.c | |
parent | c6a2f4679331206ef5d353fc9a6cda2fa4aef8c6 (diff) |
[MIPS] FPU ownership management & preemption fixes
Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel/signal32.c')
-rw-r--r-- | arch/mips/kernel/signal32.c | 29 |
1 files changed, 12 insertions, 17 deletions
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 20013b6fe725..151fd2f0893a 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c | |||
@@ -181,6 +181,7 @@ static int setup_sigcontext32(struct pt_regs *regs, | |||
181 | { | 181 | { |
182 | int err = 0; | 182 | int err = 0; |
183 | int i; | 183 | int i; |
184 | u32 used_math; | ||
184 | 185 | ||
185 | err |= __put_user(regs->cp0_epc, &sc->sc_pc); | 186 | err |= __put_user(regs->cp0_epc, &sc->sc_pc); |
186 | 187 | ||
@@ -200,22 +201,18 @@ static int setup_sigcontext32(struct pt_regs *regs, | |||
200 | err |= __put_user(mflo3(), &sc->sc_lo3); | 201 | err |= __put_user(mflo3(), &sc->sc_lo3); |
201 | } | 202 | } |
202 | 203 | ||
203 | err |= __put_user(!!used_math(), &sc->sc_used_math); | 204 | used_math = !!used_math(); |
205 | err |= __put_user(used_math, &sc->sc_used_math); | ||
204 | 206 | ||
205 | if (used_math()) { | 207 | if (used_math) { |
206 | /* | 208 | /* |
207 | * Save FPU state to signal context. Signal handler | 209 | * Save FPU state to signal context. Signal handler |
208 | * will "inherit" current FPU state. | 210 | * will "inherit" current FPU state. |
209 | */ | 211 | */ |
210 | preempt_disable(); | 212 | own_fpu(1); |
211 | 213 | enable_fp_in_kernel(); | |
212 | if (!is_fpu_owner()) { | ||
213 | own_fpu(); | ||
214 | restore_fp(current); | ||
215 | } | ||
216 | err |= save_fp_context32(sc); | 214 | err |= save_fp_context32(sc); |
217 | 215 | disable_fp_in_kernel(); | |
218 | preempt_enable(); | ||
219 | } | 216 | } |
220 | return err; | 217 | return err; |
221 | } | 218 | } |
@@ -262,20 +259,18 @@ static int restore_sigcontext32(struct pt_regs *regs, | |||
262 | err |= __get_user(used_math, &sc->sc_used_math); | 259 | err |= __get_user(used_math, &sc->sc_used_math); |
263 | conditional_used_math(used_math); | 260 | conditional_used_math(used_math); |
264 | 261 | ||
265 | preempt_disable(); | 262 | if (used_math) { |
266 | |||
267 | if (used_math()) { | ||
268 | /* restore fpu context if we have used it before */ | 263 | /* restore fpu context if we have used it before */ |
269 | own_fpu(); | 264 | own_fpu(0); |
265 | enable_fp_in_kernel(); | ||
270 | if (!err) | 266 | if (!err) |
271 | err = check_and_restore_fp_context32(sc); | 267 | err = check_and_restore_fp_context32(sc); |
268 | disable_fp_in_kernel(); | ||
272 | } else { | 269 | } else { |
273 | /* signal handler may have used FPU. Give it up. */ | 270 | /* signal handler may have used FPU. Give it up. */ |
274 | lose_fpu(); | 271 | lose_fpu(0); |
275 | } | 272 | } |
276 | 273 | ||
277 | preempt_enable(); | ||
278 | |||
279 | return err; | 274 | return err; |
280 | } | 275 | } |
281 | 276 | ||