diff options
| -rw-r--r-- | arch/x86/include/asm/i387.h | 1 | ||||
| -rw-r--r-- | arch/x86/kernel/process_32.c | 20 | ||||
| -rw-r--r-- | arch/x86/kernel/process_64.c | 23 | ||||
| -rw-r--r-- | arch/x86/kernel/traps.c | 35 |
4 files changed, 11 insertions, 68 deletions
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h index 548b2c07ac9a..86974c72d0d0 100644 --- a/arch/x86/include/asm/i387.h +++ b/arch/x86/include/asm/i387.h | |||
| @@ -30,7 +30,6 @@ extern void fpu_init(void); | |||
| 30 | extern void mxcsr_feature_mask_init(void); | 30 | extern void mxcsr_feature_mask_init(void); |
| 31 | extern int init_fpu(struct task_struct *child); | 31 | extern int init_fpu(struct task_struct *child); |
| 32 | extern void math_state_restore(void); | 32 | extern void math_state_restore(void); |
| 33 | extern void __math_state_restore(void); | ||
| 34 | extern int dump_fpu(struct pt_regs *, struct user_i387_struct *); | 33 | extern int dump_fpu(struct pt_regs *, struct user_i387_struct *); |
| 35 | 34 | ||
| 36 | extern user_regset_active_fn fpregs_active, xfpregs_active; | 35 | extern 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 485204f58cda..324cd722b447 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 9b9fe4a85c87..992b4e542bc3 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 fc676e44c77f..5afe824c66e5 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 | */ | ||
| 577 | void __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 | } |
| 629 | EXPORT_SYMBOL_GPL(math_state_restore); | 616 | EXPORT_SYMBOL_GPL(math_state_restore); |
| 630 | 617 | ||
