diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-02-20 13:24:09 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-02-20 13:24:09 -0500 |
commit | cea20ca3f3181fc36788a15bc65d1062b96a0a6c (patch) | |
tree | 86c646c0d228d1fe265536b81d86af406ff92c8e | |
parent | b01543dfe67bb1d191998e90d20534dc354de059 (diff) |
i387: fix up some fpu_counter confusion
This makes sure we clear the FPU usage counter for newly created tasks,
just so that we start off in a known state (for example, don't try to
preload the FPU state on the first task switch etc).
It also fixes a thinko in when we increment the fpu_counter at task
switch time, introduced by commit 34ddc81a230b ("i387: re-introduce FPU
state preloading at context switch time"). We should increment the
*new* task fpu_counter, not the old task, and only if we decide to use
that state (whether lazily or preloaded).
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | arch/x86/include/asm/i387.h | 3 | ||||
-rw-r--r-- | arch/x86/kernel/process_32.c | 1 | ||||
-rw-r--r-- | arch/x86/kernel/process_64.c | 1 |
3 files changed, 4 insertions, 1 deletions
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h index a850b4d8d14d..8df95849721d 100644 --- a/arch/x86/include/asm/i387.h +++ b/arch/x86/include/asm/i387.h | |||
@@ -348,10 +348,10 @@ static inline fpu_switch_t switch_fpu_prepare(struct task_struct *old, struct ta | |||
348 | if (__save_init_fpu(old)) | 348 | if (__save_init_fpu(old)) |
349 | fpu_lazy_state_intact(old); | 349 | fpu_lazy_state_intact(old); |
350 | __thread_clear_has_fpu(old); | 350 | __thread_clear_has_fpu(old); |
351 | old->fpu_counter++; | ||
352 | 351 | ||
353 | /* Don't change CR0.TS if we just switch! */ | 352 | /* Don't change CR0.TS if we just switch! */ |
354 | if (fpu.preload) { | 353 | if (fpu.preload) { |
354 | new->fpu_counter++; | ||
355 | __thread_set_has_fpu(new); | 355 | __thread_set_has_fpu(new); |
356 | prefetch(new->thread.fpu.state); | 356 | prefetch(new->thread.fpu.state); |
357 | } else | 357 | } else |
@@ -359,6 +359,7 @@ static inline fpu_switch_t switch_fpu_prepare(struct task_struct *old, struct ta | |||
359 | } else { | 359 | } else { |
360 | old->fpu_counter = 0; | 360 | old->fpu_counter = 0; |
361 | if (fpu.preload) { | 361 | if (fpu.preload) { |
362 | new->fpu_counter++; | ||
362 | if (fpu_lazy_restore(new)) | 363 | if (fpu_lazy_restore(new)) |
363 | fpu.preload = 0; | 364 | fpu.preload = 0; |
364 | else | 365 | else |
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 80bfe1ab0031..bc32761bc27a 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
@@ -214,6 +214,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
214 | 214 | ||
215 | task_user_gs(p) = get_user_gs(regs); | 215 | task_user_gs(p) = get_user_gs(regs); |
216 | 216 | ||
217 | p->fpu_counter = 0; | ||
217 | p->thread.io_bitmap_ptr = NULL; | 218 | p->thread.io_bitmap_ptr = NULL; |
218 | tsk = current; | 219 | tsk = current; |
219 | err = -ENOMEM; | 220 | err = -ENOMEM; |
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 1fd94bc4279d..8ad880b3bc1c 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -286,6 +286,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
286 | 286 | ||
287 | set_tsk_thread_flag(p, TIF_FORK); | 287 | set_tsk_thread_flag(p, TIF_FORK); |
288 | 288 | ||
289 | p->fpu_counter = 0; | ||
289 | p->thread.io_bitmap_ptr = NULL; | 290 | p->thread.io_bitmap_ptr = NULL; |
290 | 291 | ||
291 | savesegment(gs, p->thread.gsindex); | 292 | savesegment(gs, p->thread.gsindex); |