Skip to content

Commit eda32f4

Browse files
KAGA-KOKOsuryasaimadhu
authored andcommitted
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 <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent daddee2 commit eda32f4

File tree

4 files changed

+23
-29
lines changed

4 files changed

+23
-29
lines changed

arch/x86/include/asm/fpu/xstate.h

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -78,30 +78,17 @@
7878
XFEATURE_MASK_INDEPENDENT | \
7979
XFEATURE_MASK_SUPERVISOR_UNSUPPORTED)
8080

81-
static inline u64 xfeatures_mask_supervisor(void)
82-
{
83-
return fpu_kernel_cfg.max_features & XFEATURE_MASK_SUPERVISOR_SUPPORTED;
84-
}
85-
8681
/*
87-
* The xfeatures which are restored by the kernel when returning to user
88-
* mode. This is not necessarily the same as xfeatures_mask_uabi() as the
89-
* kernel does not manage all XCR0 enabled features via xsave/xrstor as
90-
* some of them have to be switched eagerly on context switch and exec().
82+
* The feature mask required to restore FPU state:
83+
* - All user states which are not eagerly switched in switch_to()/exec()
84+
* - The suporvisor states
9185
*/
92-
static inline u64 xfeatures_mask_restore_user(void)
93-
{
94-
return fpu_kernel_cfg.max_features & XFEATURE_MASK_USER_RESTORE;
95-
}
86+
#define XFEATURE_MASK_FPSTATE (XFEATURE_MASK_USER_RESTORE | \
87+
XFEATURE_MASK_SUPERVISOR_SUPPORTED)
9688

97-
/*
98-
* Like xfeatures_mask_restore_user() but additionally restors the
99-
* supported supervisor states.
100-
*/
101-
static inline u64 xfeatures_mask_fpstate(void)
89+
static inline u64 xfeatures_mask_supervisor(void)
10290
{
103-
return fpu_kernel_cfg.max_features & \
104-
(XFEATURE_MASK_USER_RESTORE | XFEATURE_MASK_SUPERVISOR_SUPPORTED);
91+
return fpu_kernel_cfg.max_features & XFEATURE_MASK_SUPERVISOR_SUPPORTED;
10592
}
10693

10794
static inline u64 xfeatures_mask_independent(void)

arch/x86/kernel/fpu/context.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,6 @@ static inline void fpregs_restore_userregs(void)
6161
return;
6262

6363
if (!fpregs_state_valid(fpu, cpu)) {
64-
u64 mask;
65-
6664
/*
6765
* This restores _all_ xstate which has not been
6866
* established yet.
@@ -72,9 +70,7 @@ static inline void fpregs_restore_userregs(void)
7270
* flush_thread(). So it is excluded because it might be
7371
* not up to date in current->thread.fpu.xsave state.
7472
*/
75-
mask = xfeatures_mask_restore_user() |
76-
xfeatures_mask_supervisor();
77-
restore_fpregs_from_fpstate(fpu->fpstate, mask);
73+
restore_fpregs_from_fpstate(fpu->fpstate, XFEATURE_MASK_FPSTATE);
7874

7975
fpregs_activate(fpu);
8076
fpu->last_cpu = cpu;

arch/x86/kernel/fpu/core.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,17 @@ void restore_fpregs_from_fpstate(struct fpstate *fpstate, u64 mask)
150150
}
151151

152152
if (use_xsave()) {
153+
/*
154+
* Restoring state always needs to modify all features
155+
* which are in @mask even if the current task cannot use
156+
* extended features.
157+
*
158+
* So fpstate->xfeatures cannot be used here, because then
159+
* a feature for which the task has no permission but was
160+
* used by the previous task would not go into init state.
161+
*/
162+
mask = fpu_kernel_cfg.max_features & mask;
163+
153164
os_xrstor(&fpstate->regs.xsave, mask);
154165
} else {
155166
if (use_fxsr())
@@ -161,7 +172,7 @@ void restore_fpregs_from_fpstate(struct fpstate *fpstate, u64 mask)
161172

162173
void fpu_reset_from_exception_fixup(void)
163174
{
164-
restore_fpregs_from_fpstate(&init_fpstate, xfeatures_mask_fpstate());
175+
restore_fpregs_from_fpstate(&init_fpstate, XFEATURE_MASK_FPSTATE);
165176
}
166177

167178
#if IS_ENABLED(CONFIG_KVM)
@@ -179,7 +190,7 @@ void fpu_swap_kvm_fpu(struct fpu *save, struct fpu *rstor, u64 restore_mask)
179190
}
180191

181192
if (rstor) {
182-
restore_mask &= xfeatures_mask_fpstate();
193+
restore_mask &= XFEATURE_MASK_FPSTATE;
183194
restore_fpregs_from_fpstate(rstor->fpstate, restore_mask);
184195
}
185196

@@ -518,7 +529,7 @@ void fpu__clear_user_states(struct fpu *fpu)
518529
}
519530

520531
/* Reset user states in registers. */
521-
restore_fpregs_from_init_fpstate(xfeatures_mask_restore_user());
532+
restore_fpregs_from_init_fpstate(XFEATURE_MASK_USER_RESTORE);
522533

523534
/*
524535
* Now all FPU registers have their desired values. Inform the FPU

arch/x86/kernel/fpu/xstate.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ static void __init print_xstate_offset_size(void)
344344
*/
345345
static __init void os_xrstor_booting(struct xregs_state *xstate)
346346
{
347-
u64 mask = xfeatures_mask_fpstate();
347+
u64 mask = fpu_kernel_cfg.max_features & XFEATURE_MASK_FPSTATE;
348348
u32 lmask = mask;
349349
u32 hmask = mask >> 32;
350350
int err;

0 commit comments

Comments
 (0)