summaryrefslogtreecommitdiff
path: root/contrib/libvhost-user/libvhost-user.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libvhost-user/libvhost-user.c')
-rw-r--r--contrib/libvhost-user/libvhost-user.c42
1 files changed, 40 insertions, 2 deletions
diff --git a/contrib/libvhost-user/libvhost-user.c b/contrib/libvhost-user/libvhost-user.c
index ed9f3148d3..9e31f47b7a 100644
--- a/contrib/libvhost-user/libvhost-user.c
+++ b/contrib/libvhost-user/libvhost-user.c
@@ -26,9 +26,20 @@
#include <sys/socket.h>
#include <sys/eventfd.h>
#include <sys/mman.h>
+#include "qemu/compiler.h"
+
+#if defined(__linux__)
+#include <sys/syscall.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
#include <linux/vhost.h>
-#include "qemu/compiler.h"
+#ifdef __NR_userfaultfd
+#include <linux/userfaultfd.h>
+#endif
+
+#endif
+
#include "qemu/atomic.h"
#include "libvhost-user.h"
@@ -888,8 +899,35 @@ vu_set_config(VuDev *dev, VhostUserMsg *vmsg)
static bool
vu_set_postcopy_advise(VuDev *dev, VhostUserMsg *vmsg)
{
- /* TODO: Open ufd, pass it back in the request */
+ dev->postcopy_ufd = -1;
+#ifdef UFFDIO_API
+ struct uffdio_api api_struct;
+
+ dev->postcopy_ufd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK);
vmsg->size = 0;
+#endif
+
+ if (dev->postcopy_ufd == -1) {
+ vu_panic(dev, "Userfaultfd not available: %s", strerror(errno));
+ goto out;
+ }
+
+#ifdef UFFDIO_API
+ api_struct.api = UFFD_API;
+ api_struct.features = 0;
+ if (ioctl(dev->postcopy_ufd, UFFDIO_API, &api_struct)) {
+ vu_panic(dev, "Failed UFFDIO_API: %s", strerror(errno));
+ close(dev->postcopy_ufd);
+ dev->postcopy_ufd = -1;
+ goto out;
+ }
+ /* TODO: Stash feature flags somewhere */
+#endif
+
+out:
+ /* Return a ufd to the QEMU */
+ vmsg->fd_num = 1;
+ vmsg->fds[0] = dev->postcopy_ufd;
return true; /* = send a reply */
}