diff mbox series

[10/11] x86/fpu: prepare copy_fpstate_to_sigframe for TIF_LOAD_FPU

Message ID 20181004140547.13014-11-bigeasy@linutronix.de (mailing list archive)
State New, archived
Headers show
Series x86: load FPU registers on return to userland | expand

Commit Message

Sebastian Andrzej Siewior Oct. 4, 2018, 2:05 p.m. UTC
From: Rik van Riel <riel@surriel.com>

If TIF_LOAD_FPU is set, then the registers are saved (not loaded). In that case
we skip the saving part.

Signed-off-by: Rik van Riel <riel@surriel.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 arch/x86/kernel/fpu/signal.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

Comments

Dave Hansen Oct. 12, 2018, 7:40 p.m. UTC | #1
On 10/04/2018 07:05 AM, Sebastian Andrzej Siewior wrote:
> From: Rik van Riel <riel@surriel.com>
> 
> If TIF_LOAD_FPU is set, then the registers are saved (not loaded). In that case
> we skip the saving part.

This sentence hurts my brain.

	"If TIF_LOAD_FPU is set the registers are ... not loaded"

I think that means that something could use some better naming.

Should TIF_LOAD_FPU be TIF_NEED_FPU_LOAD, perhaps?

> Signed-off-by: Rik van Riel <riel@surriel.com>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
>  arch/x86/kernel/fpu/signal.c | 16 ++++++++++------
>  1 file changed, 10 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c
> index c8f5ff58578ed..979dcd1ed82e0 100644
> --- a/arch/x86/kernel/fpu/signal.c
> +++ b/arch/x86/kernel/fpu/signal.c
> @@ -155,13 +155,17 @@ int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
>  			sizeof(struct user_i387_ia32_struct), NULL,
>  			(struct _fpstate_32 __user *) buf) ? -1 : 1;
>  
> -	/* Update the thread's fxstate to save the fsave header. */
> -	if (ia32_fxstate) {
> -		copy_fxregs_to_kernel(fpu);
> -	} else {
> -		copy_fpregs_to_fpstate(fpu);
> -		fpregs_deactivate(fpu);
> +	__fpregs_changes_begin();
> +	if (!test_thread_flag(TIF_LOAD_FPU)) {

This needs commenting, please.

If we do not need to load the FPU at return to userspace, it means the
state is in the the registers, not the buffer.  So, update the buffer to
match the registers.

> +		/* Update the thread's fxstate to save the fsave header. */
> +		if (ia32_fxstate) {
> +			copy_fxregs_to_kernel(fpu);
> +		} else {
> +			copy_fpregs_to_fpstate(fpu);
> +			fpregs_deactivate(fpu);
> +		}
>  	}
> +	__fpregs_changes_end();

Do we really need the __fpregs_changes_*() abstraction for this single
call site?
Borislav Petkov Oct. 15, 2018, 3:24 p.m. UTC | #2
On Fri, Oct 12, 2018 at 12:40:19PM -0700, Dave Hansen wrote:
> > +	__fpregs_changes_end();
> 
> Do we really need the __fpregs_changes_*() abstraction for this single
> call site?

Yap, I'm staring at those in patch 2, there's no documentation there what
they're supposed to do, only the commit message of patch 11 says:

"The __fpregs_changes_{begin|end}() section ensures that the register
remain unchanged. Otherwise a context switch or a BH could save the
registers to its FPU context and processor's FPU register would remain
random."

So I'd say we should drop that abstraction, use preempt_* and put that
text above the single usage site.

Thx.
Sebastian Andrzej Siewior Nov. 2, 2018, 3:44 p.m. UTC | #3
On 2018-10-15 17:24:31 [+0200], Borislav Petkov wrote:
> On Fri, Oct 12, 2018 at 12:40:19PM -0700, Dave Hansen wrote:
> > > +	__fpregs_changes_end();
> > 
> > Do we really need the __fpregs_changes_*() abstraction for this single
> > call site?
> 
> Yap, I'm staring at those in patch 2, there's no documentation there what
> they're supposed to do, only the commit message of patch 11 says:
> 
> "The __fpregs_changes_{begin|end}() section ensures that the register
> remain unchanged. Otherwise a context switch or a BH could save the
> registers to its FPU context and processor's FPU register would remain
> random."
> 
> So I'd say we should drop that abstraction, use preempt_* and put that
> text above the single usage site.

There are more than one caller and this function disables preemption and
BH in the end. Therefore I would like to keep it. But as suggested in
the previous patch I will think about renaming it.

> Thx.

Sebastian
Sebastian Andrzej Siewior Nov. 2, 2018, 10:55 p.m. UTC | #4
On 2018-10-12 12:40:19 [-0700], Dave Hansen wrote:
> On 10/04/2018 07:05 AM, Sebastian Andrzej Siewior wrote:
> > From: Rik van Riel <riel@surriel.com>
> > 
> > If TIF_LOAD_FPU is set, then the registers are saved (not loaded). In that case
> > we skip the saving part.
> 
> This sentence hurts my brain.
> 
> 	"If TIF_LOAD_FPU is set the registers are ... not loaded"
> 
> I think that means that something could use some better naming.
> 
> Should TIF_LOAD_FPU be TIF_NEED_FPU_LOAD, perhaps?

ARM has TIF_FOREIGN_FPSTATE which basically means that the current FP
stat does not belong to current().
Let me try to use TIF_NEED_FPU_LOAD and see how that works out.

> > Signed-off-by: Rik van Riel <riel@surriel.com>
> > Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> > ---
> >  arch/x86/kernel/fpu/signal.c | 16 ++++++++++------
> >  1 file changed, 10 insertions(+), 6 deletions(-)
> > 
> > diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c
> > index c8f5ff58578ed..979dcd1ed82e0 100644
> > --- a/arch/x86/kernel/fpu/signal.c
> > +++ b/arch/x86/kernel/fpu/signal.c
> > @@ -155,13 +155,17 @@ int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
> >  			sizeof(struct user_i387_ia32_struct), NULL,
> >  			(struct _fpstate_32 __user *) buf) ? -1 : 1;
> >  
> > -	/* Update the thread's fxstate to save the fsave header. */
> > -	if (ia32_fxstate) {
> > -		copy_fxregs_to_kernel(fpu);
> > -	} else {
> > -		copy_fpregs_to_fpstate(fpu);
> > -		fpregs_deactivate(fpu);
> > +	__fpregs_changes_begin();
> > +	if (!test_thread_flag(TIF_LOAD_FPU)) {
> 
> This needs commenting, please.
> 
> If we do not need to load the FPU at return to userspace, it means the
> state is in the the registers, not the buffer.  So, update the buffer to
> match the registers.

okay. Let me add this then.

Sebastian
diff mbox series

Patch

diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c
index c8f5ff58578ed..979dcd1ed82e0 100644
--- a/arch/x86/kernel/fpu/signal.c
+++ b/arch/x86/kernel/fpu/signal.c
@@ -155,13 +155,17 @@  int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
 			sizeof(struct user_i387_ia32_struct), NULL,
 			(struct _fpstate_32 __user *) buf) ? -1 : 1;
 
-	/* Update the thread's fxstate to save the fsave header. */
-	if (ia32_fxstate) {
-		copy_fxregs_to_kernel(fpu);
-	} else {
-		copy_fpregs_to_fpstate(fpu);
-		fpregs_deactivate(fpu);
+	__fpregs_changes_begin();
+	if (!test_thread_flag(TIF_LOAD_FPU)) {
+		/* Update the thread's fxstate to save the fsave header. */
+		if (ia32_fxstate) {
+			copy_fxregs_to_kernel(fpu);
+		} else {
+			copy_fpregs_to_fpstate(fpu);
+			fpregs_deactivate(fpu);
+		}
 	}
+	__fpregs_changes_end();
 
 	if (using_compacted_format()) {
 		copy_xstate_to_user(buf_fx, xsave, 0, size);