]> xenbits.xensource.com Git - xen.git/commitdiff
x86/fxsave: bring in line with recent xsave adjustments
authorJan Beulich <jbeulich@suse.com>
Tue, 2 Jul 2013 06:42:49 +0000 (08:42 +0200)
committerJan Beulich <jbeulich@suse.com>
Tue, 2 Jul 2013 06:42:49 +0000 (08:42 +0200)
Defer the FIP/FDP pointer reset needed on AMD CPUs to the restore path,
and switch from using EMMS to FFREE here too (to be resistant against
eventual future CPUs without MMX support). Also switch from using an
almost typeless pointer in fpu_fxrstor() to a properly typed one, thus
telling the compiler the truth about which memory gets accessed.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Keir Fraser <keir@xen.org>
xen/arch/x86/i387.c

index dbf24af83eb4f7a24fd9597f0943b0e4fa995982..bd162a8e1e428aa37518acb95d3c818c8ca2b1ea 100644 (file)
@@ -52,14 +52,30 @@ static inline void fpu_xrstor(struct vcpu *v, uint64_t mask)
 /* Restor x87 FPU, MMX, SSE and SSE2 state */
 static inline void fpu_fxrstor(struct vcpu *v)
 {
-    const char *fpu_ctxt = v->arch.fpu_ctxt;
+    const typeof(v->arch.xsave_area->fpu_sse) *fpu_ctxt = v->arch.fpu_ctxt;
+
+    /*
+     * AMD CPUs don't save/restore FDP/FIP/FOP unless an exception
+     * is pending. Clear the x87 state here by setting it to fixed
+     * values. The hypervisor data segment can be sometimes 0 and
+     * sometimes new user value. Both should be ok. Use the FPU saved
+     * data block as a safe address because it should be in L1.
+     */
+    if ( !(fpu_ctxt->fsw & 0x0080) &&
+         boot_cpu_data.x86_vendor == X86_VENDOR_AMD )
+    {
+        asm volatile ( "fnclex\n\t"
+                       "ffree %%st(7)\n\t" /* clear stack tag */
+                       "fildl %0"          /* load to clear state */
+                       : : "m" (*fpu_ctxt) );
+    }
 
     /*
      * FXRSTOR can fault if passed a corrupted data block. We handle this
      * possibility, which may occur if the block was passed to us by control
      * tools or through VCPUOP_initialise, by silently clearing the block.
      */
-    switch ( __builtin_expect(fpu_ctxt[FPU_WORD_SIZE_OFFSET], 8) )
+    switch ( __builtin_expect(fpu_ctxt->x[FPU_WORD_SIZE_OFFSET], 8) )
     {
     default:
         asm volatile (
@@ -80,8 +96,7 @@ static inline void fpu_fxrstor(struct vcpu *v)
             ".previous                \n"
             _ASM_EXTABLE(1b, 2b)
             :
-            : "m" (*fpu_ctxt),
-              "i" (sizeof(v->arch.xsave_area->fpu_sse) / 4),
+            : "m" (*fpu_ctxt), "i" (sizeof(*fpu_ctxt) / 4),
               "cdaSDb" (fpu_ctxt) );
         break;
     case 4: case 2:
@@ -102,8 +117,7 @@ static inline void fpu_fxrstor(struct vcpu *v)
             ".previous             \n"
             _ASM_EXTABLE(1b, 2b)
             :
-            : "m" (*fpu_ctxt),
-              "i" (sizeof(v->arch.xsave_area->fpu_sse) / 4) );
+            : "m" (*fpu_ctxt), "i" (sizeof(*fpu_ctxt) / 4) );
         break;
     }
 }
@@ -156,7 +170,7 @@ static inline void fpu_fxsave(struct vcpu *v)
          */
         if ( !(fpu_ctxt->fsw & 0x0080) &&
              boot_cpu_data.x86_vendor == X86_VENDOR_AMD )
-            word_size = -1;
+            return;
 
         if ( word_size > 0 &&
              !((fpu_ctxt->fip.addr | fpu_ctxt->fdp.addr) >> 32) )
@@ -177,25 +191,6 @@ static inline void fpu_fxsave(struct vcpu *v)
 
     if ( word_size >= 0 )
         fpu_ctxt->x[FPU_WORD_SIZE_OFFSET] = word_size;
-    
-    /* Clear exception flags if FSW.ES is set. */
-    if ( unlikely(fpu_ctxt->fsw & 0x0080) )
-        asm volatile ("fnclex");
-    
-    /*
-     * AMD CPUs don't save/restore FDP/FIP/FOP unless an exception
-     * is pending. Clear the x87 state here by setting it to fixed
-     * values. The hypervisor data segment can be sometimes 0 and
-     * sometimes new user value. Both should be ok. Use the FPU saved
-     * data block as a safe address because it should be in L1.
-     */
-    if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD )
-    {
-        asm volatile (
-            "emms\n\t"  /* clear stack tags */
-            "fildl %0"  /* load to clear state */
-            : : "m" (*fpu_ctxt) );
-    }
 }
 
 /* Save x87 FPU state */