Subject: x86/fpu: use fnsave when fxsave is not available kernel-2.6.32-754.3.5.el6 uses fxsave opcode unconditionally, which causes swapper panic on early boot on i586. Fix to use fnsave when use_fxsr() is false. Upstream kernel.org code uses union init_fpstate.fsave to reset fpu statn in drop_init_fpu() (fpu__clear() in kernel.org 4.4 code), but linux-2.6.32-754.3.5.el6 only has struct xsave_struct *init_xstate_buf; so this patch adds and initializes struct fpu init_fpstate_fsave_buf; explicitly for frstor resetting. Only init_fpstate_fsave_buf.state->fsave is used, but to initialize it using fpu_finit(), whole struct fpu is declared. diff -up ./arch/x86/include/asm/fpu-internal.h.fxsave ./arch/x86/include/asm/fpu-internal.h --- ./arch/x86/include/asm/fpu-internal.h.fxsave 2018-08-10 00:39:20.000000000 +0900 +++ ./arch/x86/include/asm/fpu-internal.h 2018-09-13 21:36:57.000000000 +0900 @@ -325,8 +325,10 @@ static inline void restore_init_xstate(v { if (use_xsave()) xrstor_state(init_xstate_buf, -1); - else + else if (use_fxsr()) fxrstor_checking(&init_xstate_buf->i387); + else + frstor_checking(&init_fpstate_fsave_buf.state->fsave); } /* @@ -463,8 +465,11 @@ static inline void __save_fpu(struct tas { if (use_xsave()) xsave_state(&tsk->thread.xstate->xsave, -1); - else + else if (use_fxsr()) fpu_fxsave((struct fpu *)&tsk->thread.xstate); + else + asm volatile("fnsave %[fx]; fwait" + : [fx] "=m" (tsk->thread.xstate->fsave)); } /* diff -up ./arch/x86/include/asm/xsave.h.fxsave ./arch/x86/include/asm/xsave.h --- ./arch/x86/include/asm/xsave.h.fxsave 2018-08-10 00:39:20.000000000 +0900 +++ ./arch/x86/include/asm/xsave.h 2018-09-13 21:43:08.000000000 +0900 @@ -42,6 +42,7 @@ extern unsigned int xstate_size; extern u64 pcntxt_mask; extern u64 xstate_fx_sw_bytes[USER_XSTATE_FX_SW_WORDS]; extern struct xsave_struct *init_xstate_buf; +extern struct fpu init_fpstate_fsave_buf; extern void xsave_init(void); extern void update_regset_xstate_info(unsigned int size, u64 xstate_mask); diff -up ./arch/x86/kernel/xsave.c.fxsave ./arch/x86/kernel/xsave.c --- ./arch/x86/kernel/xsave.c.fxsave 2018-08-10 00:39:20.000000000 +0900 +++ ./arch/x86/kernel/xsave.c 2018-09-13 22:18:55.000000000 +0900 @@ -22,6 +22,7 @@ u64 pcntxt_mask; * Represents init state for the supported extended state. */ struct xsave_struct *init_xstate_buf; +struct fpu init_fpstate_fsave_buf; static struct _fpx_sw_bytes fx_sw_reserved, fx_sw_reserved_ia32; static unsigned int *xstate_offsets, *xstate_sizes, xstate_features; @@ -489,6 +490,11 @@ static void __init setup_init_fpu_buf(vo __alignof__(struct xsave_struct)); fx_finit(&init_xstate_buf->i387); + /* Setup init_fpstate.fsave */ + init_fpstate_fsave_buf.state = alloc_bootmem_align(sizeof(union thread_xstate), + __alignof__(union thread_xstate)); + fpu_finit(&init_fpstate_fsave_buf); + if (!cpu_has_xsave) return; @@ -627,6 +633,8 @@ void __cpuinit eager_fpu_init(void) __thread_fpu_begin(current); if (cpu_has_xsave) xrstor_state(init_xstate_buf, -1); - else + else if (cpu_has_fxsr) fxrstor_checking(&init_xstate_buf->i387); + else + frstor_checking(&init_fpstate_fsave_buf.state->fsave); }