aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2006-03-25 16:29:25 +0100
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-25 09:10:52 -0800
commit45948d7720e8bd0104696087c6305fdd90e3b298 (patch)
tree0da730feffeae60461117a07efdf2ada96704fa6 /arch
parent2b514e74f4e59e3b8e54891580fef2c9ff6c7bd0 (diff)
downloadlinux-45948d7720e8bd0104696087c6305fdd90e3b298.tar.gz
[PATCH] x86_64: save FPU context slightly later
Touching of the floating point state in a kernel debugger must be NMI-safe, specifically math_state_restore() must be able to deal with being called out of an NMI context. In order to do that reliably, the context switch code must take care to not leave a window open where the current task's TS_USEDFPU flag and CR0.TS could get out of sync. Signed-off-by: Jan Beulich <jbeulich@novell.com> Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86_64/kernel/process.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index 0cb93abbf5649e..81111835722d84 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -527,8 +527,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
int cpu = smp_processor_id();
struct tss_struct *tss = &per_cpu(init_tss, cpu);
- unlazy_fpu(prev_p);
-
/*
* Reload esp0, LDT and the page table pointer:
*/
@@ -586,11 +584,14 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
}
/*
- * Switch the PDA context.
+ * Switch the PDA and FPU contexts.
*/
prev->userrsp = read_pda(oldrsp);
write_pda(oldrsp, next->userrsp);
write_pda(pcurrent, next_p);
+ /* This must be here to ensure both math_state_restore() and
+ kernel_fpu_begin() work consistently. */
+ unlazy_fpu(prev_p);
write_pda(kernelstack,
task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET);