summaryrefslogtreecommitdiff
path: root/arch/x86/kvm/irq_comm.c
diff options
context:
space:
mode:
authorDavid Hildenbrand <david@redhat.com>2017-04-28 17:06:20 +0200
committerPaolo Bonzini <pbonzini@redhat.com>2017-05-02 14:45:45 +0200
commit5c0aea0e8d98e38858fbb3a09870ed8487a01da2 (patch)
tree12549a0a41cdda2b265bf0107daca828bc52b8c5 /arch/x86/kvm/irq_comm.c
parentbcb85c887647c0f096b51ac2ee391ea792b14b9e (diff)
KVM: x86: don't hold kvm->lock in KVM_SET_GSI_ROUTING
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> Reviewed-by: Radim Krčmář <rkrcmar@redhat.com> Fixes: 1df6ddede10a ("KVM: x86: race between KVM_SET_GSI_ROUTING and KVM_CREATE_IRQCHIP") Signed-off-by: David Hildenbrand <david@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86/kvm/irq_comm.c')
-rw-r--r--arch/x86/kvm/irq_comm.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c
index 4517a4c2ac3a..3cc3b2d130a0 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))