KVM: Show lockdep the kvm->mutex vs. kvm->srcu ordering rule
authorDavid Woodhouse <dwmw@amazon.co.uk>
Fri, 13 Jan 2023 10:35:44 +0000 (10:35 +0000)
committerDavid Woodhouse <dwmw@amazon.co.uk>
Fri, 13 Jan 2023 19:54:02 +0000 (19:54 +0000)
Lockdep is learning to spot deadlocks with sleepable RCU vs. mutexes,
which can occur where one code path calls synchronize_scru() with a
mutex held, while another code path attempts to obtain the same mutex
while in a read-side section.

Since lockdep isn't very good at reading the English prose in
Documentation/virt/kvm/locking.rst, give it a demonstration by calling
synchronize_scru(&kvm->srcu) while holding kvm->lock in kvm_create_vm().
The cases where this happens naturally are relatively esoteric and may
not happen otherwise.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
virt/kvm/kvm_main.c

index d255964ec331ef5c9aebf90243990ef4da0aec2b..19fefc17bd43a9dfcabb03dd67a61ef1f2054145 100644 (file)
@@ -1165,6 +1165,16 @@ static struct kvm *kvm_create_vm(unsigned long type, const char *fdname)
        if (init_srcu_struct(&kvm->irq_srcu))
                goto out_err_no_irq_srcu;
 
+#ifdef CONFIG_LOCKDEP
+       /*
+        * Ensure lockdep knows that it's not permitted to lock kvm->lock
+        * from a SRCU read section on kvm->srcu.
+        */
+       mutex_lock(&kvm->lock);
+       synchronize_srcu(&kvm->srcu);
+       mutex_unlock(&kvm->lock);
+#endif
+
        refcount_set(&kvm->users_count, 1);
        for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) {
                for (j = 0; j < 2; j++) {