Re: [PATCH 2/2] kvm: x86: reduce collisions in mmu_page_hash

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

 




On 19/12/2016 22:58, David Matlack wrote:
> When using two-dimensional paging, the mmu_page_hash (which provides
> lookups for existing kvm_mmu_page structs), becomes imbalanced; with
> too many collisions in buckets 0 and 512.

Ouch, nice catch.  I'll apply this patch tomorrow since it's pretty much
independent of patch 1.  If you want to send out a revision of the
statistics patch, please do.

Thanks,

Paolo

 This has been seen to cause
> mmu_lock to be held for multiple milliseconds in kvm_mmu_get_page on
> VMs with a large amount of RAM mapped with 4K pages.
> 
> The current hash function uses the lower 10 bits of gfn to index into
> mmu_page_hash. When doing shadow paging, gfn is the address of the
> guest page table being shadow. These tables are 4K-aligned, which
> makes the low bits of gfn a good hash. However, with two-dimensional
> paging, no guest page tables are being shadowed, so gfn is the base
> address that is mapped by the table. Thus page tables (level=1) have
> a 2MB aligned gfn, page directories (level=2) have a 1GB aligned gfn,
> etc. This means hashes will only differ in their 10th bit.
> 
> hash_64() provides a better hash. For example, on a VM with ~200G
> (99458 direct=1 kvm_mmu_page structs):
> 
> hash            max_mmu_page_hash_collisions
> --------------------------------------------
> low 10 bits     49847
> hash_64         105
> perfect         97
> 
> While we're changing the hash, increase the table size by 4x to better
> support large VMs (further reduces number of collisions in 200G VM to
> 29).
> 
> Note that hash_64() does not provide a good distribution prior to commit
> ef703f49a6c5 ("Eliminate bad hash multipliers from hash_32() and
> hash_64()").
> 
> Signed-off-by: David Matlack <dmatlack@xxxxxxxxxx>
> Change-Id: I5aa6b13c834722813c6cca46b8b1ed6f53368ade
> ---
>  arch/x86/include/asm/kvm_host.h | 2 +-
>  arch/x86/kvm/mmu.c              | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
> index 8ba0d64..5962e4bc 100644
> --- a/arch/x86/include/asm/kvm_host.h
> +++ b/arch/x86/include/asm/kvm_host.h
> @@ -115,7 +115,7 @@ static inline gfn_t gfn_to_index(gfn_t gfn, gfn_t base_gfn, int level)
>  
>  #define KVM_PERMILLE_MMU_PAGES 20
>  #define KVM_MIN_ALLOC_MMU_PAGES 64
> -#define KVM_MMU_HASH_SHIFT 10
> +#define KVM_MMU_HASH_SHIFT 12
>  #define KVM_NUM_MMU_PAGES (1 << KVM_MMU_HASH_SHIFT)
>  #define KVM_MIN_FREE_MMU_PAGES 5
>  #define KVM_REFILL_PAGES 25
> diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
> index 58995fd9..de55653 100644
> --- a/arch/x86/kvm/mmu.c
> +++ b/arch/x86/kvm/mmu.c
> @@ -1713,7 +1713,7 @@ static void kvm_mmu_free_page(struct kvm_mmu_page *sp)
>  
>  static unsigned kvm_page_table_hashfn(gfn_t gfn)
>  {
> -	return gfn & ((1 << KVM_MMU_HASH_SHIFT) - 1);
> +	return hash_64(gfn, KVM_MMU_HASH_SHIFT);
>  }
>  
>  static void mmu_page_add_parent_pte(struct kvm_vcpu *vcpu,
> 
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux