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


Reply via email to