summaryrefslogtreecommitdiff
path: root/arch/x86/kernel/fpu/core.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2021-10-15 01:09:38 +0200
committerBorislav Petkov <bp@suse.de>2021-10-22 11:09:15 +0200
commiteda32f4f93b452c5fe3c352523e7f7cc085c8205 (patch)
tree31af7db20335b0b0f50fbbb19e4b212abbb61245 /arch/x86/kernel/fpu/core.c
parentdaddee24731938781b7876d20335ea3754d23484 (diff)
x86/fpu: Rework restore_regs_from_fpstate()
xfeatures_mask_fpstate() is no longer valid when dynamically enabled features come into play. Rework restore_regs_from_fpstate() so it takes a constant mask which will then be applied against the maximum feature set so that the restore operation brings all features which are not in the xsave buffer xfeature bitmap into init state. This ensures that if the previous task used a dynamically enabled feature that the task which restores has all unused components properly initialized. Cleanup the last user of xfeatures_mask_fpstate() as well and remove it. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Borislav Petkov <bp@suse.de> Link: https://lkml.kernel.org/r/20211014230739.461348278@linutronix.de
Diffstat (limited to 'arch/x86/kernel/fpu/core.c')
-rw-r--r--arch/x86/kernel/fpu/core.c17
1 files changed, 14 insertions, 3 deletions
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