]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
kvm tools: Fixes for ioeventfd module
authorSasha Levin <levinsasha928@gmail.com>
Sun, 18 Dec 2011 17:49:41 +0000 (19:49 +0200)
committerSasha Levin <levinsasha928@gmail.com>
Sun, 29 Jan 2012 14:37:56 +0000 (09:37 -0500)
Fixes include:
 - Error handling
 - Cleanup
 - Standard init/uninit

Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
tools/kvm/builtin-run.c
tools/kvm/include/kvm/ioeventfd.h
tools/kvm/ioeventfd.c
tools/kvm/virtio/pci.c

index 99e81b27728c65ef88773f3c3dbcee17592af348..73ca754f196893377a807d9ce811b0e384513da7 100644 (file)
@@ -1000,7 +1000,11 @@ static int kvm_cmd_run_init(int argc, const char **argv)
 
        kvm->single_step = single_step;
 
-       ioeventfd__init(kvm);
+       r = ioeventfd__init(kvm);
+       if (r < 0) {
+               pr_err("ioeventfd__init() failed with error %d\n", r);
+               goto fail;
+       }
 
        max_cpus = kvm__max_cpus(kvm);
        recommended_cpus = kvm__recommended_cpus(kvm);
@@ -1201,8 +1205,6 @@ static int kvm_cmd_run_init(int argc, const char **argv)
        }
 
        thread_pool__init(nr_online_cpus);
-       ioeventfd__start();
-
 fail:
        return r;
 }
@@ -1263,6 +1265,10 @@ static void kvm_cmd_run_exit(int guest_ret)
        if (r < 0)
                pr_warning("ioport__exit() failed with error %d\n", r);
 
+       r = ioeventfd__exit(kvm);
+       if (r < 0)
+               pr_warning("ioeventfd__exit() failed with error %d\n", r);
+
        kvm__delete(kvm);
 
        if (guest_ret == 0)
index 3a95788a515b8dac1ae929774d69b42b9d0b724b..ec70aa547a5ae9090f91e306100f2448e292b45c 100644 (file)
@@ -19,9 +19,9 @@ struct ioevent {
        struct list_head        list;
 };
 
-void ioeventfd__init(struct kvm *kvm);
-void ioeventfd__start(void);
-void ioeventfd__add_event(struct ioevent *ioevent);
-void ioeventfd__del_event(u64 addr, u64 datamatch);
+int ioeventfd__init(struct kvm *kvm);
+int ioeventfd__exit(struct kvm *kvm);
+int ioeventfd__add_event(struct ioevent *ioevent);
+int ioeventfd__del_event(u64 addr, u64 datamatch);
 
 #endif
index 1d6a7accb0d2ec134efeb21bf4da145ce58a9f34..9133101ebb02d8f12c06c6211522511b7727e59a 100644 (file)
 #define IOEVENTFD_MAX_EVENTS   20
 
 static struct  epoll_event events[IOEVENTFD_MAX_EVENTS];
-static int     epoll_fd;
+static int     epoll_fd, epoll_stop_fd;
 static LIST_HEAD(used_ioevents);
 static bool    ioeventfd_avail;
 
-void ioeventfd__init(struct kvm *kvm)
+static void *ioeventfd__thread(void *param)
 {
+       u64 tmp = 1;
+
+       for (;;) {
+               int nfds, i;
+
+               nfds = epoll_wait(epoll_fd, events, IOEVENTFD_MAX_EVENTS, -1);
+               for (i = 0; i < nfds; i++) {
+                       struct ioevent *ioevent;
+
+                       if (events[i].data.fd == epoll_stop_fd)
+                               goto done;
+
+                       ioevent = events[i].data.ptr;
+
+                       if (read(ioevent->fd, &tmp, sizeof(tmp)) < 0)
+                               die("Failed reading event");
+
+                       ioevent->fn(ioevent->fn_kvm, ioevent->fn_ptr);
+               }
+       }
+
+done:
+       tmp = 1;
+       tmp = write(epoll_stop_fd, &tmp, sizeof(tmp));
+
+       return NULL;
+}
+
+static int ioeventfd__start(void)
+{
+       pthread_t thread;
+
+       if (!ioeventfd_avail)
+               return -ENOSYS;
+
+       return pthread_create(&thread, NULL, ioeventfd__thread, NULL);
+}
+
+int ioeventfd__init(struct kvm *kvm)
+{
+       struct epoll_event epoll_event = {.events = EPOLLIN};
+       int r;
+
        ioeventfd_avail = kvm__supports_extension(kvm, KVM_CAP_IOEVENTFD);
        if (!ioeventfd_avail)
-               return;
+               return -ENOSYS;
 
        epoll_fd = epoll_create(IOEVENTFD_MAX_EVENTS);
        if (epoll_fd < 0)
-               die("Failed creating epoll fd");
+               return -errno;
+
+       epoll_stop_fd = eventfd(0, 0);
+       epoll_event.data.fd = epoll_stop_fd;
+
+       r = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, epoll_stop_fd, &epoll_event);
+       if (r < 0)
+               goto cleanup;
+
+       r = ioeventfd__start();
+       if (r < 0)
+               goto cleanup;
+
+       r = 0;
+
+       return r;
+
+cleanup:
+       close(epoll_stop_fd);
+       close(epoll_fd);
+
+       return r;
 }
 
-void ioeventfd__add_event(struct ioevent *ioevent)
+int ioeventfd__exit(struct kvm *kvm)
+{
+       u64 tmp = 1;
+       int r;
+
+       r = write(epoll_stop_fd, &tmp, sizeof(tmp));
+       if (r < 0)
+               return r;
+
+       r = read(epoll_stop_fd, &tmp, sizeof(tmp));
+       if (r < 0)
+               return r;
+
+       close(epoll_fd);
+       close(epoll_stop_fd);
+
+       return 0;
+}
+
+int ioeventfd__add_event(struct ioevent *ioevent)
 {
        struct kvm_ioeventfd kvm_ioevent;
        struct epoll_event epoll_event;
        struct ioevent *new_ioevent;
-       int event;
+       int event, r;
 
        if (!ioeventfd_avail)
-               return;
+               return -ENOSYS;
 
        new_ioevent = malloc(sizeof(*new_ioevent));
        if (new_ioevent == NULL)
-               die("Failed allocating memory for new ioevent");
+               return -ENOMEM;
 
        *new_ioevent = *ioevent;
        event = new_ioevent->fd;
@@ -56,28 +139,40 @@ void ioeventfd__add_event(struct ioevent *ioevent)
                .flags                  = KVM_IOEVENTFD_FLAG_PIO | KVM_IOEVENTFD_FLAG_DATAMATCH,
        };
 
-       if (ioctl(ioevent->fn_kvm->vm_fd, KVM_IOEVENTFD, &kvm_ioevent) != 0)
-               die("Failed creating new ioeventfd");
+       r = ioctl(ioevent->fn_kvm->vm_fd, KVM_IOEVENTFD, &kvm_ioevent);
+       if (r) {
+               r = -errno;
+               goto cleanup;
+       }
 
        epoll_event = (struct epoll_event) {
                .events                 = EPOLLIN,
                .data.ptr               = new_ioevent,
        };
 
-       if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, event, &epoll_event) != 0)
-               die("Failed assigning new event to the epoll fd");
+       r = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, event, &epoll_event);
+       if (r) {
+               r = -errno;
+               goto cleanup;
+       }
 
        list_add_tail(&new_ioevent->list, &used_ioevents);
+
+       return 0;
+
+cleanup:
+       free(new_ioevent);
+       return r;
 }
 
-void ioeventfd__del_event(u64 addr, u64 datamatch)
+int ioeventfd__del_event(u64 addr, u64 datamatch)
 {
        struct kvm_ioeventfd kvm_ioevent;
        struct ioevent *ioevent;
        u8 found = 0;
 
        if (!ioeventfd_avail)
-               return;
+               return -ENOSYS;
 
        list_for_each_entry(ioevent, &used_ioevents, list) {
                if (ioevent->io_addr == addr) {
@@ -87,7 +182,7 @@ void ioeventfd__del_event(u64 addr, u64 datamatch)
        }
 
        if (found == 0 || ioevent == NULL)
-               return;
+               return -ENOENT;
 
        kvm_ioevent = (struct kvm_ioeventfd) {
                .addr                   = ioevent->io_addr,
@@ -106,37 +201,6 @@ void ioeventfd__del_event(u64 addr, u64 datamatch)
 
        close(ioevent->fd);
        free(ioevent);
-}
-
-static void *ioeventfd__thread(void *param)
-{
-       for (;;) {
-               int nfds, i;
-
-               nfds = epoll_wait(epoll_fd, events, IOEVENTFD_MAX_EVENTS, -1);
-               for (i = 0; i < nfds; i++) {
-                       u64 tmp;
-                       struct ioevent *ioevent;
-
-                       ioevent = events[i].data.ptr;
-
-                       if (read(ioevent->fd, &tmp, sizeof(tmp)) < 0)
-                               die("Failed reading event");
-
-                       ioevent->fn(ioevent->fn_kvm, ioevent->fn_ptr);
-               }
-       }
-
-       return NULL;
-}
-
-void ioeventfd__start(void)
-{
-       pthread_t thread;
-
-       if (!ioeventfd_avail)
-               return;
 
-       if (pthread_create(&thread, NULL, ioeventfd__thread, NULL) != 0)
-               die("Failed starting ioeventfd thread");
+       return 0;
 }
index 2643d8a778732c10b317dd2ba51cca0edcc05f9c..7cc014e10e327c6b70a9d1ed7f43887da556715f 100644 (file)
@@ -34,6 +34,7 @@ static int virtio_pci__init_ioeventfd(struct kvm *kvm, struct virtio_trans *vtra
 {
        struct ioevent ioevent;
        struct virtio_pci *vpci = vtrans->virtio;
+       int r;
 
        vpci->ioeventfds[vq] = (struct virtio_pci_ioevent_param) {
                .vtrans         = vtrans,
@@ -50,7 +51,9 @@ static int virtio_pci__init_ioeventfd(struct kvm *kvm, struct virtio_trans *vtra
                .fd             = eventfd(0, 0),
        };
 
-       ioeventfd__add_event(&ioevent);
+       r = ioeventfd__add_event(&ioevent);
+       if (r)
+               return r;
 
        if (vtrans->virtio_ops->notify_vq_eventfd)
                vtrans->virtio_ops->notify_vq_eventfd(kvm, vpci->dev, vq, ioevent.fd);