]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
KVM: Portability: Split kvm_set_memory_region() to have an arch callout
authorZhang Xiantao <xiantao.zhang@intel.com>
Tue, 20 Nov 2007 08:25:04 +0000 (16:25 +0800)
committerAvi Kivity <avi@qumranet.com>
Wed, 30 Jan 2008 15:53:09 +0000 (17:53 +0200)
Moving !user_alloc case to kvm_arch to avoid unnecessary
code logic in non-x86 platform.

Signed-off-by: Zhang Xiantao <xiantao.zhang@intel.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>
drivers/kvm/kvm.h
drivers/kvm/kvm_main.c
drivers/kvm/x86.c

index c2acd74389fafe62f8e3c7e64f7e4e01f9fed04a..49094a221f6a6fbe37f3dbacd28edf3b17a35a1d 100644 (file)
@@ -391,6 +391,10 @@ int kvm_set_memory_region(struct kvm *kvm,
 int __kvm_set_memory_region(struct kvm *kvm,
                            struct kvm_userspace_memory_region *mem,
                            int user_alloc);
+int kvm_arch_set_memory_region(struct kvm *kvm,
+                               struct kvm_userspace_memory_region *mem,
+                               struct kvm_memory_slot old,
+                               int user_alloc);
 gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn);
 struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn);
 void kvm_release_page_clean(struct page *page);
index 93ecafbfb1b6bfdeb147f671ebecd3b5988e244c..9dd6ad3c6c7b15acb0a953df1c5f109a82529eb3 100644 (file)
@@ -291,33 +291,7 @@ int __kvm_set_memory_region(struct kvm *kvm,
                memset(new.rmap, 0, npages * sizeof(*new.rmap));
 
                new.user_alloc = user_alloc;
-               if (user_alloc)
-                       new.userspace_addr = mem->userspace_addr;
-               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_free;
-               }
-       } else {
-               if (!old.user_alloc && old.rmap) {
-                       int ret;
-
-                       down_write(&current->mm->mmap_sem);
-                       ret = do_munmap(current->mm, old.userspace_addr,
-                                       old.npages * PAGE_SIZE);
-                       up_write(&current->mm->mmap_sem);
-                       if (ret < 0)
-                               printk(KERN_WARNING
-                                      "kvm_vm_ioctl_set_memory_region: "
-                                      "failed to munmap memory\n");
-               }
+               new.userspace_addr = mem->userspace_addr;
        }
 
        /* Allocate page dirty bitmap if needed */
@@ -335,14 +309,12 @@ int __kvm_set_memory_region(struct kvm *kvm,
 
        *memslot = new;
 
-       if (!kvm->n_requested_mmu_pages) {
-               unsigned int nr_mmu_pages = kvm_mmu_calculate_mmu_pages(kvm);
-               kvm_mmu_change_mmu_pages(kvm, nr_mmu_pages);
+       r = kvm_arch_set_memory_region(kvm, mem, old, user_alloc);
+       if (r) {
+               *memslot = old;
+               goto out_free;
        }
 
-       kvm_mmu_slot_remove_write_access(kvm, mem->slot);
-       kvm_flush_remote_tlbs(kvm);
-
        kvm_free_physmem_slot(&old, &new);
        return 0;
 
index 5a54e328088dd6fad1d1f5f4f3089d887785e9d8..6abb2ed1a908f2b607fd5d9c372fa54662e6280e 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/fs.h>
 #include <linux/vmalloc.h>
 #include <linux/module.h>
+#include <linux/mman.h>
 
 #include <asm/uaccess.h>
 #include <asm/msr.h>
@@ -2637,3 +2638,53 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
        kvm_free_physmem(kvm);
        kfree(kvm);
 }
+
+int kvm_arch_set_memory_region(struct kvm *kvm,
+                               struct kvm_userspace_memory_region *mem,
+                               struct kvm_memory_slot old,
+                               int user_alloc)
+{
+       int npages = mem->memory_size >> PAGE_SHIFT;
+       struct kvm_memory_slot *memslot = &kvm->memslots[mem->slot];
+
+       /*To keep backward compatibility with older userspace,
+        *x86 needs to hanlde !user_alloc case.
+        */
+       if (!user_alloc) {
+               if (npages && !old.rmap) {
+                       down_write(&current->mm->mmap_sem);
+                       memslot->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 *)memslot->userspace_addr))
+                               return PTR_ERR((void *)memslot->userspace_addr);
+               } else {
+                       if (!old.user_alloc && old.rmap) {
+                               int ret;
+
+                               down_write(&current->mm->mmap_sem);
+                               ret = do_munmap(current->mm, old.userspace_addr,
+                                               old.npages * PAGE_SIZE);
+                               up_write(&current->mm->mmap_sem);
+                               if (ret < 0)
+                                       printk(KERN_WARNING
+                                      "kvm_vm_ioctl_set_memory_region: "
+                                      "failed to munmap memory\n");
+                       }
+               }
+       }
+
+       if (!kvm->n_requested_mmu_pages) {
+               unsigned int nr_mmu_pages = kvm_mmu_calculate_mmu_pages(kvm);
+               kvm_mmu_change_mmu_pages(kvm, nr_mmu_pages);
+       }
+
+       kvm_mmu_slot_remove_write_access(kvm, mem->slot);
+       kvm_flush_remote_tlbs(kvm);
+
+       return 0;
+}