From mboxrd@z Thu Jan 1 00:00:00 1970 From: Marcelo Tosatti Subject: [patch 05/13] KVM: MMU: do not write-protect large mappings Date: Sat, 06 Sep 2008 15:48:27 -0300 Message-ID: <20080906192430.876413489@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]:60553 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752404AbYIFT1N (ORCPT ); Sat, 6 Sep 2008 15:27:13 -0400 Content-Disposition: inline; filename=no-wprotected-lpage Sender: kvm-owner@vger.kernel.org List-ID: There is not much point in write protecting large mappings. This can only happen when a page is shadowed during the window between is_largepage_backed and mmu_lock acquision. Zap the entry instead, so the next pagefault will find a shadowed page via is_largepage_backed and fallback to 4k translations. Simplifies out of sync shadow. Index: kvm/arch/x86/kvm/mmu.c =================================================================== --- kvm.orig/arch/x86/kvm/mmu.c +++ kvm/arch/x86/kvm/mmu.c @@ -1210,8 +1210,7 @@ static void mmu_set_spte(struct kvm_vcpu spte |= PT_WRITABLE_MASK; shadow = kvm_mmu_lookup_page(vcpu->kvm, gfn); - if (shadow || - (largepage && has_wrprotected_page(vcpu->kvm, gfn))) { + if (shadow) { pgprintk("%s: found shadow page for %lx, marking ro\n", __func__, gfn); pte_access &= ~ACC_WRITE_MASK; @@ -1222,6 +1221,14 @@ static void mmu_set_spte(struct kvm_vcpu if (write_fault) *ptwrite = 1; } + /* + * Do not create write protected large translations. + */ + if (largepage && has_wrprotected_page(vcpu->kvm, gfn)) { + spte = shadow_trap_nonpresent_pte; + was_writeble = 0; + *ptwrite = 0; + } } if (pte_access & ACC_WRITE_MASK) Index: kvm/arch/x86/kvm/paging_tmpl.h =================================================================== --- kvm.orig/arch/x86/kvm/paging_tmpl.h +++ kvm/arch/x86/kvm/paging_tmpl.h @@ -307,11 +307,10 @@ static int FNAME(shadow_walk_entry)(stru return 1; } - if (is_shadow_present_pte(*sptep) && !is_large_pte(*sptep)) + if (is_shadow_present_pte(*sptep)) return 0; - if (is_large_pte(*sptep)) - rmap_remove(vcpu->kvm, sptep); + WARN_ON (is_large_pte(*sptep)); if (level == PT_DIRECTORY_LEVEL && gw->level == PT_DIRECTORY_LEVEL) { metaphysical = 1; --