aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/i387.h1
-rw-r--r--arch/x86/kernel/process_32.c20
-rw-r--r--arch/x86/kernel/process_64.c23
-rw-r--r--arch/x86/kernel/traps.c35
4 files changed, 11 insertions, 68 deletions
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h
index 548b2c07ac9..86974c72d0d 100644
--- a/arch/x86/include/asm/i387.h
+++ b/arch/x86/include/asm/i387.h
@@ -30,7 +30,6 @@ extern void fpu_init(void);
30extern void mxcsr_feature_mask_init(void); 30extern void mxcsr_feature_mask_init(void);
31extern int init_fpu(struct task_struct *child); 31extern int init_fpu(struct task_struct *child);
32extern void math_state_restore(void); 32extern void math_state_restore(void);
33extern void __math_state_restore(void);
34extern int dump_fpu(struct pt_regs *, struct user_i387_struct *); 33extern int dump_fpu(struct pt_regs *, struct user_i387_struct *);
35 34
36extern user_regset_active_fn fpregs_active, xfpregs_active; 35extern user_regset_active_fn fpregs_active, xfpregs_active;
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 485204f58cd..324cd722b44 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -299,23 +299,11 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
299 *next = &next_p->thread; 299 *next = &next_p->thread;
300 int cpu = smp_processor_id(); 300 int cpu = smp_processor_id();
301 struct tss_struct *tss = &per_cpu(init_tss, cpu); 301 struct tss_struct *tss = &per_cpu(init_tss, cpu);
302 bool preload_fpu;
303 302
304 /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */ 303 /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
305 304
306 /*
307 * If the task has used fpu the last 5 timeslices, just do a full
308 * restore of the math state immediately to avoid the trap; the
309 * chances of needing FPU soon are obviously high now
310 */
311 preload_fpu = tsk_used_math(next_p) && next_p->fpu_counter > 5;
312
313 __unlazy_fpu(prev_p); 305 __unlazy_fpu(prev_p);
314 306
315 /* we're going to use this soon, after a few expensive things */
316 if (preload_fpu)
317 prefetch(next->fpu.state);
318
319 /* 307 /*
320 * Reload esp0. 308 * Reload esp0.
321 */ 309 */
@@ -354,11 +342,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
354 task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT)) 342 task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT))
355 __switch_to_xtra(prev_p, next_p, tss); 343 __switch_to_xtra(prev_p, next_p, tss);
356 344
357 /* If we're going to preload the fpu context, make sure clts
358 is run while we're batching the cpu state updates. */
359 if (preload_fpu)
360 clts();
361
362 /* 345 /*
363 * Leave lazy mode, flushing any hypercalls made here. 346 * Leave lazy mode, flushing any hypercalls made here.
364 * This must be done before restoring TLS segments so 347 * This must be done before restoring TLS segments so
@@ -368,9 +351,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
368 */ 351 */
369 arch_end_context_switch(next_p); 352 arch_end_context_switch(next_p);
370 353
371 if (preload_fpu)
372 __math_state_restore();
373
374 /* 354 /*
375 * Restore %gs if needed (which is common) 355 * Restore %gs if needed (which is common)
376 */ 356 */
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 9b9fe4a85c8..992b4e542bc 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -386,18 +386,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
386 int cpu = smp_processor_id(); 386 int cpu = smp_processor_id();
387 struct tss_struct *tss = &per_cpu(init_tss, cpu); 387 struct tss_struct *tss = &per_cpu(init_tss, cpu);
388 unsigned fsindex, gsindex; 388 unsigned fsindex, gsindex;
389 bool preload_fpu;
390
391 /*
392 * If the task has used fpu the last 5 timeslices, just do a full
393 * restore of the math state immediately to avoid the trap; the
394 * chances of needing FPU soon are obviously high now
395 */
396 preload_fpu = tsk_used_math(next_p) && next_p->fpu_counter > 5;
397
398 /* we're going to use this soon, after a few expensive things */
399 if (preload_fpu)
400 prefetch(next->fpu.state);
401 389
402 /* 390 /*
403 * Reload esp0, LDT and the page table pointer: 391 * Reload esp0, LDT and the page table pointer:
@@ -430,10 +418,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
430 /* Must be after DS reload */ 418 /* Must be after DS reload */
431 __unlazy_fpu(prev_p); 419 __unlazy_fpu(prev_p);
432 420
433 /* Make sure cpu is ready for new context */
434 if (preload_fpu)
435 clts();
436
437 /* 421 /*
438 * Leave lazy mode, flushing any hypercalls made here. 422 * Leave lazy mode, flushing any hypercalls made here.
439 * This must be done before restoring TLS segments so 423 * This must be done before restoring TLS segments so
@@ -492,13 +476,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
492 task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV)) 476 task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV))
493 __switch_to_xtra(prev_p, next_p, tss); 477 __switch_to_xtra(prev_p, next_p, tss);
494 478
495 /*
496 * Preload the FPU context, now that we've determined that the
497 * task is likely to be using it.
498 */
499 if (preload_fpu)
500 __math_state_restore();
501
502 return prev_p; 479 return prev_p;
503} 480}
504 481
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index fc676e44c77..5afe824c66e 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -571,28 +571,6 @@ asmlinkage void __attribute__((weak)) smp_threshold_interrupt(void)
571} 571}
572 572
573/* 573/*
574 * __math_state_restore assumes that cr0.TS is already clear and the
575 * fpu state is all ready for use. Used during context switch.
576 */
577void __math_state_restore(void)
578{
579 struct thread_info *thread = current_thread_info();
580 struct task_struct *tsk = thread->task;
581
582 /*
583 * Paranoid restore. send a SIGSEGV if we fail to restore the state.
584 */
585 if (unlikely(restore_fpu_checking(tsk))) {
586 stts();
587 force_sig(SIGSEGV, tsk);
588 return;
589 }
590
591 __thread_set_has_fpu(thread); /* clts in caller! */
592 tsk->fpu_counter++;
593}
594
595/*
596 * 'math_state_restore()' saves the current math information in the 574 * 'math_state_restore()' saves the current math information in the
597 * old math state array, and gets the new ones from the current task 575 * old math state array, and gets the new ones from the current task
598 * 576 *
@@ -622,9 +600,18 @@ void math_state_restore(void)
622 local_irq_disable(); 600 local_irq_disable();
623 } 601 }
624 602
625 clts(); /* Allow maths ops (or we recurse) */ 603 __thread_fpu_begin(thread);
626 604
627 __math_state_restore(); 605 /*
606 * Paranoid restore. send a SIGSEGV if we fail to restore the state.
607 */
608 if (unlikely(restore_fpu_checking(tsk))) {
609 __thread_fpu_end(thread);
610 force_sig(SIGSEGV, tsk);
611 return;
612 }
613
614 tsk->fpu_counter++;
628} 615}
629EXPORT_SYMBOL_GPL(math_state_restore); 616EXPORT_SYMBOL_GPL(math_state_restore);
630 617