kvm: don't take vcpu mutex for obviously invalid vcpu ioctls
[pandora-kernel.git] / virt / kvm / kvm_main.c
index a311660..8b0617a 100644 (file)
@@ -52,6 +52,7 @@
 
 #include <asm/processor.h>
 #include <asm/io.h>
+#include <asm/ioctl.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 
@@ -788,6 +789,8 @@ skip_lpage:
                old_memslots = kvm->memslots;
                rcu_assign_pointer(kvm->memslots, slots);
                synchronize_srcu_expedited(&kvm->srcu);
+               /* slot was deleted or moved, clear iommu mapping */
+               kvm_iommu_unmap_pages(kvm, &old);
                /* From this point no new shadow pages pointing to a deleted,
                 * or moved, memslot will be created.
                 *
@@ -803,14 +806,6 @@ skip_lpage:
        if (r)
                goto out_free;
 
-       /* map/unmap the pages in iommu page table */
-       if (npages) {
-               r = kvm_iommu_map_pages(kvm, &new);
-               if (r)
-                       goto out_free;
-       } else
-               kvm_iommu_unmap_pages(kvm, &old);
-
        r = -ENOMEM;
        slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL);
        if (!slots)
@@ -820,6 +815,13 @@ skip_lpage:
                slots->nmemslots = mem->slot + 1;
        slots->generation++;
 
+       /* map new memory slot into the iommu */
+       if (npages) {
+               r = kvm_iommu_map_pages(kvm, &new);
+               if (r)
+                       goto out_slots;
+       }
+
        /* actual memory is freed via old in kvm_free_physmem_slot below */
        if (!npages) {
                new.rmap = NULL;
@@ -847,6 +849,8 @@ skip_lpage:
 
        return 0;
 
+out_slots:
+       kfree(slots);
 out_free:
        kvm_free_physmem_slot(&new, &old);
 out:
@@ -1763,6 +1767,9 @@ static long kvm_vcpu_ioctl(struct file *filp,
        if (vcpu->kvm->mm != current->mm)
                return -EIO;
 
+       if (unlikely(_IOC_TYPE(ioctl) != KVMIO))
+               return -EINVAL;
+
 #if defined(CONFIG_S390) || defined(CONFIG_PPC)
        /*
         * Special cases: vcpu ioctls that are asynchronous to vcpu execution,