x86/xsaves: Fix XSAVES known issues
v3 cover x86/xsaves: Fix XSAVES known issues
XSAVES is a kernel-mode instruction. It offers a compacted format and memory-write optimization. These patches fix known issues in the first implementation. They are intended for discussion and getting feedback before actually getting applied.
Version 3 adds a WARN_ONCE() in patch 9 to make it clear XSAVES supervisor states are not yet supported.
Version 2 fixes a mistake in handling supervisor states of ptrace function copyin_to_xsaves() and some coding style/naming issues in the first version. It also limits XSAVES only to 64-bit kernel in patch 9.
Patch 1, 2, and 4 are for converting between kernel-mode xstate area and signal frames.
Patch 3 fixes optimization issues introduced by XSAVES to the buffer init_fpstate.
Patch 5 and 6 are related to xstate component offsets.
Patch 7 is for converting between kernel-mode xstate area and ptrace frames.
Patch 8 fixes xstate area print out.
Patch 9 re-enables XSAVES.
Yu-cheng Yu (9):
x86/xsaves: Define and use user_xstate_size for xstate size in signal
context
x86/xsaves: Rename xstate_size to kernel_xstate_size to explicitly
distinguish xstate size in kernel from user space
x86/xsaves: Keep init_fpstate.xsave.header.xfeatures as zero for init
optimization
x86/xsaves: Introduce a new check that allows correct xstates copy
from kernel to user directly
x86/xsaves: Align xstate components according to CPUID x86/xsaves: Supervisor state component offset
x86/xsaves: Fix PTRACE frames for XSAVES
x86/xsaves: Fix XSTATE component offset print out x86/xsaves: Re-enable XSAVES
arch/x86/include/asm/fpu/types.h | 2 + arch/x86/include/asm/fpu/xstate.h | 8 +- arch/x86/include/asm/processor.h | 3 +- arch/x86/kernel/fpu/core.c | 6 +- arch/x86/kernel/fpu/init.c | 35 ++-- arch/x86/kernel/fpu/regset.c | 56 ++++-- arch/x86/kernel/fpu/signal.c | 69 ++++++- arch/x86/kernel/fpu/xstate.c | 400 +++++++++++++++++++++++++++++--------- 8 files changed, 443 insertions(+), 136 deletions(-)
Signature · 1 line
1.9.1
PATCH v3 1/9 x86/xsaves: Define and use user_xstate_size for xstate size in signal context
If "xsaves" is enabled, kernel always uses compacted format of xsave area. But user space still uses standard format of xsave area. Thus, xstate size in kernel's xsave area is smaller than xstate size in user's xsave area. The xstate in signal frame should be in standard format for user's signal handler to access.
In no "xsaves" case, xsave area in both user space and kernel space are in standard format. Therefore, user's and kernel's xstate sizes are equal.
In "xsaves" case, xsave area in user space is in standard format while xsave area in kernel space is in compacted format. Therefore, kernel's xstate size is smaller than user's xstate size.
So here is the problem: currently kernel assumes its own xstate size is signal frame's xstate size. This is not a problem in no "xsaves" case. It is an issue in "xsaves" case because kernel's xstate size is smaller than user's xstate size. In fpu__alloc_mathframe(), a smaller fpstate buffer is allocated for the standard format xstate in signal frame. Then kernel saves only part of xstate registers into this smaller user's fpstate buffer and user will see part of the xstate registers in signal context. Similar issue happens after returning from signal handler:
kernel will only restore part of xstate registers from user's fpstate buffer in signal frame.
This patch defines and uses user_xstate_size for xstate size in signal frame. It's read from returned value in ebx from CPUID leaf 0x0D subleaf 0x0. This is maximum size required by enabled states in XCR0 and may be different from ecx when states at the end of the xsave area are not enabled. This value indicates the size required for XSAVE to save all supported user states in legacy/standard format.
--- 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 | 26 ++++++++++---- arch/x86/kernel/fpu/xstate.c | 71 ++++++++++++++++++++++++--------------- 5 files changed, 67 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
@@ -366,6 +366,7 @@ DECLARE_PER_CPU(struct irq_stack *, softirq_stack);#endif /* X86_64 */ extern unsigned int xstate_size; +extern unsigned int user_xstate_size;struct perf_event ;
arch/x86/kernel/fpu/init.c +4 -1
@@ -193,7 +193,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.
@@ -224,6 +224,9 @@ static void __init fpu__init_system_xstate_size_legacy(void)else xstate_size =sizeof (struct fregs_state ); } + + 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 +19 -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 > user_xstate_size || fx_sw->xstate_size > fx_sw->extended_size)return -1 ;
@@ -88,7 +88,7 @@ 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 + user_xstate_size));/* * Read the xfeatures which we copied (directly from the cpu or
@@ -125,7 +125,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, user_xstate_size)) err = -EFAULT ;return err; }
@@ -175,8 +175,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, user_xstate_size))return -1 ; }
@@ -341,7 +352,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 () ? user_xstate_size +FP_XSTATE_MAGIC2_SIZE : + user_xstate_size; }/*
@@ -385,12 +397,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 = 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 = user_xstate_size;if (config_enabled (CONFIG_IA32_EMULATION ) ||config_enabled (CONFIG_X86_32 )) {
arch/x86/kernel/fpu/xstate.c +43 -28
111 lines not on this page · raw message
Signature · 1 line
1.9.1
PATCH v3 2/9 x86/xsaves: Rename xstate_size to kernel_xstate_size to explicitly distinguish xstate size in kernel from user space
In reply to Yu-cheng YuUser 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 kernel_xstate_size. This patch is not fixing a bug. It just makes kernel code more clear.
So we define the xsave area sizes in two global variables:
kernel_xstate_size (previous xstate_size): the xsave area size used in xsave area allocated in kerneluser_xstate_size: the xsave area size used in xsave area used by user.
In no "xsaves" case, xsave area in both user space and kernel space are in standard format. Therefore, kernel_xstate_size and user_xstate_size are equal.
In "xsaves" case, xsave area in user space is in standard format while xsave area in kernel space is in compact format. Therefore, kernel's xstate size is less than user's xstate size.
--- arch/x86/include/asm/processor.h | 2 +- arch/x86/kernel/fpu/core.c | 6 +++--- arch/x86/kernel/fpu/init.c | 18 +++++++++--------- arch/x86/kernel/fpu/signal.c | 2 +- arch/x86/kernel/fpu/xstate.c | 8 ++++---- 5 files changed, 18 insertions(+), 18 deletions(-)
arch/x86/include/asm/processor.h +1 -1
@@ -365,7 +365,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 kernel_xstate_size;extern unsigned int user_xstate_size;struct perf_event ;
arch/x86/kernel/fpu/core.c +3 -3
@@ -214,7 +214,7 @@ void fpstate_init(union fpregs_state *state)return ; } -memset (state,0 , xstate_size); +memset (state,0 , kernel_xstate_size);if (cpu_has_fxsr)fpstate_init_fxstate (&state->fxsave);
@@ -238,7 +238,7 @@ static void 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 , kernel_xstate_size);/* * Save current FPU registers directly into the child
@@ -258,7 +258,7 @@ static void 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, kernel_xstate_size);fpregs_deactivate (src_fpu); }preempt_enable ();
arch/x86/kernel/fpu/init.c +9 -9
@@ -143,8 +143,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 kernel_xstate_size; +EXPORT_SYMBOL_GPL (kernel_xstate_size);/* Get alignment of the TYPE. */ #define TYPE_ALIGN (TYPE ) offsetof(struct { char x; TYPE test; }, test)
@@ -176,7 +176,7 @@ static void __init fpu__init_task_struct_size(void)* Add back the dynamically-calculated register state * size. */ - task_size += xstate_size; + task_size += kernel_xstate_size;/* * We dynamically size 'struct fpu', so we require that
@@ -193,7 +193,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.
@@ -206,7 +206,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 overwriten later during * fpu__init_system_xstate(). */
@@ -217,15 +217,15 @@ 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 ); + kernel_xstate_size =sizeof (struct swregs_state ); }else {if (cpu_has_fxsr) - xstate_size =sizeof (struct fxregs_state ); + kernel_xstate_size =sizeof (struct fxregs_state );else - xstate_size =sizeof (struct fregs_state ); + kernel_xstate_size =sizeof (struct fregs_state ); } - user_xstate_size = xstate_size; + user_xstate_size = kernel_xstate_size;/* * Quirk: we don't yet handle the XSAVES* instructions
arch/x86/kernel/fpu/signal.c +1 -1
@@ -261,7 +261,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 = kernel_xstate_size;u64 xfeatures =0 ;int fx_only =0 ;
arch/x86/kernel/fpu/xstate.c +4 -4
@@ -517,7 +517,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 != kernel_xstate_size); }
@@ -596,7 +596,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; + kernel_xstate_size = possible_xstate_size;do_extra_xstate_size_checks ();/*
@@ -659,14 +659,14 @@ void __init fpu__init_system_xstate(void)return ; } -update_regset_xstate_info (xstate_size, xfeatures_mask); +update_regset_xstate_info (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, + kernel_xstate_size, cpu_has_xsaves ?"compacted" :"standard" ); }
Signature · 1 line
1.9.1
PATCH v3 3/9 x86/xsaves: Keep init_fpstate.xsave.header.xfeatures as zero for init optimization
In reply to Yu-cheng YuKeep 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
@@ -311,13 +311,11 @@ static void __init setup_init_fpu_buf(void)setup_xstate_features ();print_xstate_features (); -if (cpu_has_xsaves) { +if (cpu_has_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 v3 4/9 x86/xsaves: Introduce a new check that allows correct xstates copy from kernel to user directly
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.
Note that the path to copy_fpstate_to_sigframe() does currently check if the thread has used FPU, but add a WARN_ONCE() there to detect any potential mis-use.
Dave Hansen proposes this method to simplify copy xstate directly to user.
Signed-off by: Yu-cheng Yu <[email protected]>
--- arch/x86/kernel/fpu/signal.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-)
arch/x86/kernel/fpu/signal.c +40 -1
@@ -130,6 +130,45 @@ static inline int copy_fpregs_to_sigframe(struct xregs_state __user *buf)return err; } +static int may_copy_fpregs_to_sigframe (void ) +{ +/* +* In signal handling path, the kernel already checks if +* FPU instructions have been used before it calls +* copy_fpstate_to_sigframe(). We check this here again +* to detect any potential mis-use and saving invalid +* register values directly to a signal frame. +*/ +WARN_ONCE (!current->thread.fpu.fpstate_active, +"direct FPU save with no math use\n" ); + +/* +* In the case that we are using a compacted kernel +* xsave area, we can not copy the thread.fpu.state +* directly to userspace and *must* save it from the +* registers directly. +*/ +if (boot_cpu_has (X86_FEATURE_XSAVES )) +return 1 ; + +/* +* fpregs_active() means "Can I use the FPU hardware +* without taking a device-not-available exception?" This +* means that saving the registers directly will be +* cheaper than copying their contents out of +* thread.fpu.state. +* +* Note that fpregs_active() is inherently racy and may +* become false at any time. If this race happens, we +* will take a harmless device-not-available exception +* when we attempt the FPU save instruction. +*/ +if (fpregs_active ()) +return 1 ; + +return 0 ; +} +/* * Save the fpu, extended register state to the user signal frame. *
@@ -167,7 +206,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 (may_copy_fpregs_to_sigframe ()) {/* Save the live register state to the user directly. */ if (copy_fpregs_to_sigframe (buf_fx))return -1 ;
Signature · 1 line
1.9.1
PATCH v3 5/9 x86/xsaves: Align xstate components according to CPUID
In reply to Yu-cheng YuCPUID function 0x0d, sub function (i, i > 1) returns in ecx[1] the alignment requirement of component i when the compacted format is used.
If ecx[1] is 0, component i is located immediately following the preceding component. If ecx[1] is 1, component i is located on the next 64-byte boundary following the preceding component.
--- arch/x86/kernel/fpu/xstate.c | 60 +++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 28 deletions(-)
arch/x86/kernel/fpu/xstate.c +32 -28
@@ -252,6 +252,33 @@ static void __init print_xstate_features(void) }/* +* This check is important because it is easy to get XSTATE_* +* confused with XSTATE_BIT_*. +*/ +#define CHECK_XFEATURE (nr) do { \ + WARN_ON(nr < FIRST_EXTENDED_XFEATURE); \ + WARN_ON(nr >= XFEATURE_MAX); \ +} while (0) + +/* +* We could cache this like xstate_size[], but we only use +* it here, so it would be a waste of space. +*/ +static int xfeature_is_aligned (int xfeature_nr) +{ +u32 eax, ebx, ecx, edx; + +CHECK_XFEATURE (xfeature_nr); +cpuid_count (XSTATE_CPUID , xfeature_nr, &eax, &ebx, &ecx, &edx); +/* +* The value returned by ECX[1] indicates the alignment +* of state component i when the compacted format +* of the extended region of an XSAVE area is used +*/ +return !!(ecx &2 ); +} + +/* * This function sets up offsets and sizes of all extended states in * xsave area. This supports both standard format and compacted format * of the xsave aread.
@@ -288,10 +315,14 @@ static void __init setup_xstate_comp(void)else xstate_comp_sizes[i] =0 ; -if (i >FIRST_EXTENDED_XFEATURE ) +if (i >FIRST_EXTENDED_XFEATURE ) { xstate_comp_offsets[i] = xstate_comp_offsets[i-1 ] + xstate_comp_sizes[i-1 ]; +if (xfeature_is_aligned (i)) + xstate_comp_offsets[i] = +ALIGN (xstate_comp_offsets[i],64 ); + } } }
@@ -348,33 +379,6 @@ static int xfeature_is_user(int xfeature_nr)} */ -/* -* This check is important because it is easy to get XSTATE_* -* confused with XSTATE_BIT_*. -*/ -#define CHECK_XFEATURE (nr) do { \ - WARN_ON(nr < FIRST_EXTENDED_XFEATURE); \ - WARN_ON(nr >= XFEATURE_MAX); \ -} while (0) - -/* -* We could cache this like xstate_size[], but we only use -* it here, so it would be a waste of space. -*/ -static int xfeature_is_aligned (int xfeature_nr) -{ -u32 eax, ebx, ecx, edx; - -CHECK_XFEATURE (xfeature_nr); -cpuid_count (XSTATE_CPUID , xfeature_nr, &eax, &ebx, &ecx, &edx); -/* -* The value returned by ECX[1] indicates the alignment -* of state component i when the compacted format -* of the extended region of an XSAVE area is used -*/ -return !!(ecx &2 ); -} -static int xfeature_uncompacted_offset (int xfeature_nr) {u32 eax, ebx, ecx, edx;
Signature · 1 line
1.9.1
PATCH v3 6/9 x86/xsaves: Supervisor state component offset
In reply to Yu-cheng YuCPUID function 0x0d, sub function (i, i > 1) returns in ebx the offset of xstate component i. Zero is returned for a supervisor state. A supervisor state can only be saved by XSAVES and XSAVES uses a compacted format. There is no fixed offset for a supervisor state. This patch checks and makes sure a supervisor state offset is not recorded or mis-used. This has no effect in practice as we currently use no supervisor states, but it would be good to fix.
--- arch/x86/include/asm/fpu/types.h | 2 ++ arch/x86/include/asm/fpu/xstate.h | 3 ++ arch/x86/kernel/fpu/xstate.c | 62 ++++++++++++++++++++++++--------------- 3 files changed, 44 insertions(+), 23 deletions(-)
arch/x86/include/asm/fpu/types.h +2 -0
@@ -108,6 +108,7 @@ enum xfeature {XFEATURE_OPMASK , XFEATURE_ZMM_Hi256, XFEATURE_Hi16_ZMM, +XFEATURE_PT , XFEATURE_MAX, };
@@ -120,6 +121,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)#define XFEATURE_MASK_FPSSE (XFEATURE_MASK_FP | XFEATURE_MASK_SSE)#define XFEATURE_MASK_AVX512 (XFEATURE_MASK_OPMASK \
arch/x86/include/asm/fpu/xstate.h +3 -0
@@ -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)
arch/x86/kernel/fpu/xstate.c +39 -23
84 lines not on this page · raw message
Signature · 1 line
1.9.1
PATCH v3 7/9 x86/xsaves: Fix PTRACE frames for XSAVES
In reply to Yu-cheng YuXSAVES uses compacted format and is a kernel instruction. The kernel should use standard-format, non-supervisor state data for PTRACE.
--- arch/x86/include/asm/fpu/xstate.h | 4 + arch/x86/kernel/fpu/regset.c | 56 +++++++++--- arch/x86/kernel/fpu/xstate.c | 173 +++++++++++++++++++++++++++++++++++++- 3 files changed, 217 insertions(+), 16 deletions(-)
arch/x86/include/asm/fpu/xstate.h +4 -0
@@ -50,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 copyout_from_xsaves (unsigned int pos,unsigned int count,void *kbuf, +void __user *ubuf,const struct xregs_state *xsave); +int copyin_to_xsaves (const void *kbuf,const void __user *ubuf, +struct xregs_state *xsave);#endif
arch/x86/kernel/fpu/regset.c +42 -14
80 lines not on this page · raw message
arch/x86/kernel/fpu/xstate.c +171 -2
194 lines not on this page · raw message
Signature · 1 line
1.9.1
PATCH v3 8/9 x86/xsaves: Fix XSTATE component offset print out
In reply to Yu-cheng YuComponent offset print out was incorrect for XSAVES. Correct it and move to a separate function.
--- arch/x86/kernel/fpu/xstate.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)
arch/x86/kernel/fpu/xstate.c +16 -2
@@ -251,8 +251,6 @@ static void __init setup_xstate_features(void)WARN_ONCE (last_good_offset > xstate_offsets[i],"x86/fpu: misordered xstate at %d\n" , last_good_offset); last_good_offset = xstate_offsets[i]; - -printk (KERN_INFO "x86/fpu: xstate_offset[%d]: %4d, xstate_sizes[%d]: %4d\n" , i, ebx, i, eax); } }
@@ -355,6 +353,21 @@ static void __init setup_xstate_comp(void) }/* +* Print out xstate component offsets and sizes +*/ +static void __init print_xstate_offset_size (void ) +{ +int i; + +for (i =FIRST_EXTENDED_XFEATURE ; i <XFEATURE_MAX ; i++) { +if (!xfeature_enabled (i)) +continue ; +pr_info ("x86/fpu: xstate_offset[%d]: %4d, xstate_sizes[%d]: %4d\n" , + i, xstate_comp_offsets[i], i, xstate_sizes[i]); + } +} + +/* * setup the xstate image representing the init state */ static void __init setup_init_fpu_buf (void )
@@ -687,6 +700,7 @@ void __init fpu__init_system_xstate(void)fpu__init_prepare_fx_sw_frame ();setup_init_fpu_buf ();setup_xstate_comp (); +print_xstate_offset_size (); pr_info("x86/fpu: Enabled xstate features 0x%llx, context size is %d bytes, using '%s' format.\n", xfeatures_mask,
Signature · 1 line
1.9.1
PATCH v3 9/9 x86/xsaves: Re-enable XSAVES
In reply to Yu-cheng YuWe did not handle XSAVES* instructions correctly. There were issues in converting between standard and compacted format when interfacing with user-space. These issues have been corrected.
Add a WARN_ONCE() to make it clear that XSAVES supervisor states are not yet implemented.
--- arch/x86/kernel/fpu/init.c | 16 ++++------------ arch/x86/kernel/fpu/xstate.c | 8 ++++++++ 2 files changed, 12 insertions(+), 12 deletions(-)
arch/x86/kernel/fpu/init.c +4 -12
@@ -228,19 +228,11 @@ static void __init fpu__init_system_xstate_size_legacy(void) user_xstate_size = kernel_xstate_size;/* -* 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. ) +* Most recent CPUs supporting XSAVES can run 64-bit mode. +* Enable XSAVES for 64-bit. */ -setup_clear_cpu_cap (X86_FEATURE_XSAVES ); +if (!config_enabled (CONFIG_X86_64 )) +setup_clear_cpu_cap (X86_FEATURE_XSAVES ); }/*
arch/x86/kernel/fpu/xstate.c +8 -0
@@ -204,6 +204,14 @@ void fpu__init_cpu_xstate(void)if (!cpu_has_xsave || !xfeatures_mask)return ; +/* +* Make it clear that XSAVES supervisor states are not yet +* implemented should anyone expect it to work by changing +* bits in XFEATURE_MASK_* macros and XCR0. +*/ +WARN_ONCE ((xfeatures_mask &XFEATURE_MASK_SUPERVISOR ), +"x86/fpu: XSAVES supervisor states are not yet implemented.\n" ); +cr4_set_bits (X86_CR4_OSXSAVE );xsetbv (XCR_XFEATURE_ENABLED_MASK , xfeatures_mask); }
Signature · 1 line
1.9.1
Dave Hansen
maintainerRe: [PATCH v3 9/9] x86/xsaves: Re-enable XSAVES
Quoted 9 lines · Yu-cheng Yu
arch/x86/kernel/fpu/init.c +0
-8/* -* 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.
arch/x86/kernel/fpu/init.c static void __init fpu__init_system_xstate_size_legacy(void) · line 236
Quoted 10 lines
arch/x86/kernel/fpu/init.c +4
-4-* -* ( This is easy to backport while we are fixing -* XSAVES* support. ) +* Most recent CPUs supporting XSAVES can run 64-bit mode. +* Enable XSAVES for 64-bit. */ -setup_clear_cpu_cap (X86_FEATURE_XSAVES ); +if (!config_enabled (CONFIG_X86_64 )) +setup_clear_cpu_cap (X86_FEATURE_XSAVES ); }
I think we need a much better explanation of this for posterity. Why are we not supporting this now, and what would someone have to do in the future in order to enable it?
Quoted 10 lines
/*
arch/x86/kernel/fpu/xstate.c +1
-0@@ -204,6 +204,14 @@ void fpu__init_cpu_xstate(void)if (!cpu_has_xsave || !xfeatures_mask)return ; +/*
arch/x86/kernel/fpu/xstate.c void fpu__init_cpu_xstate(void) · line 217
Quoted 10 lines
arch/x86/kernel/fpu/xstate.c +7
-0+* Make it clear that XSAVES supervisor states are not yet +* implemented should anyone expect it to work by changing +* bits in XFEATURE_MASK_* macros and XCR0. +*/ +WARN_ONCE ((xfeatures_mask &XFEATURE_MASK_SUPERVISOR ), +"x86/fpu: XSAVES supervisor states are not yet implemented.\n" ); +cr4_set_bits (X86_CR4_OSXSAVE );xsetbv (XCR_XFEATURE_ENABLED_MASK , xfeatures_mask); }
Let's also do a:
xfeatures_mask &= ~XFEATURE_MASK_SUPERVISOR;
Otherwise, we have a broken system at the moment.
Re: [PATCH v3 9/9] x86/xsaves: Re-enable XSAVES
Quoted 16 lines · Dave Hansen
Quoted 15 lines · Yu-cheng Yu
arch/x86/kernel/fpu/init.c +2
-11/* -* 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. ) +* Most recent CPUs supporting XSAVES can run 64-bit mode. +* Enable XSAVES for 64-bit. */
Quoted 9 lines
arch/x86/kernel/fpu/init.c static void __init fpu__init_system_xstate_size_legacy(void) · line 236
Quoted 4 lines
arch/x86/kernel/fpu/init.c +2
-1-setup_clear_cpu_cap (X86_FEATURE_XSAVES ); +if (!config_enabled (CONFIG_X86_64 )) +setup_clear_cpu_cap (X86_FEATURE_XSAVES ); }I think we need a much better explanation of this for posterity. Why are we not supporting this now, and what would someone have to do in the future in order to enable it?
If anyone is using this newer feature, then that user is most likely using a 64-bit capable processor and a 64-bit kernel. The intention here is to take out the complexity and any potential of error. If the user removes the restriction and builds a private kernel, it should work but we have not checked all possible combinations. I will put these in the comments.
Quoted 23 lines
Quoted 10 lines
/*
arch/x86/kernel/fpu/xstate.c +1
-0@@ -204,6 +204,14 @@ void fpu__init_cpu_xstate(void)if (!cpu_has_xsave || !xfeatures_mask)return ; +/* arch/x86/kernel/fpu/xstate.c void fpu__init_cpu_xstate(void) · line 217
Quoted 10 lines
arch/x86/kernel/fpu/xstate.c +7
-0+* Make it clear that XSAVES supervisor states are not yet +* implemented should anyone expect it to work by changing +* bits in XFEATURE_MASK_* macros and XCR0. +*/ +WARN_ONCE ((xfeatures_mask &XFEATURE_MASK_SUPERVISOR ), +"x86/fpu: XSAVES supervisor states are not yet implemented.\n" ); +cr4_set_bits (X86_CR4_OSXSAVE );xsetbv (XCR_XFEATURE_ENABLED_MASK , xfeatures_mask); }Let's also do a:
Quoted 4 lines
xfeatures_mask &= ~XFEATURE_MASK_SUPERVISOR;Otherwise, we have a broken system at the moment.
Currently, if anyone sets any supervisor state in xfeatures_mask, the kernel prints out the warning then goes into a protection fault. That is a very strong indication to the user. Do we want to mute it?
Yu-cheng
Dave Hansen
maintainerRe: [PATCH v3 9/9] x86/xsaves: Re-enable XSAVES
Quoted 11 lines · Yu-cheng Yu
Quoted 10 lines · Dave Hansen
arch/x86/kernel/fpu/init.c static void __init fpu__init_system_xstate_size_legacy(void) · line 236
Quoted 4 lines · Yu-cheng Yu
arch/x86/kernel/fpu/init.c +2
-1-setup_clear_cpu_cap (X86_FEATURE_XSAVES ); +if (!config_enabled (CONFIG_X86_64 )) +setup_clear_cpu_cap (X86_FEATURE_XSAVES ); }I think we need a much better explanation of this for posterity. Why are we not supporting this now, and what would someone have to do in the future in order to enable it?
Quoted 5 lines
If anyone is using this newer feature, then that user is most likely using a 64-bit capable processor and a 64-bit kernel. The intention here is to take out the complexity and any potential of error. If the user removes the restriction and builds a private kernel, it should work but we have not checked all possible combinations. I will put these in the comments.
A user can go download a 32-bit version of Ubuntu or Debian and install it on a 64-bit processor today. It's a very easy mistake to make when downloading the install CD.
In any case, I don't have a _problem_ with leaving i386 in the dust here. I just want us to be very explicit about what we are doing.
Quoted 14 lines
Quoted 14 lines
arch/x86/kernel/fpu/xstate.c void fpu__init_cpu_xstate(void) · line 217
Quoted 11 lines
arch/x86/kernel/fpu/xstate.c +8
-0+/* +* Make it clear that XSAVES supervisor states are not yet +* implemented should anyone expect it to work by changing +* bits in XFEATURE_MASK_* macros and XCR0. +*/ +WARN_ONCE ((xfeatures_mask &XFEATURE_MASK_SUPERVISOR ), +"x86/fpu: XSAVES supervisor states are not yet implemented.\n" ); +cr4_set_bits (X86_CR4_OSXSAVE );xsetbv (XCR_XFEATURE_ENABLED_MASK , xfeatures_mask); }Let's also do a:
Quoted 7 lines
Quoted 4 lines
xfeatures_mask &= ~XFEATURE_MASK_SUPERVISOR;Otherwise, we have a broken system at the moment.
Currently, if anyone sets any supervisor state in
xfeatures_mask, the kernel prints out the warning then goes into a protection fault. That is a very strong indication to the user. Do we want to mute it?
By "goes into a protection fault", do you mean that it doesn't boot?
I'd just rather we put the kernel in a known-safe configuration (masking supervisor state out of xfeatures_mask) rather than rely on the general protection fault continuing to be generated by whatever is generating it.
Re: [PATCH v3 9/9] x86/xsaves: Re-enable XSAVES
Quoted 17 lines · Dave Hansen
Quoted 9 lines
Quoted 9 lines
arch/x86/kernel/fpu/xstate.c void fpu__init_cpu_xstate(void) · line 217
Quoted 6 lines
arch/x86/kernel/fpu/xstate.c +3
-0+WARN_ONCE ((xfeatures_mask &XFEATURE_MASK_SUPERVISOR ), +"x86/fpu: XSAVES supervisor states are not yet implemented.\n" ); +cr4_set_bits (X86_CR4_OSXSAVE );xsetbv (XCR_XFEATURE_ENABLED_MASK , xfeatures_mask); }Let's also do a:
Quoted 7 lines
Quoted 4 lines
xfeatures_mask &= ~XFEATURE_MASK_SUPERVISOR;Otherwise, we have a broken system at the moment.
Currently, if anyone sets any supervisor state in
xfeatures_mask, the kernel prints out the warning then goes into a protection fault. That is a very strong indication to the user. Do we want to mute it?
Quoted 6 lines
By "goes into a protection fault", do you mean that it doesn't boot?
I'd just rather we put the kernel in a known-safe configuration (masking supervisor state out of
xfeatures_mask) rather than rely on the general protection fault continuing to be generated by whatever is generating it.
Ok.
Yu-cheng
H. Peter Anvin
reviewerRe: [PATCH v3 9/9] x86/xsaves: Re-enable XSAVES
In reply to Dave HansenQuoted 54 lines · Dave Hansen
Quoted 8 lines · Yu-cheng Yu
Quoted 7 lines · Dave Hansen
arch/x86/kernel/fpu/init.c static void __init fpu__init_system_xstate_size_legacy(void) · line 236
Quoted 4 lines · Yu-cheng Yu
arch/x86/kernel/fpu/init.c +2
-1-setup_clear_cpu_cap (X86_FEATURE_XSAVES ); +if (!config_enabled (CONFIG_X86_64 )) +setup_clear_cpu_cap (X86_FEATURE_XSAVES ); }I think we need a much better explanation of this for posterity.
Why
Quoted 1 line
Quoted 1 line
are we not supporting this now, and what would someone have to do in
the
Quoted 3 lines
Quoted 2 lines
future in order to enable it?
If anyone is using this newer feature, then that user is most likely
using
Quoted 1 line
a 64-bit capable processor and a 64-bit kernel. The intention here is
to
Quoted 1 line
take out the complexity and any potential of error. If the user
removes
Quoted 1 line
the restriction and builds a private kernel, it should work but we
have
Quoted 1 line
not checked all possible combinations. I will put these in the
comments.
A user can go download a 32-bit version of Ubuntu or Debian and install it on a 64-bit processor today. It's a very easy mistake to make when downloading the install CD.
In any case, I don't have a _problem_ with leaving i386 in the dust here. I just want us to be very explicit about what we are doing.
Quoted 14 lines
Quoted 14 lines
arch/x86/kernel/fpu/xstate.c void fpu__init_cpu_xstate(void) · line 217
Quoted 11 lines
arch/x86/kernel/fpu/xstate.c +8
-0+/* +* Make it clear that XSAVES supervisor states are not yet +* implemented should anyone expect it to work by changing +* bits in XFEATURE_MASK_* macros and XCR0. +*/ +WARN_ONCE ((xfeatures_mask &XFEATURE_MASK_SUPERVISOR ), +"x86/fpu: XSAVES supervisor states are not yet implemented.\n" ); +cr4_set_bits (X86_CR4_OSXSAVE );xsetbv (XCR_XFEATURE_ENABLED_MASK , xfeatures_mask); }Let's also do a:
Quoted 7 lines
Quoted 4 lines
xfeatures_mask &= ~XFEATURE_MASK_SUPERVISOR;Otherwise, we have a broken system at the moment.
Currently, if anyone sets any supervisor state in
xfeatures_mask, the kernel prints out the warning then goes into a protection fault. That is a very strong indication to the user. Do we want to mute it?
Quoted 7 lines
By "goes into a protection fault", do you mean that it doesn't boot?
I'd just rather we put the kernel in a known-safe configuration (masking
supervisor state out ofxfeatures_mask) rather than rely on the general protection fault continuing to be generated by whatever is generating it.
Differences between i386 and x86-64 generally add problems, so unless this requires significant 32-bit-specific code we should not exclude i386 just because.
Signature · 1 line
Sent from my Android device with K-9 Mail. Please excuse brevity and formatting.
Re: [PATCH v3 9/9] x86/xsaves: Re-enable XSAVES
Quoted 1 line · H. Peter Anvin
Differences between i386 and x86-64 generally add problems, so unless this requires significant 32-bit-specific code we should not exclude i386 just because.
I have not seen any issues with 32-bit code, but will do some tests. Thanks.
Yu-cheng