Merge tag 'powerpc-4.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[cascardo/linux.git] / arch / powerpc / kernel / signal_32.c
index a7daf74..27aa913 100644 (file)
@@ -44,6 +44,7 @@
 #include <asm/vdso.h>
 #include <asm/switch_to.h>
 #include <asm/tm.h>
+#include <asm/asm-prototypes.h>
 #ifdef CONFIG_PPC64
 #include "ppc32.h"
 #include <asm/unistd.h>
@@ -315,7 +316,7 @@ unsigned long copy_vsx_from_user(struct task_struct *task,
 }
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
-unsigned long copy_transact_fpr_to_user(void __user *to,
+unsigned long copy_ckfpr_to_user(void __user *to,
                                  struct task_struct *task)
 {
        u64 buf[ELF_NFPREG];
@@ -323,12 +324,12 @@ unsigned long copy_transact_fpr_to_user(void __user *to,
 
        /* save FPR copy to local buffer then write to the thread_struct */
        for (i = 0; i < (ELF_NFPREG - 1) ; i++)
-               buf[i] = task->thread.TS_TRANS_FPR(i);
-       buf[i] = task->thread.transact_fp.fpscr;
+               buf[i] = task->thread.TS_CKFPR(i);
+       buf[i] = task->thread.ckfp_state.fpscr;
        return __copy_to_user(to, buf, ELF_NFPREG * sizeof(double));
 }
 
-unsigned long copy_transact_fpr_from_user(struct task_struct *task,
+unsigned long copy_ckfpr_from_user(struct task_struct *task,
                                          void __user *from)
 {
        u64 buf[ELF_NFPREG];
@@ -337,13 +338,13 @@ unsigned long copy_transact_fpr_from_user(struct task_struct *task,
        if (__copy_from_user(buf, from, ELF_NFPREG * sizeof(double)))
                return 1;
        for (i = 0; i < (ELF_NFPREG - 1) ; i++)
-               task->thread.TS_TRANS_FPR(i) = buf[i];
-       task->thread.transact_fp.fpscr = buf[i];
+               task->thread.TS_CKFPR(i) = buf[i];
+       task->thread.ckfp_state.fpscr = buf[i];
 
        return 0;
 }
 
-unsigned long copy_transact_vsx_to_user(void __user *to,
+unsigned long copy_ckvsx_to_user(void __user *to,
                                  struct task_struct *task)
 {
        u64 buf[ELF_NVSRHALFREG];
@@ -351,11 +352,11 @@ unsigned long copy_transact_vsx_to_user(void __user *to,
 
        /* save FPR copy to local buffer then write to the thread_struct */
        for (i = 0; i < ELF_NVSRHALFREG; i++)
-               buf[i] = task->thread.transact_fp.fpr[i][TS_VSRLOWOFFSET];
+               buf[i] = task->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET];
        return __copy_to_user(to, buf, ELF_NVSRHALFREG * sizeof(double));
 }
 
-unsigned long copy_transact_vsx_from_user(struct task_struct *task,
+unsigned long copy_ckvsx_from_user(struct task_struct *task,
                                          void __user *from)
 {
        u64 buf[ELF_NVSRHALFREG];
@@ -364,7 +365,7 @@ unsigned long copy_transact_vsx_from_user(struct task_struct *task,
        if (__copy_from_user(buf, from, ELF_NVSRHALFREG * sizeof(double)))
                return 1;
        for (i = 0; i < ELF_NVSRHALFREG ; i++)
-               task->thread.transact_fp.fpr[i][TS_VSRLOWOFFSET] = buf[i];
+               task->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i];
        return 0;
 }
 #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
@@ -384,17 +385,17 @@ inline unsigned long copy_fpr_from_user(struct task_struct *task,
 }
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
-inline unsigned long copy_transact_fpr_to_user(void __user *to,
+inline unsigned long copy_ckfpr_to_user(void __user *to,
                                         struct task_struct *task)
 {
-       return __copy_to_user(to, task->thread.transact_fp.fpr,
+       return __copy_to_user(to, task->thread.ckfp_state.fpr,
                              ELF_NFPREG * sizeof(double));
 }
 
-inline unsigned long copy_transact_fpr_from_user(struct task_struct *task,
+inline unsigned long copy_ckfpr_from_user(struct task_struct *task,
                                                 void __user *from)
 {
-       return __copy_from_user(task->thread.transact_fp.fpr, from,
+       return __copy_from_user(task->thread.ckfp_state.fpr, from,
                                ELF_NFPREG * sizeof(double));
 }
 #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
@@ -525,9 +526,6 @@ static int save_tm_user_regs(struct pt_regs *regs,
         */
        regs->msr &= ~MSR_TS_MASK;
 
-       /* Make sure floating point registers are stored in regs */
-       flush_fp_to_thread(current);
-
        /* Save both sets of general registers */
        if (save_general_regs(&current->thread.ckpt_regs, frame)
            || save_general_regs(regs, tm_frame))
@@ -545,18 +543,17 @@ static int save_tm_user_regs(struct pt_regs *regs,
 #ifdef CONFIG_ALTIVEC
        /* save altivec registers */
        if (current->thread.used_vr) {
-               flush_altivec_to_thread(current);
-               if (__copy_to_user(&frame->mc_vregs, &current->thread.vr_state,
+               if (__copy_to_user(&frame->mc_vregs, &current->thread.ckvr_state,
                                   ELF_NVRREG * sizeof(vector128)))
                        return 1;
                if (msr & MSR_VEC) {
                        if (__copy_to_user(&tm_frame->mc_vregs,
-                                          &current->thread.transact_vr,
+                                          &current->thread.vr_state,
                                           ELF_NVRREG * sizeof(vector128)))
                                return 1;
                } else {
                        if (__copy_to_user(&tm_frame->mc_vregs,
-                                          &current->thread.vr_state,
+                                          &current->thread.ckvr_state,
                                           ELF_NVRREG * sizeof(vector128)))
                                return 1;
                }
@@ -573,28 +570,28 @@ static int save_tm_user_regs(struct pt_regs *regs,
         * most significant bits of that same vector. --BenH
         */
        if (cpu_has_feature(CPU_FTR_ALTIVEC))
-               current->thread.vrsave = mfspr(SPRN_VRSAVE);
-       if (__put_user(current->thread.vrsave,
+               current->thread.ckvrsave = mfspr(SPRN_VRSAVE);
+       if (__put_user(current->thread.ckvrsave,
                       (u32 __user *)&frame->mc_vregs[32]))
                return 1;
        if (msr & MSR_VEC) {
-               if (__put_user(current->thread.transact_vrsave,
+               if (__put_user(current->thread.vrsave,
                               (u32 __user *)&tm_frame->mc_vregs[32]))
                        return 1;
        } else {
-               if (__put_user(current->thread.vrsave,
+               if (__put_user(current->thread.ckvrsave,
                               (u32 __user *)&tm_frame->mc_vregs[32]))
                        return 1;
        }
 #endif /* CONFIG_ALTIVEC */
 
-       if (copy_fpr_to_user(&frame->mc_fregs, current))
+       if (copy_ckfpr_to_user(&frame->mc_fregs, current))
                return 1;
        if (msr & MSR_FP) {
-               if (copy_transact_fpr_to_user(&tm_frame->mc_fregs, current))
+               if (copy_fpr_to_user(&tm_frame->mc_fregs, current))
                        return 1;
        } else {
-               if (copy_fpr_to_user(&tm_frame->mc_fregs, current))
+               if (copy_ckfpr_to_user(&tm_frame->mc_fregs, current))
                        return 1;
        }
 
@@ -606,15 +603,14 @@ static int save_tm_user_regs(struct pt_regs *regs,
         * contains valid data
         */
        if (current->thread.used_vsr) {
-               flush_vsx_to_thread(current);
-               if (copy_vsx_to_user(&frame->mc_vsregs, current))
+               if (copy_ckvsx_to_user(&frame->mc_vsregs, current))
                        return 1;
                if (msr & MSR_VSX) {
-                       if (copy_transact_vsx_to_user(&tm_frame->mc_vsregs,
+                       if (copy_vsx_to_user(&tm_frame->mc_vsregs,
                                                      current))
                                return 1;
                } else {
-                       if (copy_vsx_to_user(&tm_frame->mc_vsregs, current))
+                       if (copy_ckvsx_to_user(&tm_frame->mc_vsregs, current))
                                return 1;
                }
 
@@ -698,6 +694,7 @@ static long restore_user_regs(struct pt_regs *regs,
                if (__copy_from_user(&current->thread.vr_state, &sr->mc_vregs,
                                     sizeof(sr->mc_vregs)))
                        return 1;
+               current->thread.used_vr = true;
        } else if (current->thread.used_vr)
                memset(&current->thread.vr_state, 0,
                       ELF_NVRREG * sizeof(vector128));
@@ -724,6 +721,7 @@ static long restore_user_regs(struct pt_regs *regs,
                 */
                if (copy_vsx_from_user(current, &sr->mc_vsregs))
                        return 1;
+               current->thread.used_vsr = true;
        } else if (current->thread.used_vsr)
                for (i = 0; i < 32 ; i++)
                        current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = 0;
@@ -743,6 +741,7 @@ static long restore_user_regs(struct pt_regs *regs,
                if (__copy_from_user(current->thread.evr, &sr->mc_vregs,
                                     ELF_NEVRREG * sizeof(u32)))
                        return 1;
+               current->thread.used_spe = true;
        } else if (current->thread.used_spe)
                memset(current->thread.evr, 0, ELF_NEVRREG * sizeof(u32));
 
@@ -793,33 +792,34 @@ static long restore_tm_user_regs(struct pt_regs *regs,
        regs->msr &= ~MSR_VEC;
        if (msr & MSR_VEC) {
                /* restore altivec registers from the stack */
-               if (__copy_from_user(&current->thread.vr_state, &sr->mc_vregs,
+               if (__copy_from_user(&current->thread.ckvr_state, &sr->mc_vregs,
                                     sizeof(sr->mc_vregs)) ||
-                   __copy_from_user(&current->thread.transact_vr,
+                   __copy_from_user(&current->thread.vr_state,
                                     &tm_sr->mc_vregs,
                                     sizeof(sr->mc_vregs)))
                        return 1;
+               current->thread.used_vr = true;
        } else if (current->thread.used_vr) {
                memset(&current->thread.vr_state, 0,
                       ELF_NVRREG * sizeof(vector128));
-               memset(&current->thread.transact_vr, 0,
+               memset(&current->thread.ckvr_state, 0,
                       ELF_NVRREG * sizeof(vector128));
        }
 
        /* Always get VRSAVE back */
-       if (__get_user(current->thread.vrsave,
+       if (__get_user(current->thread.ckvrsave,
                       (u32 __user *)&sr->mc_vregs[32]) ||
-           __get_user(current->thread.transact_vrsave,
+           __get_user(current->thread.vrsave,
                       (u32 __user *)&tm_sr->mc_vregs[32]))
                return 1;
        if (cpu_has_feature(CPU_FTR_ALTIVEC))
-               mtspr(SPRN_VRSAVE, current->thread.vrsave);
+               mtspr(SPRN_VRSAVE, current->thread.ckvrsave);
 #endif /* CONFIG_ALTIVEC */
 
        regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1);
 
        if (copy_fpr_from_user(current, &sr->mc_fregs) ||
-           copy_transact_fpr_from_user(current, &tm_sr->mc_fregs))
+           copy_ckfpr_from_user(current, &tm_sr->mc_fregs))
                return 1;
 
 #ifdef CONFIG_VSX
@@ -829,13 +829,14 @@ static long restore_tm_user_regs(struct pt_regs *regs,
                 * Restore altivec registers from the stack to a local
                 * buffer, then write this out to the thread_struct
                 */
-               if (copy_vsx_from_user(current, &sr->mc_vsregs) ||
-                   copy_transact_vsx_from_user(current, &tm_sr->mc_vsregs))
+               if (copy_vsx_from_user(current, &tm_sr->mc_vsregs) ||
+                   copy_ckvsx_from_user(current, &sr->mc_vsregs))
                        return 1;
+               current->thread.used_vsr = true;
        } else if (current->thread.used_vsr)
                for (i = 0; i < 32 ; i++) {
                        current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = 0;
-                       current->thread.transact_fp.fpr[i][TS_VSRLOWOFFSET] = 0;
+                       current->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET] = 0;
                }
 #endif /* CONFIG_VSX */
 
@@ -848,6 +849,7 @@ static long restore_tm_user_regs(struct pt_regs *regs,
                if (__copy_from_user(current->thread.evr, &sr->mc_vregs,
                                     ELF_NEVRREG * sizeof(u32)))
                        return 1;
+               current->thread.used_spe = true;
        } else if (current->thread.used_spe)
                memset(current->thread.evr, 0, ELF_NEVRREG * sizeof(u32));
 
@@ -877,13 +879,14 @@ static long restore_tm_user_regs(struct pt_regs *regs,
        tm_recheckpoint(&current->thread, msr);
 
        /* This loads the speculative FP/VEC state, if used */
+       msr_check_and_set(msr & (MSR_FP | MSR_VEC));
        if (msr & MSR_FP) {
-               do_load_up_transact_fpu(&current->thread);
+               load_fp_state(&current->thread.fp_state);
                regs->msr |= (MSR_FP | current->thread.fpexc_mode);
        }
 #ifdef CONFIG_ALTIVEC
        if (msr & MSR_VEC) {
-               do_load_up_transact_altivec(&current->thread);
+               load_vr_state(&current->thread.vr_state);
                regs->msr |= MSR_VEC;
        }
 #endif
@@ -971,7 +974,7 @@ int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
  * (one which gets siginfo).
  */
 int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
-                      struct pt_regs *regs)
+                      struct task_struct *tsk)
 {
        struct rt_sigframe __user *rt_sf;
        struct mcontext __user *frame;
@@ -980,10 +983,13 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
        unsigned long newsp = 0;
        int sigret;
        unsigned long tramp;
+       struct pt_regs *regs = tsk->thread.regs;
+
+       BUG_ON(tsk != current);
 
        /* Set up Signal Frame */
        /* Put a Real Time Context onto stack */
-       rt_sf = get_sigframe(ksig, get_tm_stackpointer(regs), sizeof(*rt_sf), 1);
+       rt_sf = get_sigframe(ksig, get_tm_stackpointer(tsk), sizeof(*rt_sf), 1);
        addr = rt_sf;
        if (unlikely(rt_sf == NULL))
                goto badframe;
@@ -1000,9 +1006,9 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
        /* Save user registers on the stack */
        frame = &rt_sf->uc.uc_mcontext;
        addr = frame;
-       if (vdso32_rt_sigtramp && current->mm->context.vdso_base) {
+       if (vdso32_rt_sigtramp && tsk->mm->context.vdso_base) {
                sigret = 0;
-               tramp = current->mm->context.vdso_base + vdso32_rt_sigtramp;
+               tramp = tsk->mm->context.vdso_base + vdso32_rt_sigtramp;
        } else {
                sigret = __NR_rt_sigreturn;
                tramp = (unsigned long) frame->tramp;
@@ -1029,7 +1035,7 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
        }
        regs->link = tramp;
 
-       current->thread.fp_state.fpscr = 0;     /* turn off all fp exceptions */
+       tsk->thread.fp_state.fpscr = 0; /* turn off all fp exceptions */
 
        /* create a stack frame for the caller of the handler */
        newsp = ((unsigned long)rt_sf) - (__SIGNAL_FRAMESIZE + 16);
@@ -1054,7 +1060,7 @@ badframe:
                printk_ratelimited(KERN_INFO
                                   "%s[%d]: bad frame in handle_rt_signal32: "
                                   "%p nip %08lx lr %08lx\n",
-                                  current->comm, current->pid,
+                                  tsk->comm, tsk->pid,
                                   addr, regs->nip, regs->link);
 
        return 1;
@@ -1410,7 +1416,8 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
 /*
  * OK, we're invoking a handler
  */
-int handle_signal32(struct ksignal *ksig, sigset_t *oldset, struct pt_regs *regs)
+int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
+               struct task_struct *tsk)
 {
        struct sigcontext __user *sc;
        struct sigframe __user *frame;
@@ -1418,9 +1425,12 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset, struct pt_regs *regs
        unsigned long newsp = 0;
        int sigret;
        unsigned long tramp;
+       struct pt_regs *regs = tsk->thread.regs;
+
+       BUG_ON(tsk != current);
 
        /* Set up Signal Frame */
-       frame = get_sigframe(ksig, get_tm_stackpointer(regs), sizeof(*frame), 1);
+       frame = get_sigframe(ksig, get_tm_stackpointer(tsk), sizeof(*frame), 1);
        if (unlikely(frame == NULL))
                goto badframe;
        sc = (struct sigcontext __user *) &frame->sctx;
@@ -1439,9 +1449,9 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset, struct pt_regs *regs
            || __put_user(ksig->sig, &sc->signal))
                goto badframe;
 
-       if (vdso32_sigtramp && current->mm->context.vdso_base) {
+       if (vdso32_sigtramp && tsk->mm->context.vdso_base) {
                sigret = 0;
-               tramp = current->mm->context.vdso_base + vdso32_sigtramp;
+               tramp = tsk->mm->context.vdso_base + vdso32_sigtramp;
        } else {
                sigret = __NR_sigreturn;
                tramp = (unsigned long) frame->mctx.tramp;
@@ -1463,7 +1473,7 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset, struct pt_regs *regs
 
        regs->link = tramp;
 
-       current->thread.fp_state.fpscr = 0;     /* turn off all fp exceptions */
+       tsk->thread.fp_state.fpscr = 0; /* turn off all fp exceptions */
 
        /* create a stack frame for the caller of the handler */
        newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
@@ -1483,7 +1493,7 @@ badframe:
                printk_ratelimited(KERN_INFO
                                   "%s[%d]: bad frame in handle_signal32: "
                                   "%p nip %08lx lr %08lx\n",
-                                  current->comm, current->pid,
+                                  tsk->comm, tsk->pid,
                                   frame, regs->nip, regs->link);
 
        return 1;