powerpc: Fix clearing of the FPSCR when invoking a signal handler
authorPaul Mackerras <paulus@samba.org>
Mon, 14 Nov 2005 10:55:15 +0000 (21:55 +1100)
committerPaul Mackerras <paulus@samba.org>
Tue, 15 Nov 2005 00:11:32 +0000 (11:11 +1100)
As pointed out by Gary Byers, we were clearing the image of the FPSCR
(floating point status and control register) in the thread_struct before
copying it to the user stack when invoking a signal.  Thus the task
would see its FPSCR getting cleared when it took a signal.

While fixing it I noticed that our swapcontext system call was also
clearing FPSCR.  It shouldn't, so I fixed that too.

Signed-off-by: Paul Mackerras <paulus@samba.org>
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c

index 8bdf95b..5a2eba6 100644 (file)
@@ -403,8 +403,6 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
                    ELF_NFPREG * sizeof(double)))
                return 1;
 
-       current->thread.fpscr.val = 0;  /* turn off all fp exceptions */
-
 #ifdef CONFIG_ALTIVEC
        /* save altivec registers */
        if (current->thread.used_vr) {
@@ -818,6 +816,9 @@ static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka,
                        goto badframe;
                regs->link = (unsigned long) frame->tramp;
        }
+
+       current->thread.fpscr.val = 0;  /* turn off all fp exceptions */
+
        if (put_user(regs->gpr[1], (u32 __user *)newsp))
                goto badframe;
        regs->gpr[1] = newsp;
@@ -1097,6 +1098,8 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
                regs->link = (unsigned long) frame->mctx.tramp;
        }
 
+       current->thread.fpscr.val = 0;  /* turn off all fp exceptions */
+
        if (put_user(regs->gpr[1], (u32 __user *)newsp))
                goto badframe;
        regs->gpr[1] = newsp;
index 58194e1..1decf27 100644 (file)
@@ -131,9 +131,6 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
 
        flush_fp_to_thread(current);
 
-       /* Make sure signal doesn't get spurrious FP exceptions */
-       current->thread.fpscr.val = 0;
-
 #ifdef CONFIG_ALTIVEC
        err |= __put_user(v_regs, &sc->v_regs);
 
@@ -423,6 +420,9 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
        if (err)
                goto badframe;
 
+       /* Make sure signal handler doesn't get spurious FP exceptions */
+       current->thread.fpscr.val = 0;
+
        /* Set up to return from userspace. */
        if (vdso64_rt_sigtramp && current->thread.vdso_base) {
                regs->link = current->thread.vdso_base + vdso64_rt_sigtramp;