[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [V5 2/4] x86/xsaves: enable xsaves/xrstors/xsavec in xen



>>> On 21.09.15 at 13:33, <shuai.ruan@xxxxxxxxxxxxxxx> 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.

Assuming the hardware has XSAVEC but no XSAVES support - why
wouldn't we want use XSAVEC in that case?

> --- a/xen/arch/x86/domain.c
> +++ b/xen/arch/x86/domain.c
> @@ -1529,6 +1529,9 @@ static void __context_switch(void)
>              if ( xcr0 != get_xcr0() && !set_xcr0(xcr0) )
>                  BUG();
>          }
> +        if ( cpu_has_xsaves )
> +            if ( is_hvm_vcpu(n) )
> +                set_msr_xss(n->arch.hvm_vcpu.msr_xss);

The two if()s should be combined.

> --- a/xen/arch/x86/domctl.c
> +++ b/xen/arch/x86/domctl.c
> @@ -867,7 +867,7 @@ long arch_do_domctl(
>          if ( domctl->cmd == XEN_DOMCTL_getvcpuextstate )
>          {
>              unsigned int size;
> -
> +            void * xsave_area;
>              ret = 0;

Stray removal of a blank line. Stray blank after *.

> @@ -896,9 +896,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) &&

Ah, you actually use it, but don't say so in the description.

> +                 xsave_area_compressed(v->arch.xsave_area) )
> +            {
> +                xsave_area = xmalloc_bytes(size);

Perhaps this variable would better be declared here anyway.

> +                if ( !xsave_area )
> +                {
> +                    ret = -ENOMEM;
> +                    vcpu_unpause(v);
> +                    goto vcpuextstate_out;

This is unfortunate - it would be better if you could avoid failing
the request here.

> +                }
> +
> +                save_xsave_states(v, xsave_area,
> +                                  evc->size - 2*sizeof(uint64_t));

Blanks around * please.

> +
> +                if ( !ret && copy_to_guest_offset(evc->buffer, offset,

There's no way for ret to be non-zero at this point.

> +                                               xsave_area, size -

Hard tabs (more elsewhere).

> @@ -954,8 +975,13 @@ 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 || cpu_has_xsavec) &&
> +                  !xsave_area_compressed(_xsave_area) )

Is it intended to support compact input here? Where would such
come from? And if so, don't you need to validate the input (e.g.
being a certain size)?

> @@ -2248,9 +2253,15 @@ 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));
> +    if ( (cpu_has_xsaves || cpu_has_xsavec) &&
> +          !xsave_area_compressed((struct xsave_struct *)&ctxt->save_area) )

Same questions here.

> --- a/xen/arch/x86/traps.c
> +++ b/xen/arch/x86/traps.c
> @@ -935,10 +935,9 @@ void pv_cpuid(struct cpu_user_regs *regs)
>              goto unsupported;
>          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);
> +            a &= cpufeat_mask(X86_FEATURE_XSAVEOPT) |
> +                 cpufeat_mask(X86_FEATURE_XSAVEC) |
> +                 (cpu_has_xgetbv1 ? cpufeat_mask(X86_FEATURE_XGETBV1) : 0);

I think you indeed mean to drop xsaves here, but then you should
say so (i.e. PV unsupported) in the commit message

>              if ( !cpu_has_xsaves )
>                  b = c = d = 0;

And it would seem that this then needs to become unconditional?

> @@ -341,36 +357,68 @@ 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"
> +                           ".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" );
> +     else
> +            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;
>      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"
> +                           ".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" );
> +     else
> +            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" );

The amount of redundancy calls for some helper macros.

> @@ -495,18 +543,24 @@ void xstate_init(bool_t bsp)
>      cpuid_count(XSTATE_CPUID, 1, &eax, &ebx, &ecx, &edx);
>      if ( 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_xsaveopt = !!(eax & cpufeat_mask(X86_FEATURE_XSAVEOPT));
> +        cpu_has_xsavec = !!(eax & cpufeat_mask(X86_FEATURE_XSAVEC));
> +        cpu_has_xgetbv1 = !!(eax & cpufeat_mask(X86_FEATURE_XGETBV1));
> +        cpu_has_xsaves = !!(eax & cpufeat_mask(X86_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_xsaveopt != !(eax & 
> cpufeat_mask(X86_FEATURE_XSAVEOPT)));
> +        BUG_ON(!cpu_has_xsavec != !(eax & cpufeat_mask(X86_FEATURE_XSAVEC)));
> +        BUG_ON(!cpu_has_xgetbv1 != !(eax & 
> cpufeat_mask(X86_FEATURE_XGETBV1)));
> +        BUG_ON(!cpu_has_xsaves != !(eax & cpufeat_mask(X86_FEATURE_XSAVES)));
>      }
> +
> +    if( setup_xstate_features(bsp) )
> +        BUG();
> +
> +    if ( bsp && (cpu_has_xsaves || cpu_has_xsavec) )
> +        setup_xstate_comp();

Implying that the function should be annotated __init in patch 1. With
it being static there without having a caller, it also means things wouldn't
build with just patch 1 applied. This needs to be addressed.

Jan

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.