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

[Xen-devel] Ping: [PATCH 1/2] x86: improve MSR_SHADOW_GS accesses



>>> On 06.12.17 at 17:37,  wrote:
> Instead of using RDMSR/WRMSR, on fsgsbase-capable systems use a double
> SWAPGS combined with RDGSBASE/WRGSBASE. This halves execution time for
> a shadow GS update alone on my Haswell (and we have indications of
> good performance improvements by this on Skylake too), while the win is
> even higher when e.g. updating more than one base (as may and commonly
> will happen in load_segments()).
> 
> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>

The previous (short) discussion has stalled, hence the ping.

Jan

> --- a/xen/arch/x86/domain.c
> +++ b/xen/arch/x86/domain.c
> @@ -1326,9 +1326,12 @@ static void load_segments(struct vcpu *n
>          if ( n->arch.pv_vcpu.fs_base | (dirty_segment_mask & DIRTY_FS_BASE) 
> )
>              wrfsbase(n->arch.pv_vcpu.fs_base);
>  
> -        /* Most kernels have non-zero GS base, so don't bother testing. */
> -        /* (This is also a serialising instruction, avoiding AMD erratum 
> #88.) */
> -        wrmsrl(MSR_SHADOW_GS_BASE, n->arch.pv_vcpu.gs_base_kernel);
> +        /*
> +         * Most kernels have non-zero GS base, so don't bother testing.
> +         * (For old AMD hardware this is also a serialising instruction,
> +         * avoiding erratum #88.)
> +         */
> +        wrgsshadow(n->arch.pv_vcpu.gs_base_kernel);
>  
>          /* This can only be non-zero if selector is NULL. */
>          if ( n->arch.pv_vcpu.gs_base_user |
> --- a/xen/arch/x86/hvm/vmx/vmx.c
> +++ b/xen/arch/x86/hvm/vmx/vmx.c
> @@ -501,7 +501,7 @@ long_mode_do_msr_read(unsigned int msr,
>          break;
>  
>      case MSR_SHADOW_GS_BASE:
> -        rdmsrl(MSR_SHADOW_GS_BASE, *msr_content);
> +        *msr_content = rdgsshadow();
>          break;
>  
>      case MSR_STAR:
> @@ -549,7 +549,7 @@ long_mode_do_msr_write(unsigned int msr,
>          else if ( msr == MSR_GS_BASE )
>              __vmwrite(GUEST_GS_BASE, msr_content);
>          else
> -            wrmsrl(MSR_SHADOW_GS_BASE, msr_content);
> +            wrgsshadow(msr_content);
>  
>          break;
>  
> @@ -608,12 +608,12 @@ static void vmx_save_guest_msrs(struct v
>       * We cannot cache SHADOW_GS_BASE while the VCPU runs, as it can
>       * be updated at any time via SWAPGS, which we cannot trap.
>       */
> -    rdmsrl(MSR_SHADOW_GS_BASE, v->arch.hvm_vmx.shadow_gs);
> +    v->arch.hvm_vmx.shadow_gs = rdgsshadow();
>  }
>  
>  static void vmx_restore_guest_msrs(struct vcpu *v)
>  {
> -    wrmsrl(MSR_SHADOW_GS_BASE, v->arch.hvm_vmx.shadow_gs);
> +    wrgsshadow(v->arch.hvm_vmx.shadow_gs);
>      wrmsrl(MSR_STAR,           v->arch.hvm_vmx.star);
>      wrmsrl(MSR_LSTAR,          v->arch.hvm_vmx.lstar);
>      wrmsrl(MSR_SYSCALL_MASK,   v->arch.hvm_vmx.sfmask);
> --- a/xen/arch/x86/pv/emul-priv-op.c
> +++ b/xen/arch/x86/pv/emul-priv-op.c
> @@ -1027,7 +1027,7 @@ static int write_msr(unsigned int reg, u
>      case MSR_SHADOW_GS_BASE:
>          if ( is_pv_32bit_domain(currd) || !is_canonical_address(val) )
>              break;
> -        wrmsrl(MSR_SHADOW_GS_BASE, val);
> +        wrgsshadow(val);
>          curr->arch.pv_vcpu.gs_base_user = val;
>          return X86EMUL_OKAY;
>  
> --- a/xen/arch/x86/x86_64/mm.c
> +++ b/xen/arch/x86/x86_64/mm.c
> @@ -1034,7 +1034,7 @@ long do_set_segment_base(unsigned int wh
>      case SEGBASE_GS_USER:
>          if ( is_canonical_address(base) )
>          {
> -            wrmsrl(MSR_SHADOW_GS_BASE, base);
> +            wrgsshadow(base);
>              v->arch.pv_vcpu.gs_base_user = base;
>          }
>          else
> --- a/xen/arch/x86/x86_64/traps.c
> +++ b/xen/arch/x86/x86_64/traps.c
> @@ -49,7 +49,7 @@ static void read_registers(struct cpu_us
>      regs->gs = read_sreg(gs);
>      crs[5] = rdfsbase();
>      crs[6] = rdgsbase();
> -    rdmsrl(MSR_SHADOW_GS_BASE, crs[7]);
> +    crs[7] = rdgsshadow();
>  }
>  
>  static void _show_registers(
> --- a/xen/include/asm-x86/msr.h
> +++ b/xen/include/asm-x86/msr.h
> @@ -8,6 +8,7 @@
>  #include <xen/types.h>
>  #include <xen/percpu.h>
>  #include <xen/errno.h>
> +#include <asm/alternative.h>
>  #include <asm/asm_defns.h>
>  #include <asm/cpufeature.h>
>  
> @@ -172,6 +173,24 @@ static inline unsigned long rdgsbase(voi
>      return base;
>  }
>  
> +static inline unsigned long rdgsshadow(void)
> +{
> +    unsigned long base;
> +
> +    alternative_io("mov %[msr], %%ecx\n\t"
> +                   "rdmsr\n\t"
> +                   "shl $32, %%rdx\n\t"
> +                   "or %%rdx, %[res]",
> +                   "swapgs\n\t"
> +                   ".byte 0xf3, 0x48, 0x0f, 0xae, 0xc8\n\t" /* rdgsbase rax 
> */
> +                   "swapgs",
> +                   X86_FEATURE_FSGSBASE,
> +                   [res] "=&a" (base),
> +                   [msr] "i" (MSR_SHADOW_GS_BASE) : "rcx", "rdx");
> +
> +    return base;
> +}
> +
>  static inline void wrfsbase(unsigned long base)
>  {
>      if ( cpu_has_fsgsbase )
> @@ -196,6 +215,19 @@ static inline void wrgsbase(unsigned lon
>          wrmsrl(MSR_GS_BASE, base);
>  }
>  
> +static inline void wrgsshadow(unsigned long base)
> +{
> +    alternative_input("mov %[msr], %%ecx\n\t"
> +                      "shld $32, %[val], %%rdx\n\t"
> +                      "wrmsr",
> +                      "swapgs\n\t"
> +                      ".byte 0xf3, 0x48, 0x0f, 0xae, 0xd8\n\t" /* wrgsbase 
> rax */
> +                      "swapgs",
> +                      X86_FEATURE_FSGSBASE,
> +                      [val] "a" (base),
> +                      [msr] "i" (MSR_SHADOW_GS_BASE) : "rcx", "rdx");
> +}
> +
>  DECLARE_PER_CPU(u64, efer);
>  u64 read_efer(void);
>  void write_efer(u64 val);
> 
> 
> 



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

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