[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] vmx: add the support of XSAVE/XRSTOR to VMX guest



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1254220073 -3600
# Node ID ad35f39e5fdccab3b158b38e139ca3498c347cb5
# Parent  24117d67661c0c62f03901a25960cca82a732e9a
vmx: add the support of XSAVE/XRSTOR to VMX guest

XSAVE/XRSTOR manages the existing and future processor extended states
on x86 architecture.

The XSAVE/XRSTOR infrastructure is defined in Intel SDMs:
http://www.intel.com/products/processor/manuals/

The patch uses the classical CR0.TS based algorithm to manage the
states on context switch.  At present, we know 3 bits in the
XFEATURE_ENABLED_MASK: FPU, SSE and YMM.  YMM is defined in Intel AVX
Programming Reference: http://software.intel.com/sites/avx/

Signed-off-by: Dexuan Cui <dexuan.cui@xxxxxxxxx>
---
 tools/libxc/xc_cpuid_x86.c        |    2 
 xen/arch/x86/cpu/intel.c          |   10 ++++
 xen/arch/x86/hvm/hvm.c            |   57 +++++++++++++++++++++++
 xen/arch/x86/hvm/vmx/vmcs.c       |    2 
 xen/arch/x86/hvm/vmx/vmx.c        |   47 +++++++++++++++++--
 xen/arch/x86/i387.c               |   76 ++++++++++++++++++++++++++++++
 xen/include/asm-x86/cpufeature.h  |    4 +
 xen/include/asm-x86/domain.h      |    2 
 xen/include/asm-x86/hvm/hvm.h     |    3 -
 xen/include/asm-x86/hvm/vcpu.h    |    9 +++
 xen/include/asm-x86/hvm/vmx/vmx.h |    1 
 xen/include/asm-x86/i387.h        |   94 ++++++++++++++++++++++++++++++++++++--
 xen/include/asm-x86/processor.h   |    1 
 13 files changed, 296 insertions(+), 12 deletions(-)

diff -r 24117d67661c -r ad35f39e5fdc tools/libxc/xc_cpuid_x86.c
--- a/tools/libxc/xc_cpuid_x86.c        Tue Sep 29 11:22:17 2009 +0100
+++ b/tools/libxc/xc_cpuid_x86.c        Tue Sep 29 11:27:53 2009 +0100
@@ -28,7 +28,7 @@
 #define clear_bit(idx, dst) ((dst) &= ~(1u << ((idx) & 31)))
 #define set_bit(idx, dst)   ((dst) |= (1u << ((idx) & 31)))
 
-#define DEF_MAX_BASE 0x00000004u
+#define DEF_MAX_BASE 0x0000000du
 #define DEF_MAX_EXT  0x80000008u
 
 static int hypervisor_is_64bit(int xc)
diff -r 24117d67661c -r ad35f39e5fdc xen/arch/x86/cpu/intel.c
--- a/xen/arch/x86/cpu/intel.c  Tue Sep 29 11:22:17 2009 +0100
+++ b/xen/arch/x86/cpu/intel.c  Tue Sep 29 11:27:53 2009 +0100
@@ -9,6 +9,7 @@
 #include <asm/uaccess.h>
 #include <asm/mpspec.h>
 #include <asm/apic.h>
+#include <asm/i387.h>
 #include <mach_apic.h>
 #include <asm/hvm/support.h>
 
@@ -27,6 +28,9 @@ static unsigned int opt_cpuid_mask_ecx, 
 static unsigned int opt_cpuid_mask_ecx, opt_cpuid_mask_edx;
 integer_param("cpuid_mask_ecx", opt_cpuid_mask_ecx);
 integer_param("cpuid_mask_edx", opt_cpuid_mask_edx);
+
+static int use_xsave = 1;
+boolean_param("xsave", use_xsave);
 
 #ifdef CONFIG_X86_INTEL_USERCOPY
 /*
@@ -233,6 +237,12 @@ static void __devinit init_intel(struct 
                set_bit(X86_FEATURE_ARAT, c->x86_capability);
 
        start_vmx();
+
+       if ( !use_xsave )
+               clear_bit(X86_FEATURE_XSAVE, boot_cpu_data.x86_capability);
+
+       if ( cpu_has_xsave )
+               xsave_init();
 }
 
 
diff -r 24117d67661c -r ad35f39e5fdc xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Tue Sep 29 11:22:17 2009 +0100
+++ b/xen/arch/x86/hvm/hvm.c    Tue Sep 29 11:27:53 2009 +0100
@@ -43,6 +43,7 @@
 #include <asm/processor.h>
 #include <asm/types.h>
 #include <asm/msr.h>
+#include <asm/i387.h>
 #include <asm/traps.h>
 #include <asm/mc146818rtc.h>
 #include <asm/spinlock.h>
@@ -753,6 +754,18 @@ int hvm_vcpu_initialise(struct vcpu *v)
 {
     int rc;
 
+    if ( cpu_has_xsave )
+    {
+        /* XSAVE/XRSTOR requires the save area be 64-byte-boundary aligned. */
+        void *xsave_area = _xmalloc(xsave_cntxt_size, 64);
+        if ( xsave_area == NULL )
+            return -ENOMEM;
+
+        xsave_init_save_area(xsave_area);
+        v->arch.hvm_vcpu.xsave_area = xsave_area;
+        v->arch.hvm_vcpu.xfeature_mask = XSTATE_FP_SSE;
+    }
+
     if ( (rc = vlapic_init(v)) != 0 )
         goto fail1;
 
@@ -815,6 +828,7 @@ void hvm_vcpu_destroy(struct vcpu *v)
     hvm_vcpu_cacheattr_destroy(v);
     vlapic_destroy(v);
     hvm_funcs.vcpu_destroy(v);
+    xfree(v->arch.hvm_vcpu.xsave_area);
 
     /* Event channel is already freed by evtchn_destroy(). */
     /*free_xen_event_channel(v, v->arch.hvm_vcpu.xen_port);*/
@@ -1771,6 +1785,7 @@ void hvm_cpuid(unsigned int input, unsig
                                    unsigned int *ecx, unsigned int *edx)
 {
     struct vcpu *v = current;
+    unsigned int count = *ecx;
 
     if ( cpuid_viridian_leaves(input, eax, ebx, ecx, edx) )
         return;
@@ -1788,10 +1803,52 @@ void hvm_cpuid(unsigned int input, unsig
         *ebx |= (v->vcpu_id * 2) << 24;
         if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
             __clear_bit(X86_FEATURE_APIC & 31, edx);
+
+        /* Fix up XSAVE and OSXSAVE. */
+        *ecx &= ~(bitmaskof(X86_FEATURE_XSAVE) |
+                  bitmaskof(X86_FEATURE_OSXSAVE));
+        if ( cpu_has_xsave )
+        {
+            *ecx |= bitmaskof(X86_FEATURE_XSAVE);
+            *ecx |= (v->arch.hvm_vcpu.guest_cr[4] & X86_CR4_OSXSAVE) ?
+                     bitmaskof(X86_FEATURE_OSXSAVE) : 0;
+        }
         break;
     case 0xb:
         /* Fix the x2APIC identifier. */
         *edx = v->vcpu_id * 2;
+        break;
+    case 0xd:
+        if ( cpu_has_xsave )
+        {
+            /*
+             *  Fix up "Processor Extended State Enumeration". We only present
+             *  FPU(bit0) and SSE(bit1) to HVM guest for now.
+             */
+            *eax = *ebx = *ecx = *edx = 0;
+            switch ( count )
+            {
+            case 0:
+                /* No HW defines bit in EDX yet. */
+                *edx = 0;
+                /* We only enable the features we know. */
+                *eax = xfeature_low;
+                /* FP/SSE + XSAVE.HEADER + YMM. */
+                *ecx = 512 + 64 + ((*eax & XSTATE_YMM) ? XSTATE_YMM_SIZE : 0);
+                /* Let ebx equal ecx at present. */
+                *ebx = *ecx;
+                break;
+            case 2:
+                if ( !(xfeature_low & XSTATE_YMM) )
+                    break;
+                *eax = XSTATE_YMM_SIZE;
+                *ebx = XSTATE_YMM_OFFSET;
+                break;
+            case 1:
+            default:
+                break;
+            }
+        }
         break;
     }
 }
diff -r 24117d67661c -r ad35f39e5fdc xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c       Tue Sep 29 11:22:17 2009 +0100
+++ b/xen/arch/x86/hvm/vmx/vmcs.c       Tue Sep 29 11:27:53 2009 +0100
@@ -629,7 +629,7 @@ static int construct_vmcs(struct vcpu *v
     /* Host control registers. */
     v->arch.hvm_vmx.host_cr0 = read_cr0() | X86_CR0_TS;
     __vmwrite(HOST_CR0, v->arch.hvm_vmx.host_cr0);
-    __vmwrite(HOST_CR4, mmu_cr4_features);
+    __vmwrite(HOST_CR4, mmu_cr4_features | (cpu_has_xsave ? X86_CR4_OSXSAVE : 
0));
 
     /* Host CS:RIP. */
     __vmwrite(HOST_CS_SELECTOR, __HYPERVISOR_CS);
diff -r 24117d67661c -r ad35f39e5fdc xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Tue Sep 29 11:22:17 2009 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Tue Sep 29 11:27:53 2009 +0100
@@ -669,10 +669,14 @@ static void vmx_ctxt_switch_to(struct vc
 static void vmx_ctxt_switch_to(struct vcpu *v)
 {
     struct domain *d = v->domain;
-
-    /* HOST_CR4 in VMCS is always mmu_cr4_features. Sync CR4 now. */
-    if ( unlikely(read_cr4() != mmu_cr4_features) )
-        write_cr4(mmu_cr4_features);
+    unsigned long old_cr4 = read_cr4(), new_cr4 = mmu_cr4_features;
+
+    /* HOST_CR4 in VMCS is always mmu_cr4_features and
+     * CR4_OSXSAVE(if supported). Sync CR4 now. */
+    if ( cpu_has_xsave )
+        new_cr4 |= X86_CR4_OSXSAVE;
+    if ( old_cr4 != new_cr4 )
+        write_cr4(new_cr4);
 
     if ( d->arch.hvm_domain.hap_enabled )
     {
@@ -2317,6 +2321,30 @@ static int vmx_handle_eoi_write(void)
     return 0;
 }
 
+static int vmx_handle_xsetbv(u64 new_bv)
+{
+    struct vcpu *v = current;
+    u64 xfeature = (((u64)xfeature_high) << 32) | xfeature_low;
+    struct segment_register sreg;
+
+    hvm_get_segment_register(v, x86_seg_ss, &sreg);
+    if ( sreg.attr.fields.dpl != 0 )
+        goto err;
+
+    if ( ((new_bv ^ xfeature) & ~xfeature) || !(new_bv & 1) )
+        goto err;
+
+    if ( (xfeature & XSTATE_YMM & new_bv) && !(new_bv & XSTATE_SSE) )
+        goto err;
+
+    v->arch.hvm_vcpu.xfeature_mask = new_bv;
+    set_xcr0(new_bv);
+    return 0;
+err:
+    vmx_inject_hw_exception(TRAP_gp_fault, 0);
+    return -1;
+}
+
 asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
 {
     unsigned int exit_reason, idtv_info;
@@ -2668,6 +2696,17 @@ asmlinkage void vmx_vmexit_handler(struc
         do_sched_op_compat(SCHEDOP_yield, 0);
         break;
 
+    case EXIT_REASON_XSETBV:
+    {
+        u64 new_bv  =  (((u64)regs->edx) << 32) | regs->eax;
+        if ( vmx_handle_xsetbv(new_bv) == 0 )
+        {
+            inst_len = __get_instruction_length();
+            __update_guest_eip(inst_len);
+        }
+        break;
+    }
+
     default:
     exit_and_crash:
         gdprintk(XENLOG_ERR, "Bad vmexit (reason %x)\n", exit_reason);
diff -r 24117d67661c -r ad35f39e5fdc xen/arch/x86/i387.c
--- a/xen/arch/x86/i387.c       Tue Sep 29 11:22:17 2009 +0100
+++ b/xen/arch/x86/i387.c       Tue Sep 29 11:27:53 2009 +0100
@@ -33,7 +33,11 @@ void save_init_fpu(struct vcpu *v)
     if ( cr0 & X86_CR0_TS )
         clts();
 
-    if ( cpu_has_fxsr )
+    if ( cpu_has_xsave && is_hvm_vcpu(v) )
+    {
+        xsave(v);
+    }
+    else if ( cpu_has_fxsr )
     {
 #ifdef __i386__
         asm volatile (
@@ -129,6 +133,76 @@ void restore_fpu(struct vcpu *v)
 }
 
 /*
+ * Maximum size (in byte) of the XSAVE/XRSTOR save area required by all
+ * the supported and enabled features on the processor, including the
+ * XSAVE.HEADER. We only enable XCNTXT_MASK that we have known.
+ */
+u32 xsave_cntxt_size;
+
+/* A 64-bit bitmask of the XSAVE/XRSTOR features supported by processor. */
+u32 xfeature_low, xfeature_high;
+
+void xsave_init(void)
+{
+    u32 eax, ebx, ecx, edx;
+    int cpu = smp_processor_id();
+    u32 min_size;
+
+    cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx);
+
+    printk("%s: cpu%d: cntxt_max_size: 0x%x and states: %08x:%08x\n",
+        __func__, cpu, ecx, edx, eax);
+
+    if ( ((eax & XSTATE_FP_SSE) != XSTATE_FP_SSE) ||
+         ((eax & XSTATE_YMM) && !(eax & XSTATE_SSE)) )
+    {
+        BUG();
+    }
+
+    /* FP/SSE, XSAVE.HEADER, YMM */
+    min_size =  512 + 64 + ((eax & XSTATE_YMM) ? XSTATE_YMM_SIZE : 0);
+    BUG_ON(ecx < min_size);
+
+    /*
+     * We will only enable the features we know for hvm guest. Here we use
+     * set/clear CR4_OSXSAVE and re-run cpuid to get xsave_cntxt_size.
+     */
+    set_in_cr4(X86_CR4_OSXSAVE);
+    set_xcr0(eax & XCNTXT_MASK);
+    cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx);
+    clear_in_cr4(X86_CR4_OSXSAVE);
+
+    if ( cpu == 0 )
+    {
+        /*
+         * xsave_cntxt_size is the max size required by enabled features.
+         * We know FP/SSE and YMM about eax, and nothing about edx at present.
+         */
+        xsave_cntxt_size = ebx;
+        xfeature_low = eax & XCNTXT_MASK;
+        xfeature_high = 0;
+        printk("%s: using cntxt_size: 0x%x and states: %08x:%08x\n",
+            __func__, xsave_cntxt_size, xfeature_high, xfeature_low);
+    }
+    else
+    {
+        BUG_ON(xsave_cntxt_size != ebx);
+        BUG_ON(xfeature_low != (eax & XCNTXT_MASK));
+    }
+}
+
+void xsave_init_save_area(void *save_area)
+{
+    memset(save_area, 0, xsave_cntxt_size);
+
+    ((u16 *)save_area)[0] = 0x37f;   /* FCW   */
+    ((u16 *)save_area)[2] = 0xffff;  /* FTW   */
+    ((u32 *)save_area)[6] = 0x1f80;  /* MXCSR */
+
+    ((struct xsave_struct *)save_area)->xsave_hdr.xstate_bv = XSTATE_FP_SSE;
+}
+
+/*
  * Local variables:
  * mode: C
  * c-set-style: "BSD"
diff -r 24117d67661c -r ad35f39e5fdc xen/include/asm-x86/cpufeature.h
--- a/xen/include/asm-x86/cpufeature.h  Tue Sep 29 11:22:17 2009 +0100
+++ b/xen/include/asm-x86/cpufeature.h  Tue Sep 29 11:27:53 2009 +0100
@@ -98,6 +98,7 @@
 #define X86_FEATURE_X2APIC     (4*32+21) /* Extended xAPIC */
 #define X86_FEATURE_POPCNT     (4*32+23) /* POPCNT instruction */
 #define X86_FEATURE_XSAVE      (4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */
+#define X86_FEATURE_OSXSAVE    (4*32+27) /* OSXSAVE */
 #define X86_FEATURE_HYPERVISOR (4*32+31) /* Running under some hypervisor */
 
 /* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
@@ -189,6 +190,9 @@
                                  && boot_cpu_has(X86_FEATURE_FFXSR))
 
 #define cpu_has_x2apic          boot_cpu_has(X86_FEATURE_X2APIC)
+
+#define cpu_has_xsave           boot_cpu_has(X86_FEATURE_XSAVE)
+
 #define cpu_has_arch_perfmon    boot_cpu_has(X86_FEATURE_ARCH_PERFMON)
 
 #endif /* __ASM_I386_CPUFEATURE_H */
diff -r 24117d67661c -r ad35f39e5fdc xen/include/asm-x86/domain.h
--- a/xen/include/asm-x86/domain.h      Tue Sep 29 11:22:17 2009 +0100
+++ b/xen/include/asm-x86/domain.h      Tue Sep 29 11:27:53 2009 +0100
@@ -440,7 +440,7 @@ unsigned long pv_guest_cr4_fixup(unsigne
       | ((v)->domain->arch.vtsc ? X86_CR4_TSD : 0))         \
       & ~X86_CR4_DE)
 #define real_cr4_to_pv_guest_cr4(c) \
-    ((c) & ~(X86_CR4_PGE | X86_CR4_PSE | X86_CR4_TSD))
+    ((c) & ~(X86_CR4_PGE | X86_CR4_PSE | X86_CR4_TSD | X86_CR4_OSXSAVE))
 
 void domain_cpuid(struct domain *d,
                   unsigned int  input,
diff -r 24117d67661c -r ad35f39e5fdc xen/include/asm-x86/hvm/hvm.h
--- a/xen/include/asm-x86/hvm/hvm.h     Tue Sep 29 11:22:17 2009 +0100
+++ b/xen/include/asm-x86/hvm/hvm.h     Tue Sep 29 11:27:53 2009 +0100
@@ -268,7 +268,8 @@ static inline int hvm_do_pmu_interrupt(s
        (X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD |       \
         X86_CR4_DE  | X86_CR4_PSE | X86_CR4_PAE |       \
         X86_CR4_MCE | X86_CR4_PGE | X86_CR4_PCE |       \
-        X86_CR4_OSFXSR | X86_CR4_OSXMMEXCPT)))
+        X86_CR4_OSFXSR | X86_CR4_OSXMMEXCPT |           \
+        (cpu_has_xsave ? X86_CR4_OSXSAVE : 0))))
 
 /* These exceptions must always be intercepted. */
 #define HVM_TRAP_MASK ((1U << TRAP_machine_check) | (1U << TRAP_invalid_op))
diff -r 24117d67661c -r ad35f39e5fdc xen/include/asm-x86/hvm/vcpu.h
--- a/xen/include/asm-x86/hvm/vcpu.h    Tue Sep 29 11:22:17 2009 +0100
+++ b/xen/include/asm-x86/hvm/vcpu.h    Tue Sep 29 11:27:53 2009 +0100
@@ -46,6 +46,15 @@ struct hvm_vcpu {
      *  CR3:      Always used and kept up to date by paging subsystem.
      */
     unsigned long       hw_cr[5];
+
+    /*
+     * The save area for Processor Extended States and the bitmask of the
+     * XSAVE/XRSTOR features. They are used by: 1) when a vcpu (which has
+     * dirtied FPU/SSE) is scheduled out we XSAVE the states here; 2) in
+     * #NM handler, we XRSTOR the states we XSAVE-ed;
+     */
+    void *xsave_area;
+    uint64_t xfeature_mask;
 
     struct vlapic       vlapic;
     s64                 cache_tsc_offset;
diff -r 24117d67661c -r ad35f39e5fdc xen/include/asm-x86/hvm/vmx/vmx.h
--- a/xen/include/asm-x86/hvm/vmx/vmx.h Tue Sep 29 11:22:17 2009 +0100
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h Tue Sep 29 11:27:53 2009 +0100
@@ -111,6 +111,7 @@ void vmx_update_debug_state(struct vcpu 
 #define EXIT_REASON_EPT_VIOLATION       48
 #define EXIT_REASON_EPT_MISCONFIG       49
 #define EXIT_REASON_WBINVD              54
+#define EXIT_REASON_XSETBV              55
 
 /*
  * Interruption-information format
diff -r 24117d67661c -r ad35f39e5fdc xen/include/asm-x86/i387.h
--- a/xen/include/asm-x86/i387.h        Tue Sep 29 11:22:17 2009 +0100
+++ b/xen/include/asm-x86/i387.h        Tue Sep 29 11:27:53 2009 +0100
@@ -13,6 +13,82 @@
 
 #include <xen/sched.h>
 #include <asm/processor.h>
+
+extern unsigned int xsave_cntxt_size;
+extern u32 xfeature_low, xfeature_high;
+
+extern void xsave_init(void);
+extern void xsave_init_save_area(void *save_area);
+
+#define XSTATE_FP       (1 << 0)
+#define XSTATE_SSE      (1 << 1)
+#define XSTATE_YMM      (1 << 2)
+#define XSTATE_FP_SSE   (XSTATE_FP | XSTATE_SSE)
+#define XCNTXT_MASK     (XSTATE_FP | XSTATE_SSE | XSTATE_YMM)
+#define XSTATE_YMM_OFFSET  (512 + 64)
+#define XSTATE_YMM_SIZE    256
+
+struct xsave_struct
+{
+    struct { char x[512]; } fpu_sse;         /* FPU/MMX, SSE */
+
+    struct {
+        u64 xstate_bv;
+        u64 reserved[7];
+    } xsave_hdr;                            /* The 64-byte header */
+
+    struct { char x[XSTATE_YMM_SIZE]; } ymm; /* YMM */
+    char   data[];                           /* Future new states */
+} __attribute__ ((packed, aligned (64)));
+
+#define XCR_XFEATURE_ENABLED_MASK   0
+
+#ifdef CONFIG_X86_64
+#define REX_PREFIX "0x48, "
+#else
+#define REX_PREFIX
+#endif
+
+static inline void xsetbv(u32 index, u64 xfeature_mask)
+{
+    u32 hi = xfeature_mask >> 32;
+    u32 lo = (u32)xfeature_mask;
+
+    asm volatile (".byte 0x0f,0x01,0xd1" :: "c" (index),
+            "a" (lo), "d" (hi));
+}
+
+static inline void set_xcr0(u64 xfeature_mask)
+{
+    xsetbv(XCR_XFEATURE_ENABLED_MASK, xfeature_mask);
+}
+
+static inline void xsave(struct vcpu *v)
+{
+    u64 mask = v->arch.hvm_vcpu.xfeature_mask | XSTATE_FP_SSE;
+    u32 lo = mask, hi = mask >> 32;
+    struct xsave_struct *ptr;
+
+    ptr =(struct xsave_struct *)v->arch.hvm_vcpu.xsave_area;
+
+    asm volatile (".byte " REX_PREFIX "0x0f,0xae,0x27"
+        :
+        : "a" (lo), "d" (hi), "D"(ptr)
+        : "memory");
+}
+
+static inline void xrstor(struct vcpu *v)
+{
+    u64 mask = v->arch.hvm_vcpu.xfeature_mask | XSTATE_FP_SSE;
+    u32 lo = mask, hi = mask >> 32;
+    struct xsave_struct *ptr;
+
+    ptr =(struct xsave_struct *)v->arch.hvm_vcpu.xsave_area;
+
+    asm volatile (".byte " REX_PREFIX "0x0f,0xae,0x2f"
+        :
+        : "m" (*ptr), "a" (lo), "d" (hi), "D"(ptr));
+}
 
 extern void init_fpu(void);
 extern void save_init_fpu(struct vcpu *v);
@@ -36,10 +112,22 @@ static inline void setup_fpu(struct vcpu
     if ( !v->fpu_dirtied )
     {
         v->fpu_dirtied = 1;
-        if ( v->fpu_initialised )
-            restore_fpu(v);
+        if ( cpu_has_xsave && is_hvm_vcpu(v) )
+        {
+            if ( !v->fpu_initialised )
+                v->fpu_initialised = 1;
+
+            set_xcr0(v->arch.hvm_vcpu.xfeature_mask | XSTATE_FP_SSE);
+            xrstor(v);
+            set_xcr0(v->arch.hvm_vcpu.xfeature_mask);
+        }
         else
-            init_fpu();
+        {
+            if ( v->fpu_initialised )
+                restore_fpu(v);
+            else
+                init_fpu();
+        }
     }
 }
 
diff -r 24117d67661c -r ad35f39e5fdc xen/include/asm-x86/processor.h
--- a/xen/include/asm-x86/processor.h   Tue Sep 29 11:22:17 2009 +0100
+++ b/xen/include/asm-x86/processor.h   Tue Sep 29 11:27:53 2009 +0100
@@ -83,6 +83,7 @@
 #define X86_CR4_OSXMMEXCPT     0x0400  /* enable unmasked SSE exceptions */
 #define X86_CR4_VMXE           0x2000  /* enable VMX */
 #define X86_CR4_SMXE           0x4000  /* enable SMX */
+#define X86_CR4_OSXSAVE        0x40000 /* enable XSAVE/XRSTOR */
 
 /*
  * Trap/fault mnemonics.

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.