x86/fpu: Move fpu__write_begin() to regset
The only usecase for fpu__write_begin is the set() callback of regset, so the function is pointlessly global. Move it to the regset code and rename it to fpu_force_restore() which is exactly decribing what the function does. 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/20210623121453.328652975@linutronix.de
This commit is contained in:
parent
5a32fac8db
commit
dbb60ac764
@ -26,7 +26,6 @@
|
||||
/*
|
||||
* High level FPU state handling functions:
|
||||
*/
|
||||
extern void fpu__prepare_write(struct fpu *fpu);
|
||||
extern void fpu__save(struct fpu *fpu);
|
||||
extern int fpu__restore_sig(void __user *buf, int ia32_frame);
|
||||
extern void fpu__drop(struct fpu *fpu);
|
||||
|
@ -281,30 +281,6 @@ static void fpu__initialize(struct fpu *fpu)
|
||||
trace_x86_fpu_init_state(fpu);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function must be called before we write a task's fpstate.
|
||||
*
|
||||
* Invalidate any cached FPU registers.
|
||||
*
|
||||
* After this function call, after registers in the fpstate are
|
||||
* modified and the child task has woken up, the child task will
|
||||
* restore the modified FPU state from the modified context. If we
|
||||
* didn't clear its cached status here then the cached in-registers
|
||||
* state pending on its former CPU could be restored, corrupting
|
||||
* the modifications.
|
||||
*/
|
||||
void fpu__prepare_write(struct fpu *fpu)
|
||||
{
|
||||
/*
|
||||
* Only stopped child tasks can be used to modify the FPU
|
||||
* state in the fpstate buffer:
|
||||
*/
|
||||
WARN_ON_FPU(fpu == ¤t->thread.fpu);
|
||||
|
||||
/* Invalidate any cached state: */
|
||||
__fpu_invalidate_fpregs_state(fpu);
|
||||
}
|
||||
|
||||
/*
|
||||
* Drops current FPU state: deactivates the fpregs and
|
||||
* the fpstate. NOTE: it still leaves previous contents
|
||||
|
@ -44,6 +44,25 @@ static void sync_fpstate(struct fpu *fpu)
|
||||
fpu__save(fpu);
|
||||
}
|
||||
|
||||
/*
|
||||
* Invalidate cached FPU registers before modifying the stopped target
|
||||
* task's fpstate.
|
||||
*
|
||||
* This forces the target task on resume to restore the FPU registers from
|
||||
* modified fpstate. Otherwise the task might skip the restore and operate
|
||||
* with the cached FPU registers which discards the modifications.
|
||||
*/
|
||||
static void fpu_force_restore(struct fpu *fpu)
|
||||
{
|
||||
/*
|
||||
* Only stopped child tasks can be used to modify the FPU
|
||||
* state in the fpstate buffer:
|
||||
*/
|
||||
WARN_ON_FPU(fpu == ¤t->thread.fpu);
|
||||
|
||||
__fpu_invalidate_fpregs_state(fpu);
|
||||
}
|
||||
|
||||
int xfpregs_get(struct task_struct *target, const struct user_regset *regset,
|
||||
struct membuf to)
|
||||
{
|
||||
@ -88,7 +107,7 @@ int xfpregs_set(struct task_struct *target, const struct user_regset *regset,
|
||||
if (newstate.mxcsr & ~mxcsr_feature_mask)
|
||||
return -EINVAL;
|
||||
|
||||
fpu__prepare_write(fpu);
|
||||
fpu_force_restore(fpu);
|
||||
|
||||
/* Copy the state */
|
||||
memcpy(&fpu->state.fxsave, &newstate, sizeof(newstate));
|
||||
@ -146,7 +165,7 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset,
|
||||
}
|
||||
}
|
||||
|
||||
fpu__prepare_write(fpu);
|
||||
fpu_force_restore(fpu);
|
||||
ret = copy_kernel_to_xstate(&fpu->state.xsave, kbuf ?: tmpbuf);
|
||||
|
||||
out:
|
||||
@ -346,7 +365,7 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
fpu__prepare_write(fpu);
|
||||
fpu_force_restore(fpu);
|
||||
|
||||
if (cpu_feature_enabled(X86_FEATURE_FXSR))
|
||||
convert_to_fxsr(&fpu->state.fxsave, &env);
|
||||
|
Loading…
x
Reference in New Issue
Block a user