]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - arch/powerpc/kvm/book3s_64_mmu_hv.c
KVM: PPC: Book3S HV: Handle memory slot deletion and modification correctly
[karo-tx-linux.git] / arch / powerpc / kvm / book3s_64_mmu_hv.c
index a389cc62b16c7103541d3936e1893af7a1472ab4..f598366e51c648a5bbb336a5359da251487e24c2 100644 (file)
@@ -851,7 +851,8 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp,
                psize = hpte_page_size(hptep[0], ptel);
                if ((hptep[0] & HPTE_V_VALID) &&
                    hpte_rpn(ptel, psize) == gfn) {
-                       hptep[0] |= HPTE_V_ABSENT;
+                       if (kvm->arch.using_mmu_notifiers)
+                               hptep[0] |= HPTE_V_ABSENT;
                        kvmppc_invalidate_hpte(kvm, hptep, i);
                        /* Harvest R and C */
                        rcbits = hptep[1] & (HPTE_R_R | HPTE_R_C);
@@ -878,6 +879,28 @@ int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
        return 0;
 }
 
+void kvmppc_core_flush_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot)
+{
+       unsigned long *rmapp;
+       unsigned long gfn;
+       unsigned long n;
+
+       rmapp = memslot->arch.rmap;
+       gfn = memslot->base_gfn;
+       for (n = memslot->npages; n; --n) {
+               /*
+                * Testing the present bit without locking is OK because
+                * the memslot has been marked invalid already, and hence
+                * no new HPTEs referencing this page can be created,
+                * thus the present bit can't go from 0 to 1.
+                */
+               if (*rmapp & KVMPPC_RMAP_PRESENT)
+                       kvm_unmap_rmapp(kvm, rmapp, gfn);
+               ++rmapp;
+               ++gfn;
+       }
+}
+
 static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
                         unsigned long gfn)
 {
@@ -1031,16 +1054,16 @@ static int kvm_test_clear_dirty(struct kvm *kvm, unsigned long *rmapp)
        return ret;
 }
 
-long kvmppc_hv_get_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot)
+long kvmppc_hv_get_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot,
+                            unsigned long *map)
 {
        unsigned long i;
-       unsigned long *rmapp, *map;
+       unsigned long *rmapp;
 
        preempt_disable();
        rmapp = memslot->arch.rmap;
-       map = memslot->dirty_bitmap;
        for (i = 0; i < memslot->npages; ++i) {
-               if (kvm_test_clear_dirty(kvm, rmapp))
+               if (kvm_test_clear_dirty(kvm, rmapp) && map)
                        __set_bit_le(i, map);
                ++rmapp;
        }