From: Marcelo Tosatti Date: Mon, 23 Mar 2009 20:51:33 +0000 (-0300) Subject: KVM: MMU: handle large host sptes on invlpg/resync X-Git-Tag: v2.6.28.10~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2ef5df79ae93e27162a3ff9f9326cc53ef42a970;p=thirdparty%2Fkernel%2Fstable.git KVM: MMU: handle large host sptes on invlpg/resync (cherry picked from 87917239204d67a316cb89751750f86c9ed3640b) The invlpg and sync walkers lack knowledge of large host sptes, descending to non-existant pagetable level. Stop at directory level in such case. Fixes SMP Windows XP with hugepages. Signed-off-by: Marcelo Tosatti Signed-off-by: Avi Kivity Signed-off-by: Greg Kroah-Hartman --- diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 0d2918632b88d..c3c0191b37ff7 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -981,7 +981,7 @@ static int mmu_unsync_walk(struct kvm_mmu_page *sp, for_each_unsync_children(sp->unsync_child_bitmap, i) { u64 ent = sp->spt[i]; - if (is_shadow_present_pte(ent)) { + if (is_shadow_present_pte(ent) && !is_large_pte(ent)) { struct kvm_mmu_page *child; child = page_header(ent & PT64_BASE_ADDR_MASK); diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index 84eee43bbe742..9b5355ef980fa 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h @@ -467,9 +467,13 @@ static int FNAME(shadow_invlpg_entry)(struct kvm_shadow_walk *_sw, u64 *sptep, int level) { - if (level == PT_PAGE_TABLE_LEVEL) { - if (is_shadow_present_pte(*sptep)) + if (level == PT_PAGE_TABLE_LEVEL || + ((level == PT_DIRECTORY_LEVEL) && is_large_pte(*sptep))) { + if (is_shadow_present_pte(*sptep)) { rmap_remove(vcpu->kvm, sptep); + if (is_large_pte(*sptep)) + --vcpu->kvm->stat.lpages; + } set_shadow_pte(sptep, shadow_trap_nonpresent_pte); return 1; }