]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
KVM: Take vcpu->mutex outside vcpu_load
authorChristoffer Dall <christoffer.dall@linaro.org>
Mon, 4 Dec 2017 20:35:23 +0000 (21:35 +0100)
committerPaolo Bonzini <pbonzini@redhat.com>
Thu, 14 Dec 2017 08:26:49 +0000 (09:26 +0100)
As we're about to call vcpu_load() from architecture-specific
implementations of the KVM vcpu ioctls, but yet we access data
structures protected by the vcpu->mutex in the generic code, factor
this logic out from vcpu_load().

x86 is the only architecture which calls vcpu_load() outside of the main
vcpu ioctl function, and these calls will no longer take the vcpu mutex
following this patch.  However, with the exception of
kvm_arch_vcpu_postcreate (see below), the callers are either in the
creation or destruction path of the VCPU, which means there cannot be
any concurrent access to the data structure, because the file descriptor
is not yet accessible, or is already gone.

kvm_arch_vcpu_postcreate makes the newly created vcpu potentially
accessible by other in-kernel threads through the kvm->vcpus array, and
we therefore take the vcpu mutex in this case directly.

Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
include/linux/kvm_host.h
virt/kvm/kvm_main.c

index b016cf1b9f773ffbc959f8fb4f46c475e715d273..ef7d13e536a4fdde900cf96cebe4643d573e7641 100644 (file)
@@ -9496,10 +9496,8 @@ static void vmx_switch_vmcs(struct kvm_vcpu *vcpu, struct loaded_vmcs *vmcs)
 static void vmx_free_vcpu_nested(struct kvm_vcpu *vcpu)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
-       int r;
 
-       r = vcpu_load(vcpu);
-       BUG_ON(r);
+       vcpu_load(vcpu);
        vmx_switch_vmcs(vcpu, &vmx->vmcs01);
        free_nested(vmx);
        vcpu_put(vcpu);
index 54d66f238e20308783948d8095694c7587609522..3f2c78f58570273b2f21fd4ac0646f5b1fffa172 100644 (file)
@@ -7767,16 +7767,12 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
 
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
-       int r;
-
        kvm_vcpu_mtrr_init(vcpu);
-       r = vcpu_load(vcpu);
-       if (r)
-               return r;
+       vcpu_load(vcpu);
        kvm_vcpu_reset(vcpu, false);
        kvm_mmu_setup(vcpu);
        vcpu_put(vcpu);
-       return r;
+       return 0;
 }
 
 void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
@@ -7786,13 +7782,15 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
 
        kvm_hv_vcpu_postcreate(vcpu);
 
-       if (vcpu_load(vcpu))
+       if (mutex_lock_killable(&vcpu->mutex))
                return;
+       vcpu_load(vcpu);
        msr.data = 0x0;
        msr.index = MSR_IA32_TSC;
        msr.host_initiated = true;
        kvm_write_tsc(vcpu, &msr);
        vcpu_put(vcpu);
+       mutex_unlock(&vcpu->mutex);
 
        if (!kvmclock_periodic_sync)
                return;
@@ -7803,11 +7801,9 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
 
 void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 {
-       int r;
        vcpu->arch.apf.msr_val = 0;
 
-       r = vcpu_load(vcpu);
-       BUG_ON(r);
+       vcpu_load(vcpu);
        kvm_mmu_unload(vcpu);
        vcpu_put(vcpu);
 
@@ -8179,9 +8175,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 
 static void kvm_unload_vcpu_mmu(struct kvm_vcpu *vcpu)
 {
-       int r;
-       r = vcpu_load(vcpu);
-       BUG_ON(r);
+       vcpu_load(vcpu);
        kvm_mmu_unload(vcpu);
        vcpu_put(vcpu);
 }
index 6bdd4b9f661154c386754654db238d13e0a13a31..09de0ff3d67735104bc4a5230a09d01b43d0b139 100644 (file)
@@ -533,7 +533,7 @@ static inline int kvm_vcpu_get_idx(struct kvm_vcpu *vcpu)
 int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id);
 void kvm_vcpu_uninit(struct kvm_vcpu *vcpu);
 
-int __must_check vcpu_load(struct kvm_vcpu *vcpu);
+void vcpu_load(struct kvm_vcpu *vcpu);
 void vcpu_put(struct kvm_vcpu *vcpu);
 
 #ifdef __KVM_HAVE_IOAPIC
index bc092e3d1d7316309e05d9483a2f42d346232029..c4d116b336f4ea65c08b1b9c6d52047e1878e08b 100644 (file)
@@ -151,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);
 
@@ -171,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);
 
@@ -2560,9 +2554,9 @@ static long kvm_vcpu_ioctl(struct file *filp,
 #endif
 
 
-       r = vcpu_load(vcpu);
-       if (r)
-               return r;
+       if (mutex_lock_killable(&vcpu->mutex))
+               return -EINTR;
+       vcpu_load(vcpu);
        switch (ioctl) {
        case KVM_RUN: {
                struct pid *oldpid;
@@ -2735,6 +2729,7 @@ out_free1:
        }
 out:
        vcpu_put(vcpu);
+       mutex_unlock(&vcpu->mutex);
        kfree(fpu);
        kfree(kvm_sregs);
        return r;