x86/fpu/state: Fix XSAVES issues - Part 1
cover x86/fpu/state: Fix XSAVES issues - Part 1
** Based on tip/master **
This is Part 1 of previous 13 XSAVES patches. Break it down to smaller series. There are no code changes; only minor fixes in the titles.
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 from fpu_user_xstate_size
x86/fpu/xstate: Keep init_fpstate.xsave.header.xfeatures as zero for
init optimization
Yu-cheng Yu (1):
x86/fpu/xstate: Copy xstate registers directly to signal frame when
compacted format is in use
arch/x86/include/asm/fpu/xstate.h | 2 +- arch/x86/include/asm/processor.h | 3 +- arch/x86/kernel/fpu/core.c | 7 +-- arch/x86/kernel/fpu/init.c | 21 +++++---- arch/x86/kernel/fpu/signal.c | 32 ++++++++++---- arch/x86/kernel/fpu/xstate.c | 92 +++++++++++++++++++++++---------------- 6 files changed, 98 insertions(+), 59 deletions(-)
Signature · 1 line
1.9.1
PATCH 2/4 x86/fpu/xstate: Rename xstate_size to fpu_kernel_xstate_size to distinguish from fpu_user_xstate_size
From: Fenghua Yu <[email protected]>
User space uses standard format xsave area. fpstate in signal frame should have standard format size.
To explicitly distinguish between xstate size in kernel space and the one in user space, we rename xstate_size to fpu_kernel_xstate_size. This patch is not fixing a bug. It just makes kernel code more clear.
--- arch/x86/include/asm/processor.h | 2 +- arch/x86/kernel/fpu/core.c | 7 ++++--- arch/x86/kernel/fpu/init.c | 20 +++++++++++--------- arch/x86/kernel/fpu/signal.c | 2 +- arch/x86/kernel/fpu/xstate.c | 8 ++++---- 5 files changed, 21 insertions(+), 18 deletions(-)
arch/x86/include/asm/processor.h +1 -1
@@ -367,7 +367,7 @@ 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/kernel/fpu/core.c +4 -3
@@ -222,7 +222,7 @@ void fpstate_init(union fpregs_state *state)return ; } -memset (state,0 , xstate_size); +memset (state,0 , fpu_kernel_xstate_size);if (static_cpu_has (X86_FEATURE_FXSR ))fpstate_init_fxstate (&state->fxsave);
@@ -247,7 +247,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 +266,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);
arch/x86/kernel/fpu/init.c +11 -9
@@ -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 user and kernel 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,15 +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 ); } - fpu_user_xstate_size = xstate_size; + fpu_user_xstate_size = fpu_kernel_xstate_size;/* * Quirk: we don't yet handle the XSAVES* instructions
arch/x86/kernel/fpu/signal.c +1 -1
@@ -262,7 +262,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)int ia32_fxstate = (buf != buf_fx);struct task_struct *tsk = current;struct fpu *fpu = &tsk->thread.fpu; -int state_size = xstate_size; +int state_size = fpu_kernel_xstate_size;u64 xfeatures =0 ;int fx_only =0 ;
arch/x86/kernel/fpu/xstate.c +4 -4
@@ -537,7 +537,7 @@ static void do_extra_xstate_size_checks(void)*/ paranoid_xstate_size +=xfeature_size (i); } -XSTATE_WARN_ON (paranoid_xstate_size != xstate_size); +XSTATE_WARN_ON (paranoid_xstate_size != fpu_kernel_xstate_size); }
@@ -616,7 +616,7 @@ static int init_xstate_size(void)* The size is OK, we are definitely going to use xsave, * make it known to the world that we need more space. */ - xstate_size = possible_xstate_size; + fpu_kernel_xstate_size = possible_xstate_size;do_extra_xstate_size_checks ();/*
@@ -679,14 +679,14 @@ void __init fpu__init_system_xstate(void)return ; } -update_regset_xstate_info (xstate_size, xfeatures_mask); +update_regset_xstate_info (fpu_kernel_xstate_size, xfeatures_mask);fpu__init_prepare_fx_sw_frame ();setup_init_fpu_buf ();setup_xstate_comp ();pr_info ("x86/fpu: Enabled xstate features 0x%llx, context size is %d bytes, using '%s' format.\n" , xfeatures_mask, - xstate_size, + fpu_kernel_xstate_size,boot_cpu_has (X86_FEATURE_XSAVES ) ?"compacted" :"standard" ); }
Signature · 1 line
1.9.1
PATCH 3/4 x86/fpu/xstate: Keep init_fpstate.xsave.header.xfeatures as zero for init optimization
In reply to Yu-cheng YuFrom: Fenghua Yu <[email protected]>
Keep init_fpstate.xsave.header.xfeatures as zero for init optimization. This is important for init optimization that is implemented in processor. If a bit corresponding to an xstate in xstate_bv is 0, it means the xstate is in init status and will not be read from memory to the processor during XRSTOR/XRSTORS instruction. This largely impacts context switch performance.
--- arch/x86/kernel/fpu/xstate.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
arch/x86/kernel/fpu/xstate.c +2 -4
@@ -329,13 +329,11 @@ static void __init setup_init_fpu_buf(void)setup_xstate_features ();print_xstate_features (); -if (boot_cpu_has (X86_FEATURE_XSAVES )) { +if (boot_cpu_has (X86_FEATURE_XSAVES )) init_fpstate.xsave.header.xcomp_bv = (u64 )1 <<63 | xfeatures_mask; - init_fpstate.xsave.header.xfeatures = xfeatures_mask; - }/* -* Init all the features state with header_bv being 0x0 +* Init all the features state with header.xfeatures being 0x0 */ copy_kernel_to_xregs_booting (&init_fpstate.xsave);
Signature · 1 line
1.9.1
PATCH 4/4 x86/fpu/xstate: Copy xstate registers directly to signal frame when compacted format is in use
In reply to Yu-cheng YuXSAVES is a kernel instruction and uses a compacted format. When working with user space, the kernel should provide standard-format, non-supervisor state data. We cannot do __copy_to_user() from a compacted-format kernel xstate area to a signal frame.
Dave Hansen proposes this method to simplify copy xstate directly to user. Based on an earlier patch from Fenghua Yu <[email protected]>
--- arch/x86/include/asm/fpu/xstate.h | 1 + arch/x86/kernel/fpu/signal.c | 3 ++- arch/x86/kernel/fpu/xstate.c | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-)
arch/x86/include/asm/fpu/xstate.h +1 -0
@@ -47,5 +47,6 @@ 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 );#endif
arch/x86/kernel/fpu/signal.c +2 -1
@@ -8,6 +8,7 @@#include <asm/fpu/internal.h> #include <asm/fpu/signal.h> #include <asm/fpu/regset.h> +#include <asm/fpu/xstate.h> #include <asm/sigframe.h>
@@ -168,7 +169,7 @@ 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; -if (fpregs_active ()) { +if (fpregs_active () ||using_compacted_format ()) {/* Save the live register state to the user directly. */ if (copy_fpregs_to_sigframe (buf_fx))return -1 ;
arch/x86/kernel/fpu/xstate.c +1 -1
@@ -420,7 +420,7 @@ static int xfeature_size(int xfeature_nr)* that it is obvious which aspect of 'XSAVES' is being handled * by the calling code. */ -static int using_compacted_format (void ) +int using_compacted_format (void ) {return boot_cpu_has (X86_FEATURE_XSAVES ); }
Signature · 1 line
1.9.1
PATCH 1/4 x86/fpu/xstate: Define and use fpu_user_xstate_size
In reply to Yu-cheng YuFrom: Fenghua Yu <[email protected]>
The kernel xstate area can be in standard or compacted format; it is always in standard format for user mode. When XSAVES is enabled, the kernel uses the compacted format and it is necessary to use a separate fpu_user_xstate_size for signal/ptrace frames.
--- arch/x86/include/asm/fpu/xstate.h | 1 - arch/x86/include/asm/processor.h | 1 + arch/x86/kernel/fpu/init.c | 5 ++- arch/x86/kernel/fpu/signal.c | 27 ++++++++++---- arch/x86/kernel/fpu/xstate.c | 76 ++++++++++++++++++++++++--------------- 5 files changed, 73 insertions(+), 37 deletions(-)
arch/x86/include/asm/fpu/xstate.h +0 -1
@@ -39,7 +39,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 ];
arch/x86/include/asm/processor.h +1 -0
@@ -368,6 +368,7 @@ DECLARE_PER_CPU(struct irq_stack *, softirq_stack);#endif /* X86_64 */ extern unsigned int xstate_size; +extern unsigned int fpu_user_xstate_size;struct perf_event ;
arch/x86/kernel/fpu/init.c +4 -1
@@ -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_size 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.
@@ -226,6 +226,9 @@ static void __init fpu__init_system_xstate_size_legacy(void)else xstate_size =sizeof (struct fregs_state ); } + + fpu_user_xstate_size = xstate_size; +/* * Quirk: we don't yet handle the XSAVES* instructions * correctly, as we don't correctly convert between
arch/x86/kernel/fpu/signal.c +20 -7
@@ -31,7 +31,7 @@ static inline int check_for_xstate(struct fxregs_state __user *buf,/* Check for the first magic field and other error scenarios. */ if (fx_sw->magic1 !=FP_XSTATE_MAGIC1 || fx_sw->xstate_size < min_xstate_size || - fx_sw->xstate_size > xstate_size || + fx_sw->xstate_size > fpu_user_xstate_size || fx_sw->xstate_size > fx_sw->extended_size)return -1 ;
@@ -88,7 +88,8 @@ static inline int save_xstate_epilog(void __user *buf, int ia32_frame)if (!use_xsave ())return err; - err |=__put_user (FP_XSTATE_MAGIC2 , (__u32 *)(buf + xstate_size)); + err |=__put_user (FP_XSTATE_MAGIC2 , + (__u32 *)(buf + fpu_user_xstate_size));/* * Read the xfeatures which we copied (directly from the cpu or
@@ -125,7 +126,7 @@ static inline int copy_fpregs_to_sigframe(struct xregs_state __user *buf)else err =copy_fregs_to_user ((struct fregs_state __user *) buf); -if (unlikely (err) &&__clear_user (buf, xstate_size)) +if (unlikely (err) &&__clear_user (buf, fpu_user_xstate_size)) err = -EFAULT ;return err; }
@@ -175,8 +176,19 @@ int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)if (ia32_fxstate)copy_fxregs_to_kernel (&tsk->thread.fpu); }else { +/* +* It is a *bug* if kernel uses compacted-format for xsave +* area and we copy it out directly to a signal frame. It +* should have been handled above by saving the registers +* directly. +*/ +if (boot_cpu_has (X86_FEATURE_XSAVES )) { +WARN_ONCE (1 ,"x86/fpu: saving compacted-format xsave area to a signal frame!\n" ); +return -1 ; + } +fpstate_sanitize_xstate (&tsk->thread.fpu); -if (__copy_to_user (buf_fx, xsave, xstate_size)) +if (__copy_to_user (buf_fx, xsave, fpu_user_xstate_size))return -1 ; }
@@ -341,7 +353,8 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)static inline int xstate_sigframe_size (void ) { -return use_xsave () ? xstate_size +FP_XSTATE_MAGIC2_SIZE : xstate_size; +return use_xsave () ? fpu_user_xstate_size +FP_XSTATE_MAGIC2_SIZE : + fpu_user_xstate_size; }/*
@@ -385,12 +398,12 @@ fpu__alloc_mathframe(unsigned long sp, int ia32_frame,*/ void fpu__init_prepare_fx_sw_frame (void ) { -int size = xstate_size +FP_XSTATE_MAGIC2_SIZE ; +int size = fpu_user_xstate_size +FP_XSTATE_MAGIC2_SIZE ; fx_sw_reserved.magic1 =FP_XSTATE_MAGIC1 ; fx_sw_reserved.extended_size = size; fx_sw_reserved.xfeatures = xfeatures_mask; - fx_sw_reserved.xstate_size = xstate_size; + fx_sw_reserved.xstate_size = fpu_user_xstate_size;if (config_enabled (CONFIG_IA32_EMULATION ) ||config_enabled (CONFIG_X86_32 )) {
arch/x86/kernel/fpu/xstate.c +48 -28
116 lines not on this page · raw message
Signature · 1 line
1.9.1
tip-bot for Fenghua Yu
merge bot[tip:x86/fpu] x86/fpu/xstate: Define and use 'fpu_user_xstate_size'
x86/fpu/xstate: Define and use 'fpu_user_xstate_size'
Commit-ID: 4543ea7e282d313b48cd34bbb9dc89c1dbdd13a7 Gitweb: http://git.kernel.org/tip/4543ea7e282d313b48cd34bbb9dc89c1dbdd13a7 Author: Fenghua Yu <[email protected]> AuthorDate: Fri, 20 May 2016 10:47:05 -0700 Committer: Ingo Molnar <[email protected]> CommitDate: Fri, 17 Jun 2016 10:10:22 +0200
x86/fpu/xstate: Define and use 'fpu_user_xstate_size'
The kernel xstate area can be in standard or compacted format; it is always in standard format for user mode. When XSAVES is enabled, the kernel uses the compacted format and it is necessary to use a separate fpu_user_xstate_size for signal/ptrace frames.
--- arch/x86/include/asm/fpu/xstate.h | 1 - arch/x86/include/asm/processor.h | 1 + arch/x86/kernel/fpu/init.c | 5 ++- arch/x86/kernel/fpu/signal.c | 27 ++++++++++---- arch/x86/kernel/fpu/xstate.c | 76 ++++++++++++++++++++++++--------------- 5 files changed, 73 insertions(+), 37 deletions(-)
arch/x86/include/asm/fpu/xstate.h +0 -1
@@ -39,7 +39,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 ];
arch/x86/include/asm/processor.h +1 -0
@@ -368,6 +368,7 @@ DECLARE_PER_CPU(struct irq_stack *, softirq_stack);#endif /* X86_64 */ extern unsigned int xstate_size; +extern unsigned int fpu_user_xstate_size;struct perf_event ;
arch/x86/kernel/fpu/init.c +4 -1
@@ -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_size 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.
@@ -226,6 +226,9 @@ static void __init fpu__init_system_xstate_size_legacy(void)else xstate_size =sizeof (struct fregs_state ); } + + fpu_user_xstate_size = xstate_size; +/* * Quirk: we don't yet handle the XSAVES* instructions * correctly, as we don't correctly convert between
arch/x86/kernel/fpu/signal.c +20 -7
@@ -32,7 +32,7 @@ static inline int check_for_xstate(struct fxregs_state __user *buf,/* Check for the first magic field and other error scenarios. */ if (fx_sw->magic1 !=FP_XSTATE_MAGIC1 || fx_sw->xstate_size < min_xstate_size || - fx_sw->xstate_size > xstate_size || + fx_sw->xstate_size > fpu_user_xstate_size || fx_sw->xstate_size > fx_sw->extended_size)return -1 ;
@@ -89,7 +89,8 @@ static inline int save_xstate_epilog(void __user *buf, int ia32_frame)if (!use_xsave ())return err; - err |=__put_user (FP_XSTATE_MAGIC2 , (__u32 *)(buf + xstate_size)); + err |=__put_user (FP_XSTATE_MAGIC2 , + (__u32 *)(buf + fpu_user_xstate_size));/* * Read the xfeatures which we copied (directly from the cpu or
@@ -126,7 +127,7 @@ static inline int copy_fpregs_to_sigframe(struct xregs_state __user *buf)else err =copy_fregs_to_user ((struct fregs_state __user *) buf); -if (unlikely (err) &&__clear_user (buf, xstate_size)) +if (unlikely (err) &&__clear_user (buf, fpu_user_xstate_size)) err = -EFAULT ;return err; }
@@ -176,8 +177,19 @@ int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)if (ia32_fxstate)copy_fxregs_to_kernel (&tsk->thread.fpu); }else { +/* +* It is a *bug* if kernel uses compacted-format for xsave +* area and we copy it out directly to a signal frame. It +* should have been handled above by saving the registers +* directly. +*/ +if (boot_cpu_has (X86_FEATURE_XSAVES )) { +WARN_ONCE (1 ,"x86/fpu: saving compacted-format xsave area to a signal frame!\n" ); +return -1 ; + } +fpstate_sanitize_xstate (&tsk->thread.fpu); -if (__copy_to_user (buf_fx, xsave, xstate_size)) +if (__copy_to_user (buf_fx, xsave, fpu_user_xstate_size))return -1 ; }
@@ -344,7 +356,8 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)static inline int xstate_sigframe_size (void ) { -return use_xsave () ? xstate_size +FP_XSTATE_MAGIC2_SIZE : xstate_size; +return use_xsave () ? fpu_user_xstate_size +FP_XSTATE_MAGIC2_SIZE : + fpu_user_xstate_size; }/*
@@ -388,12 +401,12 @@ fpu__alloc_mathframe(unsigned long sp, int ia32_frame,*/ void fpu__init_prepare_fx_sw_frame (void ) { -int size = xstate_size +FP_XSTATE_MAGIC2_SIZE ; +int size = fpu_user_xstate_size +FP_XSTATE_MAGIC2_SIZE ; fx_sw_reserved.magic1 =FP_XSTATE_MAGIC1 ; fx_sw_reserved.extended_size = size; fx_sw_reserved.xfeatures = xfeatures_mask; - fx_sw_reserved.xstate_size = xstate_size; + fx_sw_reserved.xstate_size = fpu_user_xstate_size;if (config_enabled (CONFIG_IA32_EMULATION ) ||config_enabled (CONFIG_X86_32 )) {
arch/x86/kernel/fpu/xstate.c +48 -28
116 lines not on this page · raw message
tip-bot for Fenghua Yu
merge bot[tip:x86/fpu] x86/fpu/xstate: Rename 'xstate_size' to 'fpu_kernel_xstate_size', to distinguish it from 'fpu_user_xstate_size'
In reply to Yu-cheng Yux86/fpu/xstate: Rename 'xstate_size' to 'fpu_kernel_xstate_size', to distinguish it from 'fpu_user_xstate_size'
Commit-ID: 63a5db07a03947218e5f4fb0776df6b6ca328287 Gitweb: http://git.kernel.org/tip/63a5db07a03947218e5f4fb0776df6b6ca328287 Author: Fenghua Yu <[email protected]> AuthorDate: Fri, 20 May 2016 10:47:06 -0700 Committer: Ingo Molnar <[email protected]> CommitDate: Fri, 17 Jun 2016 10:10:22 +0200
x86/fpu/xstate: Rename 'xstate_size' to 'fpu_kernel_xstate_size', to distinguish it from 'fpu_user_xstate_size'
User space uses standard format xsave area. fpstate in signal frame should have standard format size.
To explicitly distinguish between xstate size in kernel space and the one in user space, we rename 'xstate_size' to 'fpu_kernel_xstate_size'.
Cleanup only, no change in functionality.
--- arch/x86/include/asm/processor.h | 2 +- arch/x86/kernel/fpu/core.c | 7 ++++--- arch/x86/kernel/fpu/init.c | 20 +++++++++++--------- arch/x86/kernel/fpu/signal.c | 2 +- arch/x86/kernel/fpu/xstate.c | 8 ++++---- 5 files changed, 21 insertions(+), 18 deletions(-)
arch/x86/include/asm/processor.h +1 -1
@@ -367,7 +367,7 @@ 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/kernel/fpu/core.c +4 -3
@@ -227,7 +227,7 @@ void fpstate_init(union fpregs_state *state)return ; } -memset (state,0 , xstate_size); +memset (state,0 , fpu_kernel_xstate_size);if (static_cpu_has (X86_FEATURE_FXSR ))fpstate_init_fxstate (&state->fxsave);
@@ -252,7 +252,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
@@ -271,7 +271,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);
arch/x86/kernel/fpu/init.c +11 -9
@@ -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 user and kernel 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,15 +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 ); } - fpu_user_xstate_size = xstate_size; + fpu_user_xstate_size = fpu_kernel_xstate_size;/* * Quirk: we don't yet handle the XSAVES* instructions
arch/x86/kernel/fpu/signal.c +1 -1
@@ -263,7 +263,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)int ia32_fxstate = (buf != buf_fx);struct task_struct *tsk = current;struct fpu *fpu = &tsk->thread.fpu; -int state_size = xstate_size; +int state_size = fpu_kernel_xstate_size;u64 xfeatures =0 ;int fx_only =0 ;
arch/x86/kernel/fpu/xstate.c +4 -4
@@ -537,7 +537,7 @@ static void do_extra_xstate_size_checks(void)*/ paranoid_xstate_size +=xfeature_size (i); } -XSTATE_WARN_ON (paranoid_xstate_size != xstate_size); +XSTATE_WARN_ON (paranoid_xstate_size != fpu_kernel_xstate_size); }
@@ -616,7 +616,7 @@ static int init_xstate_size(void)* The size is OK, we are definitely going to use xsave, * make it known to the world that we need more space. */ - xstate_size = possible_xstate_size; + fpu_kernel_xstate_size = possible_xstate_size;do_extra_xstate_size_checks ();/*
@@ -679,14 +679,14 @@ void __init fpu__init_system_xstate(void)return ; } -update_regset_xstate_info (xstate_size, xfeatures_mask); +update_regset_xstate_info (fpu_kernel_xstate_size, xfeatures_mask);fpu__init_prepare_fx_sw_frame ();setup_init_fpu_buf ();setup_xstate_comp ();pr_info ("x86/fpu: Enabled xstate features 0x%llx, context size is %d bytes, using '%s' format.\n" , xfeatures_mask, - xstate_size, + fpu_kernel_xstate_size,boot_cpu_has (X86_FEATURE_XSAVES ) ?"compacted" :"standard" ); }
tip-bot for Fenghua Yu
merge bot[tip:x86/fpu] x86/fpu/xstate: Keep init_fpstate.xsave.header.xfeatures as zero for init optimization
In reply to Yu-cheng Yux86/fpu/xstate: Keep init_fpstate.xsave.header.xfeatures as zero for init optimization
Commit-ID: 2729818f35c9b1a1614624e2edcd3e80c59c8689 Gitweb: http://git.kernel.org/tip/2729818f35c9b1a1614624e2edcd3e80c59c8689 Author: Fenghua Yu <[email protected]> AuthorDate: Fri, 20 May 2016 10:47:07 -0700 Committer: Ingo Molnar <[email protected]> CommitDate: Fri, 17 Jun 2016 10:10:23 +0200
x86/fpu/xstate: Keep init_fpstate.xsave.header.xfeatures as zero for init optimization
Keep init_fpstate.xsave.header.xfeatures as zero for init optimization. This is important for init optimization that is implemented in processor. If a bit corresponding to an xstate in xstate_bv is 0, it means the xstate is in init status and will not be read from memory to the processor during XRSTOR/XRSTORS instruction. This largely impacts context switch performance.
--- arch/x86/kernel/fpu/xstate.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
arch/x86/kernel/fpu/xstate.c +2 -4
@@ -329,13 +329,11 @@ static void __init setup_init_fpu_buf(void)setup_xstate_features ();print_xstate_features (); -if (boot_cpu_has (X86_FEATURE_XSAVES )) { +if (boot_cpu_has (X86_FEATURE_XSAVES )) init_fpstate.xsave.header.xcomp_bv = (u64 )1 <<63 | xfeatures_mask; - init_fpstate.xsave.header.xfeatures = xfeatures_mask; - }/* -* Init all the features state with header_bv being 0x0 +* Init all the features state with header.xfeatures being 0x0 */ copy_kernel_to_xregs_booting (&init_fpstate.xsave);
tip-bot for Yu-cheng Yu
merge bot[tip:x86/fpu] x86/fpu/xstate: Copy xstate registers directly to the signal frame when compacted format is in use
In reply to Yu-cheng Yux86/fpu/xstate: Copy xstate registers directly to the signal frame when compacted format is in use
Commit-ID: f605eb549cb2624ab36ea8d7847bc016f5dc31ce Gitweb: http://git.kernel.org/tip/f605eb549cb2624ab36ea8d7847bc016f5dc31ce Author: Yu-cheng Yu <[email protected]> AuthorDate: Fri, 20 May 2016 10:47:08 -0700 Committer: Ingo Molnar <[email protected]> CommitDate: Fri, 17 Jun 2016 10:10:24 +0200
x86/fpu/xstate: Copy xstate registers directly to the signal frame when compacted format is in use
XSAVES is a kernel instruction and uses a compacted format. When working with user space, the kernel should provide standard-format, non-supervisor state data. We cannot do __copy_to_user() from a compacted-format kernel xstate area to a signal frame.
Dave Hansen proposes this method to simplify copy xstate directly to user.
This patch is based on an earlier patch from Fenghua Yu <[email protected]>
Originally-from: Fenghua Yu <[email protected]>
--- arch/x86/include/asm/fpu/xstate.h | 1 + arch/x86/kernel/fpu/signal.c | 3 ++- arch/x86/kernel/fpu/xstate.c | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-)
arch/x86/include/asm/fpu/xstate.h +1 -0
@@ -47,5 +47,6 @@ 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 );#endif
arch/x86/kernel/fpu/signal.c +2 -1
@@ -8,6 +8,7 @@#include <asm/fpu/internal.h> #include <asm/fpu/signal.h> #include <asm/fpu/regset.h> +#include <asm/fpu/xstate.h> #include <asm/sigframe.h> #include <asm/trace/fpu.h>
@@ -169,7 +170,7 @@ 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; -if (fpregs_active ()) { +if (fpregs_active () ||using_compacted_format ()) {/* Save the live register state to the user directly. */ if (copy_fpregs_to_sigframe (buf_fx))return -1 ;
arch/x86/kernel/fpu/xstate.c +1 -1
@@ -420,7 +420,7 @@ static int xfeature_size(int xfeature_nr)* that it is obvious which aspect of 'XSAVES' is being handled * by the calling code. */ -static int using_compacted_format (void ) +int using_compacted_format (void ) {return boot_cpu_has (X86_FEATURE_XSAVES ); }
tip-bot for Fenghua Yu
merge bot[tip:x86/fpu] x86/fpu/xstate: Define and use 'fpu_user_xstate_size'
In reply to Yu-cheng Yux86/fpu/xstate: Define and use 'fpu_user_xstate_size'
Commit-ID: a1141e0b5ca6ee3e5e35d5f1a310a5ecb9c96ce5 Gitweb: http://git.kernel.org/tip/a1141e0b5ca6ee3e5e35d5f1a310a5ecb9c96ce5 Author: Fenghua Yu <[email protected]> AuthorDate: Fri, 20 May 2016 10:47:05 -0700 Committer: Ingo Molnar <[email protected]> CommitDate: Sat, 18 Jun 2016 10:10:18 +0200
x86/fpu/xstate: Define and use 'fpu_user_xstate_size'
The kernel xstate area can be in standard or compacted format; it is always in standard format for user mode. When XSAVES is enabled, the kernel uses the compacted format and it is necessary to use a separate fpu_user_xstate_size for signal/ptrace frames.
--- arch/x86/include/asm/fpu/xstate.h | 1 - arch/x86/include/asm/processor.h | 1 + arch/x86/kernel/fpu/init.c | 5 ++- arch/x86/kernel/fpu/signal.c | 27 ++++++++++---- arch/x86/kernel/fpu/xstate.c | 76 ++++++++++++++++++++++++--------------- 5 files changed, 73 insertions(+), 37 deletions(-)
arch/x86/include/asm/fpu/xstate.h +0 -1
@@ -39,7 +39,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 ];
arch/x86/include/asm/processor.h +1 -0
@@ -368,6 +368,7 @@ DECLARE_PER_CPU(struct irq_stack *, softirq_stack);#endif /* X86_64 */ extern unsigned int xstate_size; +extern unsigned int fpu_user_xstate_size;struct perf_event ;
arch/x86/kernel/fpu/init.c +4 -1
@@ -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_size 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.
@@ -226,6 +226,9 @@ static void __init fpu__init_system_xstate_size_legacy(void)else xstate_size =sizeof (struct fregs_state ); } + + fpu_user_xstate_size = xstate_size; +/* * Quirk: we don't yet handle the XSAVES* instructions * correctly, as we don't correctly convert between
arch/x86/kernel/fpu/signal.c +20 -7
@@ -32,7 +32,7 @@ static inline int check_for_xstate(struct fxregs_state __user *buf,/* Check for the first magic field and other error scenarios. */ if (fx_sw->magic1 !=FP_XSTATE_MAGIC1 || fx_sw->xstate_size < min_xstate_size || - fx_sw->xstate_size > xstate_size || + fx_sw->xstate_size > fpu_user_xstate_size || fx_sw->xstate_size > fx_sw->extended_size)return -1 ;
@@ -89,7 +89,8 @@ static inline int save_xstate_epilog(void __user *buf, int ia32_frame)if (!use_xsave ())return err; - err |=__put_user (FP_XSTATE_MAGIC2 , (__u32 *)(buf + xstate_size)); + err |=__put_user (FP_XSTATE_MAGIC2 , + (__u32 *)(buf + fpu_user_xstate_size));/* * Read the xfeatures which we copied (directly from the cpu or
@@ -126,7 +127,7 @@ static inline int copy_fpregs_to_sigframe(struct xregs_state __user *buf)else err =copy_fregs_to_user ((struct fregs_state __user *) buf); -if (unlikely (err) &&__clear_user (buf, xstate_size)) +if (unlikely (err) &&__clear_user (buf, fpu_user_xstate_size)) err = -EFAULT ;return err; }
@@ -176,8 +177,19 @@ int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)if (ia32_fxstate)copy_fxregs_to_kernel (&tsk->thread.fpu); }else { +/* +* It is a *bug* if kernel uses compacted-format for xsave +* area and we copy it out directly to a signal frame. It +* should have been handled above by saving the registers +* directly. +*/ +if (boot_cpu_has (X86_FEATURE_XSAVES )) { +WARN_ONCE (1 ,"x86/fpu: saving compacted-format xsave area to a signal frame!\n" ); +return -1 ; + } +fpstate_sanitize_xstate (&tsk->thread.fpu); -if (__copy_to_user (buf_fx, xsave, xstate_size)) +if (__copy_to_user (buf_fx, xsave, fpu_user_xstate_size))return -1 ; }
@@ -344,7 +356,8 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)static inline int xstate_sigframe_size (void ) { -return use_xsave () ? xstate_size +FP_XSTATE_MAGIC2_SIZE : xstate_size; +return use_xsave () ? fpu_user_xstate_size +FP_XSTATE_MAGIC2_SIZE : + fpu_user_xstate_size; }/*
@@ -388,12 +401,12 @@ fpu__alloc_mathframe(unsigned long sp, int ia32_frame,*/ void fpu__init_prepare_fx_sw_frame (void ) { -int size = xstate_size +FP_XSTATE_MAGIC2_SIZE ; +int size = fpu_user_xstate_size +FP_XSTATE_MAGIC2_SIZE ; fx_sw_reserved.magic1 =FP_XSTATE_MAGIC1 ; fx_sw_reserved.extended_size = size; fx_sw_reserved.xfeatures = xfeatures_mask; - fx_sw_reserved.xstate_size = xstate_size; + fx_sw_reserved.xstate_size = fpu_user_xstate_size;if (config_enabled (CONFIG_IA32_EMULATION ) ||config_enabled (CONFIG_X86_32 )) {
arch/x86/kernel/fpu/xstate.c +48 -28
116 lines not on this page · raw message
tip-bot for Fenghua Yu
merge bot[tip:x86/fpu] x86/fpu/xstate: Rename 'xstate_size' to 'fpu_kernel_xstate_size', to distinguish it from 'fpu_user_xstate_size'
In reply to Yu-cheng Yux86/fpu/xstate: Rename 'xstate_size' to 'fpu_kernel_xstate_size', to distinguish it from 'fpu_user_xstate_size'
Commit-ID: bf15a8cf8d14879b785c548728415d36ccb6a33b Gitweb: http://git.kernel.org/tip/bf15a8cf8d14879b785c548728415d36ccb6a33b Author: Fenghua Yu <[email protected]> AuthorDate: Fri, 20 May 2016 10:47:06 -0700 Committer: Ingo Molnar <[email protected]> CommitDate: Sat, 18 Jun 2016 10:10:18 +0200
x86/fpu/xstate: Rename 'xstate_size' to 'fpu_kernel_xstate_size', to distinguish it from 'fpu_user_xstate_size'
User space uses standard format xsave area. fpstate in signal frame should have standard format size.
To explicitly distinguish between xstate size in kernel space and the one in user space, we rename 'xstate_size' to 'fpu_kernel_xstate_size'.
Cleanup only, no change in functionality.
--- arch/x86/include/asm/processor.h | 2 +- arch/x86/kernel/fpu/core.c | 7 ++++--- arch/x86/kernel/fpu/init.c | 20 +++++++++++--------- arch/x86/kernel/fpu/signal.c | 2 +- arch/x86/kernel/fpu/xstate.c | 8 ++++---- 5 files changed, 21 insertions(+), 18 deletions(-)
arch/x86/include/asm/processor.h +1 -1
@@ -367,7 +367,7 @@ 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/kernel/fpu/core.c +4 -3
@@ -227,7 +227,7 @@ void fpstate_init(union fpregs_state *state)return ; } -memset (state,0 , xstate_size); +memset (state,0 , fpu_kernel_xstate_size);if (static_cpu_has (X86_FEATURE_FXSR ))fpstate_init_fxstate (&state->fxsave);
@@ -252,7 +252,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
@@ -271,7 +271,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);
arch/x86/kernel/fpu/init.c +11 -9
@@ -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 user and kernel 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,15 +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 ); } - fpu_user_xstate_size = xstate_size; + fpu_user_xstate_size = fpu_kernel_xstate_size;/* * Quirk: we don't yet handle the XSAVES* instructions
arch/x86/kernel/fpu/signal.c +1 -1
@@ -263,7 +263,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)int ia32_fxstate = (buf != buf_fx);struct task_struct *tsk = current;struct fpu *fpu = &tsk->thread.fpu; -int state_size = xstate_size; +int state_size = fpu_kernel_xstate_size;u64 xfeatures =0 ;int fx_only =0 ;
arch/x86/kernel/fpu/xstate.c +4 -4
@@ -537,7 +537,7 @@ static void do_extra_xstate_size_checks(void)*/ paranoid_xstate_size +=xfeature_size (i); } -XSTATE_WARN_ON (paranoid_xstate_size != xstate_size); +XSTATE_WARN_ON (paranoid_xstate_size != fpu_kernel_xstate_size); }
@@ -616,7 +616,7 @@ static int init_xstate_size(void)* The size is OK, we are definitely going to use xsave, * make it known to the world that we need more space. */ - xstate_size = possible_xstate_size; + fpu_kernel_xstate_size = possible_xstate_size;do_extra_xstate_size_checks ();/*
@@ -679,14 +679,14 @@ void __init fpu__init_system_xstate(void)return ; } -update_regset_xstate_info (xstate_size, xfeatures_mask); +update_regset_xstate_info (fpu_kernel_xstate_size, xfeatures_mask);fpu__init_prepare_fx_sw_frame ();setup_init_fpu_buf ();setup_xstate_comp ();pr_info ("x86/fpu: Enabled xstate features 0x%llx, context size is %d bytes, using '%s' format.\n" , xfeatures_mask, - xstate_size, + fpu_kernel_xstate_size,boot_cpu_has (X86_FEATURE_XSAVES ) ?"compacted" :"standard" ); }
tip-bot for Fenghua Yu
merge bot[tip:x86/fpu] x86/fpu/xstate: Keep init_fpstate.xsave.header.xfeatures as zero for init optimization
In reply to Yu-cheng Yux86/fpu/xstate: Keep init_fpstate.xsave.header.xfeatures as zero for init optimization
Commit-ID: 7d9370607d28afd454775c623d5447603473a3c3 Gitweb: http://git.kernel.org/tip/7d9370607d28afd454775c623d5447603473a3c3 Author: Fenghua Yu <[email protected]> AuthorDate: Fri, 20 May 2016 10:47:07 -0700 Committer: Ingo Molnar <[email protected]> CommitDate: Sat, 18 Jun 2016 10:10:19 +0200
x86/fpu/xstate: Keep init_fpstate.xsave.header.xfeatures as zero for init optimization
Keep init_fpstate.xsave.header.xfeatures as zero for init optimization. This is important for init optimization that is implemented in processor. If a bit corresponding to an xstate in xstate_bv is 0, it means the xstate is in init status and will not be read from memory to the processor during XRSTOR/XRSTORS instruction. This largely impacts context switch performance.
--- arch/x86/kernel/fpu/xstate.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
arch/x86/kernel/fpu/xstate.c +2 -4
@@ -329,13 +329,11 @@ static void __init setup_init_fpu_buf(void)setup_xstate_features ();print_xstate_features (); -if (boot_cpu_has (X86_FEATURE_XSAVES )) { +if (boot_cpu_has (X86_FEATURE_XSAVES )) init_fpstate.xsave.header.xcomp_bv = (u64 )1 <<63 | xfeatures_mask; - init_fpstate.xsave.header.xfeatures = xfeatures_mask; - }/* -* Init all the features state with header_bv being 0x0 +* Init all the features state with header.xfeatures being 0x0 */ copy_kernel_to_xregs_booting (&init_fpstate.xsave);
tip-bot for Yu-cheng Yu
merge bot[tip:x86/fpu] x86/fpu/xstate: Copy xstate registers directly to the signal frame when compacted format is in use
In reply to Yu-cheng Yux86/fpu/xstate: Copy xstate registers directly to the signal frame when compacted format is in use
Commit-ID: 99aa22d0d8f70d9317727ab40c85b2ead740a6ca Gitweb: http://git.kernel.org/tip/99aa22d0d8f70d9317727ab40c85b2ead740a6ca Author: Yu-cheng Yu <[email protected]> AuthorDate: Fri, 20 May 2016 10:47:08 -0700 Committer: Ingo Molnar <[email protected]> CommitDate: Sat, 18 Jun 2016 10:10:19 +0200
x86/fpu/xstate: Copy xstate registers directly to the signal frame when compacted format is in use
XSAVES is a kernel instruction and uses a compacted format. When working with user space, the kernel should provide standard-format, non-supervisor state data. We cannot do __copy_to_user() from a compacted-format kernel xstate area to a signal frame.
Dave Hansen proposes this method to simplify copy xstate directly to user.
This patch is based on an earlier patch from Fenghua Yu <[email protected]>
Originally-from: Fenghua Yu <[email protected]>
--- arch/x86/include/asm/fpu/xstate.h | 1 + arch/x86/kernel/fpu/signal.c | 3 ++- arch/x86/kernel/fpu/xstate.c | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-)
arch/x86/include/asm/fpu/xstate.h +1 -0
@@ -47,5 +47,6 @@ 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 );#endif
arch/x86/kernel/fpu/signal.c +2 -1
@@ -8,6 +8,7 @@#include <asm/fpu/internal.h> #include <asm/fpu/signal.h> #include <asm/fpu/regset.h> +#include <asm/fpu/xstate.h> #include <asm/sigframe.h> #include <asm/trace/fpu.h>
@@ -169,7 +170,7 @@ 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; -if (fpregs_active ()) { +if (fpregs_active () ||using_compacted_format ()) {/* Save the live register state to the user directly. */ if (copy_fpregs_to_sigframe (buf_fx))return -1 ;
arch/x86/kernel/fpu/xstate.c +1 -1
@@ -420,7 +420,7 @@ static int xfeature_size(int xfeature_nr)* that it is obvious which aspect of 'XSAVES' is being handled * by the calling code. */ -static int using_compacted_format (void ) +int using_compacted_format (void ) {return boot_cpu_has (X86_FEATURE_XSAVES ); }