/* 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 (
".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:
".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;
}
}
*/
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) )
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 */