Re: [kvm-devel] [PATCH] KVM: large page support

2008-02-23 Thread Avi Kivity
Marcelo Tosatti wrote:
> Create large pages mappings if the guest PTE's are marked as such and
> the underlying memory is hugetlbfs backed.
>
> Gives a consistent 2% improvement for data copies on ram mounted
> filesystem, without NPT/EPT.
>
>   

Applied, thanks (as well as the qemu part).

-- 
error compiling committee.c: too many arguments to function


-
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse012070mrt/direct/01/
___
kvm-devel mailing list
kvm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-devel


Re: [kvm-devel] [PATCH] KVM: large page support

2008-02-23 Thread Anthony Liguori
Marcelo Tosatti wrote:
> Create large pages mappings if the guest PTE's are marked as such and
> the underlying memory is hugetlbfs backed.
>
> Gives a consistent 2% improvement for data copies on ram mounted
> filesystem, without NPT/EPT.
>   

FWIW, with NPT, I'm seeing kernbench get about a 4% improvement in 
performance with this patch with a 4-VCPU guest.

Very nice work!

Regards,

Anthony Liguori

> Signed-off-by: Marcelo Tosatti <[EMAIL PROTECTED]>
>   


-
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse012070mrt/direct/01/
___
kvm-devel mailing list
kvm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-devel


[kvm-devel] [PATCH] KVM: large page support

2008-02-23 Thread Marcelo Tosatti

Create large pages mappings if the guest PTE's are marked as such and
the underlying memory is hugetlbfs backed.

Gives a consistent 2% improvement for data copies on ram mounted
filesystem, without NPT/EPT.

Signed-off-by: Marcelo Tosatti <[EMAIL PROTECTED]>

Index: kvm.paravirt3/arch/x86/kvm/mmu.c
===
--- kvm.paravirt3.orig/arch/x86/kvm/mmu.c
+++ kvm.paravirt3/arch/x86/kvm/mmu.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -211,6 +212,11 @@ static int is_shadow_present_pte(u64 pte
&& pte != shadow_notrap_nonpresent_pte;
 }
 
+static int is_large_pte(u64 pte)
+{
+   return pte & PT_PAGE_SIZE_MASK;
+}
+
 static int is_writeble_pte(unsigned long pte)
 {
return pte & PT_WRITABLE_MASK;
@@ -361,16 +367,100 @@ static void mmu_free_rmap_desc(struct kv
 }
 
 /*
+ * Return the pointer to the largepage write count for a given
+ * gfn, handling slots that are not large page aligned.
+ */
+static int *slot_largepage_idx(gfn_t gfn, struct kvm_memory_slot *slot)
+{
+   unsigned long idx;
+
+   idx = (gfn / KVM_PAGES_PER_HPAGE) -
+ (slot->base_gfn / KVM_PAGES_PER_HPAGE);
+   return &slot->lpage_info[idx].write_count;
+}
+
+static void account_shadowed(struct kvm *kvm, gfn_t gfn)
+{
+   int *write_count;
+
+   write_count = slot_largepage_idx(gfn, gfn_to_memslot(kvm, gfn));
+   *write_count += 1;
+   WARN_ON(*write_count > KVM_PAGES_PER_HPAGE);
+}
+
+static void unaccount_shadowed(struct kvm *kvm, gfn_t gfn)
+{
+   int *write_count;
+
+   write_count = slot_largepage_idx(gfn, gfn_to_memslot(kvm, gfn));
+   *write_count -= 1;
+   WARN_ON(*write_count < 0);
+}
+
+static int has_wrprotected_page(struct kvm *kvm, gfn_t gfn)
+{
+   struct kvm_memory_slot *slot = gfn_to_memslot(kvm, gfn);
+   int *largepage_idx;
+
+   if (slot) {
+   largepage_idx = slot_largepage_idx(gfn, slot);
+   return *largepage_idx;
+   }
+
+   return 1;
+}
+
+static int host_largepage_backed(struct kvm *kvm, gfn_t gfn)
+{
+   struct vm_area_struct *vma;
+   unsigned long addr;
+
+   addr = gfn_to_hva(kvm, gfn);
+   if (kvm_is_error_hva(addr))
+   return 0;
+
+   vma = find_vma(current->mm, addr);
+   if (vma && is_vm_hugetlb_page(vma))
+   return 1;
+
+   return 0;
+}
+
+static int is_largepage_backed(struct kvm_vcpu *vcpu, gfn_t large_gfn)
+{
+   struct kvm_memory_slot *slot;
+
+   if (has_wrprotected_page(vcpu->kvm, large_gfn))
+   return 0;
+
+   if (!host_largepage_backed(vcpu->kvm, large_gfn))
+   return 0;
+
+   slot = gfn_to_memslot(vcpu->kvm, large_gfn);
+   if (slot && slot->dirty_bitmap)
+   return 0;
+
+   return 1;
+}
+
+/*
  * Take gfn and return the reverse mapping to it.
  * Note: gfn must be unaliased before this function get called
  */
 
-static unsigned long *gfn_to_rmap(struct kvm *kvm, gfn_t gfn)
+static unsigned long *gfn_to_rmap(struct kvm *kvm, gfn_t gfn, int lpage)
 {
struct kvm_memory_slot *slot;
+   unsigned long idx;
 
slot = gfn_to_memslot(kvm, gfn);
-   return &slot->rmap[gfn - slot->base_gfn];
+   if (!lpage)
+   return &slot->rmap[gfn - slot->base_gfn];
+
+   idx = (gfn / KVM_PAGES_PER_HPAGE) -
+ (slot->base_gfn / KVM_PAGES_PER_HPAGE);
+
+   return &slot->lpage_info[idx].rmap_pde;
 }
 
 /*
@@ -382,7 +472,7 @@ static unsigned long *gfn_to_rmap(struct
  * If rmapp bit zero is one, (then rmap & ~1) points to a struct kvm_rmap_desc
  * containing more mappings.
  */
-static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn)
+static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage)
 {
struct kvm_mmu_page *sp;
struct kvm_rmap_desc *desc;
@@ -394,7 +484,7 @@ static void rmap_add(struct kvm_vcpu *vc
gfn = unalias_gfn(vcpu->kvm, gfn);
sp = page_header(__pa(spte));
sp->gfns[spte - sp->spt] = gfn;
-   rmapp = gfn_to_rmap(vcpu->kvm, gfn);
+   rmapp = gfn_to_rmap(vcpu->kvm, gfn, lpage);
if (!*rmapp) {
rmap_printk("rmap_add: %p %llx 0->1\n", spte, *spte);
*rmapp = (unsigned long)spte;
@@ -460,7 +550,7 @@ static void rmap_remove(struct kvm *kvm,
kvm_release_page_dirty(page);
else
kvm_release_page_clean(page);
-   rmapp = gfn_to_rmap(kvm, sp->gfns[spte - sp->spt]);
+   rmapp = gfn_to_rmap(kvm, sp->gfns[spte - sp->spt], is_large_pte(*spte));
if (!*rmapp) {
printk(KERN_ERR "rmap_remove: %p %llx 0->BUG\n", spte, *spte);
BUG();
@@ -526,7 +616,7 @@ static void rmap_write_protect(struct kv
int write_protected = 0;
 
gfn = unalias_gfn(kvm, gfn);
-   rmapp = gfn_to_rmap(kvm, gfn);
+   rmapp = gfn_to_rmap(kvm, gfn, 0);