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 197/208] x86/fpu: Change fpu->fpregs_active from 'int' to 'char', add lazy switching comments
Date: Tue, 5 May 2015 19:58:21 +0200 [thread overview]
Message-ID: <1430848712-28064-37-git-send-email-mingo@kernel.org> (raw)
In-Reply-To: <1430848712-28064-1-git-send-email-mingo@kernel.org>
Improve the memory layout of 'struct fpu':
- change ->fpregs_active from 'int' to 'char' - it's just a single flag
and modern x86 CPUs can do efficient byte accesses.
- pack related fields closer to each other: often 'fpu->state' will not be
touched, while the other fields will - so pack them into a group.
Also add comments to each field, describing their purpose, and add
some background information about lazy restores.
Also fix an obsolete, lazy switching related comment in fpu_copy()'s description.
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
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/types.h | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++--------
arch/x86/kernel/fpu/core.c | 6 ++---
arch/x86/kernel/fpu/xstate.c | 9 ++++---
3 files changed, 79 insertions(+), 18 deletions(-)
diff --git a/arch/x86/include/asm/fpu/types.h b/arch/x86/include/asm/fpu/types.h
index fe2ce3276a38..261cfb76065f 100644
--- a/arch/x86/include/asm/fpu/types.h
+++ b/arch/x86/include/asm/fpu/types.h
@@ -159,8 +159,44 @@ union fpregs_state {
struct fpu {
/*
+ * @state:
+ *
+ * In-memory copy of all FPU registers that we save/restore
+ * over context switches. If the task is using the FPU then
+ * the registers in the FPU are more recent than this state
+ * copy. If the task context-switches away then they get
+ * saved here and represent the FPU state.
+ *
+ * After context switches there may be a (short) time period
+ * during which the in-FPU hardware registers are unchanged
+ * and still perfectly match this state, if the tasks
+ * scheduled afterwards are not using the FPU.
+ *
+ * This is the 'lazy restore' window of optimization, which
+ * we track though 'fpu_fpregs_owner_ctx' and 'fpu->last_cpu'.
+ *
+ * We detect whether a subsequent task uses the FPU via setting
+ * CR0::TS to 1, which causes any FPU use to raise a #NM fault.
+ *
+ * During this window, if the task gets scheduled again, we
+ * might be able to skip having to do a restore from this
+ * memory buffer to the hardware registers - at the cost of
+ * incurring the overhead of #NM fault traps.
+ *
+ * Note that on modern CPUs that support the XSAVEOPT (or other
+ * optimized XSAVE instructions), we don't use #NM traps anymore,
+ * as the hardware can track whether FPU registers need saving
+ * or not. On such CPUs we activate the non-lazy ('eagerfpu')
+ * logic, which unconditionally saves/restores all FPU state
+ * across context switches. (if FPU state exists.)
+ */
+ union fpregs_state state;
+
+ /*
+ * @last_cpu:
+ *
* Records the last CPU on which this context was loaded into
- * FPU registers. (In the lazy-switching case we might be
+ * FPU registers. (In the lazy-restore case we might be
* able to reuse FPU registers across multiple context switches
* this way, if no intermediate task used the FPU.)
*
@@ -170,23 +206,49 @@ struct fpu {
*/
unsigned int last_cpu;
- unsigned int fpregs_active;
- union fpregs_state state;
/*
+ * @fpstate_active:
+ *
+ * This flag indicates whether this context is active: if the task
+ * is not running then we can restore from this context, if the task
+ * is running then we should save into this context.
+ */
+ unsigned char fpstate_active;
+
+ /*
+ * @fpregs_active:
+ *
+ * This flag determines whether a given context is actively
+ * loaded into the FPU's registers and that those registers
+ * represent the task's current FPU state.
+ *
+ * Note the interaction with fpstate_active:
+ *
+ * # task does not use the FPU:
+ * fpstate_active == 0
+ *
+ * # task uses the FPU and regs are active:
+ * fpstate_active == 1 && fpregs_active == 1
+ *
+ * # the regs are inactive but still match fpstate:
+ * fpstate_active == 1 && fpregs_active == 0 && fpregs_owner == fpu
+ *
+ * The third state is what we use for the lazy restore optimization
+ * on lazy-switching CPUs.
+ */
+ unsigned char fpregs_active;
+
+ /*
+ * @counter:
+ *
* This counter contains the number of consecutive context switches
* during which the FPU stays used. If this is over a threshold, the
- * lazy fpu saving logic becomes unlazy, to save the trap overhead.
+ * lazy FPU restore logic becomes eager, to save the trap overhead.
* This is an unsigned char so that after 256 iterations the counter
* wraps and the context switch behavior turns lazy again; this is to
* deal with bursty apps that only use the FPU for a short time:
*/
unsigned char counter;
- /*
- * This flag indicates whether this context is fpstate_active: if the task is
- * not running then we can restore from this context, if the task
- * is running then we should save into this context.
- */
- unsigned char fpstate_active;
};
#endif /* _ASM_X86_FPU_H */
diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
index 0acdfc5f8d19..63496c49a590 100644
--- a/arch/x86/kernel/fpu/core.c
+++ b/arch/x86/kernel/fpu/core.c
@@ -227,10 +227,8 @@ EXPORT_SYMBOL_GPL(fpstate_init);
/*
* Copy the current task's FPU state to a new task's FPU context.
*
- * In the 'eager' case we just save to the destination context.
- *
- * In the 'lazy' case we save to the source context, mark the FPU lazy
- * via stts() and copy the source context into the destination context.
+ * In both the 'eager' and the 'lazy' case we save hardware registers
+ * directly to the destination buffer.
*/
static void fpu_copy(struct fpu *dst_fpu, struct fpu *src_fpu)
{
diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
index 733a8aec7bd7..cd7f1a6bd933 100644
--- a/arch/x86/kernel/fpu/xstate.c
+++ b/arch/x86/kernel/fpu/xstate.c
@@ -76,10 +76,11 @@ int cpu_has_xfeatures(u64 xfeatures_needed, const char **feature_name)
EXPORT_SYMBOL_GPL(cpu_has_xfeatures);
/*
- * When executing XSAVEOPT (optimized XSAVE), if a processor implementation
- * detects that an FPU state component is still (or is again) in its
- * initialized state, it may clear the corresponding bit in the header.xfeatures
- * field, and can skip the writeout of registers to the corresponding memory layout.
+ * When executing XSAVEOPT (or other optimized XSAVE instructions), if
+ * a processor implementation detects that an FPU state component is still
+ * (or is again) in its initialized state, it may clear the corresponding
+ * bit in the header.xfeatures field, and can skip the writeout of registers
+ * to the corresponding memory layout.
*
* This means that when the bit is zero, the state component might still contain
* some previous - non-initialized register state.
--
2.1.0
next prev parent reply other threads:[~2015-05-05 18:03 UTC|newest]
Thread overview: 76+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-05-05 17:57 [PATCH 000/208] big x86 FPU code rewrite Ingo Molnar
2015-05-05 17:57 ` [PATCH 162/208] x86/fpu, crypto x86/cast6_avx: Simplify the cast6_init() xfeature checks Ingo Molnar
2015-05-05 17:57 ` [PATCH 163/208] x86/fpu, crypto x86/sha1_ssse3: Simplify the sha1_ssse3_mod_init() " Ingo Molnar
2015-05-05 17:57 ` [PATCH 164/208] x86/fpu, crypto x86/serpent_avx2: Simplify the init() " Ingo Molnar
2015-05-05 17:57 ` [PATCH 165/208] x86/fpu, crypto x86/sha1_mb: Remove FPU internal headers from sha1_mb.c Ingo Molnar
2015-05-05 17:57 ` [PATCH 166/208] x86/fpu: Move asm/xcr.h to asm/fpu/internal.h Ingo Molnar
2015-05-05 17:57 ` [PATCH 167/208] x86/fpu: Rename sanitize_i387_state() to fpstate_sanitize_xstate() Ingo Molnar
2015-05-05 17:57 ` [PATCH 168/208] x86/fpu: Simplify fpstate_sanitize_xstate() calls Ingo Molnar
2015-05-05 17:57 ` [PATCH 169/208] x86/fpu: Pass 'struct fpu' to fpstate_sanitize_xstate() Ingo Molnar
2015-05-05 17:57 ` [PATCH 170/208] x86/fpu: Rename save_xstate_sig() to copy_fpstate_to_sigframe() Ingo Molnar
2015-05-05 17:57 ` [PATCH 171/208] x86/fpu: Rename save_user_xstate() to copy_fpregs_to_sigframe() Ingo Molnar
2015-05-05 17:57 ` [PATCH 172/208] x86/fpu: Clarify ancient comments in fpu__restore() Ingo Molnar
2015-05-05 17:57 ` [PATCH 173/208] x86/fpu: Rename user_has_fpu() to fpregs_active() Ingo Molnar
2015-05-05 17:57 ` [PATCH 174/208] x86/fpu: Initialize fpregs in fpu__init_cpu_generic() Ingo Molnar
2015-05-05 17:57 ` [PATCH 175/208] x86/fpu: Clean up fpu__clear() state handling Ingo Molnar
2015-05-05 17:58 ` [PATCH 176/208] x86/alternatives, x86/fpu: Add 'alternatives_patched' debug flag and use it in xsave_state() Ingo Molnar
2015-05-05 22:47 ` Borislav Petkov
2015-05-06 2:57 ` Ingo Molnar
2015-05-05 17:58 ` [PATCH 177/208] x86/fpu: Synchronize the naming of drop_fpu() and fpu_reset_state() Ingo Molnar
2015-05-05 17:58 ` [PATCH 178/208] x86/fpu: Rename restore_fpu_checking() to copy_fpstate_to_fpregs() Ingo Molnar
2015-05-05 17:58 ` [PATCH 179/208] x86/fpu: Move all the fpu__*() high level methods closer to each other Ingo Molnar
2015-05-05 17:58 ` [PATCH 180/208] x86/fpu: Move fpu__clear() to 'struct fpu *' parameter passing Ingo Molnar
2015-05-05 17:58 ` [PATCH 181/208] x86/fpu: Rename restore_xstate_sig() to fpu__restore_sig() Ingo Molnar
2015-05-05 17:58 ` [PATCH 182/208] x86/fpu: Move the signal frame handling code closer to each other Ingo Molnar
2015-05-05 17:58 ` [PATCH 183/208] x86/fpu: Merge fpu__reset() and fpu__clear() Ingo Molnar
2015-05-05 17:58 ` [PATCH 184/208] x86/fpu: Move is_ia32*frame() helpers out of fpu/internal.h Ingo Molnar
2015-05-05 17:58 ` [PATCH 185/208] x86/fpu: Split out fpu/signal.h from fpu/internal.h for signal frame handling functions Ingo Molnar
2015-05-05 17:58 ` [PATCH 186/208] x86/fpu: Factor out fpu/regset.h from fpu/internal.h Ingo Molnar
2015-05-05 17:58 ` [PATCH 187/208] x86/fpu: Remove run-once init quirks Ingo Molnar
2015-05-05 17:58 ` [PATCH 188/208] x86/fpu: Factor out the exception error code handling code Ingo Molnar
2015-05-05 17:58 ` [PATCH 189/208] x86/fpu: Harmonize the names of the fpstate_init() helper functions Ingo Molnar
2015-05-05 17:58 ` [PATCH 190/208] x86/fpu: Create 'union thread_xstate' helper for fpstate_init() Ingo Molnar
2015-05-05 17:58 ` [PATCH 191/208] x86/fpu: Generalize 'init_xstate_ctx' Ingo Molnar
2015-05-05 17:58 ` [PATCH 192/208] x86/fpu: Move restore_init_xstate() out of fpu/internal.h Ingo Molnar
2015-05-05 17:58 ` [PATCH 193/208] x86/fpu: Rename all the fpregs, xregs, fxregs and fregs handling functions Ingo Molnar
2015-05-12 21:54 ` Dave Hansen
2015-05-05 17:58 ` [PATCH 194/208] x86/fpu: Factor out fpu/signal.c Ingo Molnar
2015-05-05 17:58 ` [PATCH 195/208] x86/fpu: Factor out the FPU regset code into fpu/regset.c Ingo Molnar
2015-05-05 17:58 ` [PATCH 196/208] x86/fpu: Harmonize FPU register state types Ingo Molnar
2015-05-05 17:58 ` Ingo Molnar [this message]
2015-05-05 17:58 ` [PATCH 198/208] x86/fpu: Document the various fpregs state formats Ingo Molnar
2015-05-05 19:52 ` Dave Hansen
2015-05-05 22:55 ` Yu, Fenghua
2015-05-06 4:20 ` Ingo Molnar
2015-05-05 17:58 ` [PATCH 199/208] x86/fpu: Move debugging check from kernel_fpu_begin() to __kernel_fpu_begin() Ingo Molnar
2015-05-05 17:58 ` [PATCH 200/208] x86/fpu/xstate: Don't assume the first zero xfeatures zero bit means the end Ingo Molnar
2015-05-05 20:10 ` Dave Hansen
2015-05-05 23:04 ` Yu, Fenghua
2015-05-06 4:13 ` Ingo Molnar
2015-05-05 17:58 ` [PATCH 201/208] x86/fpu: Clean up xstate feature reservation Ingo Molnar
2015-05-05 20:12 ` Dave Hansen
2015-05-06 4:54 ` Ingo Molnar
2015-05-05 17:58 ` [PATCH 202/208] x86/fpu/xstate: Clean up setup_xstate_comp() call Ingo Molnar
2015-05-05 17:58 ` [PATCH 203/208] x86/fpu/init: Propagate __init annotations Ingo Molnar
2015-05-05 17:58 ` [PATCH 204/208] x86/fpu: Pass 'struct fpu' to fpu__restore() Ingo Molnar
2015-05-05 17:58 ` [PATCH 205/208] x86/fpu: Fix the 'nofxsr' boot parameter to also clear X86_FEATURE_FXSR_OPT Ingo Molnar
2015-05-05 17:58 ` [PATCH 206/208] x86/fpu: Add CONFIG_X86_DEBUG_FPU=y FPU debugging code Ingo Molnar
2015-05-05 19:41 ` Borislav Petkov
2015-05-06 3:35 ` Ingo Molnar
2024-06-18 22:02 ` Mateusz Guzik
2025-02-25 13:43 ` Mateusz Guzik
2015-05-05 17:58 ` [PATCH 207/208] x86/fpu: Add FPU performance measurement subsystem Ingo Molnar
2015-05-05 19:15 ` Dave Hansen
2015-05-05 19:22 ` Borislav Petkov
2015-05-06 4:11 ` Ingo Molnar
2015-05-06 0:52 ` Andy Lutomirski
2015-05-06 4:52 ` Ingo Molnar
2015-05-06 15:53 ` Borislav Petkov
2015-05-07 2:52 ` Andy Lutomirski
2015-05-05 17:58 ` [PATCH 208/208] x86/fpu: Reorganize fpu/internal.h Ingo Molnar
2015-05-12 17:46 ` [PATCH 000/208] big x86 FPU code rewrite Dave Hansen
2015-05-29 18:53 ` Ingo Molnar
2015-05-19 21:41 ` Ingo Molnar
2015-05-27 1:22 ` Bobby Powers
2015-05-27 10:42 ` [PATCH] x86/fpu: Fix FPU register read access to the current task Ingo Molnar
2015-05-29 13:12 ` Bobby Powers
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=1430848712-28064-37-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
Powered by JetHome