summaryrefslogtreecommitdiff
path: root/arch/x86/kernel/fpu/core.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2015-04-23 12:49:20 +0200
committerIngo Molnar <mingo@kernel.org>2015-05-19 15:47:25 +0200
commitc5bedc6847c3be6efe0e671a6155c9a25fd468bf (patch)
treef1eb66ea2807447c95e915f281d6815578b7e627 /arch/x86/kernel/fpu/core.c
parentaf7f8721f1f1252473b154c38dd7583abfe3206b (diff)
downloadlinux-c5bedc6847c3be6efe0e671a6155c9a25fd468bf.tar.gz
linux-c5bedc6847c3be6efe0e671a6155c9a25fd468bf.tar.bz2
linux-c5bedc6847c3be6efe0e671a6155c9a25fd468bf.zip
x86/fpu: Get rid of PF_USED_MATH usage, convert it to fpu->fpstate_active
Introduce a simple fpu->fpstate_active flag in the fpu context data structure and use that instead of PF_USED_MATH in task->flags. Testing for this flag byte should be slightly more efficient than testing a bit in a bitmask, but the main advantage is that most FPU functions can now be performed on a 'struct fpu' alone, they don't need access to 'struct task_struct' anymore. There's a slight linecount increase, mostly due to the 'fpu' local variables and due to extra comments. The local variables will go away once we move most of the FPU methods to pure 'struct fpu' parameters. Reviewed-by: Borislav Petkov <bp@alien8.de> Cc: Andy Lutomirski <luto@amacapital.net> 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: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/kernel/fpu/core.c')
-rw-r--r--arch/x86/kernel/fpu/core.c38
1 files changed, 25 insertions, 13 deletions
diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
index 779813126f49..9e7f9e7b2cca 100644
--- a/arch/x86/kernel/fpu/core.c
+++ b/arch/x86/kernel/fpu/core.c
@@ -236,14 +236,17 @@ static void fpu_copy(struct task_struct *dst, struct task_struct *src)
int fpu__copy(struct task_struct *dst, struct task_struct *src)
{
+ struct fpu *dst_fpu = &dst->thread.fpu;
+ struct fpu *src_fpu = &src->thread.fpu;
+
dst->thread.fpu.counter = 0;
dst->thread.fpu.has_fpu = 0;
dst->thread.fpu.state = NULL;
task_disable_lazy_fpu_restore(dst);
- if (src->flags & PF_USED_MATH) {
- int err = fpstate_alloc(&dst->thread.fpu);
+ if (src_fpu->fpstate_active) {
+ int err = fpstate_alloc(dst_fpu);
if (err)
return err;
@@ -260,11 +263,12 @@ int fpu__copy(struct task_struct *dst, struct task_struct *src)
*/
int fpstate_alloc_init(struct task_struct *curr)
{
+ struct fpu *fpu = &curr->thread.fpu;
int ret;
if (WARN_ON_ONCE(curr != current))
return -EINVAL;
- if (WARN_ON_ONCE(curr->flags & PF_USED_MATH))
+ if (WARN_ON_ONCE(fpu->fpstate_active))
return -EINVAL;
/*
@@ -277,7 +281,7 @@ int fpstate_alloc_init(struct task_struct *curr)
fpstate_init(&curr->thread.fpu);
/* Safe to do for the current task: */
- curr->flags |= PF_USED_MATH;
+ fpu->fpstate_active = 1;
return 0;
}
@@ -308,12 +312,13 @@ EXPORT_SYMBOL_GPL(fpstate_alloc_init);
*/
static int fpu__unlazy_stopped(struct task_struct *child)
{
+ struct fpu *child_fpu = &child->thread.fpu;
int ret;
if (WARN_ON_ONCE(child == current))
return -EINVAL;
- if (child->flags & PF_USED_MATH) {
+ if (child_fpu->fpstate_active) {
task_disable_lazy_fpu_restore(child);
return 0;
}
@@ -328,7 +333,7 @@ static int fpu__unlazy_stopped(struct task_struct *child)
fpstate_init(&child->thread.fpu);
/* Safe to do for stopped child tasks: */
- child->flags |= PF_USED_MATH;
+ child_fpu->fpstate_active = 1;
return 0;
}
@@ -348,7 +353,7 @@ void fpu__restore(void)
struct task_struct *tsk = current;
struct fpu *fpu = &tsk->thread.fpu;
- if (!(tsk->flags & PF_USED_MATH)) {
+ if (!fpu->fpstate_active) {
local_irq_enable();
/*
* does a slab alloc which can sleep
@@ -378,6 +383,8 @@ EXPORT_SYMBOL_GPL(fpu__restore);
void fpu__flush_thread(struct task_struct *tsk)
{
+ struct fpu *fpu = &tsk->thread.fpu;
+
WARN_ON(tsk != current);
if (!use_eager_fpu()) {
@@ -385,7 +392,7 @@ void fpu__flush_thread(struct task_struct *tsk)
drop_fpu(tsk);
fpstate_free(&tsk->thread.fpu);
} else {
- if (!(tsk->flags & PF_USED_MATH)) {
+ if (!fpu->fpstate_active) {
/* kthread execs. TODO: cleanup this horror. */
if (WARN_ON(fpstate_alloc_init(tsk)))
force_sig(SIGKILL, tsk);
@@ -402,12 +409,16 @@ void fpu__flush_thread(struct task_struct *tsk)
*/
int fpregs_active(struct task_struct *target, const struct user_regset *regset)
{
- return (target->flags & PF_USED_MATH) ? regset->n : 0;
+ struct fpu *target_fpu = &target->thread.fpu;
+
+ return target_fpu->fpstate_active ? regset->n : 0;
}
int xfpregs_active(struct task_struct *target, const struct user_regset *regset)
{
- return (cpu_has_fxsr && (target->flags & PF_USED_MATH)) ? regset->n : 0;
+ struct fpu *target_fpu = &target->thread.fpu;
+
+ return (cpu_has_fxsr && target_fpu->fpstate_active) ? regset->n : 0;
}
int xfpregs_get(struct task_struct *target, const struct user_regset *regset,
@@ -733,16 +744,17 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,
* struct user_i387_struct) but is in fact only used for 32-bit
* dumps, so on 64-bit it is really struct user_i387_ia32_struct.
*/
-int dump_fpu(struct pt_regs *regs, struct user_i387_struct *fpu)
+int dump_fpu(struct pt_regs *regs, struct user_i387_struct *ufpu)
{
struct task_struct *tsk = current;
+ struct fpu *fpu = &tsk->thread.fpu;
int fpvalid;
- fpvalid = !!(tsk->flags & PF_USED_MATH);
+ fpvalid = fpu->fpstate_active;
if (fpvalid)
fpvalid = !fpregs_get(tsk, NULL,
0, sizeof(struct user_i387_ia32_struct),
- fpu, NULL);
+ ufpu, NULL);
return fpvalid;
}