Skip to content

Commit 2ebe81c

Browse files
KAGA-KOKOsuryasaimadhu
authored andcommitted
x86/fpu: Dont restore PKRU in fpregs_restore_userspace()
switch_to() and flush_thread() write the task's PKRU value eagerly so the PKRU value of current is always valid in the hardware. That means there is no point in restoring PKRU on exit to user or when reactivating the task's FPU registers in the signal frame setup path. This allows to remove all the xstate buffer updates with PKRU values once the PKRU state is stored in thread struct while a task is scheduled out. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Borislav Petkov <bp@suse.de> Reviewed-by: Borislav Petkov <bp@suse.de> Link: https://lkml.kernel.org/r/20210623121456.303919033@linutronix.de
1 parent 65e9521 commit 2ebe81c

File tree

3 files changed

+35
-2
lines changed

3 files changed

+35
-2
lines changed

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,21 @@ static inline void fpregs_restore_userregs(void)
457457
return;
458458

459459
if (!fpregs_state_valid(fpu, cpu)) {
460-
restore_fpregs_from_fpstate(&fpu->state);
460+
u64 mask;
461+
462+
/*
463+
* This restores _all_ xstate which has not been
464+
* established yet.
465+
*
466+
* If PKRU is enabled, then the PKRU value is already
467+
* correct because it was either set in switch_to() or in
468+
* flush_thread(). So it is excluded because it might be
469+
* not up to date in current->thread.fpu.xsave state.
470+
*/
471+
mask = xfeatures_mask_restore_user() |
472+
xfeatures_mask_supervisor();
473+
__restore_fpregs_from_fpstate(&fpu->state, mask);
474+
461475
fpregs_activate(fpu);
462476
fpu->last_cpu = cpu;
463477
}

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@
3535
XFEATURE_MASK_BNDREGS | \
3636
XFEATURE_MASK_BNDCSR)
3737

38+
/*
39+
* Features which are restored when returning to user space.
40+
* PKRU is not restored on return to user space because PKRU
41+
* is switched eagerly in switch_to() and flush_thread()
42+
*/
43+
#define XFEATURE_MASK_USER_RESTORE \
44+
(XFEATURE_MASK_USER_SUPPORTED & ~XFEATURE_MASK_PKRU)
45+
3846
/* All currently supported supervisor features */
3947
#define XFEATURE_MASK_SUPERVISOR_SUPPORTED (XFEATURE_MASK_PASID)
4048

@@ -92,6 +100,17 @@ static inline u64 xfeatures_mask_uabi(void)
92100
return xfeatures_mask_all & XFEATURE_MASK_USER_SUPPORTED;
93101
}
94102

103+
/*
104+
* The xfeatures which are restored by the kernel when returning to user
105+
* mode. This is not necessarily the same as xfeatures_mask_uabi() as the
106+
* kernel does not manage all XCR0 enabled features via xsave/xrstor as
107+
* some of them have to be switched eagerly on context switch and exec().
108+
*/
109+
static inline u64 xfeatures_mask_restore_user(void)
110+
{
111+
return xfeatures_mask_all & XFEATURE_MASK_USER_RESTORE;
112+
}
113+
95114
static inline u64 xfeatures_mask_independent(void)
96115
{
97116
if (!boot_cpu_has(X86_FEATURE_ARCH_LBR))

arch/x86/kernel/fpu/core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ void fpu__clear_user_states(struct fpu *fpu)
404404
}
405405

406406
/* Reset user states in registers. */
407-
restore_fpregs_from_init_fpstate(xfeatures_mask_uabi());
407+
restore_fpregs_from_init_fpstate(xfeatures_mask_restore_user());
408408

409409
/*
410410
* Now all FPU registers have their desired values. Inform the FPU

0 commit comments

Comments
 (0)