Close to 50% improvement for prefetch_page.

Index: kvm/arch/x86/kvm/paging_tmpl.h
===================================================================
--- kvm.orig/arch/x86/kvm/paging_tmpl.h
+++ kvm/arch/x86/kvm/paging_tmpl.h
@@ -477,9 +477,10 @@ static gpa_t FNAME(gva_to_gpa)(struct kv
 static void FNAME(prefetch_page)(struct kvm_vcpu *vcpu,
                                 struct kvm_mmu_page *sp)
 {
-       int i, j, offset, r;
-       pt_element_t pt[256 / sizeof(pt_element_t)];
-       gpa_t pte_gpa;
+       int i;
+       struct page *page;
+       pt_element_t *pt;
+       void *gpte_kaddr;
 
        if (sp->role.metaphysical
            || (PTTYPE == 32 && sp->role.level > PT_PAGE_TABLE_LEVEL)) {
@@ -487,21 +488,26 @@ static void FNAME(prefetch_page)(struct 
                return;
        }
 
-       pte_gpa = gfn_to_gpa(sp->gfn);
-       if (PTTYPE == 32) {
-               offset = sp->role.quadrant << PT64_LEVEL_BITS;
-               pte_gpa += offset * sizeof(pt_element_t);
+       page = gfn_to_page_atomic(vcpu->kvm, sp->gfn);
+       if (is_error_page(page)) {
+               nonpaging_prefetch_page(vcpu, sp);
+               kvm_release_page_clean(page);
+               return;
        }
+       gpte_kaddr = pt = kmap_atomic(page, KM_USER0);
+
+       if (PTTYPE == 32)
+               pt += sp->role.quadrant << PT64_LEVEL_BITS;
 
-       for (i = 0; i < PT64_ENT_PER_PAGE; i += ARRAY_SIZE(pt)) {
-               r = kvm_read_guest_atomic(vcpu->kvm, pte_gpa, pt, sizeof pt);
-               pte_gpa += ARRAY_SIZE(pt) * sizeof(pt_element_t);
-               for (j = 0; j < ARRAY_SIZE(pt); ++j)
-                       if (r || is_present_pte(pt[j]))
-                               sp->spt[i+j] = shadow_trap_nonpresent_pte;
-                       else
-                               sp->spt[i+j] = shadow_notrap_nonpresent_pte;
+       for (i = 0; i < PT64_ENT_PER_PAGE; i++) {
+               if (is_present_pte(*pt))
+                       sp->spt[i] = shadow_trap_nonpresent_pte;
+               else
+                       sp->spt[i] = shadow_notrap_nonpresent_pte;
+               pt++;
        }
+       kunmap_atomic(gpte_kaddr, KM_USER0);
+       kvm_release_page_clean(page);
 }
 
 #undef pt_element_t

-- 

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to