Skip to content

Commit 654f1f1

Browse files
xzpeterbonzini
authored andcommitted
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 <[email protected]> CC: Radim Krčmář <[email protected]> CC: Alex Williamson <[email protected]> CC: Eduardo Habkost <[email protected]> Signed-off-by: Peter Xu <[email protected]> Cc: [email protected] Signed-off-by: Paolo Bonzini <[email protected]>
1 parent c9bcd3e commit 654f1f1

File tree

3 files changed

+17
-0
lines changed

3 files changed

+17
-0
lines changed

arch/x86/kvm/irq.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,10 @@ void __kvm_migrate_timers(struct kvm_vcpu *vcpu)
172172
__kvm_migrate_apic_timer(vcpu);
173173
__kvm_migrate_pit_timer(vcpu);
174174
}
175+
176+
bool 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+
}

arch/x86/kvm/irq.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ static inline int irqchip_in_kernel(struct kvm *kvm)
114114
return mode != KVM_IRQCHIP_NONE;
115115
}
116116

117+
bool kvm_arch_irqfd_allowed(struct kvm *kvm, struct kvm_irqfd *args);
117118
void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu);
118119
void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu);
119120
void kvm_apic_nmi_wd_deliver(struct kvm_vcpu *vcpu);

virt/kvm/eventfd.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@
4444

4545
static struct workqueue_struct *irqfd_cleanup_wq;
4646

47+
bool __attribute__((weak))
48+
kvm_arch_irqfd_allowed(struct kvm *kvm, struct kvm_irqfd *args)
49+
{
50+
return true;
51+
}
52+
4753
static void
4854
irqfd_inject(struct work_struct *work)
4955
{
@@ -297,6 +303,9 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
297303
if (!kvm_arch_intc_initialized(kvm))
298304
return -EAGAIN;
299305

306+
if (!kvm_arch_irqfd_allowed(kvm, args))
307+
return -EINVAL;
308+
300309
irqfd = kzalloc(sizeof(*irqfd), GFP_KERNEL_ACCOUNT);
301310
if (!irqfd)
302311
return -ENOMEM;

0 commit comments

Comments
 (0)