diff options
author | Hendrik Brueckner <brueckner@linux.vnet.ibm.com> | 2015-06-11 16:57:20 +0200 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2015-07-22 09:58:00 +0200 |
commit | 155e839a814834a3b4b31e729f4716e59d3d2dd4 (patch) | |
tree | e23d3bd009812c8a46caa418d42bf2a18ec6d39c /arch | |
parent | 904818e2f229f3d94ec95f6932a6358c81e73d78 (diff) |
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')
-rw-r--r-- | arch/s390/include/asm/fpu-internal.h | 19 | ||||
-rw-r--r-- | arch/s390/kernel/process.c | 27 | ||||
-rw-r--r-- | arch/s390/kernel/traps.c | 4 |
3 files changed, 38 insertions, 12 deletions
diff --git a/arch/s390/include/asm/fpu-internal.h b/arch/s390/include/asm/fpu-internal.h index 04b4cfc08fb5..cc44c75fc4f7 100644 --- a/arch/s390/include/asm/fpu-internal.h +++ b/arch/s390/include/asm/fpu-internal.h @@ -8,6 +8,10 @@ #ifndef _ASM_S390_FPU_INTERNAL_H #define _ASM_S390_FPU_INTERNAL_H +#define FPU_USE_VX 1 /* Vector extension is active */ + +#ifndef __ASSEMBLY__ + #include <linux/errno.h> #include <linux/string.h> #include <asm/linkage.h> @@ -16,13 +20,16 @@ struct fpu { __u32 fpc; /* Floating-point control */ - __u32 pad; - freg_t fprs[__NUM_FPRS]; /* Floating-point register save area */ - __vector128 *vxrs; /* Vector register save area */ + __u32 flags; + union { + void *regs; + freg_t *fprs; /* Floating-point register save area */ + __vector128 *vxrs; /* Vector register save area */ + }; }; -#define is_vx_fpu(fpu) (!!(fpu)->vxrs) -#define is_vx_task(tsk) (!!(tsk)->thread.fpu.vxrs) +#define is_vx_fpu(fpu) (!!((fpu)->flags & FPU_USE_VX)) +#define is_vx_task(tsk) (!!((tsk)->thread.fpu.flags & FPU_USE_VX)) static inline int test_fp_ctl(u32 fpc) { @@ -188,4 +195,6 @@ static inline void restore_fpu_regs(struct fpu *fpu) restore_fp_regs(fpu->fprs); } +#endif + #endif /* _ASM_S390_FPU_INTERNAL_H */ 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); |