summaryrefslogtreecommitdiff
path: root/virt
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 /virt
parentbcb85c887647c0f096b51ac2ee391ea792b14b9e (diff)
downloadlwn-5c0aea0e8d98e38858fbb3a09870ed8487a01da2.tar.gz
lwn-5c0aea0e8d98e38858fbb3a09870ed8487a01da2.zip
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 'virt')
-rw-r--r--virt/kvm/irqchip.c5
-rw-r--r--virt/kvm/kvm_main.c5
2 files changed, 7 insertions, 3 deletions
diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c
index cc30d01a56be..31e40c9e81df 100644
--- a/virt/kvm/irqchip.c
+++ b/virt/kvm/irqchip.c
@@ -172,6 +172,11 @@ void __attribute__((weak)) kvm_arch_irq_routing_update(struct kvm *kvm)
{
}
+bool __weak kvm_arch_can_set_irq_routing(struct kvm *kvm)
+{
+ return true;
+}
+
int kvm_set_irq_routing(struct kvm *kvm,
const struct kvm_irq_routing_entry *ue,
unsigned nr,
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 035bc51f656f..6281cc2446d5 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -3075,6 +3075,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)
@@ -3090,11 +3092,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;