rmap_desc_cache, 1);
        if (r)
                goto out;
-       r = mmu_topup_memory_cache_page(&vcpu->mmu_page_cache, 4);
+       r = mmu_topup_memory_cache_page(&vcpu->mmu_page_cache, 8);
        if (r)
                goto out;
        r = mmu_topup_memory_cache(&vcpu->mmu_page_header_cache,
        kfree(rd);
 }
 
+/*
+ * Take gfn and return the reverse mapping to it.
+ * Note: gfn must be unaliased before this function get called
+ */
+
+static unsigned long *gfn_to_rmap(struct kvm *kvm, gfn_t gfn)
+{
+       struct kvm_memory_slot *slot;
+
+       slot = gfn_to_memslot(kvm, gfn);
+       return &slot->rmap[gfn - slot->base_gfn];
+}
+
 /*
  * Reverse mapping data structures:
  *
- * If page->private bit zero is zero, then page->private points to the
- * shadow page table entry that points to page_address(page).
+ * If rmapp bit zero is zero, then rmapp point to the shadw page table entry
+ * that points to page_address(page).
  *
- * If page->private bit zero is one, (then page->private & ~1) points
- * to a struct kvm_rmap_desc containing more mappings.
+ * If rmapp bit zero is one, (then rmap & ~1) points to a struct kvm_rmap_desc
+ * containing more mappings.
  */
-static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte)
+static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn)
 {
-       struct page *page;
+       struct kvm_mmu_page *page;
        struct kvm_rmap_desc *desc;
+       unsigned long *rmapp;
        int i;
 
        if (!is_rmap_pte(*spte))
                return;
-       page = pfn_to_page((*spte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT);
-       if (!page_private(page)) {
+       gfn = unalias_gfn(vcpu->kvm, gfn);
+       page = page_header(__pa(spte));
+       page->gfns[spte - page->spt] = gfn;
+       rmapp = gfn_to_rmap(vcpu->kvm, gfn);
+       if (!*rmapp) {
                rmap_printk("rmap_add: %p %llx 0->1\n", spte, *spte);
-               set_page_private(page,(unsigned long)spte);
-       } else if (!(page_private(page) & 1)) {
+               *rmapp = (unsigned long)spte;
+       } else if (!(*rmapp & 1)) {
                rmap_printk("rmap_add: %p %llx 1->many\n", spte, *spte);
                desc = mmu_alloc_rmap_desc(vcpu);
-               desc->shadow_ptes[0] = (u64 *)page_private(page);
+               desc->shadow_ptes[0] = (u64 *)*rmapp;
                desc->shadow_ptes[1] = spte;
-               set_page_private(page,(unsigned long)desc | 1);
+               *rmapp = (unsigned long)desc | 1;
        } else {
                rmap_printk("rmap_add: %p %llx many->many\n", spte, *spte);
-               desc = (struct kvm_rmap_desc *)(page_private(page) & ~1ul);
+               desc = (struct kvm_rmap_desc *)(*rmapp & ~1ul);
                while (desc->shadow_ptes[RMAP_EXT-1] && desc->more)
                        desc = desc->more;
                if (desc->shadow_ptes[RMAP_EXT-1]) {
        }
 }
 
-static void rmap_desc_remove_entry(struct page *page,
+static void rmap_desc_remove_entry(unsigned long *rmapp,
                                   struct kvm_rmap_desc *desc,
                                   int i,
                                   struct kvm_rmap_desc *prev_desc)
        if (j != 0)
                return;
        if (!prev_desc && !desc->more)
-               set_page_private(page,(unsigned long)desc->shadow_ptes[0]);
+               *rmapp = (unsigned long)desc->shadow_ptes[0];
        else
                if (prev_desc)
                        prev_desc->more = desc->more;
                else
-                       set_page_private(page,(unsigned long)desc->more | 1);
+                       *rmapp = (unsigned long)desc->more | 1;
        mmu_free_rmap_desc(desc);
 }
 
-static void rmap_remove(u64 *spte)
+static void rmap_remove(struct kvm *kvm, u64 *spte)
 {
-       struct page *page;
        struct kvm_rmap_desc *desc;
        struct kvm_rmap_desc *prev_desc;
+       struct kvm_mmu_page *page;
+       unsigned long *rmapp;
        int i;
 
        if (!is_rmap_pte(*spte))
                return;
-       page = pfn_to_page((*spte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT);
-       if (!page_private(page)) {
+       page = page_header(__pa(spte));
+       rmapp = gfn_to_rmap(kvm, page->gfns[spte - page->spt]);
+       if (!*rmapp) {
                printk(KERN_ERR "rmap_remove: %p %llx 0->BUG\n", spte, *spte);
                BUG();
-       } else if (!(page_private(page) & 1)) {
+       } else if (!(*rmapp & 1)) {
                rmap_printk("rmap_remove:  %p %llx 1->0\n", spte, *spte);
-               if ((u64 *)page_private(page) != spte) {
+               if ((u64 *)*rmapp != spte) {
                        printk(KERN_ERR "rmap_remove:  %p %llx 1->BUG\n",
                               spte, *spte);
                        BUG();
                }
-               set_page_private(page,0);
+               *rmapp = 0;
        } else {
                rmap_printk("rmap_remove:  %p %llx many->many\n", spte, *spte);
-               desc = (struct kvm_rmap_desc *)(page_private(page) & ~1ul);
+               desc = (struct kvm_rmap_desc *)(*rmapp & ~1ul);
                prev_desc = NULL;
                while (desc) {
                        for (i = 0; i < RMAP_EXT && desc->shadow_ptes[i]; ++i)
                                if (desc->shadow_ptes[i] == spte) {
-                                       rmap_desc_remove_entry(page,
+                                       rmap_desc_remove_entry(rmapp,
                                                               desc, i,
                                                               prev_desc);
                                        return;
 
 static void rmap_write_protect(struct kvm_vcpu *vcpu, u64 gfn)
 {
-       struct kvm *kvm = vcpu->kvm;
-       struct page *page;
        struct kvm_rmap_desc *desc;
+       unsigned long *rmapp;
        u64 *spte;
 
-       page = gfn_to_page(kvm, gfn);
-       BUG_ON(!page);
+       gfn = unalias_gfn(vcpu->kvm, gfn);
+       rmapp = gfn_to_rmap(vcpu->kvm, gfn);
 
-       while (page_private(page)) {
-               if (!(page_private(page) & 1))
-                       spte = (u64 *)page_private(page);
+       while (*rmapp) {
+               if (!(*rmapp & 1))
+                       spte = (u64 *)*rmapp;
                else {
-                       desc = (struct kvm_rmap_desc *)(page_private(page) & ~1ul);
+                       desc = (struct kvm_rmap_desc *)(*rmapp & ~1ul);
                        spte = desc->shadow_ptes[0];
                }
                BUG_ON(!spte);
-               BUG_ON((*spte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT
-                      != page_to_pfn(page));
                BUG_ON(!(*spte & PT_PRESENT_MASK));
                BUG_ON(!(*spte & PT_WRITABLE_MASK));
                rmap_printk("rmap_write_protect: spte %p %llx\n", spte, *spte);
-               rmap_remove(spte);
+               rmap_remove(vcpu->kvm, spte);
                set_shadow_pte(spte, *spte & ~PT_WRITABLE_MASK);
                kvm_flush_remote_tlbs(vcpu->kvm);
        }
        ASSERT(is_empty_shadow_page(page_head->spt));
        list_del(&page_head->link);
        __free_page(virt_to_page(page_head->spt));
+       __free_page(virt_to_page(page_head->gfns));
        kfree(page_head);
        ++kvm->n_free_mmu_pages;
 }
        page = mmu_memory_cache_alloc(&vcpu->mmu_page_header_cache,
                                      sizeof *page);
        page->spt = mmu_memory_cache_alloc(&vcpu->mmu_page_cache, PAGE_SIZE);
+       page->gfns = mmu_memory_cache_alloc(&vcpu->mmu_page_cache, PAGE_SIZE);
        set_page_private(virt_to_page(page->spt), (unsigned long)page);
        list_add(&page->link, &vcpu->kvm->active_mmu_pages);
        ASSERT(is_empty_shadow_page(page->spt));
        if (page->role.level == PT_PAGE_TABLE_LEVEL) {
                for (i = 0; i < PT64_ENT_PER_PAGE; ++i) {
                        if (is_shadow_present_pte(pt[i]))
-                               rmap_remove(&pt[i]);
+                               rmap_remove(kvm, &pt[i]);
                        pt[i] = shadow_trap_nonpresent_pte;
                }
                kvm_flush_remote_tlbs(kvm);
                        page_header_update_slot(vcpu->kvm, table, v);
                        table[index] = p | PT_PRESENT_MASK | PT_WRITABLE_MASK |
                                                                PT_USER_MASK;
-                       rmap_add(vcpu, &table[index]);
+                       rmap_add(vcpu, &table[index], v >> PAGE_SHIFT);
                        return 0;
                }
 
        pte = *spte;
        if (is_shadow_present_pte(pte)) {
                if (page->role.level == PT_PAGE_TABLE_LEVEL)
-                       rmap_remove(spte);
+                       rmap_remove(vcpu->kvm, spte);
                else {
                        child = page_header(pte & PT64_BASE_ADDR_MASK);
                        mmu_page_remove_parent_pte(child, spte);
                for (i = 0; i < PT64_ENT_PER_PAGE; ++i)
                        /* avoid RMW */
                        if (pt[i] & PT_WRITABLE_MASK) {
-                               rmap_remove(&pt[i]);
+                               rmap_remove(kvm, &pt[i]);
                                pt[i] &= ~PT_WRITABLE_MASK;
                        }
        }
                struct kvm_rmap_desc *d;
 
                for (j = 0; j < m->npages; ++j) {
-                       struct page *page = m->phys_mem[j];
+                       unsigned long *rmapp = &m->rmap[j];
 
-                       if (!page->private)
+                       if (!*rmapp)
                                continue;
-                       if (!(page->private & 1)) {
+                       if (!(*rmapp & 1)) {
                                ++nmaps;
                                continue;
                        }
-                       d = (struct kvm_rmap_desc *)(page->private & ~1ul);
+                       d = (struct kvm_rmap_desc *)(*rmapp & ~1ul);
                        while (d) {
                                for (k = 0; k < RMAP_EXT; ++k)
                                        if (d->shadow_ptes[k])
 static void audit_write_protection(struct kvm_vcpu *vcpu)
 {
        struct kvm_mmu_page *page;
+       struct kvm_memory_slot *slot;
+       unsigned long *rmapp;
+       gfn_t gfn;
 
        list_for_each_entry(page, &vcpu->kvm->active_mmu_pages, link) {
-               hfn_t hfn;
-               struct page *pg;
-
                if (page->role.metaphysical)
                        continue;
 
-               hfn = gpa_to_hpa(vcpu, (gpa_t)page->gfn << PAGE_SHIFT)
-                       >> PAGE_SHIFT;
-               pg = pfn_to_page(hfn);
-               if (pg->private)
+               slot = gfn_to_memslot(vcpu->kvm, page->gfn);
+               gfn = unalias_gfn(vcpu->kvm, page->gfn);
+               rmapp = &slot->rmap[gfn - slot->base_gfn];
+               if (*rmapp)
                        printk(KERN_ERR "%s: (%s) shadow page has writable"
                               " mappings: gfn %lx role %x\n",
                               __FUNCTION__, audit_msg, page->gfn,