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:
|
* High level FPU state handling functions:
|
||||||
*/
|
*/
|
||||||
extern void fpu__prepare_write(struct fpu *fpu);
|
|
||||||
extern void fpu__save(struct fpu *fpu);
|
extern void fpu__save(struct fpu *fpu);
|
||||||
extern int fpu__restore_sig(void __user *buf, int ia32_frame);
|
extern int fpu__restore_sig(void __user *buf, int ia32_frame);
|
||||||
extern void fpu__drop(struct fpu *fpu);
|
extern void fpu__drop(struct fpu *fpu);
|
||||||
|
@ -281,30 +281,6 @@ static void fpu__initialize(struct fpu *fpu)
|
|||||||
trace_x86_fpu_init_state(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
|
* Drops current FPU state: deactivates the fpregs and
|
||||||
* the fpstate. NOTE: it still leaves previous contents
|
* the fpstate. NOTE: it still leaves previous contents
|
||||||
|
@ -44,6 +44,25 @@ static void sync_fpstate(struct fpu *fpu)
|
|||||||
fpu__save(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,
|
int xfpregs_get(struct task_struct *target, const struct user_regset *regset,
|
||||||
struct membuf to)
|
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)
|
if (newstate.mxcsr & ~mxcsr_feature_mask)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
fpu__prepare_write(fpu);
|
fpu_force_restore(fpu);
|
||||||
|
|
||||||
/* Copy the state */
|
/* Copy the state */
|
||||||
memcpy(&fpu->state.fxsave, &newstate, sizeof(newstate));
|
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);
|
ret = copy_kernel_to_xstate(&fpu->state.xsave, kbuf ?: tmpbuf);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@ -346,7 +365,7 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
fpu__prepare_write(fpu);
|
fpu_force_restore(fpu);
|
||||||
|
|
||||||
if (cpu_feature_enabled(X86_FEATURE_FXSR))
|
if (cpu_feature_enabled(X86_FEATURE_FXSR))
|
||||||
convert_to_fxsr(&fpu->state.fxsave, &env);
|
convert_to_fxsr(&fpu->state.fxsave, &env);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user