From: Avi Kivity <[email protected]>

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 <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
Signed-off-by: Marcelo Tosatti <[email protected]>

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 747af72..d16efbe 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -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)
 {
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 69dcac0..893a75c 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -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;
--
To unsubscribe from this list: send the line "unsubscribe kvm-commits" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to