diff options
author | Atsushi Nemoto <anemo@mba.ocn.ne.jp> | 2007-03-09 11:03:48 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2007-03-16 21:03:25 -0400 |
commit | c6a2f4679331206ef5d353fc9a6cda2fa4aef8c6 (patch) | |
tree | 9634ba2d5b6c6c97f4301b28088c68254201bf74 /arch/mips/kernel/signal32.c | |
parent | f1dbf8e718ef0ddb196a28bcc71925ac7da881af (diff) |
[MIPS] Check FCSR for pending interrupts, alternative version
Commit 6d6671066a311703bca1b91645bb1e04cc983387 is incomplete and misses
non-r4k CPUs. This patch reverts the commit and fixes in other way.
o Do FCSR checking in caller of restore_fp_context.
o Send SIGFPE if the signal handler set any FPU exception bits.
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 | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 19bbef001959..20013b6fe725 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c | |||
@@ -220,6 +220,18 @@ static int setup_sigcontext32(struct pt_regs *regs, | |||
220 | return err; | 220 | return err; |
221 | } | 221 | } |
222 | 222 | ||
223 | static int | ||
224 | check_and_restore_fp_context32(struct sigcontext32 __user *sc) | ||
225 | { | ||
226 | int err, sig; | ||
227 | |||
228 | err = sig = fpcsr_pending(&sc->sc_fpc_csr); | ||
229 | if (err > 0) | ||
230 | err = 0; | ||
231 | err |= restore_fp_context32(sc); | ||
232 | return err ?: sig; | ||
233 | } | ||
234 | |||
223 | static int restore_sigcontext32(struct pt_regs *regs, | 235 | static int restore_sigcontext32(struct pt_regs *regs, |
224 | struct sigcontext32 __user *sc) | 236 | struct sigcontext32 __user *sc) |
225 | { | 237 | { |
@@ -255,7 +267,8 @@ static int restore_sigcontext32(struct pt_regs *regs, | |||
255 | if (used_math()) { | 267 | if (used_math()) { |
256 | /* restore fpu context if we have used it before */ | 268 | /* restore fpu context if we have used it before */ |
257 | own_fpu(); | 269 | own_fpu(); |
258 | err |= restore_fp_context32(sc); | 270 | if (!err) |
271 | err = check_and_restore_fp_context32(sc); | ||
259 | } else { | 272 | } else { |
260 | /* signal handler may have used FPU. Give it up. */ | 273 | /* signal handler may have used FPU. Give it up. */ |
261 | lose_fpu(); | 274 | lose_fpu(); |
@@ -508,6 +521,7 @@ asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
508 | { | 521 | { |
509 | struct sigframe32 __user *frame; | 522 | struct sigframe32 __user *frame; |
510 | sigset_t blocked; | 523 | sigset_t blocked; |
524 | int sig; | ||
511 | 525 | ||
512 | frame = (struct sigframe32 __user *) regs.regs[29]; | 526 | frame = (struct sigframe32 __user *) regs.regs[29]; |
513 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 527 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
@@ -521,8 +535,11 @@ asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
521 | recalc_sigpending(); | 535 | recalc_sigpending(); |
522 | spin_unlock_irq(¤t->sighand->siglock); | 536 | spin_unlock_irq(¤t->sighand->siglock); |
523 | 537 | ||
524 | if (restore_sigcontext32(®s, &frame->sf_sc)) | 538 | sig = restore_sigcontext32(®s, &frame->sf_sc); |
539 | if (sig < 0) | ||
525 | goto badframe; | 540 | goto badframe; |
541 | else if (sig) | ||
542 | force_sig(sig, current); | ||
526 | 543 | ||
527 | /* | 544 | /* |
528 | * Don't let your children do this ... | 545 | * Don't let your children do this ... |
@@ -545,6 +562,7 @@ asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
545 | sigset_t set; | 562 | sigset_t set; |
546 | stack_t st; | 563 | stack_t st; |
547 | s32 sp; | 564 | s32 sp; |
565 | int sig; | ||
548 | 566 | ||
549 | frame = (struct rt_sigframe32 __user *) regs.regs[29]; | 567 | frame = (struct rt_sigframe32 __user *) regs.regs[29]; |
550 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 568 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
@@ -558,8 +576,11 @@ asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
558 | recalc_sigpending(); | 576 | recalc_sigpending(); |
559 | spin_unlock_irq(¤t->sighand->siglock); | 577 | spin_unlock_irq(¤t->sighand->siglock); |
560 | 578 | ||
561 | if (restore_sigcontext32(®s, &frame->rs_uc.uc_mcontext)) | 579 | sig = restore_sigcontext32(®s, &frame->rs_uc.uc_mcontext); |
580 | if (sig < 0) | ||
562 | goto badframe; | 581 | goto badframe; |
582 | else if (sig) | ||
583 | force_sig(sig, current); | ||
563 | 584 | ||
564 | /* The ucontext contains a stack32_t, so we must convert! */ | 585 | /* The ucontext contains a stack32_t, so we must convert! */ |
565 | if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp)) | 586 | if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp)) |