From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Yang, Sheng" Subject: [PATCH 4/8] KVM: MMU: Add EPT support Date: Fri, 25 Apr 2008 16:25:57 +0800 Message-ID: <200804251625.57245.sheng.yang@intel.com> Mime-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_VWZEIEnc8N/1AHy" Cc: kvm-devel To: Avi Kivity Return-path: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: kvm-devel-bounces@lists.sourceforge.net Errors-To: kvm-devel-bounces@lists.sourceforge.net List-Id: kvm.vger.kernel.org --Boundary-00=_VWZEIEnc8N/1AHy Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline =46rom 239f38236196c2321989c64d7c61ff28490b3f00 Mon Sep 17 00:00:00 2001 =46rom: Sheng Yang Date: Fri, 25 Apr 2008 21:13:50 +0800 Subject: [PATCH 4/8] KVM: MMU: Add EPT support Enable kvm_set_spte() to generate EPT entries. Signed-off-by: Sheng Yang =2D-- arch/x86/kvm/mmu.c | 47 ++++++++++++++++++++++++++++++++--------= =2D-- arch/x86/kvm/x86.c | 3 ++ include/asm-x86/kvm_host.h | 3 ++ 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index bcfaf7e..c28a36b 100644 =2D-- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -152,6 +152,12 @@ static struct kmem_cache *mmu_page_header_cache; static u64 __read_mostly shadow_trap_nonpresent_pte; static u64 __read_mostly shadow_notrap_nonpresent_pte; +static u64 __read_mostly shadow_base_present_pte; +static u64 __read_mostly shadow_nx_mask; +static u64 __read_mostly shadow_x_mask; /* mutual exclusive with nx_mask */ +static u64 __read_mostly shadow_user_mask; +static u64 __read_mostly shadow_accessed_mask; +static u64 __read_mostly shadow_dirty_mask; void kvm_mmu_set_nonpresent_ptes(u64 trap_pte, u64 notrap_pte) { @@ -160,6 +166,23 @@ void kvm_mmu_set_nonpresent_ptes(u64 trap_pte, u64=20 notrap_pte) } EXPORT_SYMBOL_GPL(kvm_mmu_set_nonpresent_ptes); +void kvm_mmu_set_base_ptes(u64 base_pte) +{ + shadow_base_present_pte =3D base_pte; +} +EXPORT_SYMBOL_GPL(kvm_mmu_set_base_ptes); + +void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask, + u64 dirty_mask, u64 nx_mask, u64 x_mask) +{ + shadow_user_mask =3D user_mask; + shadow_accessed_mask =3D accessed_mask; + shadow_dirty_mask =3D dirty_mask; + shadow_nx_mask =3D nx_mask; + shadow_x_mask =3D x_mask; +} +EXPORT_SYMBOL_GPL(kvm_mmu_set_mask_ptes); + static int is_write_protection(struct kvm_vcpu *vcpu) { return vcpu->arch.cr0 & X86_CR0_WP; @@ -198,7 +221,7 @@ static int is_writeble_pte(unsigned long pte) static int is_dirty_pte(unsigned long pte) { =2D return pte & PT_DIRTY_MASK; + return pte & shadow_dirty_mask; } static int is_rmap_pte(u64 pte) @@ -513,7 +536,7 @@ static void rmap_remove(struct kvm *kvm, u64 *spte) return; sp =3D page_header(__pa(spte)); pfn =3D spte_to_pfn(*spte); =2D if (*spte & PT_ACCESSED_MASK) + if (*spte & shadow_accessed_mask) kvm_set_pfn_accessed(pfn); if (is_writeble_pte(*spte)) kvm_release_pfn_dirty(pfn); @@ -1039,17 +1062,17 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64= =20 *shadow_pte, * whether the guest actually used the pte (in order to detect * demand paging). */ =2D spte =3D PT_PRESENT_MASK | PT_DIRTY_MASK; + spte =3D shadow_base_present_pte | shadow_dirty_mask; if (!speculative) pte_access |=3D PT_ACCESSED_MASK; if (!dirty) pte_access &=3D ~ACC_WRITE_MASK; =2D if (!(pte_access & ACC_EXEC_MASK)) =2D spte |=3D PT64_NX_MASK; =2D =2D spte |=3D PT_PRESENT_MASK; + if (pte_access & ACC_EXEC_MASK) + spte |=3D shadow_x_mask; + else + spte |=3D shadow_nx_mask; if (pte_access & ACC_USER_MASK) =2D spte |=3D PT_USER_MASK; + spte |=3D shadow_user_mask; if (largepage) spte |=3D PT_PAGE_SIZE_MASK; @@ -1155,7 +1178,7 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t = v,=20 int write, } table[index] =3D __pa(new_table->spt) | PT_PRESENT_MASK =2D | PT_WRITABLE_MASK | PT_USER_MASK; + | PT_WRITABLE_MASK | shadow_user_mask; } table_addr =3D table[index] & PT64_BASE_ADDR_MASK; } @@ -1343,7 +1366,7 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_= t=20 gpa, spin_lock(&vcpu->kvm->mmu_lock); kvm_mmu_free_some_pages(vcpu); r =3D __direct_map(vcpu, gpa, error_code & PFERR_WRITE_MASK, =2D largepage, gfn, pfn, TDP_ROOT_LEVEL); + largepage, gfn, pfn, kvm_x86_ops->get_tdp_level()); spin_unlock(&vcpu->kvm->mmu_lock); return r; @@ -1450,7 +1473,7 @@ static int init_kvm_tdp_mmu(struct kvm_vcpu *vcpu) context->page_fault =3D tdp_page_fault; context->free =3D nonpaging_free; context->prefetch_page =3D nonpaging_prefetch_page; =2D context->shadow_root_level =3D TDP_ROOT_LEVEL; + context->shadow_root_level =3D kvm_x86_ops->get_tdp_level(); context->root_hpa =3D INVALID_PAGE; if (!is_paging(vcpu)) { @@ -1599,7 +1622,7 @@ static bool last_updated_pte_accessed(struct kvm_vcpu= =20 *vcpu) { u64 *spte =3D vcpu->arch.last_pte_updated; =2D return !!(spte && (*spte & PT_ACCESSED_MASK)); + return !!(spte && (*spte & shadow_accessed_mask)); } static void mmu_guess_page_from_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 0ce5563..0735efb 100644 =2D-- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2417,6 +2417,9 @@ int kvm_arch_init(void *opaque) kvm_x86_ops =3D ops; kvm_mmu_set_nonpresent_ptes(0ull, 0ull); + kvm_mmu_set_base_ptes(PT_PRESENT_MASK); + kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK, + PT_DIRTY_MASK, PT64_NX_MASK, 0); return 0; out: diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h index 65b27c9..715f7b9 100644 =2D-- a/include/asm-x86/kvm_host.h +++ b/include/asm-x86/kvm_host.h @@ -433,6 +433,9 @@ void kvm_mmu_destroy(struct kvm_vcpu *vcpu); int kvm_mmu_create(struct kvm_vcpu *vcpu); int kvm_mmu_setup(struct kvm_vcpu *vcpu); void kvm_mmu_set_nonpresent_ptes(u64 trap_pte, u64 notrap_pte); +void kvm_mmu_set_base_ptes(u64 base_pte); +void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask, + u64 dirty_mask, u64 nx_mask, u64 x_mask); int kvm_mmu_reset_context(struct kvm_vcpu *vcpu); void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot); =2D- 1.5.4.5 --Boundary-00=_VWZEIEnc8N/1AHy Content-Type: text/x-diff; charset="utf-8"; name="0004-KVM-MMU-Add-EPT-support.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="0004-KVM-MMU-Add-EPT-support.patch" =46rom 239f38236196c2321989c64d7c61ff28490b3f00 Mon Sep 17 00:00:00 2001 =46rom: Sheng Yang Date: Fri, 25 Apr 2008 21:13:50 +0800 Subject: [PATCH 4/8] KVM: MMU: Add EPT support Enable kvm_set_spte() to generate EPT entries. Signed-off-by: Sheng Yang =2D-- arch/x86/kvm/mmu.c | 47 ++++++++++++++++++++++++++++++++--------= =2D-- arch/x86/kvm/x86.c | 3 ++ include/asm-x86/kvm_host.h | 3 ++ 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index bcfaf7e..c28a36b 100644 =2D-- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -152,6 +152,12 @@ static struct kmem_cache *mmu_page_header_cache; =20 static u64 __read_mostly shadow_trap_nonpresent_pte; static u64 __read_mostly shadow_notrap_nonpresent_pte; +static u64 __read_mostly shadow_base_present_pte; +static u64 __read_mostly shadow_nx_mask; +static u64 __read_mostly shadow_x_mask; /* mutual exclusive with nx_mask */ +static u64 __read_mostly shadow_user_mask; +static u64 __read_mostly shadow_accessed_mask; +static u64 __read_mostly shadow_dirty_mask; =20 void kvm_mmu_set_nonpresent_ptes(u64 trap_pte, u64 notrap_pte) { @@ -160,6 +166,23 @@ void kvm_mmu_set_nonpresent_ptes(u64 trap_pte, u64 not= rap_pte) } EXPORT_SYMBOL_GPL(kvm_mmu_set_nonpresent_ptes); =20 +void kvm_mmu_set_base_ptes(u64 base_pte) +{ + shadow_base_present_pte =3D base_pte; +} +EXPORT_SYMBOL_GPL(kvm_mmu_set_base_ptes); + +void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask, + u64 dirty_mask, u64 nx_mask, u64 x_mask) +{ + shadow_user_mask =3D user_mask; + shadow_accessed_mask =3D accessed_mask; + shadow_dirty_mask =3D dirty_mask; + shadow_nx_mask =3D nx_mask; + shadow_x_mask =3D x_mask; +} +EXPORT_SYMBOL_GPL(kvm_mmu_set_mask_ptes); + static int is_write_protection(struct kvm_vcpu *vcpu) { return vcpu->arch.cr0 & X86_CR0_WP; @@ -198,7 +221,7 @@ static int is_writeble_pte(unsigned long pte) =20 static int is_dirty_pte(unsigned long pte) { =2D return pte & PT_DIRTY_MASK; + return pte & shadow_dirty_mask; } =20 static int is_rmap_pte(u64 pte) @@ -513,7 +536,7 @@ static void rmap_remove(struct kvm *kvm, u64 *spte) return; sp =3D page_header(__pa(spte)); pfn =3D spte_to_pfn(*spte); =2D if (*spte & PT_ACCESSED_MASK) + if (*spte & shadow_accessed_mask) kvm_set_pfn_accessed(pfn); if (is_writeble_pte(*spte)) kvm_release_pfn_dirty(pfn); @@ -1039,17 +1062,17 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64= *shadow_pte, * whether the guest actually used the pte (in order to detect * demand paging). */ =2D spte =3D PT_PRESENT_MASK | PT_DIRTY_MASK; + spte =3D shadow_base_present_pte | shadow_dirty_mask; if (!speculative) pte_access |=3D PT_ACCESSED_MASK; if (!dirty) pte_access &=3D ~ACC_WRITE_MASK; =2D if (!(pte_access & ACC_EXEC_MASK)) =2D spte |=3D PT64_NX_MASK; =2D =2D spte |=3D PT_PRESENT_MASK; + if (pte_access & ACC_EXEC_MASK) + spte |=3D shadow_x_mask; + else + spte |=3D shadow_nx_mask; if (pte_access & ACC_USER_MASK) =2D spte |=3D PT_USER_MASK; + spte |=3D shadow_user_mask; if (largepage) spte |=3D PT_PAGE_SIZE_MASK; =20 @@ -1155,7 +1178,7 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t = v, int write, } =20 table[index] =3D __pa(new_table->spt) | PT_PRESENT_MASK =2D | PT_WRITABLE_MASK | PT_USER_MASK; + | PT_WRITABLE_MASK | shadow_user_mask; } table_addr =3D table[index] & PT64_BASE_ADDR_MASK; } @@ -1343,7 +1366,7 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_= t gpa, spin_lock(&vcpu->kvm->mmu_lock); kvm_mmu_free_some_pages(vcpu); r =3D __direct_map(vcpu, gpa, error_code & PFERR_WRITE_MASK, =2D largepage, gfn, pfn, TDP_ROOT_LEVEL); + largepage, gfn, pfn, kvm_x86_ops->get_tdp_level()); spin_unlock(&vcpu->kvm->mmu_lock); =20 return r; @@ -1450,7 +1473,7 @@ static int init_kvm_tdp_mmu(struct kvm_vcpu *vcpu) context->page_fault =3D tdp_page_fault; context->free =3D nonpaging_free; context->prefetch_page =3D nonpaging_prefetch_page; =2D context->shadow_root_level =3D TDP_ROOT_LEVEL; + context->shadow_root_level =3D kvm_x86_ops->get_tdp_level(); context->root_hpa =3D INVALID_PAGE; =20 if (!is_paging(vcpu)) { @@ -1599,7 +1622,7 @@ static bool last_updated_pte_accessed(struct kvm_vcpu= *vcpu) { u64 *spte =3D vcpu->arch.last_pte_updated; =20 =2D return !!(spte && (*spte & PT_ACCESSED_MASK)); + return !!(spte && (*spte & shadow_accessed_mask)); } =20 static void mmu_guess_page_from_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 0ce5563..0735efb 100644 =2D-- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2417,6 +2417,9 @@ int kvm_arch_init(void *opaque) =20 kvm_x86_ops =3D ops; kvm_mmu_set_nonpresent_ptes(0ull, 0ull); + kvm_mmu_set_base_ptes(PT_PRESENT_MASK); + kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK, + PT_DIRTY_MASK, PT64_NX_MASK, 0); return 0; =20 out: diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h index 65b27c9..715f7b9 100644 =2D-- a/include/asm-x86/kvm_host.h +++ b/include/asm-x86/kvm_host.h @@ -433,6 +433,9 @@ void kvm_mmu_destroy(struct kvm_vcpu *vcpu); int kvm_mmu_create(struct kvm_vcpu *vcpu); int kvm_mmu_setup(struct kvm_vcpu *vcpu); void kvm_mmu_set_nonpresent_ptes(u64 trap_pte, u64 notrap_pte); +void kvm_mmu_set_base_ptes(u64 base_pte); +void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask, + u64 dirty_mask, u64 nx_mask, u64 x_mask); =20 int kvm_mmu_reset_context(struct kvm_vcpu *vcpu); void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot); =2D-=20 1.5.4.5 --Boundary-00=_VWZEIEnc8N/1AHy Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline ------------------------------------------------------------------------- This SF.net email is sponsored by the 2008 JavaOne(SM) Conference Don't miss this year's exciting event. There's still time to save $100. Use priority code J8TL2D2. http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone --Boundary-00=_VWZEIEnc8N/1AHy Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ kvm-devel mailing list kvm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kvm-devel --Boundary-00=_VWZEIEnc8N/1AHy--