summaryrefslogtreecommitdiff
path: root/arch/x86/kernel/fpu
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2015-05-27 12:22:29 +0200
committerIngo Molnar <mingo@kernel.org>2015-05-27 14:11:27 +0200
commit343763c3b0a4fa2d29f7c3ba405abf8771b90876 (patch)
tree50a922f793d904270cdb61f9b7517710823911e3 /arch/x86/kernel/fpu
parent6a81d7eb330479c908dab3a47ac33cfca8af5a67 (diff)
x86/fpu: Optimize fpu__activate_fpstate_write()
fpu__activate_fpstate_write() is used before ptrace writes to the fpstate context. Because it expects the modified registers to be reloaded on the nexts context switch, it's only valid to call this function for stopped child tasks. - add a debugging check for this assumption - remove code that only runs if the current task's FPU state needs to be saved, which cannot occur here - update comments to match the implementation Cc: Andy Lutomirski <luto@amacapital.net> Cc: Bobby Powers <bobbypowers@gmail.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: Fenghua Yu <fenghua.yu@intel.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/kernel/fpu')
-rw-r--r--arch/x86/kernel/fpu/core.c51
1 files changed, 19 insertions, 32 deletions
diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
index 6b0955a62d34..86a9a9a086fa 100644
--- a/arch/x86/kernel/fpu/core.c
+++ b/arch/x86/kernel/fpu/core.c
@@ -322,47 +322,34 @@ void fpu__activate_fpstate_read(struct fpu *fpu)
}
/*
- * This function must be called before we read or write a task's fpstate.
+ * This function must be called before we write a task's fpstate.
*
- * If the task has not used the FPU before then initialize its
- * fpstate.
- *
- * If the task has used the FPU before then save and unlazy it.
- *
- * [ If this function is used for non-current child tasks, then
- * 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 lazy status here then the lazy in-registers
- * state pending on its former CPU could be restored, corrupting
- * the modifications.
+ * If the task has used the FPU before then unlazy it.
+ * If the task has not used the FPU before then initialize its fpstate.
*
- * This function can be used for the current task as well, but
- * only for reading the fpstate. Modifications to the fpstate
- * will be lost on eagerfpu systems. ]
- *
- * TODO: A future optimization would be to skip the unlazying in
- * the read-only case, it's not strictly necessary for
- * read-only access to the context.
+ * 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 lazy status here then the lazy in-registers
+ * state pending on its former CPU could be restored, corrupting
+ * the modifications.
*/
void fpu__activate_fpstate_write(struct fpu *fpu)
{
/*
- * If fpregs are active (in the current CPU), then
- * copy them to the fpstate:
+ * Only stopped child tasks can be used to modify the FPU
+ * state in the fpstate buffer:
*/
- if (fpu->fpregs_active) {
- fpu__save(fpu);
+ WARN_ON_FPU(fpu == &current->thread.fpu);
+
+ if (fpu->fpstate_active) {
+ /* Invalidate any lazy state: */
+ fpu->last_cpu = -1;
} else {
- if (fpu->fpstate_active) {
- /* Invalidate any lazy state: */
- fpu->last_cpu = -1;
- } else {
- fpstate_init(&fpu->state);
+ fpstate_init(&fpu->state);
- /* Safe to do for current and for stopped child tasks: */
- fpu->fpstate_active = 1;
- }
+ /* Safe to do for stopped child tasks: */
+ fpu->fpstate_active = 1;
}
}