ppc32: More preempt fixes
PATCH 1/1 ppc32: More preempt fixes
Hi !
This patch fixes more cases of possible preempt issue when testing MSR for FP or VEC bits and then doing giveup_fpu or giveup_altivec that I missed in my previous round of fixes (bk get helps before grepping ;)
I also change the single step and program check exceptions to not re-enable interrupts right away on C code entry, it was useless and would cause interesting issues with preempt & xmon
arch/ppc/kernel/align.c +6 -2
@@ -262,8 +262,12 @@return -EFAULT ;/* bad address */ } -if ((flags &F ) && (regs->msr &MSR_FP )) -giveup_fpu (current); +if (flags &F ) { +preempt_disable (); +if (regs->msr &MSR_FP ) +giveup_fpu (current); +preempt_enable (); + }if (flags &M )return 0 ;/* too hard for now */
arch/ppc/kernel/head.S +2 -2
@@ -462,7 +462,7 @@ EXC_XFER_EE(0x600, AlignmentException) /* Program check exception */ - EXCEPTION(0x700, ProgramCheck, ProgramCheckException, EXC_XFER_EE) + EXCEPTION(0x700, ProgramCheck, ProgramCheckException, EXC_XFER_STD) /* Floating-point unavailable */ . = 0x800
@@ -485,7 +485,7 @@ EXC_XFER_EE_LITE(0xc00, DoSyscall) /* Single step - not used on 601 */ - EXCEPTION(0xd00, SingleStep, SingleStepException, EXC_XFER_EE) + EXCEPTION(0xd00, SingleStep, SingleStepException, EXC_XFER_STD) EXCEPTION(0xe00, Trap_0e, UnknownException, EXC_XFER_EE) /*
arch/ppc/kernel/ptrace.c +8 -0
@@ -242,8 +242,10 @@if (index <PT_FPR0 ) { tmp =get_reg (child, (int ) index); }else { +preempt_disable ();if (child->thread.regs->msr &MSR_FP )giveup_fpu (child); +preempt_enable (); tmp = ((unsigned long *)child->thread.fpr)[index -PT_FPR0 ]; } ret =put_user (tmp,(unsigned long *) data);
@@ -276,8 +278,10 @@if (index <PT_FPR0 ) { ret =put_reg (child, index, data); }else { +preempt_disable ();if (child->thread.regs->msr &MSR_FP )giveup_fpu (child); +preempt_enable (); ((unsigned long *)child->thread.fpr)[index -PT_FPR0 ] = data; ret =0 ; }
@@ -338,8 +342,10 @@#ifdef CONFIG_ALTIVEC case PTRACE_GETVRREGS :/* Get the child altivec register state. */ +preempt_disable ();if (child->thread.regs->msr &MSR_VEC )giveup_altivec (child); +preempt_enable (); ret =get_vrregs ((unsigned long *)data, child);break ;
@@ -347,8 +353,10 @@/* Set the child altivec register state. */ /* this is to clear the MSR_VEC bit to force a reload * of register state from memory */ +preempt_disable ();if (child->thread.regs->msr &MSR_VEC )giveup_altivec (child); +preempt_enable (); ret =set_vrregs (child, (unsigned long *)data);break ;#endif
arch/ppc/kernel/signal.c +7 -2
@@ -191,8 +191,15 @@ {/* save general and floating-point registers */ CHECK_FULL_REGS (regs); +preempt_disable ();if (regs->msr &MSR_FP )giveup_fpu (current); +#ifdef CONFIG_ALTIVEC +if (current->thread.used_vr && (regs->msr &MSR_VEC )) +giveup_altivec (current); +#endif /* CONFIG_ALTIVEC */ +preempt_enable (); +if (__copy_to_user (&frame->mc_gregs, regs,GP_REGS_SIZE ) ||__copy_to_user (&frame->mc_fregs, current->thread.fpr,ELF_NFPREG *sizeof (double )))
@@ -203,8 +210,6 @@#ifdef CONFIG_ALTIVEC /* save altivec registers */ if (current->thread.used_vr) { -if (regs->msr &MSR_VEC ) -giveup_altivec (current);if (__copy_to_user (&frame->mc_vregs, current->thread.vr,ELF_NVRREG *sizeof (vector128)))return 1 ;