aboutsummaryrefslogtreecommitdiffstats
path: root/xen/include/asm-x86/i387.h
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2009-09-29 11:27:53 +0100
committerKeir Fraser <keir.fraser@citrix.com>2009-09-29 11:27:53 +0100
commitfb7925518f22199dd55fb3e204fb609affe7f4cd (patch)
tree2372678883881b2d8574e4de9b71b2560df29264 /xen/include/asm-x86/i387.h
parent341c0e113f2b60c37813708cd91f4507ed08f3f4 (diff)
downloadxen-fb7925518f22199dd55fb3e204fb609affe7f4cd.tar.gz
xen-fb7925518f22199dd55fb3e204fb609affe7f4cd.tar.bz2
xen-fb7925518f22199dd55fb3e204fb609affe7f4cd.zip
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@intel.com>
Diffstat (limited to 'xen/include/asm-x86/i387.h')
-rw-r--r--xen/include/asm-x86/i387.h94
1 files changed, 91 insertions, 3 deletions
diff --git a/xen/include/asm-x86/i387.h b/xen/include/asm-x86/i387.h
index b0ce77aac3..39e0e7df56 100644
--- a/xen/include/asm-x86/i387.h
+++ b/xen/include/asm-x86/i387.h
@@ -14,6 +14,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);
extern void restore_fpu(struct vcpu *v);
@@ -36,10 +112,22 @@ static inline void setup_fpu(struct vcpu *v)
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();
+ }
}
}