Skip to contentSkip to conversation

eventfd support for KVM userspace

PATCH Superseded Gregory Haskins 2 participants 5 messages May 12, 2009 – Jun 2, 2009 KVM

v7 of 10 Superseded Latest is v10 →

lore
Share & tools
lore
#0 lore raw

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
#1 lore raw

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
index ba0a5d1..74a21a2 100644
@@ -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
index 4821a1e..322b4cd 100644
@@ -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);
#2 lore raw

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
#3 lore raw

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;
+}

-ENOSYS is more traditional.

Ack.

-Greg

#4 lore raw

PATCH v7 2/2 qemu-kvm: add iofd support

In reply to Gregory Haskins

An 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
index 74a21a2..0139abd 100644
@@ -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
index 322b4cd..89c558a 100644
@@ -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);