powerpc: Fix 32-bit frames for signals delivered when transactional
authorPaul Mackerras <paulus@samba.org>
Wed, 29 Jan 2014 05:33:56 +0000 (16:33 +1100)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Wed, 29 Jan 2014 05:58:49 +0000 (16:58 +1100)
Commit d31626f70b61 ("powerpc: Don't corrupt transactional state when
using FP/VMX in kernel") introduced a bug where the uc_link and uc_regs
fields of the ucontext_t that is created to hold the transactional
values of the registers in a 32-bit signal frame didn't get set
correctly.  The reason is that we now clear the MSR_TS bits in the MSR
in save_tm_user_regs(), before the code that sets uc_link and uc_regs.
To fix this, we move the setting of uc_link and uc_regs into the same
if statement that selects whether to call save_tm_user_regs() or
save_user_regs().

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

index 6ce69e6f1fcb8c4557bb3e19af8d8111ad51a4ae..a67e00aa3caad1353630f4477a8cec38fb8461e4 100644 (file)
@@ -1022,29 +1022,24 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
        tm_frame = &rt_sf->uc_transact.uc_mcontext;
        if (MSR_TM_ACTIVE(regs->msr)) {
+               if (__put_user((unsigned long)&rt_sf->uc_transact,
+                              &rt_sf->uc.uc_link) ||
+                   __put_user((unsigned long)tm_frame,
+                              &rt_sf->uc_transact.uc_regs))
+                       goto badframe;
                if (save_tm_user_regs(regs, frame, tm_frame, sigret))
                        goto badframe;
        }
        else
 #endif
        {
+               if (__put_user(0, &rt_sf->uc.uc_link))
+                       goto badframe;
                if (save_user_regs(regs, frame, tm_frame, sigret, 1))
                        goto badframe;
        }
        regs->link = tramp;
 
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
-       if (MSR_TM_ACTIVE(regs->msr)) {
-               if (__put_user((unsigned long)&rt_sf->uc_transact,
-                              &rt_sf->uc.uc_link)
-                   || __put_user((unsigned long)tm_frame, &rt_sf->uc_transact.uc_regs))
-                       goto badframe;
-       }
-       else
-#endif
-               if (__put_user(0, &rt_sf->uc.uc_link))
-                       goto badframe;
-
        current->thread.fp_state.fpscr = 0;     /* turn off all fp exceptions */
 
        /* create a stack frame for the caller of the handler */