These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / arch / s390 / kernel / process.c
index 8f587d8..114ee8b 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/kprobes.h>
 #include <linux/random.h>
 #include <linux/module.h>
+#include <linux/init_task.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/vtimer.h>
@@ -36,6 +37,9 @@
 
 asmlinkage void ret_from_fork(void) asm ("ret_from_fork");
 
+/* FPU save area for the init task */
+__vector128 init_task_fpu_regs[__NUM_VXRS] __init_task_data;
+
 /*
  * Return saved PC of a blocked thread. used in kernel/sched.
  * resume in entry.S does not create a new stack frame, it
@@ -81,8 +85,36 @@ void release_thread(struct task_struct *dead_task)
 
 void arch_release_task_struct(struct task_struct *tsk)
 {
-       if (tsk->thread.vxrs)
-               kfree(tsk->thread.vxrs);
+       /* Free either the floating-point or the vector register save area */
+       kfree(tsk->thread.fpu.regs);
+}
+
+int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
+{
+       size_t fpu_regs_size;
+
+       *dst = *src;
+
+       /*
+        * If the vector extension is available, it is enabled for all tasks,
+        * and, thus, the FPU register save area must be allocated accordingly.
+        */
+       fpu_regs_size = MACHINE_HAS_VX ? sizeof(__vector128) * __NUM_VXRS
+                                      : sizeof(freg_t) * __NUM_FPRS;
+       dst->thread.fpu.regs = kzalloc(fpu_regs_size, GFP_KERNEL|__GFP_REPEAT);
+       if (!dst->thread.fpu.regs)
+               return -ENOMEM;
+
+       /*
+        * Save the floating-point or vector register state of the current
+        * task and set the CIF_FPU flag to lazy restore the FPU register
+        * state when returning to user space.
+        */
+       save_fpu_regs();
+       dst->thread.fpu.fpc = current->thread.fpu.fpc;
+       memcpy(dst->thread.fpu.regs, current->thread.fpu.regs, fpu_regs_size);
+
+       return 0;
 }
 
 int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
@@ -139,14 +171,8 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
 
        /* Don't copy runtime instrumentation info */
        p->thread.ri_cb = NULL;
-       p->thread.ri_signum = 0;
        frame->childregs.psw.mask &= ~PSW_MASK_RI;
 
-       /* Save the fpu registers to new thread structure. */
-       save_fp_ctl(&p->thread.fp_regs.fpc);
-       save_fp_regs(p->thread.fp_regs.fprs);
-       p->thread.fp_regs.pad = 0;
-       p->thread.vxrs = NULL;
        /* Set a new TLS ?  */
        if (clone_flags & CLONE_SETTLS) {
                unsigned long tls = frame->childregs.gprs[6];
@@ -162,7 +188,7 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
 
 asmlinkage void execve_tail(void)
 {
-       current->thread.fp_regs.fpc = 0;
+       current->thread.fpu.fpc = 0;
        asm volatile("sfpc %0" : : "d" (0));
 }
 
@@ -171,8 +197,15 @@ asmlinkage void execve_tail(void)
  */
 int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs)
 {
-       save_fp_ctl(&fpregs->fpc);
-       save_fp_regs(fpregs->fprs);
+       save_fpu_regs();
+       fpregs->fpc = current->thread.fpu.fpc;
+       fpregs->pad = 0;
+       if (MACHINE_HAS_VX)
+               convert_vx_to_fp((freg_t *)&fpregs->fprs,
+                                current->thread.fpu.vxrs);
+       else
+               memcpy(&fpregs->fprs, current->thread.fpu.fprs,
+                      sizeof(fpregs->fprs));
        return 1;
 }
 EXPORT_SYMBOL(dump_fpu);
@@ -210,11 +243,7 @@ unsigned long arch_align_stack(unsigned long sp)
 
 static inline unsigned long brk_rnd(void)
 {
-       /* 8MB for 32bit, 1GB for 64bit */
-       if (is_32bit_task())
-               return (get_random_int() & 0x7ffUL) << PAGE_SHIFT;
-       else
-               return (get_random_int() & 0x3ffffUL) << PAGE_SHIFT;
+       return (get_random_int() & BRK_RND_MASK) << PAGE_SHIFT;
 }
 
 unsigned long arch_randomize_brk(struct mm_struct *mm)