From: David Hildenbrand <david@redhat.com>
To: srutherford@google.com
Cc: kvm@vger.kernel.org, rkrcmar@redhat.com, pbonzini@redhat.com,
david@redhat.com
Subject: [PATCH] KVM: x86: don't hold kvm->lock in KVM_SET_GSI_ROUTING
Date: Tue, 25 Apr 2017 21:03:06 +0200 [thread overview]
Message-ID: <20170425190306.20392-1-david@redhat.com> (raw)
In-Reply-To: <CABayD+cSO3w2jQNFK6QxX7N-kiQ3RpAJfANSxK-LD4HKV4AJfQ@mail.gmail.com>
We needed the lock to avoid racing with creation of the irqchip on x86. As
kvm_set_irq_routing() calls srcu_synchronize_expedited(), this lock
might be held for a longer time.
Let's introduce an arch specific callback to check if we can actually
add irq routes. For x86, all we have to do is check if we have an
irqchip in the kernel. We don't need kvm->lock at that point as the
irqchip is marked as inititalized only when actually fully created.
Reported-by: Steve Rutherford <srutherford@google.com>
Fixes: 1df6ddede10a ("KVM: x86: race between KVM_SET_GSI_ROUTING and KVM_CREATE_IRQCHIP")
Signed-off-by: David Hildenbrand <david@redhat.com>
---
arch/x86/include/asm/kvm_host.h | 1 -
arch/x86/kvm/irq.h | 2 +-
arch/x86/kvm/irq_comm.c | 15 +++++++++------
arch/x86/kvm/x86.c | 11 +----------
include/linux/kvm_host.h | 5 +++++
virt/kvm/kvm_main.c | 5 ++---
6 files changed, 18 insertions(+), 21 deletions(-)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 2cc5ec7..d962fa9 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -726,7 +726,6 @@ struct kvm_hv {
enum kvm_irqchip_mode {
KVM_IRQCHIP_NONE,
- KVM_IRQCHIP_INIT_IN_PROGRESS, /* temporarily set during creation */
KVM_IRQCHIP_KERNEL, /* created with KVM_CREATE_IRQCHIP */
KVM_IRQCHIP_SPLIT, /* created with KVM_CAP_SPLIT_IRQCHIP */
};
diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h
index 0edd22c..d5005cc 100644
--- a/arch/x86/kvm/irq.h
+++ b/arch/x86/kvm/irq.h
@@ -111,7 +111,7 @@ static inline int irqchip_in_kernel(struct kvm *kvm)
/* Matches smp_wmb() when setting irqchip_mode */
smp_rmb();
- return mode > KVM_IRQCHIP_INIT_IN_PROGRESS;
+ return mode != KVM_IRQCHIP_NONE;
}
void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c
index 4517a4c..3cc3b2d 100644
--- a/arch/x86/kvm/irq_comm.c
+++ b/arch/x86/kvm/irq_comm.c
@@ -274,16 +274,19 @@ void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin,
srcu_read_unlock(&kvm->irq_srcu, idx);
}
+bool kvm_arch_can_set_irq_routing(struct kvm *kvm)
+{
+ return irqchip_in_kernel(kvm);
+}
+
int kvm_set_routing_entry(struct kvm *kvm,
struct kvm_kernel_irq_routing_entry *e,
const struct kvm_irq_routing_entry *ue)
{
- /* also allow creation of routes during KVM_IRQCHIP_INIT_IN_PROGRESS */
- if (kvm->arch.irqchip_mode == KVM_IRQCHIP_NONE)
- return -EINVAL;
-
- /* Matches smp_wmb() when setting irqchip_mode */
- smp_rmb();
+ /* We can't check irqchip_in_kernel() here as some callers are
+ * currently inititalizing the irqchip. Other callers should therefore
+ * check kvm_arch_can_set_irq_routing() before calling this function.
+ */
switch (ue->type) {
case KVM_IRQ_ROUTING_IRQCHIP:
if (irqchip_split(kvm))
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 34bf64f..eae0e9c 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3911,14 +3911,9 @@ static int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
goto split_irqchip_unlock;
if (kvm->created_vcpus)
goto split_irqchip_unlock;
- kvm->arch.irqchip_mode = KVM_IRQCHIP_INIT_IN_PROGRESS;
r = kvm_setup_empty_irq_routing(kvm);
- if (r) {
- kvm->arch.irqchip_mode = KVM_IRQCHIP_NONE;
- /* Pairs with smp_rmb() when reading irqchip_mode */
- smp_wmb();
+ if (r)
goto split_irqchip_unlock;
- }
/* Pairs with irqchip_in_kernel. */
smp_wmb();
kvm->arch.irqchip_mode = KVM_IRQCHIP_SPLIT;
@@ -4004,12 +3999,8 @@ long kvm_arch_vm_ioctl(struct file *filp,
goto create_irqchip_unlock;
}
- kvm->arch.irqchip_mode = KVM_IRQCHIP_INIT_IN_PROGRESS;
r = kvm_setup_default_irq_routing(kvm);
if (r) {
- kvm->arch.irqchip_mode = KVM_IRQCHIP_NONE;
- /* Pairs with smp_rmb() when reading irqchip_mode */
- smp_wmb();
kvm_ioapic_destroy(kvm);
kvm_pic_destroy(kvm);
goto create_irqchip_unlock;
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 397b7b5..a9921b1 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -504,6 +504,7 @@ void vcpu_put(struct kvm_vcpu *vcpu);
#ifdef __KVM_HAVE_IOAPIC
void kvm_arch_post_irq_ack_notifier_list_update(struct kvm *kvm);
void kvm_arch_post_irq_routing_update(struct kvm *kvm);
+bool kvm_arch_can_set_irq_routing(struct kvm *kvm);
#else
static inline void kvm_arch_post_irq_ack_notifier_list_update(struct kvm *kvm)
{
@@ -511,6 +512,10 @@ static inline void kvm_arch_post_irq_ack_notifier_list_update(struct kvm *kvm)
static inline void kvm_arch_post_irq_routing_update(struct kvm *kvm)
{
}
+static bool kvm_arch_can_set_irq_routing(struct kvm *kvm)
+{
+ return true;
+}
#endif
#ifdef CONFIG_HAVE_KVM_IRQFD
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 357e67c..0a37ba4 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -3054,6 +3054,8 @@ static long kvm_vm_ioctl(struct file *filp,
if (copy_from_user(&routing, argp, sizeof(routing)))
goto out;
r = -EINVAL;
+ if (!kvm_arch_can_set_irq_routing(kvm))
+ goto out;
if (routing.nr > KVM_MAX_IRQ_ROUTES)
goto out;
if (routing.flags)
@@ -3069,11 +3071,8 @@ static long kvm_vm_ioctl(struct file *filp,
routing.nr * sizeof(*entries)))
goto out_free_irq_routing;
}
- /* avoid races with KVM_CREATE_IRQCHIP on x86 */
- mutex_lock(&kvm->lock);
r = kvm_set_irq_routing(kvm, entries, routing.nr,
routing.flags);
- mutex_unlock(&kvm->lock);
out_free_irq_routing:
vfree(entries);
break;
--
2.9.3
next prev parent reply other threads:[~2017-04-25 19:03 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-04-07 8:50 [PATCH v3 00/24] pic/ioapic/irqchip cleanups + minor fixes David Hildenbrand
2017-04-07 8:50 ` [PATCH v3 01/24] KVM: x86: race between KVM_SET_GSI_ROUTING and KVM_CREATE_IRQCHIP David Hildenbrand
2017-04-24 22:39 ` Steve Rutherford
2017-04-25 12:34 ` David Hildenbrand
2017-04-25 14:58 ` Radim Krčmář
2017-04-25 19:03 ` David Hildenbrand [this message]
2017-04-25 19:38 ` [PATCH] KVM: x86: don't hold kvm->lock in KVM_SET_GSI_ROUTING Steve Rutherford
2017-04-25 19:59 ` Radim Krčmář
2017-04-26 8:40 ` David Hildenbrand
2017-04-26 14:27 ` Radim Krčmář
2017-04-26 15:21 ` David Hildenbrand
2017-04-26 20:47 ` Radim Krčmář
2017-04-26 12:33 ` kbuild test robot
2017-04-26 14:24 ` Radim Krčmář
2017-04-07 8:50 ` [PATCH v3 02/24] KVM: x86: new irqchip mode KVM_IRQCHIP_INIT_IN_PROGRESS David Hildenbrand
2017-04-12 18:26 ` Radim Krčmář
2017-04-12 19:55 ` David Hildenbrand
2017-04-07 8:50 ` [PATCH v3 03/24] KVM: x86: check against irqchip_mode in kvm_set_routing_entry() David Hildenbrand
2017-04-12 18:36 ` Radim Krčmář
2017-04-12 19:56 ` David Hildenbrand
2017-04-07 8:50 ` [PATCH v3 04/24] KVM: x86: check against irqchip_mode in pic_in_kernel() David Hildenbrand
2017-04-07 8:50 ` [PATCH v3 05/24] KVM: x86: check against irqchip_mode in ioapic_in_kernel() David Hildenbrand
2017-04-07 8:50 ` [PATCH v3 06/24] KVM: x86: get rid of pic_irqchip() David Hildenbrand
2017-04-07 8:50 ` [PATCH v3 07/24] KVM: x86: get rid of ioapic_irqchip() David Hildenbrand
2017-04-07 8:50 ` [PATCH v3 08/24] KVM: x86: use ioapic_in_kernel() to check for ioapic existence David Hildenbrand
2017-04-07 8:50 ` [PATCH v3 09/24] KVM: x86: remove duplicate checks for ioapic David Hildenbrand
2017-04-07 8:50 ` [PATCH v3 10/24] KVM: x86: convert kvm_(set|get)_ioapic() into void David Hildenbrand
2017-04-07 8:50 ` [PATCH v3 11/24] KVM: x86: don't take kvm->irq_lock when creating IRQCHIP David Hildenbrand
2017-04-07 8:50 ` [PATCH v3 12/24] KVM: x86: push usage of slots_lock down David Hildenbrand
2017-04-07 8:50 ` [PATCH v3 13/24] KVM: x86: KVM_IRQCHIP_PIC_MASTER only has 8 pins David Hildenbrand
2017-04-07 8:50 ` [PATCH v3 14/24] KVM: x86: remove all-vcpu request from kvm_ioapic_init() David Hildenbrand
2017-04-07 8:50 ` [PATCH v3 15/24] KVM: x86: directly call kvm_make_scan_ioapic_request() in ioapic.c David Hildenbrand
2017-04-07 8:50 ` [PATCH v3 16/24] KVM: x86: rename kvm_vcpu_request_scan_ioapic() David Hildenbrand
2017-04-07 8:50 ` [PATCH v3 17/24] KVM: x86: drop goto label in kvm_set_routing_entry() David Hildenbrand
2017-04-07 8:50 ` [PATCH v3 18/24] KVM: x86: cleanup return handling in setup_routing_entry() David Hildenbrand
2017-04-07 8:50 ` [PATCH v3 19/24] KVM: x86: simplify pic_unlock() David Hildenbrand
2017-04-07 8:50 ` [PATCH v3 20/24] KVM: x86: make kvm_pic_reset() static David Hildenbrand
2017-04-07 8:50 ` [PATCH v3 21/24] KVM: x86: drop picdev_in_range() David Hildenbrand
2017-04-07 8:50 ` [PATCH v3 22/24] KVM: x86: set data directly in picdev_read() David Hildenbrand
2017-04-07 8:50 ` [PATCH v3 23/24] KVM: x86: simplify pic_ioport_read() David Hildenbrand
2017-04-07 8:50 ` [PATCH v3 24/24] KVM: x86: use irqchip_kernel() to check for pic+ioapic David Hildenbrand
2017-04-12 18:58 ` [PATCH v3 00/24] pic/ioapic/irqchip cleanups + minor fixes Radim Krčmář
2017-04-12 19:59 ` David Hildenbrand
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=20170425190306.20392-1-david@redhat.com \
--to=david@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=rkrcmar@redhat.com \
--cc=srutherford@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).