* [V7 0/4] add xsaves/xrstors support
@ 2015-10-20 8:21 Shuai Ruan
2015-10-20 8:21 ` [V7 1/4] x86/xsaves: add basic definitions/helpers to support xsaves Shuai Ruan
` (3 more replies)
0 siblings, 4 replies; 11+ messages in thread
From: Shuai Ruan @ 2015-10-20 8:21 UTC (permalink / raw)
To: xen-devel
Cc: kevin.tian, wei.liu2, Ian.Campbell, stefano.stabellini,
jun.nakajima, andrew.cooper3, ian.jackson, eddie.dong, jbeulich,
keir
From: Shuai Ruan <shuai.ruan@intel.com>
Changes in v7:
* Address comments form Jan,Andrew:
* Move macro XSTATE_FIXUP into patch3.
* Change lazy write to xss_msr in patch1.
* Drop inner set of brackets and stray cast in patch2.
* Move the condition and memcpy() wouldn't into the new called functions in patch2.
* Rebase patch4 base on Andrew's"tools/libxc: Improve efficiency of xc_cpuid_apply_policy()".
* For no XSS features are currently supported.For leaf 2...63,ecx remain zero at
the moment in patch4.
Changes in v6:
* Address comments from Jan.
* Rebase the code based on Andrew'patch "xen/x86: Record xsave features in c->x86_capabilities".
* Re-split the patch to avoid building errors. Move some func definitions from patch1 to patch2.
* Change func name load/save_xsave_states to compress/expand_xsave_states in patch2.
* Add macro to handle redundancy in xrstor.
* Fix some code errors and coding style errors.
* Add some descriptions in commit message.
Changes in v5:
* Address comments from Andrew/Jan,mainly:
* Add lazy writes of the xss_msr.
* Add xsave_area check when save/restore guest.
* Add xsavec support.
* Use word 2 in xen/include/asm-x86/cpufeature.h.
* Fix some code errors.
Changes in v4:
* Address comments from Andrew, mainly:
* No xsaves suporting for pv guest.
* Using xstate_sizes instead of domain_cpuid in hvm_cupid in patch 3.
* Add support for format translation when perform pv guest migration in patch 2.
* Fix some code errors.
Changes in v3:
* Address comments from Jan/Konrad
* Change the bits of eax/ebx/ecx/edx passed to guest in patch 4.
* Add code to verify whether host supports xsaves or not in patch 1.
Changes in v2:
* Address comments from Andrew/chao/Jan, mainly:
* Add details information of xsaves/xrstors feature.
* Test migration between xsaves-support machine and none-xsaves-support machine
* Remove XGETBV1/XSAVEC/XSAVEOPT out of 'else' in patch 3.
* Change macro name XGETBV to XGETBV1 in patch 4.
This patchset enable xsaves/xrstors feature which will be available on
Intel Skylake and later platform. Like xsave/xrstor, xsaves/xrstors
feature will save and load processor state from a region of memory called
XSAVE area. While unlike xsave/xrstor, xsaves/xrstors:
a) use the compacted format only for the extended region
of the XSAVE area which saves memory for you;
b) can operate on supervisor state components so the feature
is prerequisite to support new supervisor state components;
c) execute only if CPL=0.
Detail hardware spec can be found in chapter 13 (section 13.11 13.12) of the
Intel SDM [1].
patch1: add basic definition/function to support xsaves
patch2: add xsaves/xrstors support for xen
patch3-4: add xsaves/xrstors support for hvm guest
[1] Intel SDM (http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-manual-325462.pdf)
Shuai Ruan (4):
x86/xsaves: add basic definitions/helpers to support xsaves
x86/xsaves: enable xsaves/xrstors/xsavec in xen
x86/xsaves: enable xsaves/xrstors for hvm guest
libxc: expose xsaves/xgetbv1/xsavec to hvm guest
tools/libxc/xc_cpuid_x86.c | 11 +-
xen/arch/x86/domain.c | 2 +
xen/arch/x86/domctl.c | 31 ++++-
xen/arch/x86/hvm/hvm.c | 40 +++++-
xen/arch/x86/hvm/vmx/vmcs.c | 5 +-
xen/arch/x86/hvm/vmx/vmx.c | 20 +++
xen/arch/x86/i387.c | 4 +
xen/arch/x86/traps.c | 6 +-
xen/arch/x86/xstate.c | 266 ++++++++++++++++++++++++++++++++-----
xen/include/asm-x86/hvm/vcpu.h | 1 +
xen/include/asm-x86/hvm/vmx/vmcs.h | 4 +
xen/include/asm-x86/hvm/vmx/vmx.h | 2 +
xen/include/asm-x86/msr-index.h | 2 +
xen/include/asm-x86/xstate.h | 15 ++-
14 files changed, 358 insertions(+), 51 deletions(-)
--
1.9.1
^ permalink raw reply [flat|nested] 11+ messages in thread
* [V7 1/4] x86/xsaves: add basic definitions/helpers to support xsaves
2015-10-20 8:21 [V7 0/4] add xsaves/xrstors support Shuai Ruan
@ 2015-10-20 8:21 ` Shuai Ruan
2015-10-20 13:26 ` Andrew Cooper
2015-10-20 8:21 ` [V7 2/4] x86/xsaves: enable xsaves/xrstors/xsavec in xen Shuai Ruan
` (2 subsequent siblings)
3 siblings, 1 reply; 11+ messages in thread
From: Shuai Ruan @ 2015-10-20 8:21 UTC (permalink / raw)
To: xen-devel
Cc: kevin.tian, wei.liu2, Ian.Campbell, stefano.stabellini,
jun.nakajima, andrew.cooper3, ian.jackson, eddie.dong, jbeulich,
keir
This patch add basic definitions/helpers which will be used in
later patches.
Signed-off-by: Shuai Ruan <shuai.ruan@linux.intel.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
xen/arch/x86/xstate.c | 19 +++++++++++++++++++
xen/include/asm-x86/hvm/vcpu.h | 1 +
xen/include/asm-x86/msr-index.h | 2 ++
xen/include/asm-x86/xstate.h | 12 ++++++++++--
4 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/xen/arch/x86/xstate.c b/xen/arch/x86/xstate.c
index 9ddff90..4230066 100644
--- a/xen/arch/x86/xstate.c
+++ b/xen/arch/x86/xstate.c
@@ -24,6 +24,9 @@ static u32 __read_mostly xsave_cntxt_size;
/* A 64-bit bitmask of the XSAVE/XRSTOR features supported by processor. */
u64 __read_mostly xfeature_mask;
+/* Cached xss for fast read */
+static DEFINE_PER_CPU(uint64_t, xss);
+
/* Cached xcr0 for fast read */
static DEFINE_PER_CPU(uint64_t, xcr0);
@@ -60,6 +63,22 @@ uint64_t get_xcr0(void)
return this_cpu(xcr0);
}
+void set_msr_xss(u64 xss)
+{
+ u64 *this_xss = &this_cpu(xss);
+
+ if ( *this_xss != xss )
+ {
+ wrmsrl(MSR_IA32_XSS, xss);
+ this_cpu(xss) = xss;
+ }
+}
+
+uint64_t get_msr_xss(void)
+{
+ return this_cpu(xss);
+}
+
void xsave(struct vcpu *v, uint64_t mask)
{
struct xsave_struct *ptr = v->arch.xsave_area;
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 65c1d02..b8ad93c 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 f0d8f0b..b95a5b5 100644
--- a/xen/include/asm-x86/xstate.h
+++ b/xen/include/asm-x86/xstate.h
@@ -19,8 +19,12 @@
#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 XSTATE_AREA_MIN_SIZE (512 + 64) /* FP/SSE + XSAVE.HEADER */
+#define FXSAVE_SIZE 512
+#define XSAVE_HDR_OFFSET FXSAVE_SIZE
+#define XSTATE_AREA_MIN_SIZE (FXSAVE_SIZE + XSAVE_HDR_SIZE)
#define XSTATE_FP (1ULL << 0)
#define XSTATE_SSE (1ULL << 1)
@@ -38,6 +42,7 @@
#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;
@@ -68,7 +73,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 */
@@ -78,6 +84,8 @@ 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);
--
1.9.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [V7 2/4] x86/xsaves: enable xsaves/xrstors/xsavec in xen
2015-10-20 8:21 [V7 0/4] add xsaves/xrstors support Shuai Ruan
2015-10-20 8:21 ` [V7 1/4] x86/xsaves: add basic definitions/helpers to support xsaves Shuai Ruan
@ 2015-10-20 8:21 ` Shuai Ruan
2015-10-22 12:13 ` Jan Beulich
2015-10-20 8:21 ` [V7 3/4] x86/xsaves: enable xsaves/xrstors for hvm guest Shuai Ruan
2015-10-20 8:21 ` [V7 4/4] libxc: expose xsaves/xgetbv1/xsavec to " Shuai Ruan
3 siblings, 1 reply; 11+ messages in thread
From: Shuai Ruan @ 2015-10-20 8:21 UTC (permalink / raw)
To: xen-devel
Cc: kevin.tian, wei.liu2, Ian.Campbell, stefano.stabellini,
jun.nakajima, andrew.cooper3, ian.jackson, eddie.dong, jbeulich,
keir
This patch uses xsaves/xrstors/xsavec instead of xsaveopt/xrstor
to perform the xsave_area switching so that xen itself
can benefit from them when available.
For xsaves/xrstors/xsavec only use compact format. Add format conversion
support when perform guest os migration.
Also, pv guest will not support xsaves/xrstors.
Signed-off-by: Shuai Ruan <shuai.ruan@linux.intel.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
xen/arch/x86/domain.c | 2 +
xen/arch/x86/domctl.c | 31 +++++-
xen/arch/x86/hvm/hvm.c | 13 +--
xen/arch/x86/i387.c | 4 +
xen/arch/x86/traps.c | 6 +-
xen/arch/x86/xstate.c | 247 +++++++++++++++++++++++++++++++++++++------
xen/include/asm-x86/xstate.h | 2 +
7 files changed, 259 insertions(+), 46 deletions(-)
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index fe3be30..807188d 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -1568,6 +1568,8 @@ static void __context_switch(void)
if ( xcr0 != get_xcr0() && !set_xcr0(xcr0) )
BUG();
}
+ if ( cpu_has_xsaves && has_hvm_container_vcpu(n) )
+ set_msr_xss(n->arch.hvm_vcpu.msr_xss);
vcpu_restore_fpu_eager(n);
n->arch.ctxt_switch_to(n);
}
diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index 0f6fdb9..551dde2 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -897,9 +897,30 @@ long arch_do_domctl(
ret = -EFAULT;
offset += sizeof(v->arch.xcr0_accum);
- if ( !ret && copy_to_guest_offset(evc->buffer, offset,
- (void *)v->arch.xsave_area,
- size - 2 * sizeof(uint64_t)) )
+
+ if ( !ret && (cpu_has_xsaves || cpu_has_xsavec) )
+ {
+ void *xsave_area;
+
+ xsave_area = xmalloc_bytes(size);
+ if ( !xsave_area )
+ {
+ ret = -ENOMEM;
+ vcpu_unpause(v);
+ goto vcpuextstate_out;
+ }
+
+ expand_xsave_states(v, xsave_area,
+ size - 2 * sizeof(uint64_t));
+
+ if ( copy_to_guest_offset(evc->buffer, offset, xsave_area,
+ size - 2 * sizeof(uint64_t)) )
+ ret = -EFAULT;
+ xfree(xsave_area);
+ }
+ else if ( !ret && copy_to_guest_offset(evc->buffer, offset,
+ (void *)v->arch.xsave_area,
+ size - 2 * sizeof(uint64_t)) )
ret = -EFAULT;
vcpu_unpause(v);
@@ -955,8 +976,8 @@ long arch_do_domctl(
v->arch.xcr0_accum = _xcr0_accum;
if ( _xcr0_accum & XSTATE_NONLAZY )
v->arch.nonlazy_xstate_used = 1;
- memcpy(v->arch.xsave_area, _xsave_area,
- evc->size - 2 * sizeof(uint64_t));
+ compress_xsave_states(v, _xsave_area,
+ evc->size - 2 * sizeof(uint64_t));
vcpu_unpause(v);
}
else
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 3fa2280..003afb3 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -2088,6 +2088,8 @@ static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
memcpy(v->arch.xsave_area, ctxt.fpu_regs, sizeof(ctxt.fpu_regs));
xsave_area->xsave_hdr.xstate_bv = XSTATE_FP_SSE;
+ if ( cpu_has_xsaves | cpu_has_xsavec )
+ xsave_area->xsave_hdr.xcomp_bv |= XSTATE_FP_SSE;
}
else
memcpy(v->arch.fpu_ctxt, ctxt.fpu_regs, sizeof(ctxt.fpu_regs));
@@ -2157,8 +2159,8 @@ static int hvm_save_cpu_xsave_states(struct domain *d, hvm_domain_context_t *h)
ctxt->xfeature_mask = xfeature_mask;
ctxt->xcr0 = v->arch.xcr0;
ctxt->xcr0_accum = v->arch.xcr0_accum;
- memcpy(&ctxt->save_area, v->arch.xsave_area,
- size - offsetof(struct hvm_hw_cpu_xsave, save_area));
+ expand_xsave_states(v, &ctxt->save_area,
+ size - offsetof(typeof(*ctxt), save_area));
}
return 0;
@@ -2257,10 +2259,9 @@ static int hvm_load_cpu_xsave_states(struct domain *d, hvm_domain_context_t *h)
v->arch.xcr0_accum = ctxt->xcr0_accum;
if ( ctxt->xcr0_accum & XSTATE_NONLAZY )
v->arch.nonlazy_xstate_used = 1;
- memcpy(v->arch.xsave_area, &ctxt->save_area,
- min(desc->length, size) - offsetof(struct hvm_hw_cpu_xsave,
- save_area));
-
+ compress_xsave_states(v, &ctxt->save_area,
+ min(desc->length, size) -
+ offsetof(struct hvm_hw_cpu_xsave,save_area));
return 0;
}
diff --git a/xen/arch/x86/i387.c b/xen/arch/x86/i387.c
index 66b51cb..cf5a47d 100644
--- a/xen/arch/x86/i387.c
+++ b/xen/arch/x86/i387.c
@@ -282,7 +282,11 @@ int vcpu_init_fpu(struct vcpu *v)
return rc;
if ( v->arch.xsave_area )
+ {
v->arch.fpu_ctxt = &v->arch.xsave_area->fpu_sse;
+ if ( cpu_has_xsaves || cpu_has_xsavec )
+ v->arch.xsave_area->xsave_hdr.xcomp_bv |= XSTATE_COMPACTION_ENABLED;
+ }
else
{
v->arch.fpu_ctxt = _xzalloc(sizeof(v->arch.xsave_area->fpu_sse), 16);
diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index 8093535..0d30eea 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -935,9 +935,9 @@ void pv_cpuid(struct cpu_user_regs *regs)
goto unsupported;
if ( regs->_ecx == 1 )
{
- a &= boot_cpu_data.x86_capability[X86_FEATURE_XSAVEOPT / 32];
- if ( !cpu_has_xsaves )
- b = c = d = 0;
+ a &= (boot_cpu_data.x86_capability[X86_FEATURE_XSAVEOPT / 32] &
+ ~cpufeat_mask(X86_FEATURE_XSAVES));
+ b = c = d = 0;
}
break;
diff --git a/xen/arch/x86/xstate.c b/xen/arch/x86/xstate.c
index 4230066..a09d707 100644
--- a/xen/arch/x86/xstate.c
+++ b/xen/arch/x86/xstate.c
@@ -23,6 +23,10 @@ static u32 __read_mostly xsave_cntxt_size;
/* A 64-bit bitmask of the XSAVE/XRSTOR features supported by processor. */
u64 __read_mostly xfeature_mask;
+static unsigned int * __read_mostly xstate_offsets;
+static 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 xss for fast read */
static DEFINE_PER_CPU(uint64_t, xss);
@@ -79,6 +83,164 @@ uint64_t get_msr_xss(void)
return this_cpu(xss);
}
+static bool_t xsave_area_compressed(const struct xsave_struct *xsave_area)
+{
+ return xsave_area && (xsave_area->xsave_hdr.xcomp_bv
+ & XSTATE_COMPACTION_ENABLED);
+}
+
+static int setup_xstate_features(bool_t bsp)
+{
+ unsigned int leaf, tmp, eax, ebx;
+
+ if ( bsp )
+ {
+ xstate_features = fls(xfeature_mask);
+ 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 __init 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] + xstate_sizes[i] <= xsave_cntxt_size);
+ }
+}
+
+static void *get_xsave_addr(const 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 expand_xsave_states(struct vcpu *v, void *dest, unsigned int size)
+{
+ const struct xsave_struct *xsave = v->arch.xsave_area;
+ u64 xstate_bv = xsave->xsave_hdr.xstate_bv;
+ u64 valid;
+
+ if ( !cpu_has_xsaves && !cpu_has_xsavec )
+ {
+ memcpy(dest, xsave, size);
+ return;
+ }
+
+ 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);
+
+ ((struct xsave_struct *)dest)->xsave_hdr.xstate_bv = xstate_bv;
+ ((struct xsave_struct *)dest)->xsave_hdr.xcomp_bv = 0;
+
+ /*
+ * 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;
+ unsigned 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 compress_xsave_states(struct vcpu *v, const void *src, unsigned int size)
+{
+ struct xsave_struct *xsave = v->arch.xsave_area;
+ u64 xstate_bv = ((const struct xsave_struct *)src)->xsave_hdr.xstate_bv;
+ u64 valid;
+
+ if ( !cpu_has_xsaves && !cpu_has_xsavec )
+ {
+ memcpy(xsave, src, size);
+ return;
+ }
+
+ ASSERT(!xsave_area_compressed(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 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;
+ unsigned int index = fls(feature) - 1;
+ void *dest = get_xsave_addr(xsave, index);
+
+ 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;
@@ -91,7 +253,15 @@ void xsave(struct vcpu *v, uint64_t mask)
typeof(ptr->fpu_sse.fip.sel) fcs = ptr->fpu_sse.fip.sel;
typeof(ptr->fpu_sse.fdp.sel) fds = ptr->fpu_sse.fdp.sel;
- if ( cpu_has_xsaveopt )
+ if ( cpu_has_xsaves )
+ asm volatile ( ".byte 0x48,0x0f,0xc7,0x2f"
+ : "=m" (*ptr)
+ : "a" (lmask), "d" (hmask), "D" (ptr) );
+ else if ( cpu_has_xsavec )
+ asm volatile ( ".byte 0x48,0x0f,0xc7,0x27"
+ : "=m" (*ptr)
+ : "a" (lmask), "d" (hmask), "D" (ptr) );
+ else if ( cpu_has_xsaveopt )
{
/*
* xsaveopt may not write the FPU portion even when the respective
@@ -144,7 +314,15 @@ void xsave(struct vcpu *v, uint64_t mask)
}
else
{
- if ( cpu_has_xsaveopt )
+ if ( cpu_has_xsaves )
+ asm volatile ( ".byte 0x48,0x0f,0xc7,0x2f"
+ : "=m" (*ptr)
+ : "a" (lmask), "d" (hmask), "D" (ptr) );
+ else if ( cpu_has_xsavec )
+ asm volatile ( ".byte 0x48,0x0f,0xc7,0x27"
+ : "=m" (*ptr)
+ : "a" (lmask), "d" (hmask), "D" (ptr) );
+ else if ( cpu_has_xsaveopt )
asm volatile ( ".byte 0x0f,0xae,0x37"
: "=m" (*ptr)
: "a" (lmask), "d" (hmask), "D" (ptr) );
@@ -158,6 +336,20 @@ void xsave(struct vcpu *v, uint64_t mask)
ptr->fpu_sse.x[FPU_WORD_SIZE_OFFSET] = word_size;
}
+#define XSTATE_FIXUP ".section .fixup,\"ax\" \n" \
+ "2: mov %5,%%ecx \n" \
+ " xor %1,%1 \n" \
+ " rep stosb \n" \
+ " lea %2,%0 \n" \
+ " mov %3,%1 \n" \
+ " jmp 1b \n" \
+ ".previous \n" \
+ _ASM_EXTABLE(1b, 2b) \
+ : "+&D" (ptr), "+&a" (lmask) \
+ : "m" (*ptr), "g" (lmask), "d" (hmask), \
+ "m" (xsave_cntxt_size) \
+ : "ecx"
+
void xrstor(struct vcpu *v, uint64_t mask)
{
uint32_t hmask = mask >> 32;
@@ -187,36 +379,20 @@ void xrstor(struct vcpu *v, uint64_t mask)
switch ( __builtin_expect(ptr->fpu_sse.x[FPU_WORD_SIZE_OFFSET], 8) )
{
default:
- asm volatile ( "1: .byte 0x48,0x0f,0xae,0x2f\n"
- ".section .fixup,\"ax\" \n"
- "2: mov %5,%%ecx \n"
- " xor %1,%1 \n"
- " rep stosb \n"
- " lea %2,%0 \n"
- " mov %3,%1 \n"
- " jmp 1b \n"
- ".previous \n"
- _ASM_EXTABLE(1b, 2b)
- : "+&D" (ptr), "+&a" (lmask)
- : "m" (*ptr), "g" (lmask), "d" (hmask),
- "m" (xsave_cntxt_size)
- : "ecx" );
- break;
+ if ( cpu_has_xsaves )
+ asm volatile ( "1: .byte 0x48,0x0f,0xc7,0x1f\n"
+ XSTATE_FIXUP );
+ else
+ asm volatile ( "1: .byte 0x48,0x0f,0xae,0x2f\n"
+ XSTATE_FIXUP );
+ break;
case 4: case 2:
- asm volatile ( "1: .byte 0x0f,0xae,0x2f\n"
- ".section .fixup,\"ax\" \n"
- "2: mov %5,%%ecx \n"
- " xor %1,%1 \n"
- " rep stosb \n"
- " lea %2,%0 \n"
- " mov %3,%1 \n"
- " jmp 1b \n"
- ".previous \n"
- _ASM_EXTABLE(1b, 2b)
- : "+&D" (ptr), "+&a" (lmask)
- : "m" (*ptr), "g" (lmask), "d" (hmask),
- "m" (xsave_cntxt_size)
- : "ecx" );
+ if ( cpu_has_xsaves )
+ asm volatile ( "1: .byte 0x48,0x0f,0xc7,0x1f\n"
+ XSTATE_FIXUP );
+ else
+ asm volatile ( "1: .byte 0x0f,0xae,0x2f\n"
+ XSTATE_FIXUP );
break;
}
}
@@ -343,11 +519,18 @@ void xstate_init(struct cpuinfo_x86 *c)
/* Mask out features not currently understood by Xen. */
eax &= (cpufeat_mask(X86_FEATURE_XSAVEOPT) |
- cpufeat_mask(X86_FEATURE_XSAVEC));
+ cpufeat_mask(X86_FEATURE_XSAVEC) |
+ cpufeat_mask(X86_FEATURE_XGETBV1) |
+ cpufeat_mask(X86_FEATURE_XSAVES));
c->x86_capability[X86_FEATURE_XSAVEOPT / 32] = eax;
BUG_ON(eax != boot_cpu_data.x86_capability[X86_FEATURE_XSAVEOPT / 32]);
+
+ if ( setup_xstate_features(bsp) )
+ BUG();
+ if ( bsp && (cpu_has_xsaves || cpu_has_xsavec) )
+ setup_xstate_comp();
}
static bool_t valid_xcr0(u64 xcr0)
diff --git a/xen/include/asm-x86/xstate.h b/xen/include/asm-x86/xstate.h
index b95a5b5..414cc99 100644
--- a/xen/include/asm-x86/xstate.h
+++ b/xen/include/asm-x86/xstate.h
@@ -91,6 +91,8 @@ 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 expand_xsave_states(struct vcpu *v, void *dest, unsigned int size);
+void compress_xsave_states(struct vcpu *v, const void *src, unsigned int size);
/* extended state init and cleanup functions */
void xstate_free_save_area(struct vcpu *v);
--
1.9.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [V7 3/4] x86/xsaves: enable xsaves/xrstors for hvm guest
2015-10-20 8:21 [V7 0/4] add xsaves/xrstors support Shuai Ruan
2015-10-20 8:21 ` [V7 1/4] x86/xsaves: add basic definitions/helpers to support xsaves Shuai Ruan
2015-10-20 8:21 ` [V7 2/4] x86/xsaves: enable xsaves/xrstors/xsavec in xen Shuai Ruan
@ 2015-10-20 8:21 ` Shuai Ruan
2015-10-22 14:20 ` Jan Beulich
2015-10-20 8:21 ` [V7 4/4] libxc: expose xsaves/xgetbv1/xsavec to " Shuai Ruan
3 siblings, 1 reply; 11+ messages in thread
From: Shuai Ruan @ 2015-10-20 8:21 UTC (permalink / raw)
To: xen-devel
Cc: kevin.tian, wei.liu2, Ian.Campbell, stefano.stabellini,
jun.nakajima, andrew.cooper3, ian.jackson, eddie.dong, jbeulich,
keir
This patch enables xsaves for hvm guest, includes:
1.handle xsaves vmcs init and vmexit.
2.add logic to write/read the XSS msr.
Signed-off-by: Shuai Ruan <shuai.ruan@linux.intel.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
xen/arch/x86/hvm/hvm.c | 27 +++++++++++++++++++++++++++
xen/arch/x86/hvm/vmx/vmcs.c | 5 ++++-
xen/arch/x86/hvm/vmx/vmx.c | 20 ++++++++++++++++++++
xen/arch/x86/xstate.c | 4 ++--
xen/include/asm-x86/hvm/vmx/vmcs.h | 4 ++++
xen/include/asm-x86/hvm/vmx/vmx.h | 2 ++
xen/include/asm-x86/xstate.h | 1 +
7 files changed, 60 insertions(+), 3 deletions(-)
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 003afb3..ada3b0b 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -4553,6 +4553,20 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
*ebx = _eax + _ebx;
}
}
+ if ( count == 1 )
+ {
+ if ( cpu_has_xsaves && cpu_has_vmx_xsaves )
+ {
+ *ebx = XSTATE_AREA_MIN_SIZE;
+ if ( v->arch.xcr0 | v->arch.hvm_vcpu.msr_xss )
+ for ( sub_leaf = 2; sub_leaf < 63; sub_leaf++ )
+ if ( (v->arch.xcr0 | v->arch.hvm_vcpu.msr_xss)
+ & (1ULL << sub_leaf) )
+ *ebx += xstate_sizes[sub_leaf];
+ }
+ else
+ *ebx = *ecx = *edx = 0;
+ }
break;
case 0x80000001:
@@ -4652,6 +4666,12 @@ int hvm_msr_read_intercept(unsigned int msr, uint64_t *msr_content)
*msr_content = v->arch.hvm_vcpu.guest_efer;
break;
+ case MSR_IA32_XSS:
+ if ( !cpu_has_xsaves )
+ goto gp_fault;
+ *msr_content = v->arch.hvm_vcpu.msr_xss;
+ break;
+
case MSR_IA32_TSC:
*msr_content = _hvm_rdtsc_intercept();
break;
@@ -4784,6 +4804,13 @@ int hvm_msr_write_intercept(unsigned int msr, uint64_t msr_content,
return X86EMUL_EXCEPTION;
break;
+ case MSR_IA32_XSS:
+ /* No XSS features currently supported for guests. */
+ if ( !cpu_has_xsaves || msr_content != 0 )
+ goto gp_fault;
+ v->arch.hvm_vcpu.msr_xss = msr_content;
+ break;
+
case MSR_IA32_TSC:
hvm_set_guest_tsc(v, msr_content);
break;
diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c
index 3592a88..7185d55 100644
--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -240,7 +240,8 @@ static int vmx_init_vmcs_config(void)
SECONDARY_EXEC_PAUSE_LOOP_EXITING |
SECONDARY_EXEC_ENABLE_INVPCID |
SECONDARY_EXEC_ENABLE_VM_FUNCTIONS |
- SECONDARY_EXEC_ENABLE_VIRT_EXCEPTIONS);
+ SECONDARY_EXEC_ENABLE_VIRT_EXCEPTIONS |
+ SECONDARY_EXEC_XSAVES);
rdmsrl(MSR_IA32_VMX_MISC, _vmx_misc_cap);
if ( _vmx_misc_cap & VMX_MISC_VMWRITE_ALL )
opt |= SECONDARY_EXEC_ENABLE_VMCS_SHADOWING;
@@ -1249,6 +1250,8 @@ static int construct_vmcs(struct vcpu *v)
__vmwrite(HOST_PAT, host_pat);
__vmwrite(GUEST_PAT, guest_pat);
}
+ if ( cpu_has_vmx_xsaves )
+ __vmwrite(XSS_EXIT_BITMAP, 0);
vmx_vmcs_exit(v);
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index bbec0e8..5d723e8 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -2852,6 +2852,18 @@ static void vmx_idtv_reinject(unsigned long idtv_info)
}
}
+static void vmx_handle_xsaves(void)
+{
+ gdprintk(XENLOG_ERR, "xsaves should not cause vmexit\n");
+ domain_crash(current->domain);
+}
+
+static void vmx_handle_xrstors(void)
+{
+ gdprintk(XENLOG_ERR, "xrstors should not cause vmexit\n");
+ domain_crash(current->domain);
+}
+
static int vmx_handle_apic_write(void)
{
unsigned long exit_qualification;
@@ -3423,6 +3435,14 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs)
vmx_vcpu_flush_pml_buffer(v);
break;
+ case EXIT_REASON_XSAVES:
+ vmx_handle_xsaves();
+ break;
+
+ case EXIT_REASON_XRSTORS:
+ vmx_handle_xrstors();
+ break;
+
case EXIT_REASON_ACCESS_GDTR_OR_IDTR:
case EXIT_REASON_ACCESS_LDTR_OR_TR:
case EXIT_REASON_VMX_PREEMPTION_TIMER_EXPIRED:
diff --git a/xen/arch/x86/xstate.c b/xen/arch/x86/xstate.c
index a09d707..3b7eb48 100644
--- a/xen/arch/x86/xstate.c
+++ b/xen/arch/x86/xstate.c
@@ -23,8 +23,8 @@ static u32 __read_mostly xsave_cntxt_size;
/* A 64-bit bitmask of the XSAVE/XRSTOR features supported by processor. */
u64 __read_mostly xfeature_mask;
-static unsigned int * __read_mostly xstate_offsets;
-static unsigned int * __read_mostly xstate_sizes;
+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];
diff --git a/xen/include/asm-x86/hvm/vmx/vmcs.h b/xen/include/asm-x86/hvm/vmx/vmcs.h
index f1126d4..79c2c58 100644
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h
@@ -225,6 +225,7 @@ extern u32 vmx_vmentry_control;
#define SECONDARY_EXEC_ENABLE_VMCS_SHADOWING 0x00004000
#define SECONDARY_EXEC_ENABLE_PML 0x00020000
#define SECONDARY_EXEC_ENABLE_VIRT_EXCEPTIONS 0x00040000
+#define SECONDARY_EXEC_XSAVES 0x00100000
extern u32 vmx_secondary_exec_control;
#define VMX_EPT_EXEC_ONLY_SUPPORTED 0x00000001
@@ -291,6 +292,8 @@ extern u32 vmx_secondary_exec_control;
(vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_VIRT_EXCEPTIONS)
#define cpu_has_vmx_pml \
(vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_PML)
+#define cpu_has_vmx_xsaves \
+ (vmx_secondary_exec_control & SECONDARY_EXEC_XSAVES)
#define VMCS_RID_TYPE_MASK 0x80000000
@@ -365,6 +368,7 @@ enum vmcs_field {
VMREAD_BITMAP = 0x00002026,
VMWRITE_BITMAP = 0x00002028,
VIRT_EXCEPTION_INFO = 0x0000202a,
+ XSS_EXIT_BITMAP = 0x0000202c,
GUEST_PHYSICAL_ADDRESS = 0x00002400,
VMCS_LINK_POINTER = 0x00002800,
GUEST_IA32_DEBUGCTL = 0x00002802,
diff --git a/xen/include/asm-x86/hvm/vmx/vmx.h b/xen/include/asm-x86/hvm/vmx/vmx.h
index 2ed62f9..cb66925 100644
--- a/xen/include/asm-x86/hvm/vmx/vmx.h
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h
@@ -188,6 +188,8 @@ static inline unsigned long pi_get_pir(struct pi_desc *pi_desc, int group)
#define EXIT_REASON_INVPCID 58
#define EXIT_REASON_VMFUNC 59
#define EXIT_REASON_PML_FULL 62
+#define EXIT_REASON_XSAVES 63
+#define EXIT_REASON_XRSTORS 64
/*
* Interruption-information format
diff --git a/xen/include/asm-x86/xstate.h b/xen/include/asm-x86/xstate.h
index 414cc99..3de88bd 100644
--- a/xen/include/asm-x86/xstate.h
+++ b/xen/include/asm-x86/xstate.h
@@ -45,6 +45,7 @@
#define XSTATE_COMPACTION_ENABLED (1ULL << 63)
extern u64 xfeature_mask;
+extern unsigned int *xstate_offsets, *xstate_sizes;
/* extended state save area */
struct __packed __attribute__((aligned (64))) xsave_struct
--
1.9.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [V7 4/4] libxc: expose xsaves/xgetbv1/xsavec to hvm guest
2015-10-20 8:21 [V7 0/4] add xsaves/xrstors support Shuai Ruan
` (2 preceding siblings ...)
2015-10-20 8:21 ` [V7 3/4] x86/xsaves: enable xsaves/xrstors for hvm guest Shuai Ruan
@ 2015-10-20 8:21 ` Shuai Ruan
3 siblings, 0 replies; 11+ messages in thread
From: Shuai Ruan @ 2015-10-20 8:21 UTC (permalink / raw)
To: xen-devel
Cc: kevin.tian, wei.liu2, Ian.Campbell, stefano.stabellini,
jun.nakajima, andrew.cooper3, ian.jackson, eddie.dong, jbeulich,
keir
From: Shuai Ruan <shuai.ruan@intel.com>
This patch exposes xsaves/xgetbv1/xsavec to hvm guest.
The reserved bits of eax/ebx/ecx/edx must be cleaned up
when call cpuid(0dh) with leaf 1 or 2..63.
According to the spec the following bits must be reserved:
For leaf 1, bits 03-04/08-31 of ecx is reserved. Edx is reserved.
For leaf 2...63, bits 01-31 of ecx is reserved, Edx is reserved.
But as no XSS festures are currently supported, even in HVM guests,
for leaf 2...63, ecx should be zero at the moment.
Signed-off-by: Shuai Ruan <shuai.ruan@intel.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
tools/libxc/xc_cpuid_x86.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c
index 031c848..51bbc70 100644
--- a/tools/libxc/xc_cpuid_x86.c
+++ b/tools/libxc/xc_cpuid_x86.c
@@ -282,6 +282,9 @@ static void intel_xc_cpuid_policy(xc_interface *xch,
}
#define XSAVEOPT (1 << 0)
+#define XSAVEC (1 << 1)
+#define XGETBV1 (1 << 2)
+#define XSAVES (1 << 3)
/* Configure extended state enumeration leaves (0x0000000D for xsave) */
static void xc_cpuid_config_xsave(xc_interface *xch,
const struct cpuid_domain_info *info,
@@ -318,8 +321,12 @@ static void xc_cpuid_config_xsave(xc_interface *xch,
regs[1] = 512 + 64; /* FP/SSE + XSAVE.HEADER */
break;
case 1: /* leaf 1 */
- regs[0] &= XSAVEOPT;
- regs[1] = regs[2] = regs[3] = 0;
+ if ( info->hvm )
+ regs[0] &= (XSAVEOPT | XSAVEC | XGETBV1 | XSAVES);
+ else
+ regs[0] &= XSAVEOPT;
+ regs[2] &= info->xfeature_mask;
+ regs[3] = 0;
break;
case 2 ... 63: /* sub-leaves */
if ( !(info->xfeature_mask & (1ULL << input[1])) )
--
1.9.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [V7 1/4] x86/xsaves: add basic definitions/helpers to support xsaves
2015-10-20 8:21 ` [V7 1/4] x86/xsaves: add basic definitions/helpers to support xsaves Shuai Ruan
@ 2015-10-20 13:26 ` Andrew Cooper
2015-10-22 4:20 ` Shuai Ruan
0 siblings, 1 reply; 11+ messages in thread
From: Andrew Cooper @ 2015-10-20 13:26 UTC (permalink / raw)
To: Shuai Ruan, xen-devel
Cc: kevin.tian, wei.liu2, Ian.Campbell, stefano.stabellini,
eddie.dong, ian.jackson, jbeulich, jun.nakajima, keir
On 20/10/15 09:21, Shuai Ruan wrote:
> This patch add basic definitions/helpers which will be used in
> later patches.
>
> Signed-off-by: Shuai Ruan <shuai.ruan@linux.intel.com>
> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
> ---
> xen/arch/x86/xstate.c | 19 +++++++++++++++++++
> xen/include/asm-x86/hvm/vcpu.h | 1 +
> xen/include/asm-x86/msr-index.h | 2 ++
> xen/include/asm-x86/xstate.h | 12 ++++++++++--
> 4 files changed, 32 insertions(+), 2 deletions(-)
>
> diff --git a/xen/arch/x86/xstate.c b/xen/arch/x86/xstate.c
> index 9ddff90..4230066 100644
> --- a/xen/arch/x86/xstate.c
> +++ b/xen/arch/x86/xstate.c
> @@ -24,6 +24,9 @@ static u32 __read_mostly xsave_cntxt_size;
> /* A 64-bit bitmask of the XSAVE/XRSTOR features supported by processor. */
> u64 __read_mostly xfeature_mask;
>
> +/* Cached xss for fast read */
> +static DEFINE_PER_CPU(uint64_t, xss);
> +
> /* Cached xcr0 for fast read */
> static DEFINE_PER_CPU(uint64_t, xcr0);
>
> @@ -60,6 +63,22 @@ uint64_t get_xcr0(void)
> return this_cpu(xcr0);
> }
>
> +void set_msr_xss(u64 xss)
> +{
> + u64 *this_xss = &this_cpu(xss);
> +
> + if ( *this_xss != xss )
> + {
> + wrmsrl(MSR_IA32_XSS, xss);
> + this_cpu(xss) = xss;
*this_xss = xss;
Using this_cpu() multiple times cannot be optimised by compiler (because
of the underlying definition), which is why the optimisation is
performed manually by pulling the value out as a pointer.
~Andrew
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [V7 1/4] x86/xsaves: add basic definitions/helpers to support xsaves
2015-10-20 13:26 ` Andrew Cooper
@ 2015-10-22 4:20 ` Shuai Ruan
0 siblings, 0 replies; 11+ messages in thread
From: Shuai Ruan @ 2015-10-22 4:20 UTC (permalink / raw)
To: Andrew Cooper
Cc: kevin.tian, wei.liu2, Ian.Campbell, stefano.stabellini,
jun.nakajima, eddie.dong, ian.jackson, xen-devel, jbeulich, keir
On Tue, Oct 20, 2015 at 02:26:46PM +0100, Andrew Cooper wrote:
> On 20/10/15 09:21, Shuai Ruan wrote:
> > This patch add basic definitions/helpers which will be used in
> > later patches.
> >
> *this_xss = xss;
>
> Using this_cpu() multiple times cannot be optimised by compiler (because
> of the underlying definition), which is why the optimisation is
> performed manually by pulling the value out as a pointer.
>
Ok. I will fix this in next version.
> ~Andrew
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [V7 2/4] x86/xsaves: enable xsaves/xrstors/xsavec in xen
2015-10-20 8:21 ` [V7 2/4] x86/xsaves: enable xsaves/xrstors/xsavec in xen Shuai Ruan
@ 2015-10-22 12:13 ` Jan Beulich
0 siblings, 0 replies; 11+ messages in thread
From: Jan Beulich @ 2015-10-22 12:13 UTC (permalink / raw)
To: Shuai Ruan
Cc: kevin.tian, wei.liu2, Ian.Campbell, stefano.stabellini,
andrew.cooper3, ian.jackson, xen-devel, jun.nakajima, keir
>>> On 20.10.15 at 10:21, <shuai.ruan@linux.intel.com> wrote:
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -2088,6 +2088,8 @@ static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
>
> memcpy(v->arch.xsave_area, ctxt.fpu_regs, sizeof(ctxt.fpu_regs));
> xsave_area->xsave_hdr.xstate_bv = XSTATE_FP_SSE;
> + if ( cpu_has_xsaves | cpu_has_xsavec )
> + xsave_area->xsave_hdr.xcomp_bv |= XSTATE_FP_SSE;
Is this really |= ? Not just for similarity with the assignment above I
would expect this to be =, as we don't know what value the field
had before.
Also, are you intentionally using | instead of || in the if() (other than
you do elsewhere in the patch)?
> @@ -2257,10 +2259,9 @@ static int hvm_load_cpu_xsave_states(struct domain *d, hvm_domain_context_t *h)
> v->arch.xcr0_accum = ctxt->xcr0_accum;
> if ( ctxt->xcr0_accum & XSTATE_NONLAZY )
> v->arch.nonlazy_xstate_used = 1;
> - memcpy(v->arch.xsave_area, &ctxt->save_area,
> - min(desc->length, size) - offsetof(struct hvm_hw_cpu_xsave,
> - save_area));
> -
> + compress_xsave_states(v, &ctxt->save_area,
> + min(desc->length, size) -
> + offsetof(struct hvm_hw_cpu_xsave,save_area));
> return 0;
Bad removal of a blank line.
> --- a/xen/arch/x86/i387.c
> +++ b/xen/arch/x86/i387.c
> @@ -282,7 +282,11 @@ int vcpu_init_fpu(struct vcpu *v)
> return rc;
>
> if ( v->arch.xsave_area )
> + {
> v->arch.fpu_ctxt = &v->arch.xsave_area->fpu_sse;
> + if ( cpu_has_xsaves || cpu_has_xsavec )
> + v->arch.xsave_area->xsave_hdr.xcomp_bv |= XSTATE_COMPACTION_ENABLED;
Again - |= or just = ?
> --- a/xen/arch/x86/traps.c
> +++ b/xen/arch/x86/traps.c
> @@ -935,9 +935,9 @@ void pv_cpuid(struct cpu_user_regs *regs)
> goto unsupported;
> if ( regs->_ecx == 1 )
> {
> - a &= boot_cpu_data.x86_capability[X86_FEATURE_XSAVEOPT / 32];
> - if ( !cpu_has_xsaves )
> - b = c = d = 0;
> + a &= (boot_cpu_data.x86_capability[X86_FEATURE_XSAVEOPT / 32] &
> + ~cpufeat_mask(X86_FEATURE_XSAVES));
> + b = c = d = 0;
Considering that now we again seem to be black listing features here,
shouldn't we take the opportunity and convert this tho white listing now?
> +static void __init 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);
One off indentation. Also in both places "[i - 1]" please.
> + ASSERT(xstate_comp_offsets[i] + xstate_sizes[i] <= xsave_cntxt_size);
> + }
> +}
> +
> +static void *get_xsave_addr(const struct xsave_struct *xsave, unsigned int xfeature_idx)
> +{
> + if ( !((1ul << xfeature_idx) & xfeature_mask) )
> + return NULL;
> +
> + return (void *)xsave + xstate_comp_offsets[xfeature_idx];
You should never cast away constness like this. I actually don't see
why the parameter's type can't be (const) void*, avoiding any cast.
> +void expand_xsave_states(struct vcpu *v, void *dest, unsigned int size)
> +{
> + const struct xsave_struct *xsave = v->arch.xsave_area;
> + u64 xstate_bv = xsave->xsave_hdr.xstate_bv;
> + u64 valid;
> +
> + if ( !cpu_has_xsaves && !cpu_has_xsavec )
> + {
> + memcpy(dest, xsave, size);
> + return;
> + }
> +
> + 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);
> +
> + ((struct xsave_struct *)dest)->xsave_hdr.xstate_bv = xstate_bv;
> + ((struct xsave_struct *)dest)->xsave_hdr.xcomp_bv = 0;
> +
> + /*
> + * 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;
> + unsigned int index = fls(feature) - 1;
> + void *src = get_xsave_addr(xsave, index);
const
> + if ( src )
> + {
> + ASSERT((xstate_offsets[index] + xstate_sizes[index]) <= size);
> + memcpy(dest + xstate_offsets[index], src, xstate_sizes[index]);
> + }
> +
> + valid &= ~feature;
> + }
> +
> +}
Stray blank line.
> @@ -91,7 +253,15 @@ void xsave(struct vcpu *v, uint64_t mask)
> typeof(ptr->fpu_sse.fip.sel) fcs = ptr->fpu_sse.fip.sel;
> typeof(ptr->fpu_sse.fdp.sel) fds = ptr->fpu_sse.fdp.sel;
>
> - if ( cpu_has_xsaveopt )
> + if ( cpu_has_xsaves )
> + asm volatile ( ".byte 0x48,0x0f,0xc7,0x2f"
> + : "=m" (*ptr)
> + : "a" (lmask), "d" (hmask), "D" (ptr) );
> + else if ( cpu_has_xsavec )
> + asm volatile ( ".byte 0x48,0x0f,0xc7,0x27"
> + : "=m" (*ptr)
> + : "a" (lmask), "d" (hmask), "D" (ptr) );
> + else if ( cpu_has_xsaveopt )
While the REX.W prefixes are needed here, ...
> @@ -144,7 +314,15 @@ void xsave(struct vcpu *v, uint64_t mask)
> }
> else
> {
> - if ( cpu_has_xsaveopt )
> + if ( cpu_has_xsaves )
> + asm volatile ( ".byte 0x48,0x0f,0xc7,0x2f"
> + : "=m" (*ptr)
> + : "a" (lmask), "d" (hmask), "D" (ptr) );
> + else if ( cpu_has_xsavec )
> + asm volatile ( ".byte 0x48,0x0f,0xc7,0x27"
> + : "=m" (*ptr)
> + : "a" (lmask), "d" (hmask), "D" (ptr) );
> + else if ( cpu_has_xsaveopt )
> asm volatile ( ".byte 0x0f,0xae,0x37"
... they don't belong here (as also visible from the pre-existing
xsaveopt).
> @@ -187,36 +379,20 @@ void xrstor(struct vcpu *v, uint64_t mask)
> switch ( __builtin_expect(ptr->fpu_sse.x[FPU_WORD_SIZE_OFFSET], 8) )
> {
> default:
> - asm volatile ( "1: .byte 0x48,0x0f,0xae,0x2f\n"
> - ".section .fixup,\"ax\" \n"
> - "2: mov %5,%%ecx \n"
> - " xor %1,%1 \n"
> - " rep stosb \n"
> - " lea %2,%0 \n"
> - " mov %3,%1 \n"
> - " jmp 1b \n"
> - ".previous \n"
> - _ASM_EXTABLE(1b, 2b)
> - : "+&D" (ptr), "+&a" (lmask)
> - : "m" (*ptr), "g" (lmask), "d" (hmask),
> - "m" (xsave_cntxt_size)
> - : "ecx" );
> - break;
> + if ( cpu_has_xsaves )
> + asm volatile ( "1: .byte 0x48,0x0f,0xc7,0x1f\n"
> + XSTATE_FIXUP );
> + else
> + asm volatile ( "1: .byte 0x48,0x0f,0xae,0x2f\n"
> + XSTATE_FIXUP );
> + break;
> case 4: case 2:
> - asm volatile ( "1: .byte 0x0f,0xae,0x2f\n"
> - ".section .fixup,\"ax\" \n"
> - "2: mov %5,%%ecx \n"
> - " xor %1,%1 \n"
> - " rep stosb \n"
> - " lea %2,%0 \n"
> - " mov %3,%1 \n"
> - " jmp 1b \n"
> - ".previous \n"
> - _ASM_EXTABLE(1b, 2b)
> - : "+&D" (ptr), "+&a" (lmask)
> - : "m" (*ptr), "g" (lmask), "d" (hmask),
> - "m" (xsave_cntxt_size)
> - : "ecx" );
> + if ( cpu_has_xsaves )
> + asm volatile ( "1: .byte 0x48,0x0f,0xc7,0x1f\n"
> + XSTATE_FIXUP );
Same here.
Also, #undef XSTATE_FIXUP missing at the end of the function.
Jan
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [V7 3/4] x86/xsaves: enable xsaves/xrstors for hvm guest
2015-10-20 8:21 ` [V7 3/4] x86/xsaves: enable xsaves/xrstors for hvm guest Shuai Ruan
@ 2015-10-22 14:20 ` Jan Beulich
2015-10-22 14:26 ` Andrew Cooper
0 siblings, 1 reply; 11+ messages in thread
From: Jan Beulich @ 2015-10-22 14:20 UTC (permalink / raw)
To: Shuai Ruan
Cc: kevin.tian, wei.liu2, eddie.dong, stefano.stabellini,
andrew.cooper3, ian.jackson, xen-devel, jun.nakajima, keir,
Ian.Campbell
>>> On 20.10.15 at 10:21, <shuai.ruan@linux.intel.com> wrote:
> @@ -4784,6 +4804,13 @@ int hvm_msr_write_intercept(unsigned int msr, uint64_t msr_content,
> return X86EMUL_EXCEPTION;
> break;
>
> + case MSR_IA32_XSS:
> + /* No XSS features currently supported for guests. */
> + if ( !cpu_has_xsaves || msr_content != 0 )
> + goto gp_fault;
> + v->arch.hvm_vcpu.msr_xss = msr_content;
> + break;
Considering you add this write (and the msr_xss field in the first place)
despite it always being zero, I'd really like you to also add code
supporting save/restore of this new MSR. Or did I overlook something?
Jan
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [V7 3/4] x86/xsaves: enable xsaves/xrstors for hvm guest
2015-10-22 14:20 ` Jan Beulich
@ 2015-10-22 14:26 ` Andrew Cooper
2015-10-22 14:49 ` Jan Beulich
0 siblings, 1 reply; 11+ messages in thread
From: Andrew Cooper @ 2015-10-22 14:26 UTC (permalink / raw)
To: Jan Beulich, Shuai Ruan
Cc: kevin.tian, wei.liu2, Ian.Campbell, stefano.stabellini,
eddie.dong, ian.jackson, xen-devel, jun.nakajima, keir
On 22/10/15 15:20, Jan Beulich wrote:
>>>> On 20.10.15 at 10:21, <shuai.ruan@linux.intel.com> wrote:
>> @@ -4784,6 +4804,13 @@ int hvm_msr_write_intercept(unsigned int msr, uint64_t msr_content,
>> return X86EMUL_EXCEPTION;
>> break;
>>
>> + case MSR_IA32_XSS:
>> + /* No XSS features currently supported for guests. */
>> + if ( !cpu_has_xsaves || msr_content != 0 )
>> + goto gp_fault;
>> + v->arch.hvm_vcpu.msr_xss = msr_content;
>> + break;
> Considering you add this write (and the msr_xss field in the first place)
> despite it always being zero, I'd really like you to also add code
> supporting save/restore of this new MSR. Or did I overlook something?
I suppose that does mean that we don't strictly need
interception/management of MSR_IA32_XSS yet, but it is ground work for
the future work to enable Processor Trace for HVM guests.
~Andrew
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [V7 3/4] x86/xsaves: enable xsaves/xrstors for hvm guest
2015-10-22 14:26 ` Andrew Cooper
@ 2015-10-22 14:49 ` Jan Beulich
0 siblings, 0 replies; 11+ messages in thread
From: Jan Beulich @ 2015-10-22 14:49 UTC (permalink / raw)
To: Andrew Cooper, Shuai Ruan
Cc: kevin.tian, wei.liu2, Ian.Campbell, stefano.stabellini,
eddie.dong, ian.jackson, xen-devel, jun.nakajima, keir
>>> On 22.10.15 at 16:26, <andrew.cooper3@citrix.com> wrote:
> On 22/10/15 15:20, Jan Beulich wrote:
>>>>> On 20.10.15 at 10:21, <shuai.ruan@linux.intel.com> wrote:
>>> @@ -4784,6 +4804,13 @@ int hvm_msr_write_intercept(unsigned int msr, uint64_t
> msr_content,
>>> return X86EMUL_EXCEPTION;
>>> break;
>>>
>>> + case MSR_IA32_XSS:
>>> + /* No XSS features currently supported for guests. */
>>> + if ( !cpu_has_xsaves || msr_content != 0 )
>>> + goto gp_fault;
>>> + v->arch.hvm_vcpu.msr_xss = msr_content;
>>> + break;
>> Considering you add this write (and the msr_xss field in the first place)
>> despite it always being zero, I'd really like you to also add code
>> supporting save/restore of this new MSR. Or did I overlook something?
>
> I suppose that does mean that we don't strictly need
> interception/management of MSR_IA32_XSS yet, but it is ground work for
> the future work to enable Processor Trace for HVM guests.
Right, that's how I understand it. I simply think that if such ground
work is done, it shouldn't stop half ways.
Jan
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2015-10-22 14:49 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-10-20 8:21 [V7 0/4] add xsaves/xrstors support Shuai Ruan
2015-10-20 8:21 ` [V7 1/4] x86/xsaves: add basic definitions/helpers to support xsaves Shuai Ruan
2015-10-20 13:26 ` Andrew Cooper
2015-10-22 4:20 ` Shuai Ruan
2015-10-20 8:21 ` [V7 2/4] x86/xsaves: enable xsaves/xrstors/xsavec in xen Shuai Ruan
2015-10-22 12:13 ` Jan Beulich
2015-10-20 8:21 ` [V7 3/4] x86/xsaves: enable xsaves/xrstors for hvm guest Shuai Ruan
2015-10-22 14:20 ` Jan Beulich
2015-10-22 14:26 ` Andrew Cooper
2015-10-22 14:49 ` Jan Beulich
2015-10-20 8:21 ` [V7 4/4] libxc: expose xsaves/xgetbv1/xsavec to " Shuai Ruan
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.