Merge branch 'perf/urgent'
[linux-2.6/x86.git] / tools / kvm / ioeventfd.c
blob3a240e4f17df4bdf7c1890ea00aadde4b9e965f1
1 #include <sys/epoll.h>
2 #include <sys/ioctl.h>
3 #include <pthread.h>
4 #include <unistd.h>
5 #include <stdio.h>
6 #include <signal.h>
8 #include <linux/kernel.h>
9 #include <linux/kvm.h>
10 #include <linux/types.h>
12 #include "kvm/ioeventfd.h"
13 #include "kvm/kvm.h"
14 #include "kvm/util.h"
16 #define IOEVENTFD_MAX_EVENTS 20
18 static struct epoll_event events[IOEVENTFD_MAX_EVENTS];
19 static int epoll_fd;
20 static LIST_HEAD(used_ioevents);
22 void ioeventfd__init(void)
24 epoll_fd = epoll_create(IOEVENTFD_MAX_EVENTS);
25 if (epoll_fd < 0)
26 die("Failed creating epoll fd");
29 void ioeventfd__add_event(struct ioevent *ioevent)
31 struct kvm_ioeventfd kvm_ioevent;
32 struct epoll_event epoll_event;
33 struct ioevent *new_ioevent;
34 int event;
36 new_ioevent = malloc(sizeof(*new_ioevent));
37 if (new_ioevent == NULL)
38 die("Failed allocating memory for new ioevent");
40 *new_ioevent = *ioevent;
41 event = new_ioevent->fd;
43 kvm_ioevent = (struct kvm_ioeventfd) {
44 .addr = ioevent->io_addr,
45 .len = ioevent->io_len,
46 .datamatch = ioevent->datamatch,
47 .fd = event,
48 .flags = KVM_IOEVENTFD_FLAG_PIO | KVM_IOEVENTFD_FLAG_DATAMATCH,
51 if (ioctl(ioevent->fn_kvm->vm_fd, KVM_IOEVENTFD, &kvm_ioevent) != 0)
52 die("Failed creating new ioeventfd");
54 epoll_event = (struct epoll_event) {
55 .events = EPOLLIN,
56 .data.ptr = new_ioevent,
59 if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, event, &epoll_event) != 0)
60 die("Failed assigning new event to the epoll fd");
62 list_add_tail(&new_ioevent->list, &used_ioevents);
65 void ioeventfd__del_event(u64 addr, u64 datamatch)
67 struct kvm_ioeventfd kvm_ioevent;
68 struct ioevent *ioevent;
69 u8 found = 0;
71 list_for_each_entry(ioevent, &used_ioevents, list) {
72 if (ioevent->io_addr == addr) {
73 found = 1;
74 break;
78 if (found == 0 || ioevent == NULL)
79 return;
81 kvm_ioevent = (struct kvm_ioeventfd) {
82 .addr = ioevent->io_addr,
83 .len = ioevent->io_len,
84 .datamatch = ioevent->datamatch,
85 .flags = KVM_IOEVENTFD_FLAG_PIO
86 | KVM_IOEVENTFD_FLAG_DEASSIGN
87 | KVM_IOEVENTFD_FLAG_DATAMATCH,
90 ioctl(ioevent->fn_kvm->vm_fd, KVM_IOEVENTFD, &kvm_ioevent);
92 epoll_ctl(epoll_fd, EPOLL_CTL_DEL, ioevent->fd, NULL);
94 list_del(&ioevent->list);
96 close(ioevent->fd);
97 free(ioevent);
100 static void *ioeventfd__thread(void *param)
102 for (;;) {
103 int nfds, i;
105 nfds = epoll_wait(epoll_fd, events, IOEVENTFD_MAX_EVENTS, -1);
106 for (i = 0; i < nfds; i++) {
107 u64 tmp;
108 struct ioevent *ioevent;
110 ioevent = events[i].data.ptr;
112 if (read(ioevent->fd, &tmp, sizeof(tmp)) < 0)
113 die("Failed reading event");
115 ioevent->fn(ioevent->fn_kvm, ioevent->fn_ptr);
119 return NULL;
122 void ioeventfd__start(void)
124 pthread_t thread;
126 if (pthread_create(&thread, NULL, ioeventfd__thread, NULL) != 0)
127 die("Failed starting ioeventfd thread");