On Tue, Dec 16, 2025 at 11:18:48AM -0300, Fabiano Rosas wrote:
> Peter Xu <[email protected]> writes:
>
> > Support the guest-memfd type when the fd has init share enabled. It means
> > the gmemfd can be used similarly to memfd.
> >
> > Signed-off-by: Peter Xu <[email protected]>
> > ---
> > tests/qtest/migration/framework.h | 4 +++
> > tests/qtest/migration/framework.c | 60 +++++++++++++++++++++++++++++++
> > 2 files changed, 64 insertions(+)
> >
> > diff --git a/tests/qtest/migration/framework.h
> > b/tests/qtest/migration/framework.h
> > index ed85ed502d..b4c5edcad3 100644
> > --- a/tests/qtest/migration/framework.h
> > +++ b/tests/qtest/migration/framework.h
> > @@ -34,6 +34,10 @@ typedef enum {
> > * but only anonymously allocated.
> > */
> > MEM_TYPE_MEMFD,
> > + /*
> > + * Use guest-memfd, shared mappings.
> > + */
> > + MEM_TYPE_GUEST_MEMFD,
> > MEM_TYPE_NUM,
> > } MemType;
> >
> > diff --git a/tests/qtest/migration/framework.c
> > b/tests/qtest/migration/framework.c
> > index e35839c95f..9aa353bac6 100644
> > --- a/tests/qtest/migration/framework.c
> > +++ b/tests/qtest/migration/framework.c
> > @@ -26,6 +26,10 @@
> > #include "qemu/range.h"
> > #include "qemu/sockets.h"
> >
> > +#ifdef CONFIG_LINUX
> > +#include <linux/kvm.h>
> > +#include <sys/ioctl.h>
> > +#endif
> >
> > #define QEMU_VM_FILE_MAGIC 0x5145564d
> > #define QEMU_ENV_SRC "QTEST_QEMU_BINARY_SRC"
> > @@ -283,6 +287,9 @@ static char *migrate_mem_type_get_opts(MemType type,
> > const char *memory_size)
> > case MEM_TYPE_MEMFD:
> > backend = g_strdup("-object memory-backend-memfd");
> > break;
> > + case MEM_TYPE_GUEST_MEMFD:
> > + backend = g_strdup("-object memory-backend-memfd,guest-memfd=on");
> > + break;
> > default:
> > g_assert_not_reached();
> > break;
> > @@ -425,8 +432,55 @@ int migrate_args(char **from, char **to, const char
> > *uri, MigrateStart *args)
> > return 0;
> > }
> >
> > +static bool kvm_guest_memfd_init_shared_supported(const char **reason)
>
> Should be in migration-util.c, like kvm_dirty_ring_supported() and
> ufd_version_check().
Ah.. sure.
>
> > +{
> > + assert(*reason == NULL);
> > +
> > +#ifdef CONFIG_LINUX
> > + int ret, fd = -1;
> > +
> > + if (!migration_get_env()->has_kvm) {
> > + *reason = "KVM is not enabled in the current QEMU build";
> > + goto out;
> > + }
> > +
> > + fd = open("/dev/kvm", O_RDWR);
> > + if (fd < 0) {
> > + *reason = "KVM module isn't available or missing permission";
> > + goto out;
> > + }
> > +
> > + ret = ioctl(fd, KVM_CHECK_EXTENSION, KVM_CAP_GUEST_MEMFD);
> > + if (!ret) {
> > + *reason = "KVM module doesn't suport guest-memfd";
> > + goto out;
> > + }
> > +
> > + ret = ioctl(fd, KVM_CHECK_EXTENSION, KVM_CAP_GUEST_MEMFD_FLAGS);
> > + if (ret < 0) {
>
> Should this be <= ? I see there's a window between the addition of
> KVM_CAP_GUEST_MEMFD and KVM_CAP_GUEST_MEMFD_FLAGS in the kernel.
That was checked right below [1], so ret==0 will fail with a better error
message:
>
> > + *reason = "KVM doesn't support KVM_CAP_GUEST_MEMFD_FLAGS";
> > + goto out;
> > + }
> > +
> > + if (!(ret & GUEST_MEMFD_FLAG_INIT_SHARED)) {
[1]
> > + *reason = "KVM doesn't support GUEST_MEMFD_FLAG_INIT_SHARED";
> > + goto out;
> > + }
> > +out:
> > + if (fd >= 0) {
> > + close(fd);
> > + }
> > +#else
> > + *reason = "KVM not supported on non-Linux OS";
> > +#endif
> > +
> > + return !*reason;
> > +}
> > +
> > static bool migrate_mem_type_prepare(MemType type)
> > {
> > + const char *reason = NULL;
> > +
> > switch (type) {
> > case MEM_TYPE_SHMEM:
> > if (!g_file_test("/dev/shm", G_FILE_TEST_IS_DIR)) {
> > @@ -434,6 +488,12 @@ static bool migrate_mem_type_prepare(MemType type)
> > return false;
> > }
> > break;
> > + case MEM_TYPE_GUEST_MEMFD:
> > + if (!kvm_guest_memfd_init_shared_supported(&reason)) {
> > + g_test_skip(reason);
> > + return false;
> > + }
> > + break;
> > default:
> > break;
> > }
>
--
Peter Xu