aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/process_32.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-02-16 18:45:23 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-02-16 18:45:23 -0500
commitb3b0870ef3ffed72b92415423da864f440f57ad6 (patch)
treeb3e128019581669d44e6634d3b1bfb169c73598d /arch/x86/kernel/process_32.c
parent6d59d7a9f5b723a7ac1925c136e93ec83c0c3043 (diff)
i387: do not preload FPU state at task switch time
Yes, taking the trap to re-load the FPU/MMX state is expensive, but so is spending several days looking for a bug in the state save/restore code. And the preload code has some rather subtle interactions with both paravirtualization support and segment state restore, so it's not nearly as simple as it should be. Also, now that we no longer necessarily depend on a single bit (ie TS_USEDFPU) for keeping track of the state of the FPU, we migth be able to do better. If we are really switching between two processes that keep touching the FP state, save/restore is inevitable, but in the case of having one process that does most of the FPU usage, we may actually be able to do much better than the preloading. In particular, we may be able to keep track of which CPU the process ran on last, and also per CPU keep track of which process' FP state that CPU has. For modern CPU's that don't destroy the FPU contents on save time, that would allow us to do a lazy restore by just re-enabling the existing FPU state - with no restore cost at all! Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/x86/kernel/process_32.c')
-rw-r--r--arch/x86/kernel/process_32.c20
1 files changed, 0 insertions, 20 deletions
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 */