Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1316109 > unrolled thread

[PATCH v2 2/5] x86/fpu: Fix FNSAVE usage in eagerfpu mode

Started byAndy Lutomirski <luto@kernel.org>
First post2016-01-24 23:40 +0100
Last post2016-01-25 18:30 +0100
Articles 4 — 3 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  [PATCH v2 2/5] x86/fpu: Fix FNSAVE usage in eagerfpu mode Andy Lutomirski <luto@kernel.org> - 2016-01-24 23:40 +0100
    Re: [PATCH v2 2/5] x86/fpu: Fix FNSAVE usage in eagerfpu mode Dave Hansen <dave.hansen@linux.intel.com> - 2016-01-25 16:50 +0100
      Re: [PATCH v2 2/5] x86/fpu: Fix FNSAVE usage in eagerfpu mode Andy Lutomirski <luto@amacapital.net> - 2016-01-25 18:30 +0100
        Re: [PATCH v2 2/5] x86/fpu: Fix FNSAVE usage in eagerfpu mode Dave Hansen <dave.hansen@linux.intel.com> - 2016-01-25 18:30 +0100

#1316109 — [PATCH v2 2/5] x86/fpu: Fix FNSAVE usage in eagerfpu mode

FromAndy Lutomirski <luto@kernel.org>
Date2016-01-24 23:40 +0100
Subject[PATCH v2 2/5] x86/fpu: Fix FNSAVE usage in eagerfpu mode
Message-ID<qUBub-2ZJ-43@gated-at.bofh.it>
In eager fpu mode, having deactivated fpu without immediately
reloading some other context is illegal.  Therefore, to recover from
FNSAVE, we can't just deactivate the state -- we need to reload it
if we're not actively context switching.

We had this wrong in fpu__save and fpu__copy.  Fix both.
__kernel_fpu_begin was fine -- add a comment.

This fixes a warning triggerable with nofxsr eagerfpu=on.

Signed-off-by: Andy Lutomirski <luto@kernel.org>
---
 arch/x86/kernel/fpu/core.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
index 08e1e11a05ca..7a9244df33e2 100644
--- a/arch/x86/kernel/fpu/core.c
+++ b/arch/x86/kernel/fpu/core.c
@@ -114,6 +114,10 @@ void __kernel_fpu_begin(void)
 	kernel_fpu_disable();
 
 	if (fpu->fpregs_active) {
+		/*
+		 * Ignore return value -- we don't care if reg state
+		 * is clobbered.
+		 */
 		copy_fpregs_to_fpstate(fpu);
 	} else {
 		this_cpu_write(fpu_fpregs_owner_ctx, NULL);
@@ -189,8 +193,12 @@ void fpu__save(struct fpu *fpu)
 
 	preempt_disable();
 	if (fpu->fpregs_active) {
-		if (!copy_fpregs_to_fpstate(fpu))
-			fpregs_deactivate(fpu);
+		if (!copy_fpregs_to_fpstate(fpu)) {
+			if (use_eager_fpu())
+				copy_kernel_to_fpregs(&fpu->state);
+			else
+				fpregs_deactivate(fpu);
+		}
 	}
 	preempt_enable();
 }
@@ -259,7 +267,11 @@ static void fpu_copy(struct fpu *dst_fpu, struct fpu *src_fpu)
 	preempt_disable();
 	if (!copy_fpregs_to_fpstate(dst_fpu)) {
 		memcpy(&src_fpu->state, &dst_fpu->state, xstate_size);
-		fpregs_deactivate(src_fpu);
+
+		if (use_eager_fpu())
+			copy_kernel_to_fpregs(&src_fpu->state);
+		else
+			fpregs_deactivate(src_fpu);
 	}
 	preempt_enable();
 }
-- 
2.5.0

[toc] | [next] | [standalone]


#1316842

FromDave Hansen <dave.hansen@linux.intel.com>
Date2016-01-25 16:50 +0100
Message-ID<qURyW-64A-15@gated-at.bofh.it>
In reply to#1316109
On 01/24/2016 02:38 PM, Andy Lutomirski wrote:
>  	if (fpu->fpregs_active) {
> +		/*
> +		 * Ignore return value -- we don't care if reg state
> +		 * is clobbered.
> +		 */
>  		copy_fpregs_to_fpstate(fpu);
>  	} else {
>  		this_cpu_write(fpu_fpregs_owner_ctx, NULL);
> @@ -189,8 +193,12 @@ void fpu__save(struct fpu *fpu)
>  
>  	preempt_disable();
>  	if (fpu->fpregs_active) {
> -		if (!copy_fpregs_to_fpstate(fpu))
> -			fpregs_deactivate(fpu);
> +		if (!copy_fpregs_to_fpstate(fpu)) {
> +			if (use_eager_fpu())
> +				copy_kernel_to_fpregs(&fpu->state);
> +			else
> +				fpregs_deactivate(fpu);
> +		}
>  	}
>  	preempt_enable();

I wonder if we should just make the

> +			if (use_eager_fpu())
> +				copy_kernel_to_fpregs(&fpu->state);
> +			else
> +				fpregs_deactivate(fpu);

behavior the default _inside_ copy_fpregs_to_fpstate(fpu).  We evidently
got it wrong in 2/3 of the call sites that needed it.  It ends up being
an optimization for FNSAVE (because it allows us to avoid an FRSTOR),
but we only take advantage of that in cases of kernel_fpu_begin/end().

FXSAVE has been around since at _least_ 1999, and I'd expect it to get
used in place of FNSAVE everywhere that it is available.

If we don't want to do that, maybe we should add a "clobber" argument to
copy_fpregs_to_fpstate() for when it's allowed to clobber the register
state.

I just hate putting this logic at all the call sites.

[toc] | [prev] | [next] | [standalone]


#1317101

FromAndy Lutomirski <luto@amacapital.net>
Date2016-01-25 18:30 +0100
Message-ID<qUT7I-7lX-17@gated-at.bofh.it>
In reply to#1316842
On Jan 25, 2016 7:41 AM, "Dave Hansen" <dave.hansen@linux.intel.com> wrote:
>
> On 01/24/2016 02:38 PM, Andy Lutomirski wrote:
> >       if (fpu->fpregs_active) {
> > +             /*
> > +              * Ignore return value -- we don't care if reg state
> > +              * is clobbered.
> > +              */
> >               copy_fpregs_to_fpstate(fpu);
> >       } else {
> >               this_cpu_write(fpu_fpregs_owner_ctx, NULL);
> > @@ -189,8 +193,12 @@ void fpu__save(struct fpu *fpu)
> >
> >       preempt_disable();
> >       if (fpu->fpregs_active) {
> > -             if (!copy_fpregs_to_fpstate(fpu))
> > -                     fpregs_deactivate(fpu);
> > +             if (!copy_fpregs_to_fpstate(fpu)) {
> > +                     if (use_eager_fpu())
> > +                             copy_kernel_to_fpregs(&fpu->state);
> > +                     else
> > +                             fpregs_deactivate(fpu);
> > +             }
> >       }
> >       preempt_enable();
>
> I wonder if we should just make the
>
> > +                     if (use_eager_fpu())
> > +                             copy_kernel_to_fpregs(&fpu->state);
> > +                     else
> > +                             fpregs_deactivate(fpu);
>
> behavior the default _inside_ copy_fpregs_to_fpstate(fpu).  We evidently
> got it wrong in 2/3 of the call sites that needed it.  It ends up being
> an optimization for FNSAVE (because it allows us to avoid an FRSTOR),
> but we only take advantage of that in cases of kernel_fpu_begin/end().
>
> FXSAVE has been around since at _least_ 1999, and I'd expect it to get
> used in place of FNSAVE everywhere that it is available.
>
> If we don't want to do that, maybe we should add a "clobber" argument to
> copy_fpregs_to_fpstate() for when it's allowed to clobber the register
> state.
>
> I just hate putting this logic at all the call sites.

Me too.  I was thinking about having a clobber and a non-clobber variant.
The tricky part is that we have to think about preemption, too.  In
theory, copying fpregs to somewhere other then the normal spot can be
okay with preemption on except in the FNSAVE case, but all the callers
probably need preemption off anyway.

Even if we do the cleanup, I think I'd rather fix the bug in place
first so the diff is clearer and then clean it up on top of that.

Does that seem reasonable?


--Andy

[toc] | [prev] | [next] | [standalone]


#1317107

FromDave Hansen <dave.hansen@linux.intel.com>
Date2016-01-25 18:30 +0100
Message-ID<qUT7K-7lX-39@gated-at.bofh.it>
In reply to#1317101
On 01/25/2016 09:25 AM, Andy Lutomirski wrote:
> Even if we do the cleanup, I think I'd rather fix the bug in place
> first so the diff is clearer and then clean it up on top of that.
> 
> Does that seem reasonable?

Yup, sounds fine to me.

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web