qemu-kvm: add irqfd support
PATCH v8 1/1 qemu-kvm: add irqfd support
irqfd lets you create an eventfd based file-desriptor to inject interrupts to a kvm guest. We associate one gsi per fd for fine-grained routing.
Signed-off-by Gregory Haskins <[email protected]>
---
kvm/libkvm/libkvm.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ kvm/libkvm/libkvm.h | 26 +++++++++++++++++++++++ 2 files changed, 83 insertions(+), 0 deletions(-)
kvm/libkvm/libkvm.c +57 -0
@@ -34,6 +34,7 @@#include <string.h> #include <errno.h> #include <sys/ioctl.h> +#include <sys/eventfd.h> #include <inttypes.h> #include "libkvm.h"
@@ -1444,3 +1445,59 @@ int kvm_assign_set_msix_entry(kvm_context_t kvm,return ret; }#endif + +#ifdef KVM_CAP_IRQFD +static int _kvm_irqfd (kvm_context_t kvm,int fd,int gsi,int flags) +{ +int r; +struct kvm_irqfd data = { + .fd = fd, + .gsi = gsi, + .flags = flags, + }; + + r =ioctl (kvm->vm_fd,KVM_IRQFD , &data); +if (r ==-1 ) + r = -errno; +return r; +} + +int kvm_create_irqfd (kvm_context_t kvm,int gsi,int flags) +{ +int r; +int fd; + +if (!kvm_check_extension (kvm,KVM_CAP_IRQFD )) +return -ENOENT ; + + fd =eventfd (0 ,0 ); +if (fd <0 ) +return -errno; + + r =_kvm_irqfd (kvm, fd, gsi,0 ); +if (r <0 ) { +close (fd); +return -errno; + } + +return fd; +} + +int kvm_destroy_irqfd (kvm_context_t kvm,int fd,int gsi,int flags) +{ +return _kvm_irqfd (kvm, fd, gsi,KVM_IRQFD_FLAG_DEASSIGN ); +} + +#else /* KVM_CAP_IRQFD */ + +int kvm_create_irqfd (kvm_context_t kvm,int gsi,int flags) +{ +return -ENOENT ; +} + +int kvm_destroy_irqfd (kvm_context_t kvm,int fd,int gsi,int flags) +{ +return -ENOENT ; +} + +#endif /* KVM_CAP_IRQFD */
kvm/libkvm/libkvm.h +26 -0
@@ -856,6 +856,32 @@ int kvm_commit_irq_routes(kvm_context_t kvm);*/ int kvm_get_irq_route_gsi (kvm_context_t kvm); +/*! +* \brief Create a file descriptor for injecting interrupts +* +* Creates an eventfd based file-descriptor that maps to a specific GSI +* in the guest. eventfd compliant signaling (write() from userspace, or +* eventfd_signal() from kernelspace) will cause the GSI to inject +* itself into the guest at the next available window. +* +* \param kvm Pointer to the current kvm_context +* \param gsi GSI to assign to this fd +* \param flags reserved, must be zero +*/ +int kvm_create_irqfd (kvm_context_t kvm,int gsi,int flags); + +/*! +* \brief Destroy an irqfd file descriptor +* +* Destroys a file descriptor previously opened with kvm_create_irqfd() +* +* \param kvm Pointer to the current kvm_context +* \param fd fd to close +* \param gsi GSI to close +* \param flags reserved, must be zero +*/ +int kvm_destroy_irqfd (kvm_context_t kvm,int fd,int gsi,int flags); +#ifdef KVM_CAP_DEVICE_MSIX int kvm_assign_set_msix_nr (kvm_context_t kvm,struct kvm_assigned_msix_nr *msix_nr);