unsigned int lpid);
 extern int kvmppc_radix_init(void);
 extern void kvmppc_radix_exit(void);
-extern int kvm_unmap_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
-                       unsigned long gfn);
-extern int kvm_age_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
-                       unsigned long gfn);
-extern int kvm_test_age_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
-                       unsigned long gfn);
+extern bool kvm_unmap_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
+                           unsigned long gfn);
+extern bool kvm_age_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
+                         unsigned long gfn);
+extern bool kvm_test_age_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
+                              unsigned long gfn);
 extern long kvmppc_hv_get_dirty_log_radix(struct kvm *kvm,
                        struct kvm_memory_slot *memslot, unsigned long *map);
 extern void kvmppc_radix_flush_memslot(struct kvm *kvm,
 
 #include <linux/mmu_notifier.h>
 
 #define KVM_ARCH_WANT_MMU_NOTIFIER
+#define KVM_ARCH_WANT_NEW_MMU_NOTIFIER_APIS
 
 #define HPTEG_CACHE_NUM                        (1 << 15)
 #define HPTEG_HASH_BITS_PTE            13
 
                                     const struct kvm_memory_slot *old,
                                     const struct kvm_memory_slot *new,
                                     enum kvm_mr_change change);
-       int (*unmap_hva_range)(struct kvm *kvm, unsigned long start,
-                          unsigned long end);
-       int (*age_hva)(struct kvm *kvm, unsigned long start, unsigned long end);
-       int (*test_age_hva)(struct kvm *kvm, unsigned long hva);
-       void (*set_spte_hva)(struct kvm *kvm, unsigned long hva, pte_t pte);
+       bool (*unmap_gfn_range)(struct kvm *kvm, struct kvm_gfn_range *range);
+       bool (*age_gfn)(struct kvm *kvm, struct kvm_gfn_range *range);
+       bool (*test_age_gfn)(struct kvm *kvm, struct kvm_gfn_range *range);
+       bool (*set_spte_gfn)(struct kvm *kvm, struct kvm_gfn_range *range);
        void (*free_memslot)(struct kvm_memory_slot *slot);
        int (*init_vm)(struct kvm *kvm);
        void (*destroy_vm)(struct kvm *kvm);
 
        kvm->arch.kvm_ops->commit_memory_region(kvm, mem, old, new, change);
 }
 
-int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end,
-                       unsigned flags)
+bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
 {
-       return kvm->arch.kvm_ops->unmap_hva_range(kvm, start, end);
+       return kvm->arch.kvm_ops->unmap_gfn_range(kvm, range);
 }
 
-int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end)
+bool kvm_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
 {
-       return kvm->arch.kvm_ops->age_hva(kvm, start, end);
+       return kvm->arch.kvm_ops->age_gfn(kvm, range);
 }
 
-int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
+bool kvm_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
 {
-       return kvm->arch.kvm_ops->test_age_hva(kvm, hva);
+       return kvm->arch.kvm_ops->test_age_gfn(kvm, range);
 }
 
-int kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte)
+bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
 {
-       kvm->arch.kvm_ops->set_spte_hva(kvm, hva, pte);
-       return 0;
+       return kvm->arch.kvm_ops->set_spte_gfn(kvm, range);
 }
 
 int kvmppc_core_init_vm(struct kvm *kvm)
 
 
 extern void kvmppc_core_flush_memslot_hv(struct kvm *kvm,
                                         struct kvm_memory_slot *memslot);
-extern int kvm_unmap_hva_range_hv(struct kvm *kvm, unsigned long start,
-                                 unsigned long end);
-extern int kvm_age_hva_hv(struct kvm *kvm, unsigned long start,
-                         unsigned long end);
-extern int kvm_test_age_hva_hv(struct kvm *kvm, unsigned long hva);
-extern void kvm_set_spte_hva_hv(struct kvm *kvm, unsigned long hva, pte_t pte);
+extern bool kvm_unmap_gfn_range_hv(struct kvm *kvm, struct kvm_gfn_range *range);
+extern bool kvm_age_gfn_hv(struct kvm *kvm, struct kvm_gfn_range *range);
+extern bool kvm_test_age_gfn_hv(struct kvm *kvm, struct kvm_gfn_range *range);
+extern bool kvm_set_spte_gfn_hv(struct kvm *kvm, struct kvm_gfn_range *range);
 
 extern int kvmppc_mmu_init_pr(struct kvm_vcpu *vcpu);
 extern void kvmppc_mmu_destroy_pr(struct kvm_vcpu *vcpu);
 
        srcu_read_unlock(&kvm->srcu, srcu_idx);
 }
 
-typedef int (*hva_handler_fn)(struct kvm *kvm, struct kvm_memory_slot *memslot,
-                             unsigned long gfn);
-
-static int kvm_handle_hva_range(struct kvm *kvm,
-                               unsigned long start,
-                               unsigned long end,
-                               hva_handler_fn handler)
-{
-       int ret;
-       int retval = 0;
-       struct kvm_memslots *slots;
-       struct kvm_memory_slot *memslot;
-
-       slots = kvm_memslots(kvm);
-       kvm_for_each_memslot(memslot, slots) {
-               unsigned long hva_start, hva_end;
-               gfn_t gfn, gfn_end;
-
-               hva_start = max(start, memslot->userspace_addr);
-               hva_end = min(end, memslot->userspace_addr +
-                                       (memslot->npages << PAGE_SHIFT));
-               if (hva_start >= hva_end)
-                       continue;
-               /*
-                * {gfn(page) | page intersects with [hva_start, hva_end)} =
-                * {gfn, gfn+1, ..., gfn_end-1}.
-                */
-               gfn = hva_to_gfn_memslot(hva_start, memslot);
-               gfn_end = hva_to_gfn_memslot(hva_end + PAGE_SIZE - 1, memslot);
-
-               for (; gfn < gfn_end; ++gfn) {
-                       ret = handler(kvm, memslot, gfn);
-                       retval |= ret;
-               }
-       }
-
-       return retval;
-}
-
-static int kvm_handle_hva(struct kvm *kvm, unsigned long hva,
-                         hva_handler_fn handler)
-{
-       return kvm_handle_hva_range(kvm, hva, hva + 1, handler);
-}
-
 /* Must be called with both HPTE and rmap locked */
 static void kvmppc_unmap_hpte(struct kvm *kvm, unsigned long i,
                              struct kvm_memory_slot *memslot,
        }
 }
 
-static int kvm_unmap_rmapp(struct kvm *kvm, struct kvm_memory_slot *memslot,
-                          unsigned long gfn)
+static bool kvm_unmap_rmapp(struct kvm *kvm, struct kvm_memory_slot *memslot,
+                           unsigned long gfn)
 {
        unsigned long i;
        __be64 *hptep;
                unlock_rmap(rmapp);
                __unlock_hpte(hptep, be64_to_cpu(hptep[0]));
        }
-       return 0;
+       return false;
 }
 
-int kvm_unmap_hva_range_hv(struct kvm *kvm, unsigned long start, unsigned long end)
+bool kvm_unmap_gfn_range_hv(struct kvm *kvm, struct kvm_gfn_range *range)
 {
-       hva_handler_fn handler;
+       if (kvm_is_radix(kvm))
+               return kvm_unmap_radix(kvm, range->slot, range->start);
 
-       handler = kvm_is_radix(kvm) ? kvm_unmap_radix : kvm_unmap_rmapp;
-       kvm_handle_hva_range(kvm, start, end, handler);
-       return 0;
+       return kvm_unmap_rmapp(kvm, range->slot, range->start);
 }
 
 void kvmppc_core_flush_memslot_hv(struct kvm *kvm,
        }
 }
 
-static int kvm_age_rmapp(struct kvm *kvm, struct kvm_memory_slot *memslot,
-                        unsigned long gfn)
+static bool kvm_age_rmapp(struct kvm *kvm, struct kvm_memory_slot *memslot,
+                         unsigned long gfn)
 {
        struct revmap_entry *rev = kvm->arch.hpt.rev;
        unsigned long head, i, j;
        return ret;
 }
 
-int kvm_age_hva_hv(struct kvm *kvm, unsigned long start, unsigned long end)
+bool kvm_age_gfn_hv(struct kvm *kvm, struct kvm_gfn_range *range)
 {
-       hva_handler_fn handler;
+       if (kvm_is_radix(kvm))
+               kvm_age_radix(kvm, range->slot, range->start);
 
-       handler = kvm_is_radix(kvm) ? kvm_age_radix : kvm_age_rmapp;
-       return kvm_handle_hva_range(kvm, start, end, handler);
+       return kvm_age_rmapp(kvm, range->slot, range->start);
 }
 
-static int kvm_test_age_rmapp(struct kvm *kvm, struct kvm_memory_slot *memslot,
-                             unsigned long gfn)
+static bool kvm_test_age_rmapp(struct kvm *kvm, struct kvm_memory_slot *memslot,
+                              unsigned long gfn)
 {
        struct revmap_entry *rev = kvm->arch.hpt.rev;
        unsigned long head, i, j;
        unsigned long *hp;
-       int ret = 1;
+       bool ret = true;
        unsigned long *rmapp;
 
        rmapp = &memslot->arch.rmap[gfn - memslot->base_gfn];
        if (*rmapp & KVMPPC_RMAP_REFERENCED)
-               return 1;
+               return true;
 
        lock_rmap(rmapp);
        if (*rmapp & KVMPPC_RMAP_REFERENCED)
                                goto out;
                } while ((i = j) != head);
        }
-       ret = 0;
+       ret = false;
 
  out:
        unlock_rmap(rmapp);
        return ret;
 }
 
-int kvm_test_age_hva_hv(struct kvm *kvm, unsigned long hva)
+bool kvm_test_age_gfn_hv(struct kvm *kvm, struct kvm_gfn_range *range)
 {
-       hva_handler_fn handler;
+       if (kvm_is_radix(kvm))
+               kvm_test_age_radix(kvm, range->slot, range->start);
 
-       handler = kvm_is_radix(kvm) ? kvm_test_age_radix : kvm_test_age_rmapp;
-       return kvm_handle_hva(kvm, hva, handler);
+       return kvm_test_age_rmapp(kvm, range->slot, range->start);
 }
 
-void kvm_set_spte_hva_hv(struct kvm *kvm, unsigned long hva, pte_t pte)
+bool kvm_set_spte_gfn_hv(struct kvm *kvm, struct kvm_gfn_range *range)
 {
-       hva_handler_fn handler;
+       if (kvm_is_radix(kvm))
+               return kvm_unmap_radix(kvm, range->slot, range->start);
 
-       handler = kvm_is_radix(kvm) ? kvm_unmap_radix : kvm_unmap_rmapp;
-       kvm_handle_hva(kvm, hva, handler);
+       return kvm_unmap_rmapp(kvm, range->slot, range->start);
 }
 
 static int vcpus_running(struct kvm *kvm)
 
 }
 
 /* Called with kvm->mmu_lock held */
-int kvm_unmap_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
-                   unsigned long gfn)
+bool kvm_unmap_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
+                    unsigned long gfn)
 {
        pte_t *ptep;
        unsigned long gpa = gfn << PAGE_SHIFT;
 
        if (kvm->arch.secure_guest & KVMPPC_SECURE_INIT_DONE) {
                uv_page_inval(kvm->arch.lpid, gpa, PAGE_SHIFT);
-               return 0;
+               return false;
        }
 
        ptep = find_kvm_secondary_pte(kvm, gpa, &shift);
        if (ptep && pte_present(*ptep))
                kvmppc_unmap_pte(kvm, ptep, gpa, shift, memslot,
                                 kvm->arch.lpid);
-       return 0;
+       return false;
 }
 
 /* Called with kvm->mmu_lock held */
-int kvm_age_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
-                 unsigned long gfn)
+bool kvm_age_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
+                  unsigned long gfn)
 {
        pte_t *ptep;
        unsigned long gpa = gfn << PAGE_SHIFT;
        unsigned int shift;
-       int ref = 0;
+       bool ref = false;
        unsigned long old, *rmapp;
 
        if (kvm->arch.secure_guest & KVMPPC_SECURE_INIT_DONE)
                kvmhv_update_nest_rmap_rc_list(kvm, rmapp, _PAGE_ACCESSED, 0,
                                               old & PTE_RPN_MASK,
                                               1UL << shift);
-               ref = 1;
+               ref = true;
        }
        return ref;
 }
 
 /* Called with kvm->mmu_lock held */
-int kvm_test_age_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
-                      unsigned long gfn)
+bool kvm_test_age_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
+                       unsigned long gfn)
+
 {
        pte_t *ptep;
        unsigned long gpa = gfn << PAGE_SHIFT;
        unsigned int shift;
-       int ref = 0;
+       bool ref = false;
 
        if (kvm->arch.secure_guest & KVMPPC_SECURE_INIT_DONE)
                return ref;
 
        ptep = find_kvm_secondary_pte(kvm, gpa, &shift);
        if (ptep && pte_present(*ptep) && pte_young(*ptep))
-               ref = 1;
+               ref = true;
        return ref;
 }
 
 
                kvmhv_release_all_nested(kvm);
        kvmppc_rmap_reset(kvm);
        kvm->arch.process_table = 0;
-       /* Mutual exclusion with kvm_unmap_hva_range etc. */
+       /* Mutual exclusion with kvm_unmap_gfn_range etc. */
        spin_lock(&kvm->mmu_lock);
        kvm->arch.radix = 0;
        spin_unlock(&kvm->mmu_lock);
        if (err)
                return err;
        kvmppc_rmap_reset(kvm);
-       /* Mutual exclusion with kvm_unmap_hva_range etc. */
+       /* Mutual exclusion with kvm_unmap_gfn_range etc. */
        spin_lock(&kvm->mmu_lock);
        kvm->arch.radix = 1;
        spin_unlock(&kvm->mmu_lock);
        .flush_memslot  = kvmppc_core_flush_memslot_hv,
        .prepare_memory_region = kvmppc_core_prepare_memory_region_hv,
        .commit_memory_region  = kvmppc_core_commit_memory_region_hv,
-       .unmap_hva_range = kvm_unmap_hva_range_hv,
-       .age_hva  = kvm_age_hva_hv,
-       .test_age_hva = kvm_test_age_hva_hv,
-       .set_spte_hva = kvm_set_spte_hva_hv,
+       .unmap_gfn_range = kvm_unmap_gfn_range_hv,
+       .age_gfn = kvm_age_gfn_hv,
+       .test_age_gfn = kvm_test_age_gfn_hv,
+       .set_spte_gfn = kvm_set_spte_gfn_hv,
        .free_memslot = kvmppc_core_free_memslot_hv,
        .init_vm =  kvmppc_core_init_vm_hv,
        .destroy_vm = kvmppc_core_destroy_vm_hv,
 
 }
 
 /************* MMU Notifiers *************/
-static void do_kvm_unmap_hva(struct kvm *kvm, unsigned long start,
-                            unsigned long end)
+static bool do_kvm_unmap_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
 {
        long i;
        struct kvm_vcpu *vcpu;
-       struct kvm_memslots *slots;
-       struct kvm_memory_slot *memslot;
 
-       slots = kvm_memslots(kvm);
-       kvm_for_each_memslot(memslot, slots) {
-               unsigned long hva_start, hva_end;
-               gfn_t gfn, gfn_end;
+       kvm_for_each_vcpu(i, vcpu, kvm)
+               kvmppc_mmu_pte_pflush(vcpu, range->start << PAGE_SHIFT,
+                                     range->end << PAGE_SHIFT);
 
-               hva_start = max(start, memslot->userspace_addr);
-               hva_end = min(end, memslot->userspace_addr +
-                                       (memslot->npages << PAGE_SHIFT));
-               if (hva_start >= hva_end)
-                       continue;
-               /*
-                * {gfn(page) | page intersects with [hva_start, hva_end)} =
-                * {gfn, gfn+1, ..., gfn_end-1}.
-                */
-               gfn = hva_to_gfn_memslot(hva_start, memslot);
-               gfn_end = hva_to_gfn_memslot(hva_end + PAGE_SIZE - 1, memslot);
-               kvm_for_each_vcpu(i, vcpu, kvm)
-                       kvmppc_mmu_pte_pflush(vcpu, gfn << PAGE_SHIFT,
-                                             gfn_end << PAGE_SHIFT);
-       }
+       return false;
 }
 
-static int kvm_unmap_hva_range_pr(struct kvm *kvm, unsigned long start,
-                                 unsigned long end)
+static bool kvm_unmap_gfn_range_pr(struct kvm *kvm, struct kvm_gfn_range *range)
 {
-       do_kvm_unmap_hva(kvm, start, end);
-
-       return 0;
+       return do_kvm_unmap_gfn(kvm, range);
 }
 
-static int kvm_age_hva_pr(struct kvm *kvm, unsigned long start,
-                         unsigned long end)
+static bool kvm_age_gfn_pr(struct kvm *kvm, struct kvm_gfn_range *range)
 {
        /* XXX could be more clever ;) */
-       return 0;
+       return false;
 }
 
-static int kvm_test_age_hva_pr(struct kvm *kvm, unsigned long hva)
+static bool kvm_test_age_gfn_pr(struct kvm *kvm, struct kvm_gfn_range *range)
 {
        /* XXX could be more clever ;) */
-       return 0;
+       return false;
 }
 
-static void kvm_set_spte_hva_pr(struct kvm *kvm, unsigned long hva, pte_t pte)
+static bool kvm_set_spte_gfn_pr(struct kvm *kvm, struct kvm_gfn_range *range)
 {
        /* The page will get remapped properly on its next fault */
-       do_kvm_unmap_hva(kvm, hva, hva + PAGE_SIZE);
+       return do_kvm_unmap_gfn(kvm, range);
 }
 
 /*****************************************/
        .flush_memslot = kvmppc_core_flush_memslot_pr,
        .prepare_memory_region = kvmppc_core_prepare_memory_region_pr,
        .commit_memory_region = kvmppc_core_commit_memory_region_pr,
-       .unmap_hva_range = kvm_unmap_hva_range_pr,
-       .age_hva  = kvm_age_hva_pr,
-       .test_age_hva = kvm_test_age_hva_pr,
-       .set_spte_hva = kvm_set_spte_hva_pr,
+       .unmap_gfn_range = kvm_unmap_gfn_range_pr,
+       .age_gfn  = kvm_age_gfn_pr,
+       .test_age_gfn = kvm_test_age_gfn_pr,
+       .set_spte_gfn = kvm_set_spte_gfn_pr,
        .free_memslot = kvmppc_core_free_memslot_pr,
        .init_vm = kvmppc_core_init_vm_pr,
        .destroy_vm = kvmppc_core_destroy_vm_pr,
 
 
 /************* MMU Notifiers *************/
 
-static int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
+static bool kvm_e500_mmu_unmap_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
 {
        /*
         * Flush all shadow tlb entries everywhere. This is slow, but
         * we are 100% sure that we catch the to be unmapped page
         */
-       kvm_flush_remote_tlbs(kvm);
-
-       return 0;
+       return true;
 }
 
-int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end,
-                       unsigned flags)
+bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
 {
-       /* kvm_unmap_hva flushes everything anyways */
-       kvm_unmap_hva(kvm, start);
-
-       return 0;
+       return kvm_e500_mmu_unmap_gfn(kvm, range);
 }
 
-int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end)
+bool kvm_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
 {
        /* XXX could be more clever ;) */
-       return 0;
+       return false;
 }
 
-int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
+bool kvm_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
 {
        /* XXX could be more clever ;) */
-       return 0;
+       return false;
 }
 
-int kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte)
+bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
 {
        /* The page will get remapped properly on its next fault */
-       kvm_unmap_hva(kvm, hva);
-       return 0;
+       return kvm_e500_mmu_unmap_gfn(kvm, range);
 }
 
 /*****************************************/