소스 검색

powerpc: fix giveup_vsx to save registers correctly

giveup_vsx didn't save the FPU and VMX regsiters.  Change it to be
like giveup_fpr/altivec which save these registers.

Also update call sites where FPU and VMX are already saved to use the
original giveup_vsx (renamed to __giveup_vsx).

Signed-off-by: Michael Neuling <mikey@neuling.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Michael Neuling 17 년 전
부모
커밋
7c29217096
5개의 변경된 파일16개의 추가작업 그리고 7개의 파일을 삭제
  1. 4 4
      arch/powerpc/kernel/misc_64.S
  2. 9 1
      arch/powerpc/kernel/process.c
  3. 1 1
      arch/powerpc/kernel/signal_32.c
  4. 1 1
      arch/powerpc/kernel/signal_64.c
  5. 1 0
      include/asm-powerpc/system.h

+ 4 - 4
arch/powerpc/kernel/misc_64.S

@@ -508,12 +508,12 @@ _GLOBAL(giveup_altivec)
 
 #ifdef CONFIG_VSX
 /*
- * giveup_vsx(tsk)
- * Disable VSX for the task given as the argument,
- * and save the vector registers in its thread_struct.
+ * __giveup_vsx(tsk)
+ * Disable VSX for the task given as the argument.
+ * Does NOT save vsx registers.
  * Enables the VSX for use in the kernel on return.
  */
-_GLOBAL(giveup_vsx)
+_GLOBAL(__giveup_vsx)
 	mfmsr	r5
 	oris	r5,r5,MSR_VSX@h
 	mtmsrd	r5			/* enable use of VSX now */

+ 9 - 1
arch/powerpc/kernel/process.c

@@ -159,6 +159,13 @@ void enable_kernel_vsx(void)
 EXPORT_SYMBOL(enable_kernel_vsx);
 #endif
 
+void giveup_vsx(struct task_struct *tsk)
+{
+	giveup_fpu(tsk);
+	giveup_altivec(tsk);
+	__giveup_vsx(tsk);
+}
+
 void flush_vsx_to_thread(struct task_struct *tsk)
 {
 	if (tsk->thread.regs) {
@@ -290,7 +297,8 @@ struct task_struct *__switch_to(struct task_struct *prev,
 #endif /* CONFIG_ALTIVEC */
 #ifdef CONFIG_VSX
 	if (prev->thread.regs && (prev->thread.regs->msr & MSR_VSX))
-		giveup_vsx(prev);
+		/* VMX and FPU registers are already save here */
+		__giveup_vsx(prev);
 #endif /* CONFIG_VSX */
 #ifdef CONFIG_SPE
 	/*

+ 1 - 1
arch/powerpc/kernel/signal_32.c

@@ -452,7 +452,7 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
 	 * contains valid data
 	 */
 	if (current->thread.used_vsr) {
-		flush_vsx_to_thread(current);
+		__giveup_vsx(current);
 		if (copy_vsx_to_user(&frame->mc_vsregs, current))
 			return 1;
 		msr |= MSR_VSX;

+ 1 - 1
arch/powerpc/kernel/signal_64.c

@@ -122,7 +122,7 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
 	 * VMX data.
 	 */
 	if (current->thread.used_vsr) {
-		flush_vsx_to_thread(current);
+		__giveup_vsx(current);
 		v_regs += ELF_NVRREG;
 		err |= copy_vsx_to_user(v_regs, current);
 		/* set MSR_VSX in the MSR value in the frame to

+ 1 - 0
include/asm-powerpc/system.h

@@ -139,6 +139,7 @@ extern void enable_kernel_altivec(void);
 extern void giveup_altivec(struct task_struct *);
 extern void load_up_altivec(struct task_struct *);
 extern int emulate_altivec(struct pt_regs *);
+extern void __giveup_vsx(struct task_struct *);
 extern void giveup_vsx(struct task_struct *);
 extern void enable_kernel_spe(void);
 extern void giveup_spe(struct task_struct *);