diff options
author | Jan Beulich <jbeulich@novell.com> | 2006-03-25 16:29:25 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-25 09:10:52 -0800 |
commit | 45948d7720e8bd0104696087c6305fdd90e3b298 (patch) | |
tree | 0da730feffeae60461117a07efdf2ada96704fa6 /arch/x86_64/kernel/process.c | |
parent | 2b514e74f4e59e3b8e54891580fef2c9ff6c7bd0 (diff) | |
download | blackbird-op-linux-45948d7720e8bd0104696087c6305fdd90e3b298.tar.gz blackbird-op-linux-45948d7720e8bd0104696087c6305fdd90e3b298.zip |
[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/x86_64/kernel/process.c')
-rw-r--r-- | arch/x86_64/kernel/process.c | 7 |
1 files changed, 4 insertions, 3 deletions
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index 0cb93abbf564..81111835722d 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); |