#include <linux/config.h>
#include <linux/sched.h>
#include <linux/init.h>
+#include <linux/kernel_stat.h>
#include <asm/processor.h>
#include <asm/i387.h>
#include <asm/math_emu.h>
static inline void __save_init_fpu( struct task_struct *tsk )
{
if ( cpu_has_fxsr ) {
- asm volatile( "fxsave %0 ; fnclex"
+ asm volatile( "fxsave %0"
: "=m" (tsk->thread.i387.fxsave) );
+ if (tsk->thread.i387.fxsave.swd & (1<<7))
+ asm volatile("fnclex");
+ /* AMD CPUs leak F?P. Clear it here */
+ asm volatile("ffree %%st(7) ; fildl %0" :: "m" (kstat.context_swtch));
} else {
asm volatile( "fnsave %0 ; fwait"
: "=m" (tsk->thread.i387.fsave) );
*next = &next_p->thread;
struct tss_struct *tss = init_tss + smp_processor_id();
- unlazy_fpu(prev_p);
-
/*
* Reload rsp0, LDT and the page table pointer:
*/
loadsegment(ds, next->ds);
/*
+ * Must be after DS reload for AMD workaround.
+ */
+ unlazy_fpu(prev_p);
+
+ /*
* Switch FS and GS.
*/
{
static inline void save_init_fpu( struct task_struct *tsk )
{
- asm volatile( "fxsave %0 ; fnclex"
+ asm volatile( "fxsave %0"
: "=m" (tsk->thread.i387.fxsave));
+ if (tsk->thread.i387.fxsave.swd & (1<<7))
+ asm volatile("fnclex");
+ /* AMD CPUs leak F?P through FXSAVE. Clear it here */
+ asm volatile("ffree %st(7) ; fildl %gs:0");
tsk->flags &= ~PF_USEDFPU;
stts();
}