All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Woodhouse <dwmw2@infradead.org>
To: Paolo Bonzini <pbonzini@redhat.com>, paul <paul@xen.org>,
	Sean Christopherson <seanjc@google.com>
Cc: kvm <kvm@vger.kernel.org>, Peter Zijlstra <peterz@infradead.org>,
	Michal Luczaj <mhal@rbox.co>
Subject: [PATCH 2/3] KVM: x86/xen: Fix potential deadlock in kvm_xen_update_runstate_guest()
Date: Wed, 11 Jan 2023 09:37:50 +0000	[thread overview]
Message-ID: <03f0a9ddf3db211d969ff4eb4e0aeb8789683776.camel@infradead.org> (raw)
In-Reply-To: <99b1da6ca8293b201fe0a89fd973a9b2f70dc450.camel@infradead.org>

[-- Attachment #1: Type: text/plain, Size: 4044 bytes --]

From: David Woodhouse <dwmw@amazon.co.uk>

The kvm_xen_update_runstate_guest() function can be called when the vCPU
is being scheduled out, from a preempt notifier. It *opportunistically*
updates the runstate area in the guest memory, if the gfn_to_pfn_cache
which caches the appropriate address is still valid.

If there is *contention* when it attempts to obtain gpc->lock, then
locking inside the priority inheritance checks may cause a deadlock.
Lockdep reports:

[13890.148997] Chain exists of:
                 &gpc->lock --> &p->pi_lock --> &rq->__lock

[13890.149002]  Possible unsafe locking scenario:

[13890.149003]        CPU0                    CPU1
[13890.149004]        ----                    ----
[13890.149005]   lock(&rq->__lock);
[13890.149007]                                lock(&p->pi_lock);
[13890.149009]                                lock(&rq->__lock);
[13890.149011]   lock(&gpc->lock);
[13890.149013]
                *** DEADLOCK ***

In the general case, if there's contention for a read lock on gpc->lock,
that's going to be because something else is either invalidating or
revalidating the cache. Either way, we've raced with seeing it in an
invalid state, in which case we would have aborted the opportunistic
update anyway.

So in the 'atomic' case when called from the preempt notifier, just
switch to using read_trylock() and avoid the PI handling altogether.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---

First patch in this series was '[PATCH] KVM: x86/xen: Fix lockdep
warning on "recursive" gpc locking' but now there are three.


 arch/x86/kvm/xen.c | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index 07e61cc9881e..c444948ab1ac 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -272,7 +272,12 @@ static void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, bool atomic)
         * Attempt to obtain the GPC lock on *both* (if there are two)
         * gfn_to_pfn caches that cover the region.
         */
-       read_lock_irqsave(&gpc1->lock, flags);
+       local_irq_save(flags);
+       if (!read_trylock(&gpc1->lock)) {
+               if (atomic)
+                       return;
+               read_lock(&gpc1->lock);
+       }
        while (!kvm_gpc_check(gpc1, user_len1)) {
                read_unlock_irqrestore(&gpc1->lock, flags);
 
@@ -283,7 +288,7 @@ static void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, bool atomic)
                if (kvm_gpc_refresh(gpc1, user_len1))
                        return;
 
-               read_lock_irqsave(&gpc1->lock, flags);
+               goto retry;
        }
 
        if (likely(!user_len2)) {
@@ -309,7 +314,13 @@ static void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, bool atomic)
                 * gpc1 lock to make lockdep shut up about it.
                 */
                lock_set_subclass(&gpc1->lock.dep_map, 1, _THIS_IP_);
-               read_lock(&gpc2->lock);
+               if (!read_trylock(&gpc2->lock)) {
+                       if (atomic) {
+                               read_unlock_irqrestore(&gpc1->lock, flags);
+                               return;
+                       }
+                       read_lock(&gpc2->lock);
+               }
 
                if (!kvm_gpc_check(gpc2, user_len2)) {
                        read_unlock(&gpc2->lock);
-- 
2.34.1



[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 5965 bytes --]

  reply	other threads:[~2023-01-11  9:43 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-10 15:25 [PATCH] KVM: x86/xen: Fix lockdep warning on "recursive" gpc locking David Woodhouse
2023-01-11  9:37 ` David Woodhouse [this message]
2023-01-11 16:54   ` [PATCH 2/3] KVM: x86/xen: Fix potential deadlock in kvm_xen_update_runstate_guest() Peter Zijlstra
2023-01-11 17:43     ` David Woodhouse
2023-01-11  9:37 ` [PATCH 3/3] KVM: Ensure lockdep knows about kvm->lock vs. vcpu->mutex ordering rule David Woodhouse

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=03f0a9ddf3db211d969ff4eb4e0aeb8789683776.camel@infradead.org \
    --to=dwmw2@infradead.org \
    --cc=kvm@vger.kernel.org \
    --cc=mhal@rbox.co \
    --cc=paul@xen.org \
    --cc=pbonzini@redhat.com \
    --cc=peterz@infradead.org \
    --cc=seanjc@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.