diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2009-09-29 11:27:53 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2009-09-29 11:27:53 +0100 |
commit | fb7925518f22199dd55fb3e204fb609affe7f4cd (patch) | |
tree | 2372678883881b2d8574e4de9b71b2560df29264 /xen/include/asm-x86/i387.h | |
parent | 341c0e113f2b60c37813708cd91f4507ed08f3f4 (diff) | |
download | xen-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.h | 94 |
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(); + } } } |