From mboxrd@z Thu Jan 1 00:00:00 1970 From: Marcelo Tosatti Subject: [patch 04/13] KVM: MMU: switch prefetch_page to gfn_to_page_atomic Date: Sat, 06 Sep 2008 15:48:26 -0300 Message-ID: <20080906192430.763900534@localhost.localdomain> References: <20080906184822.560099087@localhost.localdomain> Cc: kvm@vger.kernel.org To: Avi Kivity Return-path: Received: from mx1.redhat.com ([66.187.233.31]:60550 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752394AbYIFT1I (ORCPT ); Sat, 6 Sep 2008 15:27:08 -0400 Content-Disposition: inline; filename=prefetch-page-use-gfn-to-page-atomic Sender: kvm-owner@vger.kernel.org List-ID: 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 --