* [PATCH 0/3] Fix small issues in XSAVES @ 2019-12-05 18:26 Yu-cheng Yu 2019-12-05 18:26 ` [PATCH 1/3] x86/fpu/xstate: Fix small issues before adding supervisor xstates Yu-cheng Yu ` (2 more replies) 0 siblings, 3 replies; 5+ messages in thread From: Yu-cheng Yu @ 2019-12-05 18:26 UTC (permalink / raw) To: linux-kernel, x86, H. Peter Anvin, Thomas Gleixner, Ingo Molnar, Dave Hansen, Tony Luck, Andy Lutomirski, Borislav Petkov, Rik van Riel, Ravi V. Shankar, Sebastian Andrzej Siewior, Fenghua Yu, Peter Zijlstra Cc: Yu-cheng Yu The first two patches in this series are split from my supervisor xstate patches [1]. The third is to fix a vital issue in __fpu_restore_sig(), and more RFC than the others. All three are not directly related to supervisor xstates or CET, split them out and submit first. I will re-submit supervisor xstate patches shortly. When__fpu_restore_sig() fails, partially cleared FPU registers still belong to the previous owner task. That causes that task to use corrupted xregs. Fix it by doing __cpu_invalidate_fpregs_state() in functions that copy into fpregs. Further details are in the commit log of patch #3. [1] Support XSAVES supervisor states https://lkml.kernel.org/r/20190925151022.21688-1-yu-cheng.yu@intel.com/ [2] CET patches: https://lkml.kernel.org/r/20190813205225.12032-1-yu-cheng.yu@intel.com/ https://lkml.kernel.org/r/20190813205359.12196-1-yu-cheng.yu@intel.com/ Yu-cheng Yu (3): x86/fpu/xstate: Fix small issues before adding supervisor xstates x86/fpu/xstate: Make xfeature_is_supervisor()/xfeature_is_user() return bool x86/fpu/xstate: Invalidate fpregs when __fpu_restore_sig() fails arch/x86/include/asm/fpu/internal.h | 14 ++++++++++++++ arch/x86/kernel/fpu/core.c | 15 +++++++++++++-- arch/x86/kernel/fpu/xstate.c | 22 ++++++++++------------ 3 files changed, 37 insertions(+), 14 deletions(-) -- 2.17.1 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/3] x86/fpu/xstate: Fix small issues before adding supervisor xstates 2019-12-05 18:26 [PATCH 0/3] Fix small issues in XSAVES Yu-cheng Yu @ 2019-12-05 18:26 ` Yu-cheng Yu 2019-12-05 18:26 ` [PATCH 2/3] x86/fpu/xstate: Make xfeature_is_supervisor()/xfeature_is_user() return bool Yu-cheng Yu 2019-12-05 18:26 ` [PATCH 3/3] x86/fpu/xstate: Invalidate fpregs when __fpu_restore_sig() fails Yu-cheng Yu 2 siblings, 0 replies; 5+ messages in thread From: Yu-cheng Yu @ 2019-12-05 18:26 UTC (permalink / raw) To: linux-kernel, x86, H. Peter Anvin, Thomas Gleixner, Ingo Molnar, Dave Hansen, Tony Luck, Andy Lutomirski, Borislav Petkov, Rik van Riel, Ravi V. Shankar, Sebastian Andrzej Siewior, Fenghua Yu, Peter Zijlstra Cc: Yu-cheng Yu In response to earlier comments, fix small issues before introducing XSAVES supervisor states: - Add spaces around '*'. - Fix comments of xfeature_is_supervisor(). - Replace ((u64)1 << 63) with XCOMP_BV_COMPACTED_FORMAT. No functional changes from this patch. Signed-off-by: Yu-cheng Yu <yu-cheng.yu@intel.com> Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com> Reviewed-by: Tony Luck <tony.luck@intel.com> --- arch/x86/kernel/fpu/xstate.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c index e5cb67d67c03..cfcac7b42e5e 100644 --- a/arch/x86/kernel/fpu/xstate.c +++ b/arch/x86/kernel/fpu/xstate.c @@ -60,7 +60,7 @@ u64 xfeatures_mask __read_mostly; static unsigned int xstate_offsets[XFEATURE_MAX] = { [ 0 ... XFEATURE_MAX - 1] = -1}; static unsigned int xstate_sizes[XFEATURE_MAX] = { [ 0 ... XFEATURE_MAX - 1] = -1}; -static unsigned int xstate_comp_offsets[sizeof(xfeatures_mask)*8]; +static unsigned int xstate_comp_offsets[sizeof(xfeatures_mask) * 8]; /* * The XSAVE area of kernel can be in standard or compacted format; @@ -110,12 +110,9 @@ EXPORT_SYMBOL_GPL(cpu_has_xfeatures); static int xfeature_is_supervisor(int xfeature_nr) { /* - * We currently do not support supervisor states, but if - * we did, we could find out like this. - * - * SDM says: If state component 'i' is a user state component, - * ECX[0] return 0; if state component i is a supervisor - * state component, ECX[0] returns 1. + * Extended State Enumeration Sub-leaves (EAX = 0DH, ECX = n, n > 1) + * returns ECX[0] set to (1) for a supervisor state, and cleared (0) + * for a user state. */ u32 eax, ebx, ecx, edx; @@ -342,7 +339,7 @@ static int xfeature_is_aligned(int xfeature_nr) */ static void __init setup_xstate_comp(void) { - unsigned int xstate_comp_sizes[sizeof(xfeatures_mask)*8]; + unsigned int xstate_comp_sizes[sizeof(xfeatures_mask) * 8]; int i; /* @@ -415,7 +412,8 @@ static void __init setup_init_fpu_buf(void) print_xstate_features(); if (boot_cpu_has(X86_FEATURE_XSAVES)) - init_fpstate.xsave.header.xcomp_bv = (u64)1 << 63 | xfeatures_mask; + init_fpstate.xsave.header.xcomp_bv = XCOMP_BV_COMPACTED_FORMAT | + xfeatures_mask; /* * Init all the features state with header.xfeatures being 0x0 -- 2.17.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/3] x86/fpu/xstate: Make xfeature_is_supervisor()/xfeature_is_user() return bool 2019-12-05 18:26 [PATCH 0/3] Fix small issues in XSAVES Yu-cheng Yu 2019-12-05 18:26 ` [PATCH 1/3] x86/fpu/xstate: Fix small issues before adding supervisor xstates Yu-cheng Yu @ 2019-12-05 18:26 ` Yu-cheng Yu 2019-12-05 18:26 ` [PATCH 3/3] x86/fpu/xstate: Invalidate fpregs when __fpu_restore_sig() fails Yu-cheng Yu 2 siblings, 0 replies; 5+ messages in thread From: Yu-cheng Yu @ 2019-12-05 18:26 UTC (permalink / raw) To: linux-kernel, x86, H. Peter Anvin, Thomas Gleixner, Ingo Molnar, Dave Hansen, Tony Luck, Andy Lutomirski, Borislav Petkov, Rik van Riel, Ravi V. Shankar, Sebastian Andrzej Siewior, Fenghua Yu, Peter Zijlstra Cc: Yu-cheng Yu In the previous patch, xfeature_is_supervisor()'s description is revised, and since xfeature_is_supervisor()/xfeature_is_user() are used only in boolean context, make both return bool. Suggested-by: Borislav Petkov <bp@suse.de> Signed-off-by: Yu-cheng Yu <yu-cheng.yu@intel.com> --- arch/x86/kernel/fpu/xstate.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c index cfcac7b42e5e..912bdfce10dd 100644 --- a/arch/x86/kernel/fpu/xstate.c +++ b/arch/x86/kernel/fpu/xstate.c @@ -107,7 +107,7 @@ int cpu_has_xfeatures(u64 xfeatures_needed, const char **feature_name) } EXPORT_SYMBOL_GPL(cpu_has_xfeatures); -static int xfeature_is_supervisor(int xfeature_nr) +static bool xfeature_is_supervisor(int xfeature_nr) { /* * Extended State Enumeration Sub-leaves (EAX = 0DH, ECX = n, n > 1) @@ -117,10 +117,10 @@ static int xfeature_is_supervisor(int xfeature_nr) u32 eax, ebx, ecx, edx; cpuid_count(XSTATE_CPUID, xfeature_nr, &eax, &ebx, &ecx, &edx); - return !!(ecx & 1); + return ecx & 1; } -static int xfeature_is_user(int xfeature_nr) +static bool xfeature_is_user(int xfeature_nr) { return !xfeature_is_supervisor(xfeature_nr); } -- 2.17.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 3/3] x86/fpu/xstate: Invalidate fpregs when __fpu_restore_sig() fails 2019-12-05 18:26 [PATCH 0/3] Fix small issues in XSAVES Yu-cheng Yu 2019-12-05 18:26 ` [PATCH 1/3] x86/fpu/xstate: Fix small issues before adding supervisor xstates Yu-cheng Yu 2019-12-05 18:26 ` [PATCH 2/3] x86/fpu/xstate: Make xfeature_is_supervisor()/xfeature_is_user() return bool Yu-cheng Yu @ 2019-12-05 18:26 ` Yu-cheng Yu 2019-12-07 4:38 ` [PATCH v2 " Yu-cheng Yu 2 siblings, 1 reply; 5+ messages in thread From: Yu-cheng Yu @ 2019-12-05 18:26 UTC (permalink / raw) To: linux-kernel, x86, H. Peter Anvin, Thomas Gleixner, Ingo Molnar, Dave Hansen, Tony Luck, Andy Lutomirski, Borislav Petkov, Rik van Riel, Ravi V. Shankar, Sebastian Andrzej Siewior, Fenghua Yu, Peter Zijlstra Cc: Yu-cheng Yu In __fpu_restore_sig(),'init_fpstate.xsave' and part of 'fpu->state.xsave' are restored separately to xregs. However, as stated in __cpu_invalidate_ fpregs_state(), Any code that clobbers the FPU registers or updates the in-memory FPU state for a task MUST let the rest of the kernel know that the FPU registers are no longer valid for this task. and this code violates that rule. Should the restoration fail, the other task's context is corrupted. This problem does not occur very often because copy_*_to_xregs() succeeds most of the time. It occurs, for instance, in copy_user_to_fpregs_ zeroing() when the first half of the restoration succeeds and the other half fails. This can be triggered by running glibc tests, where a non- present user stack page causes the XRSTOR to fail. The introduction of supervisor xstates and CET, while not contributing to the problem, makes it more detectable. After init_fpstate and the Shadow Stack pointer have been restored to xregs, the XRSTOR from user stack fails and fpu_fpregs_owner_ctx is not updated. The task currently owning fpregs then uses the corrupted Shadow Stack pointer and triggers a control- protection fault. Fix it by adding __cpu_invalidate_fpregs_state() to functions that copy fpstate to fpregs: copy_*_to_xregs_*(), copy_*_to_fxregs_*(), and copy_*_to_fregs_*(). The alternative is to hit all of the call sites themselves. The function __cpu_invalidate_fpregs_state() is chosen over fpregs_ deactivate() as it is called under fpregs_lock() protection. In addition to sigreturn, also checked all call sites of these functions: - copy_init_fpstate_to_fpregs(); - copy_kernel_to_fpregs(); - ex_handler_fprestore(); - fpu__save(); and - fpu__copy(). In fpu__save() and fpu__copy(), fpregs are re-activated because they are considered valid in both cases. Signed-off-by: Yu-cheng Yu <yu-cheng.yu@intel.com> Acked-by: Dave Hansen <dave.hansen@linux.intel.com> --- arch/x86/include/asm/fpu/internal.h | 14 ++++++++++++++ arch/x86/kernel/fpu/core.c | 15 +++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h index 4c95c365058a..cd380d14e4e2 100644 --- a/arch/x86/include/asm/fpu/internal.h +++ b/arch/x86/include/asm/fpu/internal.h @@ -142,6 +142,8 @@ extern void fpstate_sanitize_xstate(struct fpu *fpu); _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_fprestore) \ : output : input) +static inline void __cpu_invalidate_fpregs_state(void); + static inline int copy_fregs_to_user(struct fregs_state __user *fx) { return user_insn(fnsave %[fx]; fwait, [fx] "=m" (*fx), "m" (*fx)); @@ -158,6 +160,8 @@ static inline int copy_fxregs_to_user(struct fxregs_state __user *fx) static inline void copy_kernel_to_fxregs(struct fxregs_state *fx) { + __cpu_invalidate_fpregs_state(); + if (IS_ENABLED(CONFIG_X86_32)) kernel_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx)); else @@ -166,6 +170,8 @@ static inline void copy_kernel_to_fxregs(struct fxregs_state *fx) static inline int copy_kernel_to_fxregs_err(struct fxregs_state *fx) { + __cpu_invalidate_fpregs_state(); + if (IS_ENABLED(CONFIG_X86_32)) return kernel_insn_err(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx)); else @@ -174,6 +180,8 @@ static inline int copy_kernel_to_fxregs_err(struct fxregs_state *fx) static inline int copy_user_to_fxregs(struct fxregs_state __user *fx) { + __cpu_invalidate_fpregs_state(); + if (IS_ENABLED(CONFIG_X86_32)) return user_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx)); else @@ -182,16 +190,19 @@ static inline int copy_user_to_fxregs(struct fxregs_state __user *fx) static inline void copy_kernel_to_fregs(struct fregs_state *fx) { + __cpu_invalidate_fpregs_state(); kernel_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx)); } static inline int copy_kernel_to_fregs_err(struct fregs_state *fx) { + __cpu_invalidate_fpregs_state(); return kernel_insn_err(frstor %[fx], "=m" (*fx), [fx] "m" (*fx)); } static inline int copy_user_to_fregs(struct fregs_state __user *fx) { + __cpu_invalidate_fpregs_state(); return user_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx)); } @@ -340,6 +351,7 @@ static inline void copy_kernel_to_xregs(struct xregs_state *xstate, u64 mask) u32 lmask = mask; u32 hmask = mask >> 32; + __cpu_invalidate_fpregs_state(); XSTATE_XRESTORE(xstate, lmask, hmask); } @@ -382,6 +394,7 @@ static inline int copy_user_to_xregs(struct xregs_state __user *buf, u64 mask) u32 hmask = mask >> 32; int err; + __cpu_invalidate_fpregs_state(); stac(); XSTATE_OP(XRSTOR, xstate, lmask, hmask, err); clac(); @@ -399,6 +412,7 @@ static inline int copy_kernel_to_xregs_err(struct xregs_state *xstate, u64 mask) u32 hmask = mask >> 32; int err; + __cpu_invalidate_fpregs_state(); XSTATE_OP(XRSTOR, xstate, lmask, hmask, err); return err; diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c index 12c70840980e..743ff5ea4076 100644 --- a/arch/x86/kernel/fpu/core.c +++ b/arch/x86/kernel/fpu/core.c @@ -127,7 +127,12 @@ void fpu__save(struct fpu *fpu) if (!test_thread_flag(TIF_NEED_FPU_LOAD)) { if (!copy_fpregs_to_fpstate(fpu)) { + /* + * copy_kernel_to_fpregs deactivates fpregs; + * re-activate fpregs after that. + */ copy_kernel_to_fpregs(&fpu->state); + fpregs_activate(fpu); } } @@ -191,11 +196,17 @@ int fpu__copy(struct task_struct *dst, struct task_struct *src) * register contents so we have to load them back. ) */ fpregs_lock(); - if (test_thread_flag(TIF_NEED_FPU_LOAD)) + if (test_thread_flag(TIF_NEED_FPU_LOAD)) { memcpy(&dst_fpu->state, &src_fpu->state, fpu_kernel_xstate_size); - else if (!copy_fpregs_to_fpstate(dst_fpu)) + } else if (!copy_fpregs_to_fpstate(dst_fpu)) { + /* + * copy_kernel_to_fpregs deactivates fpregs; + * re-activate fpregs after that. + */ copy_kernel_to_fpregs(&dst_fpu->state); + fpregs_activate(src_fpu); + } fpregs_unlock(); -- 2.17.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 3/3] x86/fpu/xstate: Invalidate fpregs when __fpu_restore_sig() fails 2019-12-05 18:26 ` [PATCH 3/3] x86/fpu/xstate: Invalidate fpregs when __fpu_restore_sig() fails Yu-cheng Yu @ 2019-12-07 4:38 ` Yu-cheng Yu 0 siblings, 0 replies; 5+ messages in thread From: Yu-cheng Yu @ 2019-12-07 4:38 UTC (permalink / raw) To: linux-kernel, x86, H. Peter Anvin, Thomas Gleixner, Ingo Molnar, Dave Hansen, Tony Luck, Andy Lutomirski, Borislav Petkov, Rik van Riel, Ravi V. Shankar, Sebastian Andrzej Siewior, Fenghua Yu, Peter Zijlstra Cc: Yu-cheng Yu In __fpu_restore_sig(),'init_fpstate.xsave' and part of 'fpu->state.xsave' are restored separately to xregs. However, as stated in __cpu_invalidate_ fpregs_state(), Any code that clobbers the FPU registers or updates the in-memory FPU state for a task MUST let the rest of the kernel know that the FPU registers are no longer valid for this task. and this code violates that rule. Should the restoration fail, the other task's context is corrupted. This problem does not occur very often because copy_*_to_xregs() succeeds most of the time. It occurs, for instance, in copy_user_to_fpregs_ zeroing() when the first half of the restoration succeeds and the other half fails. This can be triggered by running glibc tests, where a non- present user stack page causes the XRSTOR to fail. The introduction of supervisor xstates and CET, while not contributing to the problem, makes it more detectable. After init_fpstate and the Shadow Stack pointer have been restored to xregs, the XRSTOR from user stack fails and fpu_fpregs_owner_ctx is not updated. The task currently owning fpregs then uses the corrupted Shadow Stack pointer and triggers a control- protection fault. Fix it by adding __cpu_invalidate_fpregs_state() to functions that copy fpstate to fpregs: copy_*_to_xregs_*(), copy_*_to_fxregs_*(), and copy_*_to_fregs_*(). The alternative is to hit all of the call sites themselves. The function __cpu_invalidate_fpregs_state() is chosen over fpregs_ deactivate() as it is called under fpregs_lock() protection. In addition to sigreturn, also checked all call sites of these functions: - copy_init_fpstate_to_fpregs(); - copy_kernel_to_fpregs(); - ex_handler_fprestore(); - fpu__save(); and - fpu__copy(). In fpu__save() and fpu__copy(), fpregs are re-activated because they are considered valid in both cases. v2: Add the missing EXPORT_SYMBOL_GPL(fpu_fpregs_owner_ctx). Signed-off-by: Yu-cheng Yu <yu-cheng.yu@intel.com> Acked-by: Dave Hansen <dave.hansen@linux.intel.com> --- arch/x86/include/asm/fpu/internal.h | 14 ++++++++++++++ arch/x86/kernel/fpu/core.c | 16 ++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h index 4c95c365058a..cd380d14e4e2 100644 --- a/arch/x86/include/asm/fpu/internal.h +++ b/arch/x86/include/asm/fpu/internal.h @@ -142,6 +142,8 @@ extern void fpstate_sanitize_xstate(struct fpu *fpu); _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_fprestore) \ : output : input) +static inline void __cpu_invalidate_fpregs_state(void); + static inline int copy_fregs_to_user(struct fregs_state __user *fx) { return user_insn(fnsave %[fx]; fwait, [fx] "=m" (*fx), "m" (*fx)); @@ -158,6 +160,8 @@ static inline int copy_fxregs_to_user(struct fxregs_state __user *fx) static inline void copy_kernel_to_fxregs(struct fxregs_state *fx) { + __cpu_invalidate_fpregs_state(); + if (IS_ENABLED(CONFIG_X86_32)) kernel_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx)); else @@ -166,6 +170,8 @@ static inline void copy_kernel_to_fxregs(struct fxregs_state *fx) static inline int copy_kernel_to_fxregs_err(struct fxregs_state *fx) { + __cpu_invalidate_fpregs_state(); + if (IS_ENABLED(CONFIG_X86_32)) return kernel_insn_err(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx)); else @@ -174,6 +180,8 @@ static inline int copy_kernel_to_fxregs_err(struct fxregs_state *fx) static inline int copy_user_to_fxregs(struct fxregs_state __user *fx) { + __cpu_invalidate_fpregs_state(); + if (IS_ENABLED(CONFIG_X86_32)) return user_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx)); else @@ -182,16 +190,19 @@ static inline int copy_user_to_fxregs(struct fxregs_state __user *fx) static inline void copy_kernel_to_fregs(struct fregs_state *fx) { + __cpu_invalidate_fpregs_state(); kernel_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx)); } static inline int copy_kernel_to_fregs_err(struct fregs_state *fx) { + __cpu_invalidate_fpregs_state(); return kernel_insn_err(frstor %[fx], "=m" (*fx), [fx] "m" (*fx)); } static inline int copy_user_to_fregs(struct fregs_state __user *fx) { + __cpu_invalidate_fpregs_state(); return user_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx)); } @@ -340,6 +351,7 @@ static inline void copy_kernel_to_xregs(struct xregs_state *xstate, u64 mask) u32 lmask = mask; u32 hmask = mask >> 32; + __cpu_invalidate_fpregs_state(); XSTATE_XRESTORE(xstate, lmask, hmask); } @@ -382,6 +394,7 @@ static inline int copy_user_to_xregs(struct xregs_state __user *buf, u64 mask) u32 hmask = mask >> 32; int err; + __cpu_invalidate_fpregs_state(); stac(); XSTATE_OP(XRSTOR, xstate, lmask, hmask, err); clac(); @@ -399,6 +412,7 @@ static inline int copy_kernel_to_xregs_err(struct xregs_state *xstate, u64 mask) u32 hmask = mask >> 32; int err; + __cpu_invalidate_fpregs_state(); XSTATE_OP(XRSTOR, xstate, lmask, hmask, err); return err; diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c index 12c70840980e..4e5151e43a2c 100644 --- a/arch/x86/kernel/fpu/core.c +++ b/arch/x86/kernel/fpu/core.c @@ -42,6 +42,7 @@ static DEFINE_PER_CPU(bool, in_kernel_fpu); * Track which context is using the FPU on the CPU: */ DEFINE_PER_CPU(struct fpu *, fpu_fpregs_owner_ctx); +EXPORT_SYMBOL_GPL(fpu_fpregs_owner_ctx); static bool kernel_fpu_disabled(void) { @@ -127,7 +128,12 @@ void fpu__save(struct fpu *fpu) if (!test_thread_flag(TIF_NEED_FPU_LOAD)) { if (!copy_fpregs_to_fpstate(fpu)) { + /* + * copy_kernel_to_fpregs deactivates fpregs; + * re-activate fpregs after that. + */ copy_kernel_to_fpregs(&fpu->state); + fpregs_activate(fpu); } } @@ -191,11 +197,17 @@ int fpu__copy(struct task_struct *dst, struct task_struct *src) * register contents so we have to load them back. ) */ fpregs_lock(); - if (test_thread_flag(TIF_NEED_FPU_LOAD)) + if (test_thread_flag(TIF_NEED_FPU_LOAD)) { memcpy(&dst_fpu->state, &src_fpu->state, fpu_kernel_xstate_size); - else if (!copy_fpregs_to_fpstate(dst_fpu)) + } else if (!copy_fpregs_to_fpstate(dst_fpu)) { + /* + * copy_kernel_to_fpregs deactivates fpregs; + * re-activate fpregs after that. + */ copy_kernel_to_fpregs(&dst_fpu->state); + fpregs_activate(src_fpu); + } fpregs_unlock(); -- 2.17.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2019-12-07 4:50 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2019-12-05 18:26 [PATCH 0/3] Fix small issues in XSAVES Yu-cheng Yu 2019-12-05 18:26 ` [PATCH 1/3] x86/fpu/xstate: Fix small issues before adding supervisor xstates Yu-cheng Yu 2019-12-05 18:26 ` [PATCH 2/3] x86/fpu/xstate: Make xfeature_is_supervisor()/xfeature_is_user() return bool Yu-cheng Yu 2019-12-05 18:26 ` [PATCH 3/3] x86/fpu/xstate: Invalidate fpregs when __fpu_restore_sig() fails Yu-cheng Yu 2019-12-07 4:38 ` [PATCH v2 " Yu-cheng Yu
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).