From: riel@redhat.com
To: linux-kernel@vger.kernel.org
Cc: mingo@redhat.com, hpa@zytor.com, matt.fleming@intel.com,
bp@suse.de, oleg@redhat.com, pbonzini@redhat.com,
tglx@linutronix.de, luto@amacapital.net
Subject: [RFC PATCH 04/11] x86,fpu: defer FPU restore until return to userspace
Date: Sun, 11 Jan 2015 16:46:26 -0500 [thread overview]
Message-ID: <1421012793-30106-5-git-send-email-riel@redhat.com> (raw)
In-Reply-To: <1421012793-30106-1-git-send-email-riel@redhat.com>
From: Rik van Riel <riel@redhat.com>
Defer restoring the FPU state, if so desired, until the task returns to
userspace.
In case of kernel threads, KVM VCPU threads, and tasks performing longer
running operations in kernel space, this could mean skipping the FPU state
restore entirely for several context switches.
This also allows the kernel to preserve the FPU state of a userspace task
that gets interrupted by a kernel thread in kernel mode.
If the old task left TIF_LOAD_FPU set, and the new task does not want
an FPU state restore (or does not have an FPU state), clear the flag
to prevent attempted restoring of a non-existent FPU state.
TODO: remove superfluous irq disabling from entry_{32,64}.S, Andy has
some conflicting changes in that part of the code, so wait with that.
Signed-off-by: Rik van Riel <riel@redhat.com>
---
arch/x86/include/asm/fpu-internal.h | 33 +++++++++++++++++++++------------
arch/x86/kernel/process_32.c | 2 --
arch/x86/kernel/process_64.c | 2 --
arch/x86/kernel/signal.c | 9 +++++++++
4 files changed, 30 insertions(+), 16 deletions(-)
diff --git a/arch/x86/include/asm/fpu-internal.h b/arch/x86/include/asm/fpu-internal.h
index 27556f4..539b050 100644
--- a/arch/x86/include/asm/fpu-internal.h
+++ b/arch/x86/include/asm/fpu-internal.h
@@ -382,6 +382,7 @@ static inline void drop_init_fpu(struct task_struct *tsk)
else
fxrstor_checking(&init_xstate_buf->i387);
}
+ clear_thread_flag(TIF_LOAD_FPU);
}
/*
@@ -435,24 +436,32 @@ static inline void switch_fpu_prepare(struct task_struct *old, struct task_struc
prefetch(new->thread.fpu.state);
set_thread_flag(TIF_LOAD_FPU);
}
- }
- /* else: CR0.TS is still set from a previous FPU switch */
+ } else
+ /*
+ * The new task does not want an FPU state restore,
+ * and may not even have an FPU state. However, the
+ * old task may have left TIF_LOAD_FPU set.
+ * Clear it to avoid trouble.
+ *
+ * CR0.TS is still set from a previous FPU switch
+ */
+ clear_thread_flag(TIF_LOAD_FPU);
}
}
/*
- * By the time this gets called, we've already cleared CR0.TS and
- * given the process the FPU if we are going to preload the FPU
- * state - all we need to do is to conditionally restore the register
- * state itself.
+ * This is called if and when the task returns to userspace.
+ * Clear CR0.TS if necessary, so the task can access the FPU register
+ * state this function restores.
*/
-static inline void switch_fpu_finish(struct task_struct *new)
+static inline void switch_fpu_finish(void)
{
- if (test_and_clear_thread_flag(TIF_LOAD_FPU)) {
- __thread_fpu_begin(new);
- if (unlikely(restore_fpu_checking(new)))
- drop_init_fpu(new);
- }
+ struct task_struct *tsk = current;
+
+ __thread_fpu_begin(tsk);
+
+ if (unlikely(restore_fpu_checking(tsk)))
+ drop_init_fpu(tsk);
}
/*
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index c4b00e6..4da02ae 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -319,8 +319,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
if (prev->gs | next->gs)
lazy_load_gs(next->gs);
- switch_fpu_finish(next_p);
-
this_cpu_write(current_task, next_p);
return prev_p;
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index ee3824f..20e206e 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -350,8 +350,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
wrmsrl(MSR_KERNEL_GS_BASE, next->gs);
prev->gsindex = gsindex;
- switch_fpu_finish(next_p);
-
/*
* Switch the PDA and FPU contexts.
*/
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index ed37a76..46e3008 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -761,6 +761,15 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
fire_user_return_notifiers();
user_enter();
+
+ /*
+ * Test thread flag, as the signal code may have cleared TIF_LOAD_FPU.
+ * We cannot reschedule after loading the FPU state back into the CPU.
+ * IRQs will be re-enabled on the switch to userspace.
+ */
+ local_irq_disable();
+ if (test_thread_flag(TIF_LOAD_FPU))
+ switch_fpu_finish();
}
void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
--
1.9.3
next prev parent reply other threads:[~2015-01-11 22:05 UTC|newest]
Thread overview: 76+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-01-11 21:46 [RFC PATCH 0/11 BROKEN] move FPU context loading to userspace switch riel
2015-01-11 21:46 ` [RFC PATCH 01/11] x86,fpu: document the data structures a little riel
2015-01-12 21:18 ` Borislav Petkov
2015-01-12 21:38 ` Rik van Riel
2015-01-12 21:52 ` Dave Hansen
2015-01-13 15:59 ` Rik van Riel
2015-01-11 21:46 ` [RFC PATCH 02/11] x86,fpu: replace fpu_switch_t with a thread flag riel
2015-01-13 15:24 ` Oleg Nesterov
2015-01-13 16:35 ` Rik van Riel
2015-01-13 16:55 ` Oleg Nesterov
2015-01-11 21:46 ` [RFC PATCH 03/11] x86,fpu: move __thread_fpu_begin to when the task has the fpu riel
2015-01-13 15:24 ` Oleg Nesterov
2015-01-13 16:37 ` Rik van Riel
2015-01-11 21:46 ` riel [this message]
2015-01-13 15:53 ` [RFC PATCH 04/11] x86,fpu: defer FPU restore until return to userspace Oleg Nesterov
2015-01-13 17:07 ` Andy Lutomirski
2015-01-13 17:11 ` Oleg Nesterov
2015-01-13 17:18 ` Andy Lutomirski
2015-01-13 17:44 ` Rik van Riel
2015-01-13 17:57 ` Andy Lutomirski
2015-01-13 18:13 ` Rik van Riel
2015-01-13 18:26 ` Andy Lutomirski
2015-01-13 17:54 ` Rik van Riel
2015-01-13 18:22 ` Oleg Nesterov
2015-01-13 18:30 ` Oleg Nesterov
2015-01-13 20:06 ` Rik van Riel
2015-01-14 17:56 ` Oleg Nesterov
2015-01-13 17:58 ` Oleg Nesterov
2015-01-13 19:32 ` Rik van Riel
2015-01-11 21:46 ` [RFC PATCH 05/11] x86,fpu: ensure FPU state is reloaded from memory if task is traced riel
2015-01-13 16:19 ` Oleg Nesterov
2015-01-13 16:33 ` Rik van Riel
2015-01-13 16:50 ` Oleg Nesterov
2015-01-13 16:57 ` Rik van Riel
2015-01-11 21:46 ` [RFC PATCH 06/11] x86,fpu: lazily skip fpu restore with eager fpu mode, too riel
2015-01-13 17:11 ` Andy Lutomirski
2015-01-13 20:43 ` Rik van Riel
2015-01-14 18:36 ` Oleg Nesterov
2015-01-15 2:49 ` Rik van Riel
2015-01-15 19:34 ` Oleg Nesterov
2015-01-11 21:46 ` [RFC PATCH 07/11] x86,fpu: store current fpu pointer, instead of fpu_owner_task riel
2015-01-11 21:46 ` [RFC PATCH 08/11] x86,fpu: restore user FPU state lazily after __kernel_fpu_end riel
2015-01-14 18:43 ` Oleg Nesterov
2015-01-14 19:08 ` Oleg Nesterov
2015-01-11 21:46 ` [RFC PATCH 09/11] x86,fpu,kvm: keep vcpu FPU active as long as it is resident riel
2015-01-11 21:46 ` [RFC PATCH 10/11] x86,fpu: fix fpu_copy to deal with not-loaded fpu riel
2015-01-11 21:46 ` [RFC PATCH 11/11] (BROKEN) x86,fpu: broken signal handler stack setup riel
2015-01-15 19:19 ` [PATCH 0/3] x86, fpu: kernel_fpu_begin/end initial cleanups/fix Oleg Nesterov
2015-01-15 19:19 ` [PATCH 1/3] x86, fpu: introduce per-cpu "bool in_kernel_fpu" Oleg Nesterov
2015-01-16 2:22 ` Rik van Riel
2015-01-20 12:54 ` [tip:x86/fpu] x86, fpu: Introduce per-cpu in_kernel_fpu state tip-bot for Oleg Nesterov
2015-01-15 19:20 ` [PATCH 2/3] x86, fpu: don't abuse ->has_fpu in __kernel_fpu_{begin,end}() Oleg Nesterov
2015-01-16 2:27 ` Rik van Riel
2015-01-16 15:54 ` Oleg Nesterov
2015-01-16 16:07 ` Rik van Riel
2015-01-20 12:55 ` [tip:x86/fpu] x86, fpu: Don't abuse has_fpu in __kernel_fpu_begin /end() tip-bot for Oleg Nesterov
2015-01-15 19:20 ` [PATCH 3/3] x86, fpu: fix math_state_restore() race with kernel_fpu_begin() Oleg Nesterov
2015-01-16 2:30 ` Rik van Riel
2015-01-16 16:03 ` Oleg Nesterov
2015-01-20 12:55 ` [tip:x86/fpu] x86, fpu: Fix " tip-bot for Oleg Nesterov
2015-01-19 18:51 ` [PATCH 0/3] x86, fpu: more eagerfpu cleanups Oleg Nesterov
2015-01-19 18:51 ` [PATCH 1/3] x86, fpu: __kernel_fpu_begin() should clear fpu_owner_task even if use_eager_fpu() Oleg Nesterov
2015-01-20 14:15 ` Rik van Riel
2015-02-20 18:13 ` Borislav Petkov
2015-03-03 11:27 ` [tip:x86/fpu] x86/fpu: " tip-bot for Oleg Nesterov
2015-01-19 18:51 ` [PATCH 2/3] x86, fpu: always allow FPU in interrupt " Oleg Nesterov
2015-01-20 14:46 ` Rik van Riel
2015-01-20 22:46 ` Andy Lutomirski
2015-02-20 21:48 ` Borislav Petkov
2015-03-03 11:28 ` [tip:x86/fpu] x86/fpu: Always " tip-bot for Oleg Nesterov
2015-01-19 18:52 ` [PATCH 3/3] x86, fpu: don't abuse FPU in kernel threads " Oleg Nesterov
2015-01-20 14:53 ` Rik van Riel
2015-02-23 15:31 ` Borislav Petkov
2015-03-03 11:28 ` [tip:x86/fpu] x86/fpu: Don' t " tip-bot for Oleg Nesterov
2015-02-20 12:10 ` [PATCH 0/3] x86, fpu: more eagerfpu cleanups Borislav Petkov
2015-02-20 13:30 ` Oleg Nesterov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1421012793-30106-5-git-send-email-riel@redhat.com \
--to=riel@redhat.com \
--cc=bp@suse.de \
--cc=hpa@zytor.com \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@amacapital.net \
--cc=matt.fleming@intel.com \
--cc=mingo@redhat.com \
--cc=oleg@redhat.com \
--cc=pbonzini@redhat.com \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome