x86/fpu changes for v4.8
Linus,
Please pull the latest x86-fpu-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86-fpu-for-linus
# HEAD: ec3ed4a2104b8d1ab8da2db5b1221b2ba8a7a6e1 x86/fpu: Do not BUG_ON() in early FPU code
The main x86 FPU changes in this cycle were:
- A large series of cleanups, fixes and enhancements to re-enable the XSAVES instruction on Intel CPUs - which is the most advanced instruction to do FPU context switches. (Yu-cheng Yu, Fenghua Yu)
- Add FPU tracepoints for the FPU state machine (Dave Hansen)
Thanks,
Ingo
------------------>
Dave Hansen (2):
x86/fpu: Add tracepoints to dump FPU state at key points x86/fpu: Do not BUG_ON() in early FPU code
Fenghua Yu (3):
x86/fpu/xstate: Define and use 'fpu_user_xstate_size'
x86/fpu/xstate: Rename 'xstate_size' to 'fpu_kernel_xstate_size', to distinguish it from 'fpu_user_xstate_size' x86/fpu/xstate: Keep init_fpstate.xsave.header.xfeatures as zero for init optimization
Yu-cheng Yu (10):
x86/fpu/xstate: Copy xstate registers directly to the signal frame when compacted format is in use x86/fpu/xstate: Align xstate components according to CPUID
x86/fpu/xstate: Fix supervisor xstate component offset
x86/fpu/xstate: Fix PTRACE frames for XSAVES
x86/fpu/xstate: Fix XSTATE component offset print out
x86/fpu/xstate: Fix xstate_offsets, xstate_sizes for non-extended xstates x86/fpu/xstate: Fix __fpu_restore_sig() for XSAVES
x86/fpu/xstate: Return NULL for disabled xstate component address
x86/fpu/xstate: Fix fpstate_init() for XRSTORS
x86/fpu/xstate: Re-enable XSAVES
arch/x86/include/asm/fpu/internal.h | 5 + arch/x86/include/asm/fpu/types.h | 7 + arch/x86/include/asm/fpu/xstate.h | 10 +- arch/x86/include/asm/processor.h | 3 +- arch/x86/include/asm/trace/fpu.h | 119 ++++++++++ arch/x86/kernel/fpu/core.c | 33 ++- arch/x86/kernel/fpu/init.c | 34 +-- arch/x86/kernel/fpu/regset.c | 52 +++-- arch/x86/kernel/fpu/signal.c | 46 +++- arch/x86/kernel/fpu/xstate.c | 451 ++++++++++++++++++++++++++++-------- arch/x86/kvm/x86.c | 6 +- 11 files changed, 608 insertions(+), 158 deletions(-) create mode 100644 arch/x86/include/asm/trace/fpu.h
arch/x86/include/asm/fpu/internal.h +5 -0
@@ -18,6 +18,7 @@#include <asm/fpu/api.h> #include <asm/fpu/xstate.h> #include <asm/cpufeature.h> +#include <asm/trace/fpu.h> /* * High level FPU state handling functions:
@@ -524,6 +525,7 @@ static inline void __fpregs_deactivate(struct fpu *fpu) fpu->fpregs_active =0 ;this_cpu_write (fpu_fpregs_owner_ctx,NULL ); +trace_x86_fpu_regs_deactivated (fpu); }/* Must be paired with a 'clts' (fpregs_activate_hw()) before! */
@@ -533,6 +535,7 @@ static inline void __fpregs_activate(struct fpu *fpu) fpu->fpregs_active =1 ;this_cpu_write (fpu_fpregs_owner_ctx, fpu); +trace_x86_fpu_regs_activated (fpu); }/*
@@ -604,11 +607,13 @@ switch_fpu_prepare(struct fpu *old_fpu, struct fpu *new_fpu, int cpu)/* But leave fpu_fpregs_owner_ctx! */ old_fpu->fpregs_active =0 ; +trace_x86_fpu_regs_deactivated (old_fpu);/* Don't change CR0.TS if we just switch! */ if (fpu.preload) { new_fpu->counter++;__fpregs_activate (new_fpu); +trace_x86_fpu_regs_activated (new_fpu);prefetch (&new_fpu->state); }else {__fpregs_deactivate_hw ();
arch/x86/include/asm/fpu/types.h +7 -0
@@ -122,6 +122,7 @@ enum xfeature {#define XFEATURE_MASK_OPMASK (1 << XFEATURE_OPMASK)#define XFEATURE_MASK_ZMM_Hi256 (1 << XFEATURE_ZMM_Hi256)#define XFEATURE_MASK_Hi16_ZMM (1 << XFEATURE_Hi16_ZMM) +#define XFEATURE_MASK_PT (1 << XFEATURE_PT_UNIMPLEMENTED_SO_FAR)#define XFEATURE_MASK_PKRU (1 << XFEATURE_PKRU)#define XFEATURE_MASK_FPSSE (XFEATURE_MASK_FP | XFEATURE_MASK_SSE)
@@ -231,6 +232,12 @@ struct xstate_header { } __attribute__((packed));/* +* xstate_header.xcomp_bv[63] indicates that the extended_state_area +* is in compacted format. +*/ +#define XCOMP_BV_COMPACTED_FORMAT ((u64)1 << 63) + +/* * This is our most modern FPU state format, as saved by the XSAVE * and restored by the XRSTOR instructions. *
arch/x86/include/asm/fpu/xstate.h +8 -2
@@ -18,6 +18,9 @@#define XSAVE_YMM_SIZE 256#define XSAVE_YMM_OFFSET (XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET) +/* Supervisor features */ +#define XFEATURE_MASK_SUPERVISOR (XFEATURE_MASK_PT) +/* Supported features which support lazy state saving */ #define XFEATURE_MASK_LAZY (XFEATURE_MASK_FP | \ XFEATURE_MASK_SSE | \
@@ -39,7 +42,6 @@#define REX_PREFIX #endif -extern unsigned int xstate_size;extern u64 xfeatures_mask;extern u64 xstate_fx_sw_bytes[USER_XSTATE_FX_SW_WORDS ];
@@ -48,5 +50,9 @@ extern void update_regset_xstate_info(unsigned int size, u64 xstate_mask);void fpu__xstate_clear_all_cpu_caps (void );void *get_xsave_addr (struct xregs_state *xsave,int xstate);const void *get_xsave_field_ptr (int xstate_field); - +int using_compacted_format (void ); +int copyout_from_xsaves (unsigned int pos,unsigned int count,void *kbuf, +void __user *ubuf,struct xregs_state *xsave); +int copyin_to_xsaves (const void *kbuf,const void __user *ubuf, +struct xregs_state *xsave);#endif
arch/x86/include/asm/processor.h +2 -1
@@ -367,7 +367,8 @@ DECLARE_PER_CPU(struct irq_stack *, hardirq_stack); DECLARE_PER_CPU(struct irq_stack *, softirq_stack);#endif /* X86_64 */ -extern unsigned int xstate_size; +extern unsigned int fpu_kernel_xstate_size; +extern unsigned int fpu_user_xstate_size;struct perf_event ;
arch/x86/include/asm/trace/fpu.h new file +119 -0
119 lines not on this page · raw message
arch/x86/kernel/fpu/core.c +30 -3
@@ -8,10 +8,14 @@#include <asm/fpu/internal.h> #include <asm/fpu/regset.h> #include <asm/fpu/signal.h> +#include <asm/fpu/types.h> #include <asm/traps.h> #include <linux/hardirq.h> +#define CREATE_TRACE_POINTS +#include <asm/trace/fpu.h> +/* * Represents the initial FPU state. It's mostly (but not completely) zeroes, * depending on the FPU hardware format:
@@ -192,6 +196,7 @@ void fpu__save(struct fpu *fpu)WARN_ON_FPU (fpu != ¤t->thread.fpu);preempt_disable (); +trace_x86_fpu_before_save (fpu);if (fpu->fpregs_active) {if (!copy_fpregs_to_fpstate (fpu)) {if (use_eager_fpu ())
@@ -200,6 +205,7 @@ void fpu__save(struct fpu *fpu)fpregs_deactivate (fpu); } } +trace_x86_fpu_after_save (fpu);preempt_enable (); }EXPORT_SYMBOL_GPL (fpu__save);
@@ -222,7 +228,14 @@ void fpstate_init(union fpregs_state *state)return ; } -memset (state,0 , xstate_size); +memset (state,0 , fpu_kernel_xstate_size); + +/* +* XRSTORS requires that this bit is set in xcomp_bv, or +* it will #GP. Make sure it is replaced after the memset(). +*/ +if (static_cpu_has (X86_FEATURE_XSAVES )) + state->xsave.header.xcomp_bv =XCOMP_BV_COMPACTED_FORMAT ;if (static_cpu_has (X86_FEATURE_FXSR ))fpstate_init_fxstate (&state->fxsave);
@@ -247,7 +260,7 @@ int fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu)* leak into the child task: */ if (use_eager_fpu ()) -memset (&dst_fpu->state.xsave,0 , xstate_size); +memset (&dst_fpu->state.xsave,0 , fpu_kernel_xstate_size);/* * Save current FPU registers directly into the child
@@ -266,7 +279,8 @@ int 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); +memcpy (&src_fpu->state, &dst_fpu->state, + fpu_kernel_xstate_size);if (use_eager_fpu ())copy_kernel_to_fpregs (&src_fpu->state);
@@ -275,6 +289,9 @@ int fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu) }preempt_enable (); +trace_x86_fpu_copy_src (src_fpu); +trace_x86_fpu_copy_dst (dst_fpu); +return 0 ; }
@@ -288,7 +305,9 @@ void fpu__activate_curr(struct fpu *fpu)if (!fpu->fpstate_active) {fpstate_init (&fpu->state); +trace_x86_fpu_init_state (fpu); +trace_x86_fpu_activate_state (fpu);/* Safe to do for the current task: */ fpu->fpstate_active =1 ; }
@@ -314,7 +333,9 @@ void fpu__activate_fpstate_read(struct fpu *fpu) }else {if (!fpu->fpstate_active) {fpstate_init (&fpu->state); +trace_x86_fpu_init_state (fpu); +trace_x86_fpu_activate_state (fpu);/* Safe to do for current and for stopped child tasks: */ fpu->fpstate_active =1 ; }
@@ -347,7 +368,9 @@ void fpu__activate_fpstate_write(struct fpu *fpu) fpu->last_cpu =-1 ; }else {fpstate_init (&fpu->state); +trace_x86_fpu_init_state (fpu); +trace_x86_fpu_activate_state (fpu);/* Safe to do for stopped child tasks: */ fpu->fpstate_active =1 ; }
@@ -432,9 +455,11 @@ void fpu__restore(struct fpu *fpu)/* Avoid __kernel_fpu_begin() right after fpregs_activate() */ kernel_fpu_disable (); +trace_x86_fpu_before_restore (fpu);fpregs_activate (fpu);copy_kernel_to_fpregs (&fpu->state); fpu->counter++; +trace_x86_fpu_after_restore (fpu);kernel_fpu_enable (); }EXPORT_SYMBOL_GPL (fpu__restore);
@@ -463,6 +488,8 @@ void fpu__drop(struct fpu *fpu) fpu->fpstate_active =0 ; +trace_x86_fpu_dropped (fpu); +preempt_enable (); }
arch/x86/kernel/fpu/init.c +12 -22
@@ -145,8 +145,8 @@ static void __init fpu__init_system_generic(void)* This is inherent to the XSAVE architecture which puts all state * components into a single, continuous memory block: */ -unsigned int xstate_size; -EXPORT_SYMBOL_GPL (xstate_size); +unsigned int fpu_kernel_xstate_size; +EXPORT_SYMBOL_GPL (fpu_kernel_xstate_size);/* Get alignment of the TYPE. */ #define TYPE_ALIGN (TYPE ) offsetof(struct { char x; TYPE test; }, test)
@@ -178,7 +178,7 @@ static void __init fpu__init_task_struct_size(void)* Add back the dynamically-calculated register state * size. */ - task_size += xstate_size; + task_size += fpu_kernel_xstate_size;/* * We dynamically size 'struct fpu', so we require that
@@ -195,7 +195,7 @@ static void __init fpu__init_task_struct_size(void) }/* -* Set up the xstate_size based on the legacy FPU context size. +* Set up the user and kernel xstate sizes based on the legacy FPU context size. * * We set this up first, and later it will be overwritten by * fpu__init_system_xstate() if the CPU knows about xstates.
@@ -208,7 +208,7 @@ static void __init fpu__init_system_xstate_size_legacy(void) on_boot_cpu =0 ;/* -* Note that xstate_size might be overwriten later during +* Note that xstate sizes might be overwritten later during * fpu__init_system_xstate(). */
@@ -219,27 +219,17 @@ static void __init fpu__init_system_xstate_size_legacy(void)*/ setup_clear_cpu_cap (X86_FEATURE_XSAVE );setup_clear_cpu_cap (X86_FEATURE_XSAVEOPT ); - xstate_size =sizeof (struct swregs_state ); + fpu_kernel_xstate_size =sizeof (struct swregs_state ); }else {if (boot_cpu_has (X86_FEATURE_FXSR )) - xstate_size =sizeof (struct fxregs_state ); + fpu_kernel_xstate_size = +sizeof (struct fxregs_state );else - xstate_size =sizeof (struct fregs_state ); + fpu_kernel_xstate_size = +sizeof (struct fregs_state ); } -/* -* Quirk: we don't yet handle the XSAVES* instructions -* correctly, as we don't correctly convert between -* standard and compacted format when interfacing -* with user-space - so disable it for now. -* -* The difference is small: with recent CPUs the -* compacted format is only marginally smaller than -* the standard FPU state format. -* -* ( This is easy to backport while we are fixing -* XSAVES* support. ) -*/ -setup_clear_cpu_cap (X86_FEATURE_XSAVES ); + + fpu_user_xstate_size = fpu_kernel_xstate_size; }/*
arch/x86/kernel/fpu/regset.c +37 -15
75 lines not on this page · raw message
arch/x86/kernel/fpu/signal.c +35 -11
120 lines not on this page · raw message
arch/x86/kernel/fpu/xstate.c +350 -101
624 lines not on this page · raw message
arch/x86/kvm/x86.c +3 -3
@@ -55,9 +55,6 @@#include <linux/irqbypass.h> #include <trace/events/kvm.h> -#define CREATE_TRACE_POINTS -#include "trace.h" -#include <asm/debugreg.h> #include <asm/msr.h> #include <asm/desc.h>
@@ -68,6 +65,9 @@#include <asm/div64.h> #include <asm/irq_remapping.h> +#define CREATE_TRACE_POINTS +#include "trace.h" +#define MAX_IO_MSRS 256#define KVM_MAX_MCE_BANKS 32#define KVM_MCE_CAP_SUPPORTED (MCG_CTL_P | MCG_SER_P)