These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / arch / s390 / kernel / ptrace.c
index d363c9c..01c37b3 100644 (file)
@@ -45,39 +45,27 @@ void update_cr_regs(struct task_struct *task)
        struct per_regs old, new;
 
        /* Take care of the enable/disable of transactional execution. */
-       if (MACHINE_HAS_TE || MACHINE_HAS_VX) {
+       if (MACHINE_HAS_TE) {
                unsigned long cr, cr_new;
 
                __ctl_store(cr, 0, 0);
-               cr_new = cr;
-               if (MACHINE_HAS_TE) {
-                       /* Set or clear transaction execution TXC bit 8. */
-                       cr_new |= (1UL << 55);
-                       if (task->thread.per_flags & PER_FLAG_NO_TE)
-                               cr_new &= ~(1UL << 55);
-               }
-               if (MACHINE_HAS_VX) {
-                       /* Enable/disable of vector extension */
-                       cr_new &= ~(1UL << 17);
-                       if (task->thread.vxrs)
-                               cr_new |= (1UL << 17);
-               }
+               /* Set or clear transaction execution TXC bit 8. */
+               cr_new = cr | (1UL << 55);
+               if (task->thread.per_flags & PER_FLAG_NO_TE)
+                       cr_new &= ~(1UL << 55);
                if (cr_new != cr)
                        __ctl_load(cr_new, 0, 0);
-               if (MACHINE_HAS_TE) {
-                       /* Set/clear transaction execution TDC bits 62/63. */
-                       __ctl_store(cr, 2, 2);
-                       cr_new = cr & ~3UL;
-                       if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND) {
-                               if (task->thread.per_flags &
-                                   PER_FLAG_TE_ABORT_RAND_TEND)
-                                       cr_new |= 1UL;
-                               else
-                                       cr_new |= 2UL;
-                       }
-                       if (cr_new != cr)
-                               __ctl_load(cr_new, 2, 2);
+               /* Set or clear transaction execution TDC bits 62 and 63. */
+               __ctl_store(cr, 2, 2);
+               cr_new = cr & ~3UL;
+               if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND) {
+                       if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND_TEND)
+                               cr_new |= 1UL;
+                       else
+                               cr_new |= 2UL;
                }
+               if (cr_new != cr)
+                       __ctl_load(cr_new, 2, 2);
        }
        /* Copy user specified PER registers */
        new.control = thread->per_user.control;
@@ -242,21 +230,21 @@ static unsigned long __peek_user(struct task_struct *child, addr_t addr)
                /*
                 * floating point control reg. is in the thread structure
                 */
-               tmp = child->thread.fp_regs.fpc;
+               tmp = child->thread.fpu.fpc;
                tmp <<= BITS_PER_LONG - 32;
 
        } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
                /*
-                * floating point regs. are either in child->thread.fp_regs
-                * or the child->thread.vxrs array
+                * floating point regs. are either in child->thread.fpu
+                * or the child->thread.fpu.vxrs array
                 */
                offset = addr - (addr_t) &dummy->regs.fp_regs.fprs;
-               if (child->thread.vxrs)
+               if (MACHINE_HAS_VX)
                        tmp = *(addr_t *)
-                              ((addr_t) child->thread.vxrs + 2*offset);
+                              ((addr_t) child->thread.fpu.vxrs + 2*offset);
                else
                        tmp = *(addr_t *)
-                              ((addr_t) &child->thread.fp_regs.fprs + offset);
+                              ((addr_t) child->thread.fpu.fprs + offset);
 
        } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) {
                /*
@@ -387,20 +375,20 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data)
                if ((unsigned int) data != 0 ||
                    test_fp_ctl(data >> (BITS_PER_LONG - 32)))
                        return -EINVAL;
-               child->thread.fp_regs.fpc = data >> (BITS_PER_LONG - 32);
+               child->thread.fpu.fpc = data >> (BITS_PER_LONG - 32);
 
        } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
                /*
-                * floating point regs. are either in child->thread.fp_regs
-                * or the child->thread.vxrs array
+                * floating point regs. are either in child->thread.fpu
+                * or the child->thread.fpu.vxrs array
                 */
                offset = addr - (addr_t) &dummy->regs.fp_regs.fprs;
-               if (child->thread.vxrs)
+               if (MACHINE_HAS_VX)
                        *(addr_t *)((addr_t)
-                               child->thread.vxrs + 2*offset) = data;
+                               child->thread.fpu.vxrs + 2*offset) = data;
                else
                        *(addr_t *)((addr_t)
-                               &child->thread.fp_regs.fprs + offset) = data;
+                               child->thread.fpu.fprs + offset) = data;
 
        } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) {
                /*
@@ -621,20 +609,20 @@ static u32 __peek_user_compat(struct task_struct *child, addr_t addr)
                /*
                 * floating point control reg. is in the thread structure
                 */
-               tmp = child->thread.fp_regs.fpc;
+               tmp = child->thread.fpu.fpc;
 
        } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
                /*
-                * floating point regs. are either in child->thread.fp_regs
-                * or the child->thread.vxrs array
+                * floating point regs. are either in child->thread.fpu
+                * or the child->thread.fpu.vxrs array
                 */
                offset = addr - (addr_t) &dummy32->regs.fp_regs.fprs;
-               if (child->thread.vxrs)
+               if (MACHINE_HAS_VX)
                        tmp = *(__u32 *)
-                              ((addr_t) child->thread.vxrs + 2*offset);
+                              ((addr_t) child->thread.fpu.vxrs + 2*offset);
                else
                        tmp = *(__u32 *)
-                              ((addr_t) &child->thread.fp_regs.fprs + offset);
+                              ((addr_t) child->thread.fpu.fprs + offset);
 
        } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) {
                /*
@@ -746,20 +734,20 @@ static int __poke_user_compat(struct task_struct *child,
                 */
                if (test_fp_ctl(tmp))
                        return -EINVAL;
-               child->thread.fp_regs.fpc = data;
+               child->thread.fpu.fpc = data;
 
        } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
                /*
-                * floating point regs. are either in child->thread.fp_regs
-                * or the child->thread.vxrs array
+                * floating point regs. are either in child->thread.fpu
+                * or the child->thread.fpu.vxrs array
                 */
                offset = addr - (addr_t) &dummy32->regs.fp_regs.fprs;
-               if (child->thread.vxrs)
+               if (MACHINE_HAS_VX)
                        *(__u32 *)((addr_t)
-                               child->thread.vxrs + 2*offset) = tmp;
+                               child->thread.fpu.vxrs + 2*offset) = tmp;
                else
                        *(__u32 *)((addr_t)
-                               &child->thread.fp_regs.fprs + offset) = tmp;
+                               child->thread.fpu.fprs + offset) = tmp;
 
        } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) {
                /*
@@ -952,18 +940,16 @@ static int s390_fpregs_get(struct task_struct *target,
                           const struct user_regset *regset, unsigned int pos,
                           unsigned int count, void *kbuf, void __user *ubuf)
 {
-       if (target == current) {
-               save_fp_ctl(&target->thread.fp_regs.fpc);
-               save_fp_regs(target->thread.fp_regs.fprs);
-       } else if (target->thread.vxrs) {
-               int i;
+       _s390_fp_regs fp_regs;
+
+       if (target == current)
+               save_fpu_regs();
+
+       fp_regs.fpc = target->thread.fpu.fpc;
+       fpregs_store(&fp_regs, &target->thread.fpu);
 
-               for (i = 0; i < __NUM_VXRS_LOW; i++)
-                       target->thread.fp_regs.fprs[i] =
-                               *(freg_t *)(target->thread.vxrs + i);
-       }
        return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-                                  &target->thread.fp_regs, 0, -1);
+                                  &fp_regs, 0, -1);
 }
 
 static int s390_fpregs_set(struct task_struct *target,
@@ -972,41 +958,33 @@ static int s390_fpregs_set(struct task_struct *target,
                           const void __user *ubuf)
 {
        int rc = 0;
+       freg_t fprs[__NUM_FPRS];
 
-       if (target == current) {
-               save_fp_ctl(&target->thread.fp_regs.fpc);
-               save_fp_regs(target->thread.fp_regs.fprs);
-       }
+       if (target == current)
+               save_fpu_regs();
 
        /* If setting FPC, must validate it first. */
        if (count > 0 && pos < offsetof(s390_fp_regs, fprs)) {
-               u32 ufpc[2] = { target->thread.fp_regs.fpc, 0 };
+               u32 ufpc[2] = { target->thread.fpu.fpc, 0 };
                rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ufpc,
                                        0, offsetof(s390_fp_regs, fprs));
                if (rc)
                        return rc;
                if (ufpc[1] != 0 || test_fp_ctl(ufpc[0]))
                        return -EINVAL;
-               target->thread.fp_regs.fpc = ufpc[0];
+               target->thread.fpu.fpc = ufpc[0];
        }
 
        if (rc == 0 && count > 0)
                rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-                                       target->thread.fp_regs.fprs,
-                                       offsetof(s390_fp_regs, fprs), -1);
-
-       if (rc == 0) {
-               if (target == current) {
-                       restore_fp_ctl(&target->thread.fp_regs.fpc);
-                       restore_fp_regs(target->thread.fp_regs.fprs);
-               } else if (target->thread.vxrs) {
-                       int i;
-
-                       for (i = 0; i < __NUM_VXRS_LOW; i++)
-                               *(freg_t *)(target->thread.vxrs + i) =
-                                       target->thread.fp_regs.fprs[i];
-               }
-       }
+                                       fprs, offsetof(s390_fp_regs, fprs), -1);
+       if (rc)
+               return rc;
+
+       if (MACHINE_HAS_VX)
+               convert_fp_to_vx(target->thread.fpu.vxrs, fprs);
+       else
+               memcpy(target->thread.fpu.fprs, &fprs, sizeof(fprs));
 
        return rc;
 }
@@ -1069,13 +1047,10 @@ static int s390_vxrs_low_get(struct task_struct *target,
 
        if (!MACHINE_HAS_VX)
                return -ENODEV;
-       if (target->thread.vxrs) {
-               if (target == current)
-                       save_vx_regs(target->thread.vxrs);
-               for (i = 0; i < __NUM_VXRS_LOW; i++)
-                       vxrs[i] = *((__u64 *)(target->thread.vxrs + i) + 1);
-       } else
-               memset(vxrs, 0, sizeof(vxrs));
+       if (target == current)
+               save_fpu_regs();
+       for (i = 0; i < __NUM_VXRS_LOW; i++)
+               vxrs[i] = *((__u64 *)(target->thread.fpu.vxrs + i) + 1);
        return user_regset_copyout(&pos, &count, &kbuf, &ubuf, vxrs, 0, -1);
 }
 
@@ -1089,20 +1064,13 @@ static int s390_vxrs_low_set(struct task_struct *target,
 
        if (!MACHINE_HAS_VX)
                return -ENODEV;
-       if (!target->thread.vxrs) {
-               rc = alloc_vector_registers(target);
-               if (rc)
-                       return rc;
-       } else if (target == current)
-               save_vx_regs(target->thread.vxrs);
+       if (target == current)
+               save_fpu_regs();
 
        rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf, vxrs, 0, -1);
-       if (rc == 0) {
+       if (rc == 0)
                for (i = 0; i < __NUM_VXRS_LOW; i++)
-                       *((__u64 *)(target->thread.vxrs + i) + 1) = vxrs[i];
-               if (target == current)
-                       restore_vx_regs(target->thread.vxrs);
-       }
+                       *((__u64 *)(target->thread.fpu.vxrs + i) + 1) = vxrs[i];
 
        return rc;
 }
@@ -1116,13 +1084,10 @@ static int s390_vxrs_high_get(struct task_struct *target,
 
        if (!MACHINE_HAS_VX)
                return -ENODEV;
-       if (target->thread.vxrs) {
-               if (target == current)
-                       save_vx_regs(target->thread.vxrs);
-               memcpy(vxrs, target->thread.vxrs + __NUM_VXRS_LOW,
-                      sizeof(vxrs));
-       } else
-               memset(vxrs, 0, sizeof(vxrs));
+       if (target == current)
+               save_fpu_regs();
+       memcpy(vxrs, target->thread.fpu.vxrs + __NUM_VXRS_LOW, sizeof(vxrs));
+
        return user_regset_copyout(&pos, &count, &kbuf, &ubuf, vxrs, 0, -1);
 }
 
@@ -1135,18 +1100,11 @@ static int s390_vxrs_high_set(struct task_struct *target,
 
        if (!MACHINE_HAS_VX)
                return -ENODEV;
-       if (!target->thread.vxrs) {
-               rc = alloc_vector_registers(target);
-               if (rc)
-                       return rc;
-       } else if (target == current)
-               save_vx_regs(target->thread.vxrs);
+       if (target == current)
+               save_fpu_regs();
 
        rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-                               target->thread.vxrs + __NUM_VXRS_LOW, 0, -1);
-       if (rc == 0 && target == current)
-               restore_vx_regs(target->thread.vxrs);
-
+                               target->thread.fpu.vxrs + __NUM_VXRS_LOW, 0, -1);
        return rc;
 }