]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - virt/kvm/kvm_main.c
KVM: introduce kvm_arch_vcpu_async_ioctl
[linux.git] / virt / kvm / kvm_main.c
index f169ecc4f2e87f44ece32540b8428529aa01ae84..b4414842b02392136a4c6625153bb6680ab4d733 100644 (file)
@@ -135,6 +135,11 @@ static void kvm_uevent_notify_change(unsigned int type, struct kvm *kvm);
 static unsigned long long kvm_createvm_count;
 static unsigned long long kvm_active_vms;
 
+__weak void kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm,
+               unsigned long start, unsigned long end)
+{
+}
+
 bool kvm_is_reserved_pfn(kvm_pfn_t pfn)
 {
        if (pfn_valid(pfn))
@@ -146,17 +151,12 @@ bool kvm_is_reserved_pfn(kvm_pfn_t pfn)
 /*
  * Switches to specified vcpu, until a matching vcpu_put()
  */
-int vcpu_load(struct kvm_vcpu *vcpu)
+void vcpu_load(struct kvm_vcpu *vcpu)
 {
-       int cpu;
-
-       if (mutex_lock_killable(&vcpu->mutex))
-               return -EINTR;
-       cpu = get_cpu();
+       int cpu = get_cpu();
        preempt_notifier_register(&vcpu->preempt_notifier);
        kvm_arch_vcpu_load(vcpu, cpu);
        put_cpu();
-       return 0;
 }
 EXPORT_SYMBOL_GPL(vcpu_load);
 
@@ -166,7 +166,6 @@ void vcpu_put(struct kvm_vcpu *vcpu)
        kvm_arch_vcpu_put(vcpu);
        preempt_notifier_unregister(&vcpu->preempt_notifier);
        preempt_enable();
-       mutex_unlock(&vcpu->mutex);
 }
 EXPORT_SYMBOL_GPL(vcpu_put);
 
@@ -360,6 +359,9 @@ static void kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
                kvm_flush_remote_tlbs(kvm);
 
        spin_unlock(&kvm->mmu_lock);
+
+       kvm_arch_mmu_notifier_invalidate_range(kvm, start, end);
+
        srcu_read_unlock(&kvm->srcu, idx);
 }
 
@@ -2065,6 +2067,29 @@ void kvm_vcpu_mark_page_dirty(struct kvm_vcpu *vcpu, gfn_t gfn)
 }
 EXPORT_SYMBOL_GPL(kvm_vcpu_mark_page_dirty);
 
+void kvm_sigset_activate(struct kvm_vcpu *vcpu)
+{
+       if (!vcpu->sigset_active)
+               return;
+
+       /*
+        * This does a lockless modification of ->real_blocked, which is fine
+        * because, only current can change ->real_blocked and all readers of
+        * ->real_blocked don't care as long ->real_blocked is always a subset
+        * of ->blocked.
+        */
+       sigprocmask(SIG_SETMASK, &vcpu->sigset, &current->real_blocked);
+}
+
+void kvm_sigset_deactivate(struct kvm_vcpu *vcpu)
+{
+       if (!vcpu->sigset_active)
+               return;
+
+       sigprocmask(SIG_SETMASK, &current->real_blocked, NULL);
+       sigemptyset(&current->real_blocked);
+}
+
 static void grow_halt_poll_ns(struct kvm_vcpu *vcpu)
 {
        unsigned int old, val, grow;
@@ -2519,19 +2544,16 @@ static long kvm_vcpu_ioctl(struct file *filp,
        if (unlikely(_IOC_TYPE(ioctl) != KVMIO))
                return -EINVAL;
 
-#if defined(CONFIG_S390) || defined(CONFIG_PPC) || defined(CONFIG_MIPS)
        /*
-        * Special cases: vcpu ioctls that are asynchronous to vcpu execution,
-        * so vcpu_load() would break it.
+        * Some architectures have vcpu ioctls that are asynchronous to vcpu
+        * execution; mutex_lock() would break them.
         */
-       if (ioctl == KVM_S390_INTERRUPT || ioctl == KVM_S390_IRQ || ioctl == KVM_INTERRUPT)
-               return kvm_arch_vcpu_ioctl(filp, ioctl, arg);
-#endif
-
-
-       r = vcpu_load(vcpu);
-       if (r)
+       r = kvm_arch_vcpu_async_ioctl(filp, ioctl, arg);
+       if (r != -ENOIOCTLCMD)
                return r;
+
+       if (mutex_lock_killable(&vcpu->mutex))
+               return -EINTR;
        switch (ioctl) {
        case KVM_RUN: {
                struct pid *oldpid;
@@ -2703,7 +2725,7 @@ static long kvm_vcpu_ioctl(struct file *filp,
                r = kvm_arch_vcpu_ioctl(filp, ioctl, arg);
        }
 out:
-       vcpu_put(vcpu);
+       mutex_unlock(&vcpu->mutex);
        kfree(fpu);
        kfree(kvm_sregs);
        return r;
@@ -3155,21 +3177,18 @@ static int kvm_dev_ioctl_create_vm(unsigned long type)
                return PTR_ERR(kvm);
 #ifdef CONFIG_KVM_MMIO
        r = kvm_coalesced_mmio_init(kvm);
-       if (r < 0) {
-               kvm_put_kvm(kvm);
-               return r;
-       }
+       if (r < 0)
+               goto put_kvm;
 #endif
        r = get_unused_fd_flags(O_CLOEXEC);
-       if (r < 0) {
-               kvm_put_kvm(kvm);
-               return r;
-       }
+       if (r < 0)
+               goto put_kvm;
+
        file = anon_inode_getfile("kvm-vm", &kvm_vm_fops, kvm, O_RDWR);
        if (IS_ERR(file)) {
                put_unused_fd(r);
-               kvm_put_kvm(kvm);
-               return PTR_ERR(file);
+               r = PTR_ERR(file);
+               goto put_kvm;
        }
 
        /*
@@ -3187,6 +3206,10 @@ static int kvm_dev_ioctl_create_vm(unsigned long type)
 
        fd_install(r, file);
        return r;
+
+put_kvm:
+       kvm_put_kvm(kvm);
+       return r;
 }
 
 static long kvm_dev_ioctl(struct file *filp,