Commit 155e839a authored by Hendrik Brueckner's avatar Hendrik Brueckner Committed by Martin Schwidefsky

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: default avatarHendrik Brueckner <brueckner@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 904818e2
...@@ -8,6 +8,10 @@ ...@@ -8,6 +8,10 @@
#ifndef _ASM_S390_FPU_INTERNAL_H #ifndef _ASM_S390_FPU_INTERNAL_H
#define _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/errno.h>
#include <linux/string.h> #include <linux/string.h>
#include <asm/linkage.h> #include <asm/linkage.h>
...@@ -16,13 +20,16 @@ ...@@ -16,13 +20,16 @@
struct fpu { struct fpu {
__u32 fpc; /* Floating-point control */ __u32 fpc; /* Floating-point control */
__u32 pad; __u32 flags;
freg_t fprs[__NUM_FPRS]; /* Floating-point register save area */ union {
void *regs;
freg_t *fprs; /* Floating-point register save area */
__vector128 *vxrs; /* Vector register save area */ __vector128 *vxrs; /* Vector register save area */
};
}; };
#define is_vx_fpu(fpu) (!!(fpu)->vxrs) #define is_vx_fpu(fpu) (!!((fpu)->flags & FPU_USE_VX))
#define is_vx_task(tsk) (!!(tsk)->thread.fpu.vxrs) #define is_vx_task(tsk) (!!((tsk)->thread.fpu.flags & FPU_USE_VX))
static inline int test_fp_ctl(u32 fpc) static inline int test_fp_ctl(u32 fpc)
{ {
...@@ -188,4 +195,6 @@ static inline void restore_fpu_regs(struct fpu *fpu) ...@@ -188,4 +195,6 @@ static inline void restore_fpu_regs(struct fpu *fpu)
restore_fp_regs(fpu->fprs); restore_fp_regs(fpu->fprs);
} }
#endif
#endif /* _ASM_S390_FPU_INTERNAL_H */ #endif /* _ASM_S390_FPU_INTERNAL_H */
...@@ -81,8 +81,26 @@ void release_thread(struct task_struct *dead_task) ...@@ -81,8 +81,26 @@ void release_thread(struct task_struct *dead_task)
void arch_release_task_struct(struct task_struct *tsk) void arch_release_task_struct(struct task_struct *tsk)
{ {
if (is_vx_task(tsk)) /* Free either the floating-point or the vector register save area */
kfree(tsk->thread.fpu.vxrs); 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, 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, ...@@ -142,11 +160,6 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
p->thread.ri_signum = 0; p->thread.ri_signum = 0;
frame->childregs.psw.mask &= ~PSW_MASK_RI; 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 ? */ /* Set a new TLS ? */
if (clone_flags & CLONE_SETTLS) { if (clone_flags & CLONE_SETTLS) {
unsigned long tls = frame->childregs.gprs[6]; unsigned long tls = frame->childregs.gprs[6];
......
...@@ -227,6 +227,7 @@ DO_ERROR_INFO(specification_exception, SIGILL, ILL_ILLOPN, ...@@ -227,6 +227,7 @@ DO_ERROR_INFO(specification_exception, SIGILL, ILL_ILLOPN,
int alloc_vector_registers(struct task_struct *tsk) int alloc_vector_registers(struct task_struct *tsk)
{ {
__vector128 *vxrs; __vector128 *vxrs;
freg_t *fprs;
/* Allocate vector register save area. */ /* Allocate vector register save area. */
vxrs = kzalloc(sizeof(__vector128) * __NUM_VXRS, vxrs = kzalloc(sizeof(__vector128) * __NUM_VXRS,
...@@ -238,7 +239,10 @@ int alloc_vector_registers(struct task_struct *tsk) ...@@ -238,7 +239,10 @@ int alloc_vector_registers(struct task_struct *tsk)
save_fp_regs(tsk->thread.fpu.fprs); save_fp_regs(tsk->thread.fpu.fprs);
/* Copy the 16 floating point registers */ /* Copy the 16 floating point registers */
convert_fp_to_vx(vxrs, tsk->thread.fpu.fprs); convert_fp_to_vx(vxrs, tsk->thread.fpu.fprs);
fprs = tsk->thread.fpu.fprs;
tsk->thread.fpu.vxrs = vxrs; tsk->thread.fpu.vxrs = vxrs;
tsk->thread.fpu.flags |= FPU_USE_VX;
kfree(fprs);
if (tsk == current) { if (tsk == current) {
__ctl_set_bit(0, 17); __ctl_set_bit(0, 17);
restore_vx_regs(vxrs); restore_vx_regs(vxrs);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment