Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[pandora-kernel.git] / arch / x86 / kvm / paging_tmpl.h
index 146b681..6bccc24 100644 (file)
@@ -550,6 +550,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
        int r;
        pfn_t pfn;
        int level = PT_PAGE_TABLE_LEVEL;
+       int force_pt_level;
        unsigned long mmu_seq;
        bool map_writable;
 
@@ -577,7 +578,11 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
                return 0;
        }
 
-       if (walker.level >= PT_DIRECTORY_LEVEL) {
+       if (walker.level >= PT_DIRECTORY_LEVEL)
+               force_pt_level = mapping_level_dirty_bitmap(vcpu, walker.gfn);
+       else
+               force_pt_level = 1;
+       if (!force_pt_level) {
                level = min(walker.level, mapping_level(vcpu, walker.gfn));
                walker.gfn = walker.gfn & ~(KVM_PAGES_PER_HPAGE(level) - 1);
        }
@@ -593,15 +598,14 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
        if (is_error_pfn(pfn))
                return kvm_handle_bad_page(vcpu->kvm, walker.gfn, pfn);
 
-       if (!map_writable)
-               walker.pte_access &= ~ACC_WRITE_MASK;
-
        spin_lock(&vcpu->kvm->mmu_lock);
        if (mmu_notifier_retry(vcpu, mmu_seq))
                goto out_unlock;
 
        trace_kvm_mmu_audit(vcpu, AUDIT_PRE_PAGE_FAULT);
        kvm_mmu_free_some_pages(vcpu);
+       if (!force_pt_level)
+               transparent_hugepage_adjust(vcpu, &walker.gfn, &pfn, &level);
        sptep = FNAME(fetch)(vcpu, addr, &walker, user_fault, write_fault,
                             level, &write_pt, pfn, map_writable, prefault);
        (void)sptep;
@@ -809,12 +813,8 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
 
                nr_present++;
                pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte);
-               if (!(sp->spt[i] & SPTE_HOST_WRITEABLE)) {
-                       pte_access &= ~ACC_WRITE_MASK;
-                       host_writable = 0;
-               } else {
-                       host_writable = 1;
-               }
+               host_writable = sp->spt[i] & SPTE_HOST_WRITEABLE;
+
                set_spte(vcpu, &sp->spt[i], pte_access, 0, 0,
                         is_dirty_gpte(gpte), PT_PAGE_TABLE_LEVEL, gfn,
                         spte_to_pfn(sp->spt[i]), true, false,