eventfd support for KVM userspace
v7 cover eventfd support for KVM userspace
This is the userspace support for the irqfd/iofd interfaces published here:
http://lkml.org/lkml/2009/5/12/372
---
Gregory Haskins (2):
qemu-kvm: add iofd support
qemu-kvm: add irqfd support
kvm/libkvm/libkvm.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++ kvm/libkvm/libkvm.h | 56 ++++++++++++++++++++++++ 2 files changed, 174 insertions(+), 0 deletions(-)
Signature · 1 line
Signature
PATCH v7 1/2 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.
---
kvm/libkvm/libkvm.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++ kvm/libkvm/libkvm.h | 25 +++++++++++++++++++ 2 files changed, 91 insertions(+), 0 deletions(-)
kvm/libkvm/libkvm.c +66 -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,68 @@ int kvm_assign_set_msix_entry(kvm_context_t kvm,return ret; }#endif + +#ifdef KVM_CAP_EVENTFD +static int _assign_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_ASSIGN_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_EVENTFD )) +return -ENOENT ; + + fd =eventfd (0 ,0 ); +if (fd <0 ) +return -errno; + + r =_assign_irqfd (kvm, fd, gsi, flags); +if (r <0 ) { +close (fd); +return -errno; + } + +return fd; +} + +int kvm_destroy_irqfd (kvm_context_t kvm,int fd,int flags) +{ +int r; +__u32 data = fd; + + r =ioctl (kvm->vm_fd,KVM_DEASSIGN_IRQFD , &data); +if (r ==-1 ) + r = -errno; + +close (fd); + +return r; +} + +#else /* KVM_CAP_EVENTFD */ + +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 flags) +{ +return -ENOENT ; +} + +#endif /* KVM_CAP_EVENTFD */
kvm/libkvm/libkvm.h +25 -0
@@ -856,6 +856,31 @@ 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 flags reserved, must be zero +*/ +int kvm_destroy_irqfd (kvm_context_t kvm,int fd,int flags); +#ifdef KVM_CAP_DEVICE_MSIX int kvm_assign_set_msix_nr (kvm_context_t kvm,struct kvm_assigned_msix_nr *msix_nr);
Re: [PATCH v7 1/2] qemu-kvm: add irqfd support
Quoted 4 lines · Gregory Haskins
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.
Sorry, getting to userspace a little late in the game.
kvm/libkvm/libkvm.c line 38
Quoted 6 lines
kvm/libkvm/libkvm.c +1
-0@@ -34,6 +34,7 @@#include <string.h> #include <errno.h> #include <sys/ioctl.h> +#include <sys/eventfd.h>
This only made it in 2.6.22. So it needs a ./configure -time check for existence.
kvm/libkvm/libkvm.c int kvm_assign_set_msix_entry(kvm_context_t kvm, · line 1505
Quoted 10 lines
kvm/libkvm/libkvm.c +9
-0+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 flags) +{ +return -ENOENT ; +}
-ENOSYS is more traditional.
Signature · 1 line
error compiling committee.c: too many arguments to function
Re: [PATCH v7 1/2] qemu-kvm: add irqfd support
Quoted 8 lines · Avi Kivity
Quoted 5 lines · Gregory Haskins
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.Sorry, getting to userspace a little late in the game.
Np.. I need to re-work this for the POLLHUP patch I am about to push anyway.
Quoted 10 lines
kvm/libkvm/libkvm.c line 38
Quoted 7 lines
kvm/libkvm/libkvm.c +1
-0@@ -34,6 +34,7 @@#include <string.h> #include <errno.h> #include <sys/ioctl.h> +#include <sys/eventfd.h> This only made it in 2.6.22. So it needs a ./configure -time check for existence.
I could also just put this within the #ifdef KVM_CAP_IRQFD?
Quoted 14 lines
kvm/libkvm/libkvm.c int kvm_assign_set_msix_entry(kvm_context_t kvm, · line 1505
Quoted 11 lines
kvm/libkvm/libkvm.c +9
-0+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 flags) +{ +return -ENOENT ; +}
-ENOSYSis more traditional.
Ack.
-Greg
PATCH v7 2/2 qemu-kvm: add iofd support
In reply to Gregory HaskinsAn iofd allows an eventfd to attach to a specific PIO/MMIO region in the guest. Any guest-writes to that region will trigger an eventfd signal.
---
kvm/libkvm/libkvm.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++ kvm/libkvm/libkvm.h | 31 ++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 0 deletions(-)
kvm/libkvm/libkvm.c +52 -0
@@ -1497,6 +1497,45 @@ int kvm_destroy_irqfd(kvm_context_t kvm, int fd, int flags)return r; } +int kvm_assign_iofd (kvm_context_t kvm,unsigned long addr,size_t len, +int fd,int type,int flags) +{ +int r; +struct kvm_iofd data = { + .addr = addr, + .len = len, + .fd = fd, + .flags = type ?KVM_IOFD_FLAG_PIO :0 , + }; + +if (!kvm_check_extension (kvm,KVM_CAP_EVENTFD )) +return -ENOENT ; + + r =ioctl (kvm->vm_fd,KVM_IOFD , &data); +if (r ==-1 ) + r = -errno; +return r; +} + +int kvm_deassign_iofd (kvm_context_t kvm,unsigned long addr,size_t len, +int type,int flags) +{ +int r; +struct kvm_iofd data = { + .addr = addr, + .len = len, + .flags =KVM_IOFD_FLAG_DEASSIGN | (type ?KVM_IOFD_FLAG_PIO :0 ), + }; + +if (!kvm_check_extension (kvm,KVM_CAP_EVENTFD )) +return -ENOENT ; + + r =ioctl (kvm->vm_fd,KVM_IOFD , &data); +if (r ==-1 ) + r = -errno; +return r; +} +#else /* KVM_CAP_EVENTFD */ int kvm_create_irqfd (kvm_context_t kvm,int gsi,int flags)
@@ -1509,4 +1548,17 @@ int kvm_destroy_irqfd(kvm_context_t kvm, int fd, int flags) return -ENOENT; } +int kvm_assign_iofd (kvm_context_t kvm,unsigned long addr,size_t len, +int fd,int type,int flags) +{ +return -ENOENT ; +} + +int kvm_deassign_iofd (kvm_context_t kvm,unsigned long addr,size_t len, +int type,int flags) +{ +return -ENOENT ; +} +#endif /* KVM_CAP_EVENTFD */ +
kvm/libkvm/libkvm.h +31 -0
@@ -881,6 +881,37 @@ int kvm_create_irqfd(kvm_context_t kvm, int gsi, int flags);*/ int kvm_destroy_irqfd (kvm_context_t kvm,int fd,int flags); +/*! +* \brief Assign an eventfd to an IO port (PIO or MMIO) +* +* Assigns an eventfd based file-descriptor to a specific PIO or MMIO +* address range. Any guest writes to the specified range will generate +* an eventfd signal. +* +* \param kvm Pointer to the current kvm_context +* \param addr The IO address +* \param len The length of the IO region at the address +* \param fd The eventfd file-descriptor +* \param type MMIO=0, PIO=1 +* \param flags reserved, must be zero +*/ +int kvm_assign_iofd (kvm_context_t kvm,unsigned long addr,size_t len, +int fd,int type,int flags); + +/*! +* \brief Deassign an iofd from a previously registered IO port +* +* Deassigns an iofd previously registered with kvm_assign_iofd() +* +* \param kvm Pointer to the current kvm_context +* \param addr The IO address +* \param len The length of the IO region at the address +* \param type MMIO=0, PIO=1 +* \param flags reserved, must be zero +*/ +int kvm_deassign_iofd (kvm_context_t kvm,unsigned long addr,size_t len, +int type,int flags); +#ifdef KVM_CAP_DEVICE_MSIX int kvm_assign_set_msix_nr (kvm_context_t kvm,struct kvm_assigned_msix_nr *msix_nr);