util/userfaultfd: Add uffd_open()

Add a helper to create the uffd handle.

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
This commit is contained in:
Peter Xu 2023-02-01 16:10:54 -05:00 committed by Juan Quintela
parent d9df92925e
commit d5890ea072
4 changed files with 30 additions and 10 deletions

View File

@ -13,10 +13,20 @@
#ifndef USERFAULTFD_H #ifndef USERFAULTFD_H
#define USERFAULTFD_H #define USERFAULTFD_H
#ifdef CONFIG_LINUX
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "exec/hwaddr.h" #include "exec/hwaddr.h"
#include <linux/userfaultfd.h> #include <linux/userfaultfd.h>
/**
* uffd_open(): Open an userfaultfd handle for current context.
*
* @flags: The flags we want to pass in when creating the handle.
*
* Returns: the uffd handle if >=0, or <0 if error happens.
*/
int uffd_open(int flags);
int uffd_query_features(uint64_t *features); int uffd_query_features(uint64_t *features);
int uffd_create_fd(uint64_t features, bool non_blocking); int uffd_create_fd(uint64_t features, bool non_blocking);
void uffd_close_fd(int uffd_fd); void uffd_close_fd(int uffd_fd);
@ -32,4 +42,6 @@ int uffd_wakeup(int uffd_fd, void *addr, uint64_t length);
int uffd_read_events(int uffd_fd, struct uffd_msg *msgs, int count); int uffd_read_events(int uffd_fd, struct uffd_msg *msgs, int count);
bool uffd_poll_events(int uffd_fd, int tmo); bool uffd_poll_events(int uffd_fd, int tmo);
#endif /* CONFIG_LINUX */
#endif /* USERFAULTFD_H */ #endif /* USERFAULTFD_H */

View File

@ -37,6 +37,7 @@
#include "qemu-file.h" #include "qemu-file.h"
#include "yank_functions.h" #include "yank_functions.h"
#include "tls.h" #include "tls.h"
#include "qemu/userfaultfd.h"
/* Arbitrary limit on size of each discard command, /* Arbitrary limit on size of each discard command,
* keeps them around ~200 bytes * keeps them around ~200 bytes
@ -226,11 +227,9 @@ static bool receive_ufd_features(uint64_t *features)
int ufd; int ufd;
bool ret = true; bool ret = true;
/* if we are here __NR_userfaultfd should exists */ ufd = uffd_open(O_CLOEXEC);
ufd = syscall(__NR_userfaultfd, O_CLOEXEC);
if (ufd == -1) { if (ufd == -1) {
error_report("%s: syscall __NR_userfaultfd failed: %s", __func__, error_report("%s: uffd_open() failed: %s", __func__, strerror(errno));
strerror(errno));
return false; return false;
} }
@ -375,7 +374,7 @@ bool postcopy_ram_supported_by_host(MigrationIncomingState *mis)
goto out; goto out;
} }
ufd = syscall(__NR_userfaultfd, O_CLOEXEC); ufd = uffd_open(O_CLOEXEC);
if (ufd == -1) { if (ufd == -1) {
error_report("%s: userfaultfd not available: %s", __func__, error_report("%s: userfaultfd not available: %s", __func__,
strerror(errno)); strerror(errno));
@ -1160,7 +1159,7 @@ static int postcopy_temp_pages_setup(MigrationIncomingState *mis)
int postcopy_ram_incoming_setup(MigrationIncomingState *mis) int postcopy_ram_incoming_setup(MigrationIncomingState *mis)
{ {
/* Open the fd for the kernel to give us userfaults */ /* Open the fd for the kernel to give us userfaults */
mis->userfault_fd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK); mis->userfault_fd = uffd_open(O_CLOEXEC | O_NONBLOCK);
if (mis->userfault_fd == -1) { if (mis->userfault_fd == -1) {
error_report("%s: Failed to open userfault fd: %s", __func__, error_report("%s: Failed to open userfault fd: %s", __func__,
strerror(errno)); strerror(errno));

View File

@ -61,14 +61,14 @@ static bool uffd_feature_thread_id;
#if defined(__linux__) && defined(__NR_userfaultfd) && defined(CONFIG_EVENTFD) #if defined(__linux__) && defined(__NR_userfaultfd) && defined(CONFIG_EVENTFD)
#include <sys/eventfd.h> #include <sys/eventfd.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <linux/userfaultfd.h> #include "qemu/userfaultfd.h"
static bool ufd_version_check(void) static bool ufd_version_check(void)
{ {
struct uffdio_api api_struct; struct uffdio_api api_struct;
uint64_t ioctl_mask; uint64_t ioctl_mask;
int ufd = syscall(__NR_userfaultfd, O_CLOEXEC); int ufd = uffd_open(O_CLOEXEC);
if (ufd == -1) { if (ufd == -1) {
g_test_message("Skipping test: userfaultfd not available"); g_test_message("Skipping test: userfaultfd not available");

View File

@ -19,6 +19,15 @@
#include <sys/syscall.h> #include <sys/syscall.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
int uffd_open(int flags)
{
#if defined(__NR_userfaultfd)
return syscall(__NR_userfaultfd, flags);
#else
return -EINVAL;
#endif
}
/** /**
* uffd_query_features: query UFFD features * uffd_query_features: query UFFD features
* *
@ -32,7 +41,7 @@ int uffd_query_features(uint64_t *features)
struct uffdio_api api_struct = { 0 }; struct uffdio_api api_struct = { 0 };
int ret = -1; int ret = -1;
uffd_fd = syscall(__NR_userfaultfd, O_CLOEXEC); uffd_fd = uffd_open(O_CLOEXEC);
if (uffd_fd < 0) { if (uffd_fd < 0) {
trace_uffd_query_features_nosys(errno); trace_uffd_query_features_nosys(errno);
return -1; return -1;
@ -69,7 +78,7 @@ int uffd_create_fd(uint64_t features, bool non_blocking)
uint64_t ioctl_mask = BIT(_UFFDIO_REGISTER) | BIT(_UFFDIO_UNREGISTER); uint64_t ioctl_mask = BIT(_UFFDIO_REGISTER) | BIT(_UFFDIO_UNREGISTER);
flags = O_CLOEXEC | (non_blocking ? O_NONBLOCK : 0); flags = O_CLOEXEC | (non_blocking ? O_NONBLOCK : 0);
uffd_fd = syscall(__NR_userfaultfd, flags); uffd_fd = uffd_open(flags);
if (uffd_fd < 0) { if (uffd_fd < 0) {
trace_uffd_create_fd_nosys(errno); trace_uffd_create_fd_nosys(errno);
return -1; return -1;