|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH V4 2/4] x86/xsaves: enable xsaves/xrstors in xen
On 25/08/15 11:54, Shuai Ruan wrote:
> This patch uses xsaves/xrstors instead of xsaveopt/xrstor
> to perform the xsave_area switching so that xen itself
> can benefit from them when available.
>
> For xsaves/xrstors only use compact format. Add format conversion
> support when perform guest os migration.
>
> Signed-off-by: Shuai Ruan <shuai.ruan@xxxxxxxxxxxxxxx>
> ---
> xen/arch/x86/domain.c | 2 +
> xen/arch/x86/domctl.c | 34 ++++++++++++---
> xen/arch/x86/hvm/hvm.c | 19 ++++++---
> xen/arch/x86/i387.c | 4 ++
> xen/arch/x86/traps.c | 7 ++--
> xen/arch/x86/xstate.c | 112
> ++++++++++++++++++++++++++++++++++---------------
> 6 files changed, 132 insertions(+), 46 deletions(-)
>
> diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
> index 045f6ff..7b8f649 100644
> --- a/xen/arch/x86/domain.c
> +++ b/xen/arch/x86/domain.c
> @@ -1529,6 +1529,8 @@ static void __context_switch(void)
> if ( xcr0 != get_xcr0() && !set_xcr0(xcr0) )
> BUG();
> }
> + if ( cpu_has_xsaves )
> + wrmsrl(MSR_IA32_XSS, n->arch.msr_ia32_xss);
This is still not appropriate. You need a per cpu variable and only
perform lazy writes of the MSR.
> 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 bf62a88..da136876 100644
> --- a/xen/arch/x86/domctl.c
> +++ b/xen/arch/x86/domctl.c
> @@ -867,6 +867,7 @@ long arch_do_domctl(
> if ( domctl->cmd == XEN_DOMCTL_getvcpuextstate )
> {
> unsigned int size;
> + void * xsave_area;
Unnecessary space.
>
> ret = 0;
> vcpu_pause(v);
> @@ -896,9 +897,28 @@ 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 ( cpu_has_xsaves )
I think this would be more correct to gate on v->arch.xsave_area
actually being compressed.
> + {
> + xsave_area = xmalloc_bytes(size);
> + if ( !xsave_area )
> + {
> + ret = -ENOMEM;
> + goto vcpuextstate_out;
> + }
> +
> + save_xsave_states(v, xsave_area,
> + evc->size - 2*sizeof(uint64_t));
And on a similar note, save_xsave_states() is really
uncompress_xsave_area(). On further consideration, it should ASSERT()
that the source is currently compressed.
> +
> + if ( !ret && 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);
> @@ -954,8 +974,12 @@ 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));
> + if ( cpu_has_xsaves )
> + load_xsave_states(v, (void *)_xsave_area,
> + evc->size - 2*sizeof(uint64_t));
Similarly, load_xsave_states() is really compress_xsave_area().
You should check to see whether the area is already compressed, and just
memcpy() in that case.
> + else
> + memcpy(v->arch.xsave_area, (void *)_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 c957610..dc444ac 100644
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -2148,8 +2148,12 @@ 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));
> + if ( cpu_has_xsaves )
Stray hard tab.
> + save_xsave_states(v, (void *)&ctxt->save_area,
> + size - offsetof(struct
> hvm_hw_cpu_xsave,save_area));
These offsetof()s can become far shorter by using offsetof(*ctxt,
save_area).
> diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
> index 9f5a6c6..e9beec1 100644
> --- a/xen/arch/x86/traps.c
> +++ b/xen/arch/x86/traps.c
> @@ -936,9 +936,10 @@ void pv_cpuid(struct cpu_user_regs *regs)
> if ( regs->_ecx == 1 )
> {
> a &= XSTATE_FEATURE_XSAVEOPT |
> - XSTATE_FEATURE_XSAVEC |
> - (cpu_has_xgetbv1 ? XSTATE_FEATURE_XGETBV1 : 0) |
> - (cpu_has_xsaves ? XSTATE_FEATURE_XSAVES : 0);
> + XSTATE_FEATURE_XSAVEC;
> + /* PV guest will not support xsaves. */
> + /* (cpu_has_xgetbv1 ? XSTATE_FEATURE_XGETBV1 : 0) |
> + (cpu_has_xsaves ? XSTATE_FEATURE_XSAVES : 0); */
Don't leave this code commented out like this. Just delete it.
> if ( !cpu_has_xsaves )
> b = c = d = 0;
> }
> diff --git a/xen/arch/x86/xstate.c b/xen/arch/x86/xstate.c
> index 3986515..9050607 100644
> --- a/xen/arch/x86/xstate.c
> +++ b/xen/arch/x86/xstate.c
> @@ -214,6 +214,11 @@ 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_xsaves )
> + asm volatile ( ".byte 0x48,0x0f,0xc7,0x2f"
> + : "=m" (*ptr)
> + : "a" (lmask), "d" (hmask), "D" (ptr) );
> + else
> if ( cpu_has_xsaveopt )
Please join the if() onto the previous line.
> {
> /*
> @@ -267,6 +272,11 @@ void xsave(struct vcpu *v, uint64_t mask)
> }
> else
> {
> + if ( cpu_has_xsaves )
> + asm volatile ( ".byte 0x48,0x0f,0xc7,0x2f"
> + : "=m" (*ptr)
> + : "a" (lmask), "d" (hmask), "D" (ptr) );
> + else
> if ( cpu_has_xsaveopt )
And here.
> @@ -466,16 +508,20 @@ void xstate_init(bool_t bsp)
> {
> cpu_has_xsaveopt = !!(eax & XSTATE_FEATURE_XSAVEOPT);
> cpu_has_xsavec = !!(eax & XSTATE_FEATURE_XSAVEC);
> - /* XXX cpu_has_xgetbv1 = !!(eax & XSTATE_FEATURE_XGETBV1); */
> - /* XXX cpu_has_xsaves = !!(eax & XSTATE_FEATURE_XSAVES); */
> + cpu_has_xgetbv1 = !!(eax & XSTATE_FEATURE_XGETBV1);
> + cpu_has_xsaves = !!(eax & XSTATE_FEATURE_XSAVES);
> }
> else
> {
> BUG_ON(!cpu_has_xsaveopt != !(eax & XSTATE_FEATURE_XSAVEOPT));
> BUG_ON(!cpu_has_xsavec != !(eax & XSTATE_FEATURE_XSAVEC));
> - /* XXX BUG_ON(!cpu_has_xgetbv1 != !(eax & XSTATE_FEATURE_XGETBV1));
> */
> - /* XXX BUG_ON(!cpu_has_xsaves != !(eax & XSTATE_FEATURE_XSAVES)); */
> + BUG_ON(!cpu_has_xgetbv1 != !(eax & XSTATE_FEATURE_XGETBV1));
> + BUG_ON(!cpu_has_xsaves != !(eax & XSTATE_FEATURE_XSAVES));
> }
> +
> + setup_xstate_features();
> + if ( cpu_has_xsaves )
> + setup_xstate_comp();
setup_state_comp() should only be called on the bsp, and
setup_xstate_features() should have a similar bsp/ap split with
generating or validating state.
~Andrew
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |