diff options
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/x86/kernel/process_64.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index c9b8904736db..a28279dbb07c 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
| @@ -386,9 +386,17 @@ __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; | ||
| 389 | 397 | ||
| 390 | /* we're going to use this soon, after a few expensive things */ | 398 | /* we're going to use this soon, after a few expensive things */ |
| 391 | if (next_p->fpu_counter > 5) | 399 | if (preload_fpu) |
| 392 | prefetch(next->xstate); | 400 | prefetch(next->xstate); |
| 393 | 401 | ||
| 394 | /* | 402 | /* |
| @@ -422,6 +430,10 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |||
| 422 | /* Must be after DS reload */ | 430 | /* Must be after DS reload */ |
| 423 | unlazy_fpu(prev_p); | 431 | unlazy_fpu(prev_p); |
| 424 | 432 | ||
| 433 | /* Make sure cpu is ready for new context */ | ||
| 434 | if (preload_fpu) | ||
| 435 | clts(); | ||
| 436 | |||
| 425 | /* | 437 | /* |
| 426 | * Leave lazy mode, flushing any hypercalls made here. | 438 | * Leave lazy mode, flushing any hypercalls made here. |
| 427 | * This must be done before restoring TLS segments so | 439 | * This must be done before restoring TLS segments so |
| @@ -480,15 +492,12 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |||
| 480 | task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV)) | 492 | task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV)) |
| 481 | __switch_to_xtra(prev_p, next_p, tss); | 493 | __switch_to_xtra(prev_p, next_p, tss); |
| 482 | 494 | ||
| 483 | /* If the task has used fpu the last 5 timeslices, just do a full | 495 | /* |
| 484 | * restore of the math state immediately to avoid the trap; the | 496 | * Preload the FPU context, now that we've determined that the |
| 485 | * chances of needing FPU soon are obviously high now | 497 | * task is likely to be using it. |
| 486 | * | ||
| 487 | * tsk_used_math() checks prevent calling math_state_restore(), | ||
| 488 | * which can sleep in the case of !tsk_used_math() | ||
| 489 | */ | 498 | */ |
| 490 | if (tsk_used_math(next_p) && next_p->fpu_counter > 5) | 499 | if (preload_fpu) |
| 491 | math_state_restore(); | 500 | __math_state_restore(); |
| 492 | return prev_p; | 501 | return prev_p; |
| 493 | } | 502 | } |
| 494 | 503 | ||
