linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ingo Molnar <mingo@kernel.org>
To: linux-kernel@vger.kernel.org
Cc: Andy Lutomirski <luto@amacapital.net>,
	Borislav Petkov <bp@alien8.de>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	Fenghua Yu <fenghua.yu@intel.com>,
	"H. Peter Anvin" <hpa@zytor.com>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Oleg Nesterov <oleg@redhat.com>,
	Thomas Gleixner <tglx@linutronix.de>
Subject: [PATCH 132/208] x86/fpu: Rename fpu_save_init() to copy_fpregs_to_fpstate()
Date: Tue,  5 May 2015 19:50:24 +0200	[thread overview]
Message-ID: <1430848300-27877-54-git-send-email-mingo@kernel.org> (raw)
In-Reply-To: <1430848300-27877-1-git-send-email-mingo@kernel.org>

So fpu_save_init() is a historic name that got its name when the only
way the FPU state was FNSAVE, which cleared (well, destroyed) the FPU
state after saving it.

Nowadays the name is misleading, because ever since the introduction of
FXSAVE (and more modern FPU saving instructions) the 'we need to reload
the FPU state' part is only true if there's a pending FPU exception [*],
which is almost never the case.

So rename it to copy_fpregs_to_fpstate() to make it clear what's
happening. Also add a few comments about why we cannot keep registers
in certain cases.

Also clean up the control flow a bit, to make it more apparent when
we are dropping/keeping FP registers, and to optimize the common
case (of keeping fpregs) some more.

[*] Probably not true anymore, modern instructions always leave the FPU
    state intact, even if exceptions are pending: because pending FP
    exceptions are posted on the next FP instruction, not asynchronously.

    They were truly asynchronous back in the IRQ13 case, and we had to
    synchronize with them, but that code is not working anymore: we don't
    have IRQ13 mapped in the IDT anymore.

    But a cleanup patch is obviously not the place to change subtle behavior.

Reviewed-by: Borislav Petkov <bp@alien8.de>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/include/asm/fpu/internal.h | 34 ++++++++++++++++++++++++----------
 arch/x86/kernel/fpu/core.c          |  4 ++--
 arch/x86/kernel/traps.c             |  2 +-
 arch/x86/kvm/x86.c                  |  2 +-
 arch/x86/mm/mpx.c                   |  2 +-
 5 files changed, 29 insertions(+), 15 deletions(-)

diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h
index 89c6ec80c1ac..11055f51e67a 100644
--- a/arch/x86/include/asm/fpu/internal.h
+++ b/arch/x86/include/asm/fpu/internal.h
@@ -265,9 +265,15 @@ static inline void fpu_fxsave(struct fpu *fpu)
 
 /*
  * These must be called with preempt disabled. Returns
- * 'true' if the FPU state is still intact.
+ * 'true' if the FPU state is still intact and we can
+ * keep registers active.
+ *
+ * The legacy FNSAVE instruction cleared all FPU state
+ * unconditionally, so registers are essentially destroyed.
+ * Modern FPU state can be kept in registers, if there are
+ * no pending FP exceptions. (Note the FIXME below.)
  */
-static inline int fpu_save_init(struct fpu *fpu)
+static inline int copy_fpregs_to_fpstate(struct fpu *fpu)
 {
 	if (use_xsave()) {
 		xsave_state(&fpu->state->xsave);
@@ -276,13 +282,16 @@ static inline int fpu_save_init(struct fpu *fpu)
 		 * xsave header may indicate the init state of the FP.
 		 */
 		if (!(fpu->state->xsave.header.xfeatures & XSTATE_FP))
-			return 1;
-	} else if (use_fxsr()) {
-		fpu_fxsave(fpu);
+			goto keep_fpregs;
 	} else {
-		asm volatile("fnsave %[fx]; fwait"
-			     : [fx] "=m" (fpu->state->fsave));
-		return 0;
+		if (use_fxsr()) {
+			fpu_fxsave(fpu);
+		} else {
+			/* FNSAVE always clears FPU registers: */
+			asm volatile("fnsave %[fx]; fwait"
+				     : [fx] "=m" (fpu->state->fsave));
+			goto drop_fpregs;
+		}
 	}
 
 	/*
@@ -295,9 +304,14 @@ static inline int fpu_save_init(struct fpu *fpu)
 	 */
 	if (unlikely(fpu->state->fxsave.swd & X87_FSW_ES)) {
 		asm volatile("fnclex");
-		return 0;
+		goto drop_fpregs;
 	}
+
+keep_fpregs:
 	return 1;
+
+drop_fpregs:
+	return 0;
 }
 
 extern void fpu__save(struct fpu *fpu);
@@ -448,7 +462,7 @@ switch_fpu_prepare(struct fpu *old_fpu, struct fpu *new_fpu, int cpu)
 		      (use_eager_fpu() || new_fpu->counter > 5);
 
 	if (old_fpu->fpregs_active) {
-		if (!fpu_save_init(old_fpu))
+		if (!copy_fpregs_to_fpstate(old_fpu))
 			old_fpu->last_cpu = -1;
 		else
 			old_fpu->last_cpu = cpu;
diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
index 34a4e1032424..538f2541b7f7 100644
--- a/arch/x86/kernel/fpu/core.c
+++ b/arch/x86/kernel/fpu/core.c
@@ -102,7 +102,7 @@ void __kernel_fpu_begin(void)
 	kernel_fpu_disable();
 
 	if (fpu->fpregs_active) {
-		fpu_save_init(fpu);
+		copy_fpregs_to_fpstate(fpu);
 	} else {
 		this_cpu_write(fpu_fpregs_owner_ctx, NULL);
 		if (!use_eager_fpu())
@@ -196,7 +196,7 @@ void fpu__save(struct fpu *fpu)
 		if (use_eager_fpu()) {
 			__save_fpu(fpu);
 		} else {
-			fpu_save_init(fpu);
+			copy_fpregs_to_fpstate(fpu);
 			fpregs_deactivate(fpu);
 		}
 	}
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index a65586edbb57..f028f1da3480 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -395,7 +395,7 @@ dotraplinkage void do_bounds(struct pt_regs *regs, long error_code)
 	 * It is not directly accessible, though, so we need to
 	 * do an xsave and then pull it out of the xsave buffer.
 	 */
-	fpu_save_init(&tsk->thread.fpu);
+	copy_fpregs_to_fpstate(&tsk->thread.fpu);
 	xsave_buf = &(tsk->thread.fpu.state->xsave);
 	bndcsr = get_xsave_addr(xsave_buf, XSTATE_BNDCSR);
 	if (!bndcsr)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 0b58b9397098..d90bf4afa2b0 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -7058,7 +7058,7 @@ void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)
 		return;
 
 	vcpu->guest_fpu_loaded = 0;
-	fpu_save_init(&vcpu->arch.guest_fpu);
+	copy_fpregs_to_fpstate(&vcpu->arch.guest_fpu);
 	__kernel_fpu_end();
 	++vcpu->stat.fpu_reload;
 	kvm_make_request(KVM_REQ_DEACTIVATE_FPU, vcpu);
diff --git a/arch/x86/mm/mpx.c b/arch/x86/mm/mpx.c
index 5563be313fd6..3287215be60a 100644
--- a/arch/x86/mm/mpx.c
+++ b/arch/x86/mm/mpx.c
@@ -357,7 +357,7 @@ static __user void *task_get_bounds_dir(struct task_struct *tsk)
 	 * The bounds directory pointer is stored in a register
 	 * only accessible if we first do an xsave.
 	 */
-	fpu_save_init(&tsk->thread.fpu);
+	copy_fpregs_to_fpstate(&tsk->thread.fpu);
 	bndcsr = get_xsave_addr(&tsk->thread.fpu.state->xsave, XSTATE_BNDCSR);
 	if (!bndcsr)
 		return MPX_INVALID_BOUNDS_DIR;
-- 
2.1.0


  parent reply	other threads:[~2015-05-05 17:53 UTC|newest]

Thread overview: 111+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-05 17:49 [PATCH 000/208] big x86 FPU code rewrite Ingo Molnar
2015-05-05 17:49 ` [PATCH 080/208] x86/fpu: Rename 'xstate_features' to 'xfeatures_nr' Ingo Molnar
2015-05-05 17:49 ` [PATCH 081/208] x86/fpu: Move XCR0 manipulation to the FPU code proper Ingo Molnar
2015-05-05 17:49 ` [PATCH 082/208] x86/fpu: Clean up regset functions Ingo Molnar
2015-05-05 17:49 ` [PATCH 083/208] x86/fpu: Rename 'xsave_hdr' to 'header' Ingo Molnar
2015-05-05 17:49 ` [PATCH 084/208] x86/fpu: Rename xsave.header::xstate_bv to 'xfeatures' Ingo Molnar
2015-05-05 17:57   ` Dave Hansen
2015-05-05 18:16     ` Ingo Molnar
2015-05-05 18:25       ` Dave Hansen
2015-05-06  6:16         ` Ingo Molnar
2015-05-06 12:46           ` Ingo Molnar
2015-05-06 15:09             ` Dave Hansen
2015-05-07 11:46               ` Ingo Molnar
2015-05-06 18:27           ` Dave Hansen
2015-05-07 10:59             ` Borislav Petkov
2015-05-07 12:22             ` Ingo Molnar
2015-05-07 14:58               ` Dave Hansen
2015-05-07 15:33                 ` Ingo Molnar
2015-05-07 15:58                   ` Dave Hansen
2015-05-07 19:35                     ` Ingo Molnar
2015-05-05 17:49 ` [PATCH 085/208] x86/fpu: Clean up and fix MXCSR handling Ingo Molnar
2015-05-05 17:49 ` [PATCH 086/208] x86/fpu: Rename regset FPU register accessors Ingo Molnar
2015-05-05 17:49 ` [PATCH 087/208] x86/fpu: Explain the AVX register layout in the xsave area Ingo Molnar
2015-05-05 17:49 ` [PATCH 088/208] x86/fpu: Improve the __sanitize_i387_state() documentation Ingo Molnar
2015-05-05 17:49 ` [PATCH 089/208] x86/fpu: Rename fpu->has_fpu to fpu->fpregs_active Ingo Molnar
2015-05-05 17:49 ` [PATCH 090/208] x86/fpu: Rename __thread_set_has_fpu() to __fpregs_activate() Ingo Molnar
2015-05-05 17:49 ` [PATCH 091/208] x86/fpu: Rename __thread_clear_has_fpu() to __fpregs_deactivate() Ingo Molnar
2015-05-05 17:49 ` [PATCH 092/208] x86/fpu: Rename __thread_fpu_begin() to fpregs_activate() Ingo Molnar
2015-05-05 17:49 ` [PATCH 093/208] x86/fpu: Rename __thread_fpu_end() to fpregs_deactivate() Ingo Molnar
2015-05-05 17:49 ` [PATCH 094/208] x86/fpu: Remove fpstate_xstate_init_size() boot quirk Ingo Molnar
2015-05-05 17:49 ` [PATCH 095/208] x86/fpu: Remove xsave_init() bootmem allocations Ingo Molnar
2015-05-05 17:49 ` [PATCH 096/208] x86/fpu: Make setup_init_fpu_buf() run-once explicitly Ingo Molnar
2015-05-05 17:49 ` [PATCH 097/208] x86/fpu: Remove 'init_xstate_buf' bootmem allocation Ingo Molnar
2015-07-14 19:46   ` 4.2-rc2: early boot memory corruption from FPU rework Dave Hansen
2015-07-15  1:25     ` H. Peter Anvin
2015-07-15 11:07     ` Ingo Molnar
2015-07-16  0:34       ` [REGRESSION] " Dave Hansen
2015-07-16  2:39         ` Linus Torvalds
2015-07-16  2:51         ` Linus Torvalds
2015-07-17  7:45         ` Ingo Molnar
2015-07-17  8:51           ` Ingo Molnar
2015-07-17 16:58           ` Dave Hansen
2015-07-17 19:32             ` Ingo Molnar
2015-07-17 20:01               ` Dave Hansen
2015-05-05 17:49 ` [PATCH 098/208] x86/fpu: Split fpu__cpu_init() into early-boot and cpu-boot parts Ingo Molnar
2015-05-05 17:49 ` [PATCH 099/208] x86/fpu: Make the system/cpu init distinction clear in the xstate code as well Ingo Molnar
2015-05-05 17:49 ` [PATCH 100/208] x86/fpu: Move CPU capability check into fpu__init_cpu_xstate() Ingo Molnar
2015-05-05 17:49 ` [PATCH 101/208] x86/fpu: Move legacy check to fpu__init_system_xstate() Ingo Molnar
2015-05-05 17:49 ` [PATCH 102/208] x86/fpu: Propagate once per boot quirk into fpu__init_system_xstate() Ingo Molnar
2015-05-05 17:49 ` [PATCH 103/208] x86/fpu: Remove xsave_init() Ingo Molnar
2015-05-05 17:49 ` [PATCH 104/208] x86/fpu: Do fpu__init_system_xstate only from fpu__init_system() Ingo Molnar
2015-05-05 17:49 ` [PATCH 105/208] x86/fpu: Set up the legacy FPU init image " Ingo Molnar
2015-05-05 17:49 ` [PATCH 106/208] x86/fpu: Remove setup_init_fpu_buf() call from eager_fpu_init() Ingo Molnar
2015-05-05 17:49 ` [PATCH 107/208] x86/fpu: Move all eager-fpu setup code to eager_fpu_init() Ingo Molnar
2015-05-05 17:50 ` [PATCH 108/208] x86/fpu: Move eager_fpu_init() to fpu/init.c Ingo Molnar
2015-05-05 17:50 ` [PATCH 109/208] x86/fpu: Clean up eager_fpu_init() and rename it to fpu__ctx_switch_init() Ingo Molnar
2015-05-05 17:50 ` [PATCH 110/208] x86/fpu: Split fpu__ctx_switch_init() into _cpu() and _system() portions Ingo Molnar
2015-05-05 17:50 ` [PATCH 111/208] x86/fpu: Do CLTS fpu__init_system() Ingo Molnar
2015-05-05 17:50 ` [PATCH 112/208] x86/fpu: Move the fpstate_xstate_init_size() call into fpu__init_system() Ingo Molnar
2015-05-05 17:50 ` [PATCH 113/208] x86/fpu: Call fpu__init_cpu_ctx_switch() from fpu__init_cpu() Ingo Molnar
2015-05-05 17:50 ` [PATCH 114/208] x86/fpu: Do system-wide setup from fpu__detect() Ingo Molnar
2015-05-05 17:50 ` [PATCH 115/208] x86/fpu: Remove fpu__init_cpu_ctx_switch() call from fpu__init_system() Ingo Molnar
2015-05-05 17:50 ` [PATCH 116/208] x86/fpu: Simplify fpu__cpu_init() Ingo Molnar
2015-05-05 17:50 ` [PATCH 117/208] x86/fpu: Factor out fpu__init_cpu_generic() Ingo Molnar
2015-05-05 17:50 ` [PATCH 118/208] x86/fpu: Factor out fpu__init_system_generic() Ingo Molnar
2015-05-05 17:50 ` [PATCH 119/208] x86/fpu: Factor out fpu__init_system_early_generic() Ingo Molnar
2015-05-05 17:50 ` [PATCH 120/208] x86/fpu: Move !FPU check ingo fpu__init_system_early_generic() Ingo Molnar
2015-05-05 17:50 ` [PATCH 121/208] x86/fpu: Factor out FPU bug checks into fpu/bugs.c Ingo Molnar
2015-05-05 17:50 ` [PATCH 122/208] x86/fpu: Make check_fpu() init ordering independent Ingo Molnar
2015-05-05 17:50 ` [PATCH 123/208] x86/fpu: Move fpu__init_system_early_generic() out of fpu__detect() Ingo Molnar
2015-05-05 17:50 ` [PATCH 124/208] x86/fpu: Remove the extra fpu__detect() layer Ingo Molnar
2015-05-05 17:50 ` [PATCH 125/208] x86/fpu: Rename fpstate_xstate_init_size() to fpu__init_system_xstate_size_legacy() Ingo Molnar
2015-05-05 17:50 ` [PATCH 126/208] x86/fpu: Reorder init methods Ingo Molnar
2015-05-05 17:50 ` [PATCH 127/208] x86/fpu: Add more comments to the FPU init code Ingo Molnar
2015-05-05 17:50 ` [PATCH 128/208] x86/fpu: Move fpu__save() to fpu/internals.h Ingo Molnar
2015-05-05 17:50 ` [PATCH 129/208] x86/fpu: Uninline kernel_fpu_begin()/end() Ingo Molnar
2015-05-05 17:50 ` [PATCH 130/208] x86/fpu: Move various internal function prototypes to fpu/internal.h Ingo Molnar
2015-05-05 17:50 ` [PATCH 131/208] x86/fpu: Uninline the irq_ts_save()/restore() functions Ingo Molnar
2015-05-05 17:50 ` Ingo Molnar [this message]
2015-05-05 17:50 ` [PATCH 133/208] x86/fpu: Optimize copy_fpregs_to_fpstate() by removing the FNCLEX synchronization with FP exceptions Ingo Molnar
2015-05-05 17:50 ` [PATCH 134/208] x86/fpu: Simplify FPU handling by embedding the fpstate in task_struct (again) Ingo Molnar
2015-05-05 17:50 ` [PATCH 135/208] x86/fpu: Remove failure paths from fpstate-alloc low level functions Ingo Molnar
2015-05-05 17:50 ` [PATCH 136/208] x86/fpu: Remove failure return from fpstate_alloc_init() Ingo Molnar
2015-05-05 17:50 ` [PATCH 137/208] x86/fpu: Rename fpstate_alloc_init() to fpstate_init_curr() Ingo Molnar
2015-05-05 17:50 ` [PATCH 138/208] x86/fpu: Simplify fpu__unlazy_stopped() error handling Ingo Molnar
2015-05-05 17:50 ` [PATCH 139/208] x86/fpu, kvm: Simplify fx_init() Ingo Molnar
2015-05-05 17:50 ` [PATCH 140/208] x86/fpu: Simplify fpstate_init_curr() usage Ingo Molnar
2015-05-05 17:50 ` [PATCH 141/208] x86/fpu: Rename fpu__unlazy_stopped() to fpu__activate_stopped() Ingo Molnar
2015-05-05 17:50 ` [PATCH 142/208] x86/fpu: Factor out FPU hw activation/deactivation Ingo Molnar
2015-05-05 17:50 ` [PATCH 143/208] x86/fpu: Simplify __save_fpu() Ingo Molnar
2015-05-05 17:50 ` [PATCH 144/208] x86/fpu: Eliminate __save_fpu() Ingo Molnar
2015-05-05 17:50 ` [PATCH 145/208] x86/fpu: Simplify fpu__save() Ingo Molnar
2015-05-05 17:50 ` [PATCH 146/208] x86/fpu: Optimize fpu__save() Ingo Molnar
2015-05-05 17:50 ` [PATCH 147/208] x86/fpu: Optimize fpu_copy() Ingo Molnar
2015-05-05 17:50 ` [PATCH 148/208] x86/fpu: Optimize fpu_copy() some more on lazy switching systems Ingo Molnar
2015-05-05 17:50 ` [PATCH 149/208] x86/fpu: Rename fpu/xsave.h to fpu/xstate.h Ingo Molnar
2015-05-05 17:50 ` [PATCH 150/208] x86/fpu: Rename fpu/xsave.c to fpu/xstate.c Ingo Molnar
2015-05-05 17:50 ` [PATCH 151/208] x86/fpu: Introduce cpu_has_xfeatures(xfeatures_mask, feature_name) Ingo Molnar
2015-05-05 22:15   ` Yu, Fenghua
2015-05-06  5:00     ` Ingo Molnar
2015-05-05 17:50 ` [PATCH 152/208] x86/fpu: Simplify print_xstate_features() Ingo Molnar
2015-05-05 17:50 ` [PATCH 153/208] x86/fpu: Enumerate xfeature bits Ingo Molnar
2015-05-05 17:50 ` [PATCH 154/208] x86/fpu: Move xfeature type enumeration to fpu/types.h Ingo Molnar
2015-05-05 17:50 ` [PATCH 155/208] x86/fpu, crypto x86/camellia_aesni_avx: Simplify the camellia_aesni_init() xfeature checks Ingo Molnar
2015-05-05 17:50 ` [PATCH 156/208] x86/fpu, crypto x86/sha256_ssse3: Simplify the sha256_ssse3_mod_init() " Ingo Molnar
2015-05-05 17:50 ` [PATCH 157/208] x86/fpu, crypto x86/camellia_aesni_avx2: Simplify the camellia_aesni_init() " Ingo Molnar
2015-05-05 17:50 ` [PATCH 158/208] x86/fpu, crypto x86/twofish_avx: Simplify the twofish_init() " Ingo Molnar
2015-05-05 17:50 ` [PATCH 159/208] x86/fpu, crypto x86/serpent_avx: Simplify the serpent_init() " Ingo Molnar
2015-05-05 17:50 ` [PATCH 160/208] x86/fpu, crypto x86/cast5_avx: Simplify the cast5_init() " Ingo Molnar
2015-05-05 17:50 ` [PATCH 161/208] x86/fpu, crypto x86/sha512_ssse3: Simplify the sha512_ssse3_mod_init() " Ingo Molnar
2015-05-05 17:50 ` [PATCH 162/208] x86/fpu, crypto x86/cast6_avx: Simplify the cast6_init() " Ingo Molnar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1430848300-27877-54-git-send-email-mingo@kernel.org \
    --to=mingo@kernel.org \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=fenghua.yu@intel.com \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@amacapital.net \
    --cc=oleg@redhat.com \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).