This patch add basic definitions/helpers which will be used in later patches.
Signed-off-by: Shuai Ruan <shuai.r...@linux.intel.com> --- xen/arch/x86/xstate.c | 168 +++++++++++++++++++++++++++++++++++++++ xen/include/asm-x86/cpufeature.h | 6 +- xen/include/asm-x86/hvm/vcpu.h | 1 + xen/include/asm-x86/msr-index.h | 2 + xen/include/asm-x86/xstate.h | 14 +++- 5 files changed, 189 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/xstate.c b/xen/arch/x86/xstate.c index d5f5e3b..ff03b31 100644 --- a/xen/arch/x86/xstate.c +++ b/xen/arch/x86/xstate.c @@ -29,12 +29,21 @@ static u32 __read_mostly xsave_cntxt_size; /* A 64-bit bitmask of the XSAVE/XRSTOR features supported by processor. */ u64 __read_mostly xfeature_mask; +unsigned int * __read_mostly xstate_offsets; +unsigned int * __read_mostly xstate_sizes; +static unsigned int __read_mostly xstate_features; +static unsigned int __read_mostly xstate_comp_offsets[sizeof(xfeature_mask)*8]; + +/* Cached msr_xss for fast read */ +static DEFINE_PER_CPU(uint64_t, msr_xss); + /* Cached xcr0 for fast read */ static DEFINE_PER_CPU(uint64_t, xcr0); /* Because XCR0 is cached for each CPU, xsetbv() is not exposed. Users should * use set_xcr0() instead. */ + static inline bool_t xsetbv(u32 index, u64 xfeatures) { u32 hi = xfeatures >> 32; @@ -65,6 +74,165 @@ uint64_t get_xcr0(void) return this_cpu(xcr0); } +void set_msr_xss(u64 xss) +{ + wrmsrl(MSR_IA32_XSS, xss); + this_cpu(msr_xss) = xss; +} + +uint64_t get_msr_xss(void) +{ + return this_cpu(msr_xss); +} + +bool_t xsave_area_compressed(const struct xsave_struct *xsave_area) +{ + if ( xsave_area && (xsave_area->xsave_hdr.xcomp_bv + & XSTATE_COMPACTION_ENABLED)) + return 1; + return 0; +} + +static int setup_xstate_features(bool_t bsp) +{ + unsigned int leaf, tmp, eax, ebx; + + if ( bsp ) + xstate_features = fls(xfeature_mask); + + if ( bsp ) + { + xstate_offsets = xzalloc_array(unsigned int, xstate_features); + if( !xstate_offsets ) + return -ENOMEM; + + xstate_sizes = xzalloc_array(unsigned int, xstate_features); + if( !xstate_sizes ) + return -ENOMEM; + } + + for (leaf = 2; leaf < xstate_features; leaf++) + { + if( bsp ) + cpuid_count(XSTATE_CPUID, leaf, &xstate_sizes[leaf], + &xstate_offsets[leaf], &tmp, &tmp); + else + { + cpuid_count(XSTATE_CPUID, leaf, &eax, + &ebx, &tmp, &tmp); + BUG_ON(eax != xstate_sizes[leaf]); + BUG_ON(ebx != xstate_offsets[leaf]); + } + } + return 0; +} + +static void setup_xstate_comp(void) +{ + unsigned int i; + + /* + * The FP xstates and SSE xstates are legacy states. They are always + * in the fixed offsets in the xsave area in either compacted form + * or standard form. + */ + xstate_comp_offsets[0] = 0; + xstate_comp_offsets[1] = XSAVE_SSE_OFFSET; + + xstate_comp_offsets[2] = FXSAVE_SIZE + XSAVE_HDR_SIZE; + + for (i = 3; i < xstate_features; i++) + { + xstate_comp_offsets[i] = xstate_comp_offsets[i-1] + (((1ul << i) + & xfeature_mask) ? xstate_sizes[i-1] : 0); + ASSERT(xstate_comp_offsets[i] <= xsave_cntxt_size); + } +} + +static void *get_xsave_addr(struct xsave_struct *xsave, unsigned int xfeature_idx) +{ + if ( !((1ul << xfeature_idx) & xfeature_mask) ) + return NULL; + + return (void *)xsave + xstate_comp_offsets[xfeature_idx]; +} + +void save_xsave_states(struct vcpu *v, void *dest, unsigned int size) +{ + struct xsave_struct *xsave = v->arch.xsave_area; + u64 xstate_bv = xsave->xsave_hdr.xstate_bv; + u64 valid; + + ASSERT(xsave_area_compressed(xsave)); + /* + * Copy legacy XSAVE area, to avoid complications with CPUID + * leaves 0 and 1 in the loop below. + */ + memcpy(dest, xsave, FXSAVE_SIZE); + + /* Set XSTATE_BV */ + *(u64 *)(dest + XSAVE_HDR_OFFSET) = xstate_bv; + + /* + * Copy each region from the possibly compacted offset to the + * non-compacted offset. + */ + valid = xstate_bv & ~XSTATE_FP_SSE; + while ( valid ) + { + u64 feature = valid & -valid; + int index = fls(feature) - 1; + void *src = get_xsave_addr(xsave, index); + + if ( src ) + { + ASSERT((xstate_offsets[index] + xstate_sizes[index]) <= size); + memcpy(dest + xstate_offsets[index], src, xstate_sizes[index]); + } + + valid -= feature; + } + +} + +void load_xsave_states(struct vcpu *v, const void *src, unsigned int size) +{ + struct xsave_struct *xsave = v->arch.xsave_area; + u64 xstate_bv = *(u64 *)(src + XSAVE_HDR_OFFSET); + u64 valid; + + ASSERT(!xsave_area_compressed((struct xsave_struct *)src)); + /* + * Copy legacy XSAVE area, to avoid complications with CPUID + * leaves 0 and 1 in the loop below. + */ + memcpy(xsave, src, FXSAVE_SIZE); + + /* Set XSTATE_BV and possibly XCOMP_BV. */ + xsave->xsave_hdr.xstate_bv = xstate_bv; + xsave->xsave_hdr.xcomp_bv = v->arch.xcr0_accum | XSTATE_COMPACTION_ENABLED; + + /* + * Copy each region from the non-compacted offset to the + * possibly compacted offset. + */ + valid = xstate_bv & ~XSTATE_FP_SSE; + while ( valid ) + { + u64 feature = valid & -valid; + int index = fls(feature) - 1; + void *dest = get_xsave_addr(xsave, feature); + + if ( dest ) + { + ASSERT((xstate_offsets[index] + xstate_sizes[index]) <= size); + memcpy(dest, src + xstate_offsets[index], xstate_sizes[index]); + } + + valid -= feature; + } +} + void xsave(struct vcpu *v, uint64_t mask) { struct xsave_struct *ptr = v->arch.xsave_area; diff --git a/xen/include/asm-x86/cpufeature.h b/xen/include/asm-x86/cpufeature.h index 9a01563..ea60176 100644 --- a/xen/include/asm-x86/cpufeature.h +++ b/xen/include/asm-x86/cpufeature.h @@ -57,7 +57,11 @@ #define X86_FEATURE_3DNOWEXT (1*32+30) /* AMD 3DNow! extensions */ #define X86_FEATURE_3DNOW (1*32+31) /* 3DNow! */ -/* *** Available for re-use ***, word 2 */ +/* Intel-defined CPU features, CPUID level 0x0000000d (eax), word 2 */ +#define X86_FEATURE_XSAVEOPT (2*32+0) +#define X86_FEATURE_XSAVEC (2*32+1) +#define X86_FEATURE_XGETBV1 (2*32+2) +#define X86_FEATURE_XSAVES (2*32+3) /* Other features, Linux-defined mapping, word 3 */ /* This range is used for feature bits which conflict or are synthesized */ diff --git a/xen/include/asm-x86/hvm/vcpu.h b/xen/include/asm-x86/hvm/vcpu.h index f553814..de81f8a 100644 --- a/xen/include/asm-x86/hvm/vcpu.h +++ b/xen/include/asm-x86/hvm/vcpu.h @@ -173,6 +173,7 @@ struct hvm_vcpu { u32 msr_tsc_aux; u64 msr_tsc_adjust; + u64 msr_xss; union { struct arch_vmx_struct vmx; diff --git a/xen/include/asm-x86/msr-index.h b/xen/include/asm-x86/msr-index.h index e9c4723..4e5b31f 100644 --- a/xen/include/asm-x86/msr-index.h +++ b/xen/include/asm-x86/msr-index.h @@ -58,6 +58,8 @@ #define MSR_IA32_BNDCFGS 0x00000D90 +#define MSR_IA32_XSS 0x00000da0 + #define MSR_MTRRfix64K_00000 0x00000250 #define MSR_MTRRfix16K_80000 0x00000258 #define MSR_MTRRfix16K_A0000 0x00000259 diff --git a/xen/include/asm-x86/xstate.h b/xen/include/asm-x86/xstate.h index 4c690db..a256525 100644 --- a/xen/include/asm-x86/xstate.h +++ b/xen/include/asm-x86/xstate.h @@ -22,7 +22,11 @@ #define XCR_XFEATURE_ENABLED_MASK 0x00000000 /* index of XCR0 */ +#define XSAVE_HDR_SIZE 64 +#define XSAVE_SSE_OFFSET 160 #define XSTATE_YMM_SIZE 256 +#define FXSAVE_SIZE 512 +#define XSAVE_HDR_OFFSET FXSAVE_SIZE #define XSTATE_AREA_MIN_SIZE (512 + 64) /* FP/SSE + XSAVE.HEADER */ #define XSTATE_FP (1ULL << 0) @@ -41,9 +45,11 @@ #define XSTATE_ALL (~(1ULL << 63)) #define XSTATE_NONLAZY (XSTATE_LWP | XSTATE_BNDREGS | XSTATE_BNDCSR) #define XSTATE_LAZY (XSTATE_ALL & ~XSTATE_NONLAZY) +#define XSTATE_COMPACTION_ENABLED (1ULL << 63) extern u64 xfeature_mask; extern bool_t cpu_has_xsaves, cpu_has_xgetbv1; +extern unsigned int *xstate_offsets, *xstate_sizes; /* extended state save area */ struct __packed __attribute__((aligned (64))) xsave_struct @@ -72,7 +78,8 @@ struct __packed __attribute__((aligned (64))) xsave_struct struct { u64 xstate_bv; - u64 reserved[7]; + u64 xcomp_bv; + u64 reserved[6]; } xsave_hdr; /* The 64-byte header */ struct { char x[XSTATE_YMM_SIZE]; } ymm; /* YMM */ @@ -82,11 +89,16 @@ struct __packed __attribute__((aligned (64))) xsave_struct /* extended state operations */ bool_t __must_check set_xcr0(u64 xfeatures); uint64_t get_xcr0(void); +void set_msr_xss(u64 xss); +uint64_t get_msr_xss(void); void xsave(struct vcpu *v, uint64_t mask); void xrstor(struct vcpu *v, uint64_t mask); bool_t xsave_enabled(const struct vcpu *v); int __must_check validate_xstate(u64 xcr0, u64 xcr0_accum, u64 xstate_bv); int __must_check handle_xsetbv(u32 index, u64 new_bv); +void save_xsave_states(struct vcpu *v, void *dest, unsigned int size); +void load_xsave_states(struct vcpu *v, const void *src, unsigned int size); +bool_t xsave_area_compressed(const struct xsave_struct *xsave_area); /* extended state init and cleanup functions */ void xstate_free_save_area(struct vcpu *v); -- 1.9.1 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel