aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel
diff options
context:
space:
mode:
authorHendrik Brueckner <brueckner@linux.vnet.ibm.com>2015-06-11 16:57:20 +0200
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2015-07-22 09:58:00 +0200
commit155e839a814834a3b4b31e729f4716e59d3d2dd4 (patch)
treee23d3bd009812c8a46caa418d42bf2a18ec6d39c /arch/s390/kernel
parents390/kernel: introduce fpu-internal.h with fpu helper functions (diff)
downloadlinux-dev-155e839a814834a3b4b31e729f4716e59d3d2dd4.tar.xz
linux-dev-155e839a814834a3b4b31e729f4716e59d3d2dd4.zip
s390/kernel: dynamically allocate FP register save area
Make the floating-point save area dynamically allocated and uses a flag to distinguish whether a task uses floating-point or vector registers. Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r--arch/s390/kernel/process.c27
-rw-r--r--arch/s390/kernel/traps.c4
2 files changed, 24 insertions, 7 deletions
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 61795bc2fff4..56949c9cda97 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -81,8 +81,26 @@ void release_thread(struct task_struct *dead_task)
void arch_release_task_struct(struct task_struct *tsk)
{
- if (is_vx_task(tsk))
- kfree(tsk->thread.fpu.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)
+{
+ *dst = *src;
+
+ /* Set up a new floating-point register save area */
+ dst->thread.fpu.fprs = kzalloc(sizeof(freg_t) * __NUM_FPRS,
+ GFP_KERNEL|__GFP_REPEAT);
+ if (!dst->thread.fpu.fprs)
+ return -ENOMEM;
+
+ /* Save the fpu registers to new thread structure. */
+ save_fp_ctl(&dst->thread.fpu.fpc);
+ save_fp_regs(dst->thread.fpu.fprs);
+ dst->thread.fpu.flags = 0; /* Always start with VX disabled */
+
+ return 0;
}
int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
@@ -142,11 +160,6 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
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.fpu.fpc);
- save_fp_regs(p->thread.fpu.fprs);
- p->thread.fpu.pad = 0;
- p->thread.fpu.vxrs = NULL;
/* Set a new TLS ? */
if (clone_flags & CLONE_SETTLS) {
unsigned long tls = frame->childregs.gprs[6];
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 97598d1876c7..7b09224c05a3 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -227,6 +227,7 @@ DO_ERROR_INFO(specification_exception, SIGILL, ILL_ILLOPN,
int alloc_vector_registers(struct task_struct *tsk)
{
__vector128 *vxrs;
+ freg_t *fprs;
/* Allocate vector register save area. */
vxrs = kzalloc(sizeof(__vector128) * __NUM_VXRS,
@@ -238,7 +239,10 @@ int alloc_vector_registers(struct task_struct *tsk)
save_fp_regs(tsk->thread.fpu.fprs);
/* Copy the 16 floating point registers */
convert_fp_to_vx(vxrs, tsk->thread.fpu.fprs);
+ fprs = tsk->thread.fpu.fprs;
tsk->thread.fpu.vxrs = vxrs;
+ tsk->thread.fpu.flags |= FPU_USE_VX;
+ kfree(fprs);
if (tsk == current) {
__ctl_set_bit(0, 17);
restore_vx_regs(vxrs);