aboutsummaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorPaolo Bonzini2016-03-21 04:15:25 -0500
committerGreg Kroah-Hartman2016-04-12 11:08:34 -0500
commit4e2fa4bbbac1c2e198e4c980d451c9ec568ae798 (patch)
treebc50b66b49525fba5fe27cb47ab9807e2271f8ad /virt
parent49f0cbfc3e73108c319c3d3cc5fe04587d96b654 (diff)
downloadkernel-omap-4e2fa4bbbac1c2e198e4c980d451c9ec568ae798.tar.gz
kernel-omap-4e2fa4bbbac1c2e198e4c980d451c9ec568ae798.tar.xz
kernel-omap-4e2fa4bbbac1c2e198e4c980d451c9ec568ae798.zip
KVM: fix spin_lock_init order on x86
commit e9ad4ec8379ad1ba6f68b8ca1c26b50b5ae0a327 upstream. Moving the initialization earlier is needed in 4.6 because kvm_arch_init_vm is now using mmu_lock, causing lockdep to complain: [ 284.440294] INFO: trying to register non-static key. [ 284.445259] the code is fine but needs lockdep annotation. [ 284.450736] turning off the locking correctness validator. ... [ 284.528318] [<ffffffff810aecc3>] lock_acquire+0xd3/0x240 [ 284.533733] [<ffffffffa0305aa0>] ? kvm_page_track_register_notifier+0x20/0x60 [kvm] [ 284.541467] [<ffffffff81715581>] _raw_spin_lock+0x41/0x80 [ 284.546960] [<ffffffffa0305aa0>] ? kvm_page_track_register_notifier+0x20/0x60 [kvm] [ 284.554707] [<ffffffffa0305aa0>] kvm_page_track_register_notifier+0x20/0x60 [kvm] [ 284.562281] [<ffffffffa02ece70>] kvm_mmu_init_vm+0x20/0x30 [kvm] [ 284.568381] [<ffffffffa02dbf7a>] kvm_arch_init_vm+0x1ea/0x200 [kvm] [ 284.574740] [<ffffffffa02bff3f>] kvm_dev_ioctl+0xbf/0x4d0 [kvm] However, it also helps fixing a preexisting problem, which is why this patch is also good for stable kernels: kvm_create_vm was incrementing current->mm->mm_count but not decrementing it at the out_err label (in case kvm_init_mmu_notifier failed). The new initialization order makes it possible to add the required mmdrop without adding a new error label. Reported-by: Borislav Petkov <bp@alien8.de> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/kvm_main.c21
1 files changed, 11 insertions, 10 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 7338e30421d8..fefbf2d148ef 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -547,6 +547,16 @@ static struct kvm *kvm_create_vm(unsigned long type)
547 if (!kvm) 547 if (!kvm)
548 return ERR_PTR(-ENOMEM); 548 return ERR_PTR(-ENOMEM);
549 549
550 spin_lock_init(&kvm->mmu_lock);
551 atomic_inc(&current->mm->mm_count);
552 kvm->mm = current->mm;
553 kvm_eventfd_init(kvm);
554 mutex_init(&kvm->lock);
555 mutex_init(&kvm->irq_lock);
556 mutex_init(&kvm->slots_lock);
557 atomic_set(&kvm->users_count, 1);
558 INIT_LIST_HEAD(&kvm->devices);
559
550 r = kvm_arch_init_vm(kvm, type); 560 r = kvm_arch_init_vm(kvm, type);
551 if (r) 561 if (r)
552 goto out_err_no_disable; 562 goto out_err_no_disable;
@@ -579,16 +589,6 @@ static struct kvm *kvm_create_vm(unsigned long type)
579 goto out_err; 589 goto out_err;
580 } 590 }
581 591
582 spin_lock_init(&kvm->mmu_lock);
583 kvm->mm = current->mm;
584 atomic_inc(&kvm->mm->mm_count);
585 kvm_eventfd_init(kvm);
586 mutex_init(&kvm->lock);
587 mutex_init(&kvm->irq_lock);
588 mutex_init(&kvm->slots_lock);
589 atomic_set(&kvm->users_count, 1);
590 INIT_LIST_HEAD(&kvm->devices);
591
592 r = kvm_init_mmu_notifier(kvm); 592 r = kvm_init_mmu_notifier(kvm);
593 if (r) 593 if (r)
594 goto out_err; 594 goto out_err;
@@ -613,6 +613,7 @@ out_err_no_disable:
613 for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) 613 for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++)
614 kvm_free_memslots(kvm, kvm->memslots[i]); 614 kvm_free_memslots(kvm, kvm->memslots[i]);
615 kvm_arch_free_vm(kvm); 615 kvm_arch_free_vm(kvm);
616 mmdrop(current->mm);
616 return ERR_PTR(r); 617 return ERR_PTR(r);
617} 618}
618 619