On 1/15/16, Denis Kirjanov <k...@linux-powerpc.org> wrote: > On 1/15/16, Cyril Bur <cyril...@gmail.com> wrote: >> This patch adds the ability to be able to save the FPU registers to the >> thread struct without giving up (disabling the facility) next time the >> process returns to userspace. >> >> This patch optimises the thread copy path (as a result of a fork() or >> clone()) so that the parent thread can return to userspace with hot >> registers avoiding a possibly pointless reload of FPU register state. > > Ok, but if the patch optimizes the copy path then show the performance > numbers. > > Thanks!
Oh, I've missed your cover letter. >> >> Signed-off-by: Cyril Bur <cyril...@gmail.com> >> --- >> arch/powerpc/include/asm/switch_to.h | 2 +- >> arch/powerpc/kernel/fpu.S | 21 ++++------------ >> arch/powerpc/kernel/process.c | 46 >> +++++++++++++++++++++++++++++++++++- >> 3 files changed, 50 insertions(+), 19 deletions(-) >> >> diff --git a/arch/powerpc/include/asm/switch_to.h >> b/arch/powerpc/include/asm/switch_to.h >> index 5b268b6..c4d50e9 100644 >> --- a/arch/powerpc/include/asm/switch_to.h >> +++ b/arch/powerpc/include/asm/switch_to.h >> @@ -28,7 +28,7 @@ extern void giveup_all(struct task_struct *); >> extern void enable_kernel_fp(void); >> extern void flush_fp_to_thread(struct task_struct *); >> extern void giveup_fpu(struct task_struct *); >> -extern void __giveup_fpu(struct task_struct *); >> +extern void save_fpu(struct task_struct *); >> static inline void disable_kernel_fp(void) >> { >> msr_check_and_clear(MSR_FP); >> diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S >> index b063524..15da2b5 100644 >> --- a/arch/powerpc/kernel/fpu.S >> +++ b/arch/powerpc/kernel/fpu.S >> @@ -143,33 +143,20 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) >> blr >> >> /* >> - * __giveup_fpu(tsk) >> - * Disable FP for the task given as the argument, >> - * and save the floating-point registers in its thread_struct. >> + * save_fpu(tsk) >> + * Save the floating-point registers in its thread_struct. >> * Enables the FPU for use in the kernel on return. >> */ >> -_GLOBAL(__giveup_fpu) >> +_GLOBAL(save_fpu) >> addi r3,r3,THREAD /* want THREAD of task */ >> PPC_LL r6,THREAD_FPSAVEAREA(r3) >> PPC_LL r5,PT_REGS(r3) >> PPC_LCMPI 0,r6,0 >> bne 2f >> addi r6,r3,THREAD_FPSTATE >> -2: PPC_LCMPI 0,r5,0 >> - SAVE_32FPVSRS(0, R4, R6) >> +2: SAVE_32FPVSRS(0, R4, R6) >> mffs fr0 >> stfd fr0,FPSTATE_FPSCR(r6) >> - beq 1f >> - PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5) >> - li r3,MSR_FP|MSR_FE0|MSR_FE1 >> -#ifdef CONFIG_VSX >> -BEGIN_FTR_SECTION >> - oris r3,r3,MSR_VSX@h >> -END_FTR_SECTION_IFSET(CPU_FTR_VSX) >> -#endif >> - andc r4,r4,r3 /* disable FP for previous task */ >> - PPC_STL r4,_MSR-STACK_FRAME_OVERHEAD(r5) >> -1: >> blr >> >> /* >> diff --git a/arch/powerpc/kernel/process.c >> b/arch/powerpc/kernel/process.c >> index ec53468..8a96e4f 100644 >> --- a/arch/powerpc/kernel/process.c >> +++ b/arch/powerpc/kernel/process.c >> @@ -133,6 +133,16 @@ void __msr_check_and_clear(unsigned long bits) >> EXPORT_SYMBOL(__msr_check_and_clear); >> >> #ifdef CONFIG_PPC_FPU >> +void __giveup_fpu(struct task_struct *tsk) >> +{ >> + save_fpu(tsk); >> + tsk->thread.regs->msr &= ~MSR_FP; >> +#ifdef CONFIG_VSX >> + if (cpu_has_feature(CPU_FTR_VSX)) >> + tsk->thread.regs->msr &= ~MSR_VSX; >> +#endif >> +} >> + >> void giveup_fpu(struct task_struct *tsk) >> { >> check_if_tm_restore_required(tsk); >> @@ -421,12 +431,46 @@ void restore_math(struct pt_regs *regs) >> regs->msr = msr; >> } >> >> +void save_all(struct task_struct *tsk) >> +{ >> + unsigned long usermsr; >> + >> + if (!tsk->thread.regs) >> + return; >> + >> + usermsr = tsk->thread.regs->msr; >> + >> + if ((usermsr & msr_all_available) == 0) >> + return; >> + >> + msr_check_and_set(msr_all_available); >> + >> +#ifdef CONFIG_PPC_FPU >> + if (usermsr & MSR_FP) >> + save_fpu(tsk); >> +#endif >> +#ifdef CONFIG_ALTIVEC >> + if (usermsr & MSR_VEC) >> + __giveup_altivec(tsk); >> +#endif >> +#ifdef CONFIG_VSX >> + if (usermsr & MSR_VSX) >> + __giveup_vsx(tsk); >> +#endif >> +#ifdef CONFIG_SPE >> + if (usermsr & MSR_SPE) >> + __giveup_spe(tsk); >> +#endif >> + >> + msr_check_and_clear(msr_all_available); >> +} >> + >> void flush_all_to_thread(struct task_struct *tsk) >> { >> if (tsk->thread.regs) { >> preempt_disable(); >> BUG_ON(tsk != current); >> - giveup_all(tsk); >> + save_all(tsk); >> >> #ifdef CONFIG_SPE >> if (tsk->thread.regs->msr & MSR_SPE) >> -- >> 2.7.0 >> >> _______________________________________________ >> Linuxppc-dev mailing list >> Linuxppc-dev@lists.ozlabs.org >> https://lists.ozlabs.org/listinfo/linuxppc-dev > _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev