aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Xu <peterx@redhat.com>2019-05-05 04:56:42 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2019-05-24 15:27:12 -0400
commit654f1f13ea56b92bacade8ce2725aea0457f91c0 (patch)
treec15b056aac1508450ab54caef254c419f9963ce2
parentc9bcd3e3335d0a29d89fabd2c385e1b989e6f1b0 (diff)
kvm: Check irqchip mode before assign irqfd
When assigning kvm irqfd we didn't check the irqchip mode but we allow KVM_IRQFD to succeed with all the irqchip modes. However it does not make much sense to create irqfd even without the kernel chips. Let's provide a arch-dependent helper to check whether a specific irqfd is allowed by the arch. At least for x86, it should make sense to check: - when irqchip mode is NONE, all irqfds should be disallowed, and, - when irqchip mode is SPLIT, irqfds that are with resamplefd should be disallowed. For either of the case, previously we'll silently ignore the irq or the irq ack event if the irqchip mode is incorrect. However that can cause misterious guest behaviors and it can be hard to triage. Let's fail KVM_IRQFD even earlier to detect these incorrect configurations. CC: Paolo Bonzini <pbonzini@redhat.com> CC: Radim Krčmář <rkrcmar@redhat.com> CC: Alex Williamson <alex.williamson@redhat.com> CC: Eduardo Habkost <ehabkost@redhat.com> Signed-off-by: Peter Xu <peterx@redhat.com> Cc: stable@vger.kernel.org Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--arch/x86/kvm/irq.c7
-rw-r--r--arch/x86/kvm/irq.h1
-rw-r--r--virt/kvm/eventfd.c9
3 files changed, 17 insertions, 0 deletions
diff --git a/arch/x86/kvm/irq.c b/arch/x86/kvm/irq.c
index faa264822cee..007bc654f928 100644
--- a/arch/x86/kvm/irq.c
+++ b/arch/x86/kvm/irq.c
@@ -172,3 +172,10 @@ void __kvm_migrate_timers(struct kvm_vcpu *vcpu)
172 __kvm_migrate_apic_timer(vcpu); 172 __kvm_migrate_apic_timer(vcpu);
173 __kvm_migrate_pit_timer(vcpu); 173 __kvm_migrate_pit_timer(vcpu);
174} 174}
175
176bool kvm_arch_irqfd_allowed(struct kvm *kvm, struct kvm_irqfd *args)
177{
178 bool resample = args->flags & KVM_IRQFD_FLAG_RESAMPLE;
179
180 return resample ? irqchip_kernel(kvm) : irqchip_in_kernel(kvm);
181}
diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h
index d5005cc26521..fd210cdd4983 100644
--- a/arch/x86/kvm/irq.h
+++ b/arch/x86/kvm/irq.h
@@ -114,6 +114,7 @@ static inline int irqchip_in_kernel(struct kvm *kvm)
114 return mode != KVM_IRQCHIP_NONE; 114 return mode != KVM_IRQCHIP_NONE;
115} 115}
116 116
117bool kvm_arch_irqfd_allowed(struct kvm *kvm, struct kvm_irqfd *args);
117void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu); 118void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu);
118void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu); 119void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu);
119void kvm_apic_nmi_wd_deliver(struct kvm_vcpu *vcpu); 120void kvm_apic_nmi_wd_deliver(struct kvm_vcpu *vcpu);
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
index 001aeda4c154..3972a9564c76 100644
--- a/virt/kvm/eventfd.c
+++ b/virt/kvm/eventfd.c
@@ -44,6 +44,12 @@
44 44
45static struct workqueue_struct *irqfd_cleanup_wq; 45static struct workqueue_struct *irqfd_cleanup_wq;
46 46
47bool __attribute__((weak))
48kvm_arch_irqfd_allowed(struct kvm *kvm, struct kvm_irqfd *args)
49{
50 return true;
51}
52
47static void 53static void
48irqfd_inject(struct work_struct *work) 54irqfd_inject(struct work_struct *work)
49{ 55{
@@ -297,6 +303,9 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
297 if (!kvm_arch_intc_initialized(kvm)) 303 if (!kvm_arch_intc_initialized(kvm))
298 return -EAGAIN; 304 return -EAGAIN;
299 305
306 if (!kvm_arch_irqfd_allowed(kvm, args))
307 return -EINVAL;
308
300 irqfd = kzalloc(sizeof(*irqfd), GFP_KERNEL_ACCOUNT); 309 irqfd = kzalloc(sizeof(*irqfd), GFP_KERNEL_ACCOUNT);
301 if (!irqfd) 310 if (!irqfd)
302 return -ENOMEM; 311 return -ENOMEM;