diff options
author | Jan Beulich <jbeulich@novell.com> | 2006-03-25 10:29:25 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-25 12:10:52 -0500 |
commit | 45948d7720e8bd0104696087c6305fdd90e3b298 (patch) | |
tree | 0da730feffeae60461117a07efdf2ada96704fa6 /arch/x86_64 | |
parent | 2b514e74f4e59e3b8e54891580fef2c9ff6c7bd0 (diff) |
[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')
-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) | |||
527 | int cpu = smp_processor_id(); | 527 | int cpu = smp_processor_id(); |
528 | struct tss_struct *tss = &per_cpu(init_tss, cpu); | 528 | struct tss_struct *tss = &per_cpu(init_tss, cpu); |
529 | 529 | ||
530 | unlazy_fpu(prev_p); | ||
531 | |||
532 | /* | 530 | /* |
533 | * Reload esp0, LDT and the page table pointer: | 531 | * Reload esp0, LDT and the page table pointer: |
534 | */ | 532 | */ |
@@ -586,11 +584,14 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |||
586 | } | 584 | } |
587 | 585 | ||
588 | /* | 586 | /* |
589 | * Switch the PDA context. | 587 | * Switch the PDA and FPU contexts. |
590 | */ | 588 | */ |
591 | prev->userrsp = read_pda(oldrsp); | 589 | prev->userrsp = read_pda(oldrsp); |
592 | write_pda(oldrsp, next->userrsp); | 590 | write_pda(oldrsp, next->userrsp); |
593 | write_pda(pcurrent, next_p); | 591 | write_pda(pcurrent, next_p); |
592 | /* This must be here to ensure both math_state_restore() and | ||
593 | kernel_fpu_begin() work consistently. */ | ||
594 | unlazy_fpu(prev_p); | ||
594 | write_pda(kernelstack, | 595 | write_pda(kernelstack, |
595 | task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET); | 596 | task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET); |
596 | 597 | ||