浏览代码

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>
Hendrik Brueckner 10 年之前
父节点
当前提交
155e839a81
共有 3 个文件被更改,包括 38 次插入12 次删除
  1. 14 5
      arch/s390/include/asm/fpu-internal.h
  2. 20 7
      arch/s390/kernel/process.c
  3. 4 0
      arch/s390/kernel/traps.c

+ 14 - 5
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 */

+ 20 - 7
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];

+ 4 - 0
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);