summaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r--arch/x86/kernel/fpu/context.h6
-rw-r--r--arch/x86/kernel/fpu/core.c17
-rw-r--r--arch/x86/kernel/fpu/xstate.c2
3 files changed, 16 insertions, 9 deletions
diff --git a/arch/x86/kernel/fpu/context.h b/arch/x86/kernel/fpu/context.h
index f8f510519688..a06ebf315d83 100644
--- a/arch/x86/kernel/fpu/context.h
+++ b/arch/x86/kernel/fpu/context.h
@@ -61,8 +61,6 @@ static inline void fpregs_restore_userregs(void)
return;
if (!fpregs_state_valid(fpu, cpu)) {
- u64 mask;
-
/*
* This restores _all_ xstate which has not been
* established yet.
@@ -72,9 +70,7 @@ static inline void fpregs_restore_userregs(void)
* flush_thread(). So it is excluded because it might be
* not up to date in current->thread.fpu.xsave state.
*/
- mask = xfeatures_mask_restore_user() |
- xfeatures_mask_supervisor();
- restore_fpregs_from_fpstate(fpu->fpstate, mask);
+ restore_fpregs_from_fpstate(fpu->fpstate, XFEATURE_MASK_FPSTATE);
fpregs_activate(fpu);
fpu->last_cpu = cpu;
diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
index 5acc077cb9f1..0fb9defaba47 100644
--- a/arch/x86/kernel/fpu/core.c
+++ b/arch/x86/kernel/fpu/core.c
@@ -150,6 +150,17 @@ void restore_fpregs_from_fpstate(struct fpstate *fpstate, u64 mask)
}
if (use_xsave()) {
+ /*
+ * Restoring state always needs to modify all features
+ * which are in @mask even if the current task cannot use
+ * extended features.
+ *
+ * So fpstate->xfeatures cannot be used here, because then
+ * a feature for which the task has no permission but was
+ * used by the previous task would not go into init state.
+ */
+ mask = fpu_kernel_cfg.max_features & mask;
+
os_xrstor(&fpstate->regs.xsave, mask);
} else {
if (use_fxsr())
@@ -161,7 +172,7 @@ void restore_fpregs_from_fpstate(struct fpstate *fpstate, u64 mask)
void fpu_reset_from_exception_fixup(void)
{
- restore_fpregs_from_fpstate(&init_fpstate, xfeatures_mask_fpstate());
+ restore_fpregs_from_fpstate(&init_fpstate, XFEATURE_MASK_FPSTATE);
}
#if IS_ENABLED(CONFIG_KVM)
@@ -179,7 +190,7 @@ void fpu_swap_kvm_fpu(struct fpu *save, struct fpu *rstor, u64 restore_mask)
}
if (rstor) {
- restore_mask &= xfeatures_mask_fpstate();
+ restore_mask &= XFEATURE_MASK_FPSTATE;
restore_fpregs_from_fpstate(rstor->fpstate, restore_mask);
}
@@ -518,7 +529,7 @@ void fpu__clear_user_states(struct fpu *fpu)
}
/* Reset user states in registers. */
- restore_fpregs_from_init_fpstate(xfeatures_mask_restore_user());
+ restore_fpregs_from_init_fpstate(XFEATURE_MASK_USER_RESTORE);
/*
* Now all FPU registers have their desired values. Inform the FPU
diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
index 9f92abd230db..cbba3812a160 100644
--- a/arch/x86/kernel/fpu/xstate.c
+++ b/arch/x86/kernel/fpu/xstate.c
@@ -344,7 +344,7 @@ static void __init print_xstate_offset_size(void)
*/
static __init void os_xrstor_booting(struct xregs_state *xstate)
{
- u64 mask = xfeatures_mask_fpstate();
+ u64 mask = fpu_kernel_cfg.max_features & XFEATURE_MASK_FPSTATE;
u32 lmask = mask;
u32 hmask = mask >> 32;
int err;