[PATCH] x86_64: save FPU context slightly later
authorJan Beulich <jbeulich@novell.com>
Sat, 25 Mar 2006 15:29:25 +0000 (16:29 +0100)
committerLinus Torvalds <torvalds@g5.osdl.org>
Sat, 25 Mar 2006 17:10:52 +0000 (09:10 -0800)
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>
arch/x86_64/kernel/process.c

index 0cb93abbf5649eacc12683cadb008f32e0ff8981..81111835722d84cf7e561d4ffd21a75f33f0a708 100644 (file)
@@ -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);