|
|
7f1c5b |
From 80445fed73a7d1a87e8ce96f6cb7d505e437f845 Mon Sep 17 00:00:00 2001
|
|
|
7f1c5b |
From: Peter Xu <peterx@redhat.com>
|
|
|
7f1c5b |
Date: Wed, 1 Feb 2023 16:10:54 -0500
|
|
|
7f1c5b |
Subject: [PATCH 4/8] util/userfaultfd: Add uffd_open()
|
|
|
7f1c5b |
MIME-Version: 1.0
|
|
|
7f1c5b |
Content-Type: text/plain; charset=UTF-8
|
|
|
7f1c5b |
Content-Transfer-Encoding: 8bit
|
|
|
7f1c5b |
|
|
|
7f1c5b |
RH-Author: Peter Xu <peterx@redhat.com>
|
|
|
7f1c5b |
RH-MergeRequest: 149: Support /dev/userfaultfd
|
|
|
7f1c5b |
RH-Bugzilla: 2158704
|
|
|
7f1c5b |
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
|
|
7f1c5b |
RH-Acked-by: quintela1 <quintela@redhat.com>
|
|
|
7f1c5b |
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
7f1c5b |
RH-Commit: [2/3] 4c81696314ab26db47c3415fa2c2501c6a572b5c (peterx/qemu-kvm)
|
|
|
7f1c5b |
|
|
|
7f1c5b |
Add a helper to create the uffd handle.
|
|
|
7f1c5b |
|
|
|
7f1c5b |
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
|
|
7f1c5b |
Reviewed-by: Juan Quintela <quintela@redhat.com>
|
|
|
7f1c5b |
Signed-off-by: Peter Xu <peterx@redhat.com>
|
|
|
7f1c5b |
Signed-off-by: Juan Quintela <quintela@redhat.com>
|
|
|
7f1c5b |
(cherry picked from commit d5890ea0722831eea76a0efd23a496b3e8815fe8)
|
|
|
7f1c5b |
Signed-off-by: Peter Xu <peterx@redhat.com>
|
|
|
7f1c5b |
---
|
|
|
7f1c5b |
include/qemu/userfaultfd.h | 12 ++++++++++++
|
|
|
7f1c5b |
migration/postcopy-ram.c | 11 +++++------
|
|
|
7f1c5b |
tests/qtest/migration-test.c | 4 ++--
|
|
|
7f1c5b |
util/userfaultfd.c | 13 +++++++++++--
|
|
|
7f1c5b |
4 files changed, 30 insertions(+), 10 deletions(-)
|
|
|
7f1c5b |
|
|
|
7f1c5b |
diff --git a/include/qemu/userfaultfd.h b/include/qemu/userfaultfd.h
|
|
|
7f1c5b |
index 6b74f92792..d764496f0b 100644
|
|
|
7f1c5b |
--- a/include/qemu/userfaultfd.h
|
|
|
7f1c5b |
+++ b/include/qemu/userfaultfd.h
|
|
|
7f1c5b |
@@ -13,10 +13,20 @@
|
|
|
7f1c5b |
#ifndef USERFAULTFD_H
|
|
|
7f1c5b |
#define USERFAULTFD_H
|
|
|
7f1c5b |
|
|
|
7f1c5b |
+#ifdef CONFIG_LINUX
|
|
|
7f1c5b |
+
|
|
|
7f1c5b |
#include "qemu/osdep.h"
|
|
|
7f1c5b |
#include "exec/hwaddr.h"
|
|
|
7f1c5b |
#include <linux/userfaultfd.h>
|
|
|
7f1c5b |
|
|
|
7f1c5b |
+/**
|
|
|
7f1c5b |
+ * uffd_open(): Open an userfaultfd handle for current context.
|
|
|
7f1c5b |
+ *
|
|
|
7f1c5b |
+ * @flags: The flags we want to pass in when creating the handle.
|
|
|
7f1c5b |
+ *
|
|
|
7f1c5b |
+ * Returns: the uffd handle if >=0, or <0 if error happens.
|
|
|
7f1c5b |
+ */
|
|
|
7f1c5b |
+int uffd_open(int flags);
|
|
|
7f1c5b |
int uffd_query_features(uint64_t *features);
|
|
|
7f1c5b |
int uffd_create_fd(uint64_t features, bool non_blocking);
|
|
|
7f1c5b |
void uffd_close_fd(int uffd_fd);
|
|
|
7f1c5b |
@@ -32,4 +42,6 @@ int uffd_wakeup(int uffd_fd, void *addr, uint64_t length);
|
|
|
7f1c5b |
int uffd_read_events(int uffd_fd, struct uffd_msg *msgs, int count);
|
|
|
7f1c5b |
bool uffd_poll_events(int uffd_fd, int tmo);
|
|
|
7f1c5b |
|
|
|
7f1c5b |
+#endif /* CONFIG_LINUX */
|
|
|
7f1c5b |
+
|
|
|
7f1c5b |
#endif /* USERFAULTFD_H */
|
|
|
7f1c5b |
diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c
|
|
|
7f1c5b |
index b9a37ef255..0c55df0e52 100644
|
|
|
7f1c5b |
--- a/migration/postcopy-ram.c
|
|
|
7f1c5b |
+++ b/migration/postcopy-ram.c
|
|
|
7f1c5b |
@@ -37,6 +37,7 @@
|
|
|
7f1c5b |
#include "qemu-file.h"
|
|
|
7f1c5b |
#include "yank_functions.h"
|
|
|
7f1c5b |
#include "tls.h"
|
|
|
7f1c5b |
+#include "qemu/userfaultfd.h"
|
|
|
7f1c5b |
|
|
|
7f1c5b |
/* Arbitrary limit on size of each discard command,
|
|
|
7f1c5b |
* keeps them around ~200 bytes
|
|
|
7f1c5b |
@@ -226,11 +227,9 @@ static bool receive_ufd_features(uint64_t *features)
|
|
|
7f1c5b |
int ufd;
|
|
|
7f1c5b |
bool ret = true;
|
|
|
7f1c5b |
|
|
|
7f1c5b |
- /* if we are here __NR_userfaultfd should exists */
|
|
|
7f1c5b |
- ufd = syscall(__NR_userfaultfd, O_CLOEXEC);
|
|
|
7f1c5b |
+ ufd = uffd_open(O_CLOEXEC);
|
|
|
7f1c5b |
if (ufd == -1) {
|
|
|
7f1c5b |
- error_report("%s: syscall __NR_userfaultfd failed: %s", __func__,
|
|
|
7f1c5b |
- strerror(errno));
|
|
|
7f1c5b |
+ error_report("%s: uffd_open() failed: %s", __func__, strerror(errno));
|
|
|
7f1c5b |
return false;
|
|
|
7f1c5b |
}
|
|
|
7f1c5b |
|
|
|
7f1c5b |
@@ -375,7 +374,7 @@ bool postcopy_ram_supported_by_host(MigrationIncomingState *mis)
|
|
|
7f1c5b |
goto out;
|
|
|
7f1c5b |
}
|
|
|
7f1c5b |
|
|
|
7f1c5b |
- ufd = syscall(__NR_userfaultfd, O_CLOEXEC);
|
|
|
7f1c5b |
+ ufd = uffd_open(O_CLOEXEC);
|
|
|
7f1c5b |
if (ufd == -1) {
|
|
|
7f1c5b |
error_report("%s: userfaultfd not available: %s", __func__,
|
|
|
7f1c5b |
strerror(errno));
|
|
|
7f1c5b |
@@ -1160,7 +1159,7 @@ static int postcopy_temp_pages_setup(MigrationIncomingState *mis)
|
|
|
7f1c5b |
int postcopy_ram_incoming_setup(MigrationIncomingState *mis)
|
|
|
7f1c5b |
{
|
|
|
7f1c5b |
/* Open the fd for the kernel to give us userfaults */
|
|
|
7f1c5b |
- mis->userfault_fd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK);
|
|
|
7f1c5b |
+ mis->userfault_fd = uffd_open(O_CLOEXEC | O_NONBLOCK);
|
|
|
7f1c5b |
if (mis->userfault_fd == -1) {
|
|
|
7f1c5b |
error_report("%s: Failed to open userfault fd: %s", __func__,
|
|
|
7f1c5b |
strerror(errno));
|
|
|
7f1c5b |
diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
|
|
|
7f1c5b |
index dbde726adf..0100e1bdbc 100644
|
|
|
7f1c5b |
--- a/tests/qtest/migration-test.c
|
|
|
7f1c5b |
+++ b/tests/qtest/migration-test.c
|
|
|
7f1c5b |
@@ -61,14 +61,14 @@ static bool uffd_feature_thread_id;
|
|
|
7f1c5b |
#if defined(__linux__) && defined(__NR_userfaultfd) && defined(CONFIG_EVENTFD)
|
|
|
7f1c5b |
#include <sys/eventfd.h>
|
|
|
7f1c5b |
#include <sys/ioctl.h>
|
|
|
7f1c5b |
-#include <linux/userfaultfd.h>
|
|
|
7f1c5b |
+#include "qemu/userfaultfd.h"
|
|
|
7f1c5b |
|
|
|
7f1c5b |
static bool ufd_version_check(void)
|
|
|
7f1c5b |
{
|
|
|
7f1c5b |
struct uffdio_api api_struct;
|
|
|
7f1c5b |
uint64_t ioctl_mask;
|
|
|
7f1c5b |
|
|
|
7f1c5b |
- int ufd = syscall(__NR_userfaultfd, O_CLOEXEC);
|
|
|
7f1c5b |
+ int ufd = uffd_open(O_CLOEXEC);
|
|
|
7f1c5b |
|
|
|
7f1c5b |
if (ufd == -1) {
|
|
|
7f1c5b |
g_test_message("Skipping test: userfaultfd not available");
|
|
|
7f1c5b |
diff --git a/util/userfaultfd.c b/util/userfaultfd.c
|
|
|
7f1c5b |
index f1cd6af2b1..4953b3137d 100644
|
|
|
7f1c5b |
--- a/util/userfaultfd.c
|
|
|
7f1c5b |
+++ b/util/userfaultfd.c
|
|
|
7f1c5b |
@@ -19,6 +19,15 @@
|
|
|
7f1c5b |
#include <sys/syscall.h>
|
|
|
7f1c5b |
#include <sys/ioctl.h>
|
|
|
7f1c5b |
|
|
|
7f1c5b |
+int uffd_open(int flags)
|
|
|
7f1c5b |
+{
|
|
|
7f1c5b |
+#if defined(__NR_userfaultfd)
|
|
|
7f1c5b |
+ return syscall(__NR_userfaultfd, flags);
|
|
|
7f1c5b |
+#else
|
|
|
7f1c5b |
+ return -EINVAL;
|
|
|
7f1c5b |
+#endif
|
|
|
7f1c5b |
+}
|
|
|
7f1c5b |
+
|
|
|
7f1c5b |
/**
|
|
|
7f1c5b |
* uffd_query_features: query UFFD features
|
|
|
7f1c5b |
*
|
|
|
7f1c5b |
@@ -32,7 +41,7 @@ int uffd_query_features(uint64_t *features)
|
|
|
7f1c5b |
struct uffdio_api api_struct = { 0 };
|
|
|
7f1c5b |
int ret = -1;
|
|
|
7f1c5b |
|
|
|
7f1c5b |
- uffd_fd = syscall(__NR_userfaultfd, O_CLOEXEC);
|
|
|
7f1c5b |
+ uffd_fd = uffd_open(O_CLOEXEC);
|
|
|
7f1c5b |
if (uffd_fd < 0) {
|
|
|
7f1c5b |
trace_uffd_query_features_nosys(errno);
|
|
|
7f1c5b |
return -1;
|
|
|
7f1c5b |
@@ -69,7 +78,7 @@ int uffd_create_fd(uint64_t features, bool non_blocking)
|
|
|
7f1c5b |
uint64_t ioctl_mask = BIT(_UFFDIO_REGISTER) | BIT(_UFFDIO_UNREGISTER);
|
|
|
7f1c5b |
|
|
|
7f1c5b |
flags = O_CLOEXEC | (non_blocking ? O_NONBLOCK : 0);
|
|
|
7f1c5b |
- uffd_fd = syscall(__NR_userfaultfd, flags);
|
|
|
7f1c5b |
+ uffd_fd = uffd_open(flags);
|
|
|
7f1c5b |
if (uffd_fd < 0) {
|
|
|
7f1c5b |
trace_uffd_create_fd_nosys(errno);
|
|
|
7f1c5b |
return -1;
|
|
|
7f1c5b |
--
|
|
|
7f1c5b |
2.31.1
|
|
|
7f1c5b |
|