mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-19 02:04:19 +08:00
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>
This commit is contained in:
parent
904818e2f2
commit
155e839a81
@ -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 */
|
||||
|
@ -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];
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user