Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=8d4e1288ebb753d3140d81cb349f22b0a6829a4a
Commit:     8d4e1288ebb753d3140d81cb349f22b0a6829a4a
Parent:     e56a7a28e21aa2d1af659d8f38952411ce9ae40e
Author:     Anthony Liguori <[EMAIL PROTECTED]>
AuthorDate: Thu Oct 18 09:59:34 2007 -0500
Committer:  Avi Kivity <[EMAIL PROTECTED]>
CommitDate: Wed Jan 30 17:52:54 2008 +0200

    KVM: Allocate userspace memory for older userspace
    
    Allocate a userspace buffer for older userspaces.  Also eliminate phys_mem
    buffer.  The memset() in kvmctl really kills initial memory usage but 
swapping
    works even with old userspaces.
    
    A side effect is that maximum guest side is reduced for older userspace on
    i386.
    
    Signed-off-by: Anthony Liguori <[EMAIL PROTECTED]>
    Signed-off-by: Avi Kivity <[EMAIL PROTECTED]>
---
 drivers/kvm/kvm.h      |    2 -
 drivers/kvm/kvm_main.c |   83 +++++++++++++++++------------------------------
 2 files changed, 30 insertions(+), 55 deletions(-)

diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index e8a21e8..eb006ed 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -406,10 +406,8 @@ struct kvm_memory_slot {
        gfn_t base_gfn;
        unsigned long npages;
        unsigned long flags;
-       struct page **phys_mem;
        unsigned long *rmap;
        unsigned long *dirty_bitmap;
-       int user_alloc; /* user allocated memory */
        unsigned long userspace_addr;
 };
 
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index f86a47c..8f6c21d 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -42,6 +42,7 @@
 #include <linux/profile.h>
 #include <linux/kvm_para.h>
 #include <linux/pagemap.h>
+#include <linux/mman.h>
 
 #include <asm/processor.h>
 #include <asm/msr.h>
@@ -300,36 +301,21 @@ static struct kvm *kvm_create_vm(void)
        return kvm;
 }
 
-static void kvm_free_kernel_physmem(struct kvm_memory_slot *free)
-{
-       int i;
-
-       for (i = 0; i < free->npages; ++i)
-               if (free->phys_mem[i])
-                       __free_page(free->phys_mem[i]);
-}
-
 /*
  * Free any memory in @free but not in @dont.
  */
 static void kvm_free_physmem_slot(struct kvm_memory_slot *free,
                                  struct kvm_memory_slot *dont)
 {
-       if (!dont || free->phys_mem != dont->phys_mem)
-               if (free->phys_mem) {
-                       if (!free->user_alloc)
-                               kvm_free_kernel_physmem(free);
-                       vfree(free->phys_mem);
-               }
        if (!dont || free->rmap != dont->rmap)
                vfree(free->rmap);
 
        if (!dont || free->dirty_bitmap != dont->dirty_bitmap)
                vfree(free->dirty_bitmap);
 
-       free->phys_mem = NULL;
        free->npages = 0;
        free->dirty_bitmap = NULL;
+       free->rmap = NULL;
 }
 
 static void kvm_free_physmem(struct kvm *kvm)
@@ -712,10 +698,6 @@ static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,
                        goto out_unlock;
        }
 
-       /* Deallocate if slot is being removed */
-       if (!npages)
-               new.phys_mem = NULL;
-
        /* Free page dirty bitmap if unneeded */
        if (!(new.flags & KVM_MEM_LOG_DIRTY_PAGES))
                new.dirty_bitmap = NULL;
@@ -723,29 +705,27 @@ static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,
        r = -ENOMEM;
 
        /* Allocate if a slot is being created */
-       if (npages && !new.phys_mem) {
-               new.phys_mem = vmalloc(npages * sizeof(struct page *));
-
-               if (!new.phys_mem)
-                       goto out_unlock;
-
+       if (npages && !new.rmap) {
                new.rmap = vmalloc(npages * sizeof(struct page *));
 
                if (!new.rmap)
                        goto out_unlock;
 
-               memset(new.phys_mem, 0, npages * sizeof(struct page *));
                memset(new.rmap, 0, npages * sizeof(*new.rmap));
-               if (user_alloc) {
-                       new.user_alloc = 1;
+
+               if (user_alloc)
                        new.userspace_addr = mem->userspace_addr;
-               } else {
-                       for (i = 0; i < npages; ++i) {
-                               new.phys_mem[i] = alloc_page(GFP_HIGHUSER
-                                                            | __GFP_ZERO);
-                               if (!new.phys_mem[i])
-                                       goto out_unlock;
-                       }
+               else {
+                       down_write(&current->mm->mmap_sem);
+                       new.userspace_addr = do_mmap(NULL, 0,
+                                                    npages * PAGE_SIZE,
+                                                    PROT_READ | PROT_WRITE,
+                                                    MAP_SHARED | MAP_ANONYMOUS,
+                                                    0);
+                       up_write(&current->mm->mmap_sem);
+
+                       if (IS_ERR((void *)new.userspace_addr))
+                               goto out_unlock;
                }
        }
 
@@ -1010,6 +990,8 @@ struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, 
gfn_t gfn)
 struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn)
 {
        struct kvm_memory_slot *slot;
+       struct page *page[1];
+       int npages;
 
        gfn = unalias_gfn(kvm, gfn);
        slot = __gfn_to_memslot(kvm, gfn);
@@ -1017,24 +999,19 @@ struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn)
                get_page(bad_page);
                return bad_page;
        }
-       if (slot->user_alloc) {
-               struct page *page[1];
-               int npages;
-
-               down_read(&current->mm->mmap_sem);
-               npages = get_user_pages(current, current->mm,
-                                       slot->userspace_addr
-                                       + (gfn - slot->base_gfn) * PAGE_SIZE, 1,
-                                       1, 1, page, NULL);
-               up_read(&current->mm->mmap_sem);
-               if (npages != 1) {
-                       get_page(bad_page);
-                       return bad_page;
-               }
-               return page[0];
+
+       down_read(&current->mm->mmap_sem);
+       npages = get_user_pages(current, current->mm,
+                               slot->userspace_addr
+                               + (gfn - slot->base_gfn) * PAGE_SIZE, 1,
+                               1, 1, page, NULL);
+       up_read(&current->mm->mmap_sem);
+       if (npages != 1) {
+               get_page(bad_page);
+               return bad_page;
        }
-       get_page(slot->phys_mem[gfn - slot->base_gfn]);
-       return slot->phys_mem[gfn - slot->base_gfn];
+
+       return page[0];
 }
 EXPORT_SYMBOL_GPL(gfn_to_page);
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to