]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
KVM: MMU: Add validate_direct_spte() helper
authorAvi Kivity <avi@redhat.com>
Tue, 13 Jul 2010 11:27:07 +0000 (14:27 +0300)
committerAvi Kivity <avi@redhat.com>
Mon, 2 Aug 2010 03:40:43 +0000 (06:40 +0300)
Add a helper to verify that a direct shadow page is valid wrt the required
access permissions; drop the page if it is not valid.

Reviewed-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
arch/x86/kvm/mmu.c
arch/x86/kvm/paging_tmpl.h

index b75d6cb44ab63038e42a7885e6a69c779beab585..36c62f33513fb2d0f534c5bf63bfa709ab40d8a2 100644 (file)
@@ -1500,6 +1500,29 @@ static void drop_large_spte(struct kvm_vcpu *vcpu, u64 *sptep)
        }
 }
 
+static void validate_direct_spte(struct kvm_vcpu *vcpu, u64 *sptep,
+                                  unsigned direct_access)
+{
+       if (is_shadow_present_pte(*sptep) && !is_large_pte(*sptep)) {
+               struct kvm_mmu_page *child;
+
+               /*
+                * For the direct sp, if the guest pte's dirty bit
+                * changed form clean to dirty, it will corrupt the
+                * sp's access: allow writable in the read-only sp,
+                * so we should update the spte at this point to get
+                * a new sp with the correct access.
+                */
+               child = page_header(*sptep & PT64_BASE_ADDR_MASK);
+               if (child->role.access == direct_access)
+                       return;
+
+               mmu_page_remove_parent_pte(child, sptep);
+               __set_spte(sptep, shadow_trap_nonpresent_pte);
+               kvm_flush_remote_tlbs(vcpu->kvm);
+       }
+}
+
 static void kvm_mmu_page_unlink_children(struct kvm *kvm,
                                         struct kvm_mmu_page *sp)
 {
index 0fb7068d64c7f612df1a06d7ae5d93232cb7d819..0c7461d3a5be68750d5f12710315d8f45d857237 100644 (file)
@@ -338,30 +338,15 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
                        break;
                }
 
-               if (is_shadow_present_pte(*sptep) && !is_large_pte(*sptep)) {
-                       struct kvm_mmu_page *child;
-
-                       if (level != gw->level)
-                               continue;
-
-                       /*
-                        * For the direct sp, if the guest pte's dirty bit
-                        * changed form clean to dirty, it will corrupt the
-                        * sp's access: allow writable in the read-only sp,
-                        * so we should update the spte at this point to get
-                        * a new sp with the correct access.
-                        */
-                       child = page_header(*sptep & PT64_BASE_ADDR_MASK);
-                       if (child->role.access == direct_access)
-                               continue;
-
-                       mmu_page_remove_parent_pte(child, sptep);
-                       __set_spte(sptep, shadow_trap_nonpresent_pte);
-                       kvm_flush_remote_tlbs(vcpu->kvm);
-               }
+               if (is_shadow_present_pte(*sptep) && !is_large_pte(*sptep)
+                   && level == gw->level)
+                       validate_direct_spte(vcpu, sptep, direct_access);
 
                drop_large_spte(vcpu, sptep);
 
+               if (is_shadow_present_pte(*sptep))
+                       continue;
+
                if (level <= gw->level) {
                        direct = 1;
                        access = direct_access;