powerpc: Fix VRSAVE handling
[linux.git] / arch / powerpc / kernel / signal_64.c
index 887e99d85bc270eefeb949d30dcf4d45fd3d3647..d0106b8a748431152dbbf0304ec1e7c9b06b53d9 100644 (file)
@@ -114,6 +114,8 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
        /* We always copy to/from vrsave, it's 0 if we don't have or don't
         * use altivec.
         */
+       if (cpu_has_feature(CPU_FTR_ALTIVEC))
+               current->thread.vrsave = mfspr(SPRN_VRSAVE);
        err |= __put_user(current->thread.vrsave, (u32 __user *)&v_regs[33]);
 #else /* CONFIG_ALTIVEC */
        err |= __put_user(0, &sc->v_regs);
@@ -217,6 +219,8 @@ static long setup_tm_sigcontexts(struct sigcontext __user *sc,
        /* We always copy to/from vrsave, it's 0 if we don't have or don't
         * use altivec.
         */
+       if (cpu_has_feature(CPU_FTR_ALTIVEC))
+               current->thread.vrsave = mfspr(SPRN_VRSAVE);
        err |= __put_user(current->thread.vrsave, (u32 __user *)&v_regs[33]);
        if (msr & MSR_VEC)
                err |= __put_user(current->thread.transact_vrsave,
@@ -346,16 +350,18 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
        if (v_regs && !access_ok(VERIFY_READ, v_regs, 34 * sizeof(vector128)))
                return -EFAULT;
        /* Copy 33 vec registers (vr0..31 and vscr) from the stack */
-       if (v_regs != 0 && (msr & MSR_VEC) != 0)
+       if (v_regs != NULL && (msr & MSR_VEC) != 0)
                err |= __copy_from_user(current->thread.vr, v_regs,
                                        33 * sizeof(vector128));
        else if (current->thread.used_vr)
                memset(current->thread.vr, 0, 33 * sizeof(vector128));
        /* Always get VRSAVE back */
-       if (v_regs != 0)
+       if (v_regs != NULL)
                err |= __get_user(current->thread.vrsave, (u32 __user *)&v_regs[33]);
        else
                current->thread.vrsave = 0;
+       if (cpu_has_feature(CPU_FTR_ALTIVEC))
+               mtspr(SPRN_VRSAVE, current->thread.vrsave);
 #endif /* CONFIG_ALTIVEC */
        /* restore floating point */
        err |= copy_fpr_from_user(current, &sc->fp_regs);
@@ -463,7 +469,7 @@ static long restore_tm_sigcontexts(struct pt_regs *regs,
                                    tm_v_regs, 34 * sizeof(vector128)))
                return -EFAULT;
        /* Copy 33 vec registers (vr0..31 and vscr) from the stack */
-       if (v_regs != 0 && tm_v_regs != 0 && (msr & MSR_VEC) != 0) {
+       if (v_regs != NULL && tm_v_regs != NULL && (msr & MSR_VEC) != 0) {
                err |= __copy_from_user(current->thread.vr, v_regs,
                                        33 * sizeof(vector128));
                err |= __copy_from_user(current->thread.transact_vr, tm_v_regs,
@@ -474,7 +480,7 @@ static long restore_tm_sigcontexts(struct pt_regs *regs,
                memset(current->thread.transact_vr, 0, 33 * sizeof(vector128));
        }
        /* Always get VRSAVE back */
-       if (v_regs != 0 && tm_v_regs != 0) {
+       if (v_regs != NULL && tm_v_regs != NULL) {
                err |= __get_user(current->thread.vrsave,
                                  (u32 __user *)&v_regs[33]);
                err |= __get_user(current->thread.transact_vrsave,
@@ -484,6 +490,8 @@ static long restore_tm_sigcontexts(struct pt_regs *regs,
                current->thread.vrsave = 0;
                current->thread.transact_vrsave = 0;
        }
+       if (cpu_has_feature(CPU_FTR_ALTIVEC))
+               mtspr(SPRN_VRSAVE, current->thread.vrsave);
 #endif /* CONFIG_ALTIVEC */
        /* restore floating point */
        err |= copy_fpr_from_user(current, &sc->fp_regs);