kvm: add support for irqfd via eventfd-notification interface
PATCH v8 1/1 kvm: add support for irqfd via eventfd-notification interface
KVM provides a complete virtual system environment for guests, including support for injecting interrupts modeled after the real exception/interrupt facilities present on the native platform (such as the IDT on x86). Virtual interrupts can come from a variety of sources (emulated devices, pass-through devices, etc) but all must be injected to the guest via the KVM infrastructure. This patch adds a new mechanism to inject a specific interrupt to a guest using a decoupled eventfd mechnanism: Any legal signal on the irqfd (using eventfd semantics from either userspace or kernel) will translate into an injected interrupt in the guest at the next available interrupt window.
---
arch/x86/kvm/Makefile | 2 arch/x86/kvm/x86.c | 1 include/linux/kvm.h | 11 +++ include/linux/kvm_host.h | 4 + virt/kvm/eventfd.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++ virt/kvm/kvm_main.c | 11 +++ 6 files changed, 226 insertions(+), 1 deletions(-) create mode 100644 virt/kvm/eventfd.c
arch/x86/kvm/Makefile +1 -1
@@ -3,7 +3,7 @@ # common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o \ - coalesced_mmio.o irq_comm.o) + coalesced_mmio.o irq_comm.o eventfd.o) ifeq ($(CONFIG_KVM_TRACE),y) common-objs += $(addprefix ../../../virt/kvm/, kvm_trace.o) endif
arch/x86/kvm/x86.c +1 -0
@@ -1026,6 +1026,7 @@ int kvm_dev_ioctl_check_extension(long ext)case KVM_CAP_REINJECT_CONTROL :case KVM_CAP_IRQ_INJECT_STATUS :case KVM_CAP_ASSIGN_DEV_IRQ : +case KVM_CAP_IRQFD : r =1 ;break ;case KVM_CAP_COALESCED_MMIO :
include/linux/kvm.h +11 -0
@@ -415,6 +415,7 @@ struct kvm_trace_rec {#define KVM_CAP_ASSIGN_DEV_IRQ 29/* Another bug in KVM_SET_USER_MEMORY_REGION fixed: */ #define KVM_CAP_JOIN_MEMORY_REGIONS_WORKS 30 +#define KVM_CAP_IRQFD 31#ifdef KVM_CAP_IRQ_ROUTING
@@ -454,6 +455,15 @@ struct kvm_irq_routing {#endif +#define KVM_IRQFD_FLAG_DEASSIGN (1 << 0) + +struct kvm_irqfd { +__u32 fd; +__u32 gsi; +__u32 flags; +__u8 pad[20 ]; +}; +/* * ioctls for VM fds */
@@ -498,6 +508,7 @@ struct kvm_irq_routing {#define KVM_ASSIGN_SET_MSIX_ENTRY \ _IOW(KVMIO, 0x74, struct kvm_assigned_msix_entry)#define KVM_DEASSIGN_DEV_IRQ _IOW(KVMIO, 0x75, struct kvm_assigned_irq) +#define KVM_IRQFD _IOW(KVMIO, 0x76, struct kvm_irqfd)/* * ioctls for vcpu fds
include/linux/kvm_host.h +4 -0
@@ -134,6 +134,7 @@ struct kvm {struct list_head vm_list;struct kvm_io_bus mmio_bus;struct kvm_io_bus pio_bus; +struct list_head irqfds;struct kvm_vm_stat stat;struct kvm_arch arch;atomic_t users_count;
@@ -525,4 +526,7 @@ static inline void kvm_free_irq_routing(struct kvm *kvm) {}#endif +int kvm_irqfd (struct kvm *kvm,int fd,int gsi,int flags); +void kvm_irqfd_release (struct kvm *kvm); +#endif
virt/kvm/eventfd.c new file +198 -0
198 lines not on this page · raw message
virt/kvm/kvm_main.c +11 -0
@@ -983,6 +983,7 @@ static struct kvm *kvm_create_vm(void)atomic_inc (&kvm->mm->mm_count);spin_lock_init (&kvm->mmu_lock);kvm_io_bus_init (&kvm->pio_bus); +INIT_LIST_HEAD (&kvm->irqfds);mutex_init (&kvm->lock);kvm_io_bus_init (&kvm->mmio_bus);init_rwsem (&kvm->slots_lock);
@@ -1034,6 +1035,7 @@ static void kvm_destroy_vm(struct kvm *kvm)spin_lock (&kvm_lock);list_del (&kvm->vm_list);spin_unlock (&kvm_lock); +kvm_irqfd_release (kvm);kvm_free_irq_routing (kvm);kvm_io_bus_destroy (&kvm->pio_bus);kvm_io_bus_destroy (&kvm->mmio_bus);
@@ -2208,6 +2210,15 @@ static long kvm_vm_ioctl(struct file *filp, }#endif #endif /* KVM_CAP_IRQ_ROUTING */ +case KVM_IRQFD : { +struct kvm_irqfd data; + + r = -EFAULT ; +if (copy_from_user (&data, argp,sizeof data)) + goto out; + r =kvm_irqfd (kvm, data.fd, data.gsi, data.flags); +break ; + }default : r =kvm_arch_vm_ioctl (filp, ioctl, arg); }