From mboxrd@z Thu Jan 1 00:00:00 1970 From: Marcelo Tosatti Subject: [patch 06/13] KVM: MMU: global page keeping Date: Sat, 06 Sep 2008 15:48:28 -0300 Message-ID: <20080906192430.958862856@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]:60556 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752462AbYIFT1T (ORCPT ); Sat, 6 Sep 2008 15:27:19 -0400 Content-Disposition: inline; filename=kvm-oos-global-keeping Sender: kvm-owner@vger.kernel.org List-ID: Account pages that only have global entries. Such pages need to be synced on cr4 writes, but not cr3 writes. Index: kvm/arch/x86/kvm/mmu.c =================================================================== --- kvm.orig/arch/x86/kvm/mmu.c +++ kvm/arch/x86/kvm/mmu.c @@ -778,6 +778,7 @@ static struct kvm_mmu_page *kvm_mmu_allo ASSERT(is_empty_shadow_page(sp->spt)); sp->slot_bitmap = 0; sp->multimapped = 0; + sp->flags = (1 << KVM_PG_global); sp->parent_pte = parent_pte; --vcpu->kvm->arch.n_free_mmu_pages; return sp; @@ -1147,18 +1148,22 @@ struct page *gva_to_page(struct kvm_vcpu static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, unsigned pt_access, unsigned pte_access, int user_fault, int write_fault, int dirty, - int *ptwrite, int largepage, gfn_t gfn, - pfn_t pfn, bool speculative) + int global, int *ptwrite, int largepage, + gfn_t gfn, pfn_t pfn, bool speculative) { u64 spte; int was_rmapped = 0; int was_writeble = is_writeble_pte(*shadow_pte); + struct kvm_mmu_page *sp = page_header(__pa(shadow_pte)); pgprintk("%s: spte %llx access %x write_fault %d" " user_fault %d gfn %lx\n", __func__, *shadow_pte, pt_access, write_fault, user_fault, gfn); + if (!global) + kvm_clear_pg_global(sp); + if (is_rmap_pte(*shadow_pte)) { /* * If we overwrite a PTE page pointer with a 2MB PMD, unlink @@ -1285,7 +1290,7 @@ static int direct_map_entry(struct kvm_s if (level == PT_PAGE_TABLE_LEVEL || (walk->largepage && level == PT_DIRECTORY_LEVEL)) { mmu_set_spte(vcpu, sptep, ACC_ALL, ACC_ALL, - 0, walk->write, 1, &walk->pt_write, + 0, walk->write, 1, 0, &walk->pt_write, walk->largepage, gfn, walk->pfn, false); ++vcpu->stat.pf_fixed; return 1; Index: kvm/include/asm-x86/kvm_host.h =================================================================== --- kvm.orig/include/asm-x86/kvm_host.h +++ kvm/include/asm-x86/kvm_host.h @@ -199,6 +199,7 @@ struct kvm_mmu_page { u64 *parent_pte; /* !multimapped */ struct hlist_head parent_ptes; /* multimapped, kvm_pte_chain */ }; + unsigned long flags; }; struct kvm_pv_mmu_op_buffer { @@ -757,4 +758,20 @@ asmlinkage void kvm_handle_fault_on_rebo int kvm_unmap_hva(struct kvm *kvm, unsigned long hva); int kvm_age_hva(struct kvm *kvm, unsigned long hva); +enum kvm_page_flags { + KVM_PG_global, +}; + +#define KVMPGFLAG(name) \ +static inline int kvm_page_##name(struct kvm_mmu_page *sp) \ + { return test_bit(KVM_PG_##name, &sp->flags); } \ +static inline void kvm_set_pg_##name(struct kvm_mmu_page *sp) \ + { set_bit(KVM_PG_##name, &sp->flags); } \ +static inline void kvm_clear_pg_##name(struct kvm_mmu_page *sp) \ + { clear_bit(KVM_PG_##name, &sp->flags); } \ +static inline int kvm_test_clear_pg_##name(struct kvm_mmu_page *sp) \ + { return test_and_clear_bit(KVM_PG_##name, &sp->flags); } + +KVMPGFLAG(global); + #endif Index: kvm/arch/x86/kvm/paging_tmpl.h =================================================================== --- kvm.orig/arch/x86/kvm/paging_tmpl.h +++ kvm/arch/x86/kvm/paging_tmpl.h @@ -274,8 +274,8 @@ static void FNAME(update_pte)(struct kvm return; kvm_get_pfn(pfn); mmu_set_spte(vcpu, spte, page->role.access, pte_access, 0, 0, - gpte & PT_DIRTY_MASK, NULL, largepage, gpte_to_gfn(gpte), - pfn, true); + gpte & PT_DIRTY_MASK, gpte & PT_GLOBAL_MASK, NULL, + largepage, gpte_to_gfn(gpte), pfn, true); } /* @@ -301,6 +301,7 @@ static int FNAME(shadow_walk_entry)(stru mmu_set_spte(vcpu, sptep, access, gw->pte_access & access, sw->user_fault, sw->write_fault, gw->ptes[gw->level-1] & PT_DIRTY_MASK, + gw->ptes[gw->level-1] & PT_GLOBAL_MASK, sw->ptwrite, sw->largepage, gw->gfn, sw->pfn, false); sw->sptep = sptep; --