On Mon, Dec 15, 2025 at 03:51:59PM -0500, Peter Xu wrote:
> Host backends supports guest-memfd now by detecting whether it's a
> confidential VM.  There's no way to choose it yet from the memory level to
> use it fully shared.  If we use guest-memfd, it so far always implies we
> need two layers of memory backends, while the guest-memfd only provides the
> private set of pages.
> 
> This patch introduces a way so that QEMU can consume guest memfd as the
> only source of memory to back the object (aka, fully shared).
> 
> To use the fully shared guest-memfd, one can add a memfd object with:
> 
>   -object memory-backend-memfd,guest-memfd=on,share=on
> 
> Note that share=on is required with fully shared guest_memfd.
> 
> PS: there's a trivial touch-up on fd<0 check, because the stub to create
> guest-memfd may return negative but not -1.
> 
> Signed-off-by: Peter Xu <[email protected]>
> ---
>  qapi/qom.json            |  6 ++++-
>  backends/hostmem-memfd.c | 53 ++++++++++++++++++++++++++++++++++++----
>  2 files changed, 53 insertions(+), 6 deletions(-)
> 
> diff --git a/qapi/qom.json b/qapi/qom.json
> index 6f5c9de0f0..9ebf17bfc7 100644
> --- a/qapi/qom.json
> +++ b/qapi/qom.json
> @@ -763,13 +763,17 @@
>  # @seal: if true, create a sealed-file, which will block further
>  #     resizing of the memory (default: true)
>  #
> +# @guest-memfd: if true, use guest-memfd to back the memory region.
> +#     (default: false, since: 11.0)
> +#
>  # Since: 2.12
>  ##
>  { 'struct': 'MemoryBackendMemfdProperties',
>    'base': 'MemoryBackendProperties',
>    'data': { '*hugetlb': 'bool',
>              '*hugetlbsize': 'size',
> -            '*seal': 'bool' },
> +            '*seal': 'bool',
> +            '*guest-memfd': 'bool' },
>    'if': 'CONFIG_LINUX' }
>  
>  ##
> diff --git a/backends/hostmem-memfd.c b/backends/hostmem-memfd.c
> index ea93f034e4..9299cd7675 100644
> --- a/backends/hostmem-memfd.c
> +++ b/backends/hostmem-memfd.c
> @@ -18,6 +18,8 @@
>  #include "qapi/error.h"
>  #include "qom/object.h"
>  #include "migration/cpr.h"
> +#include "system/kvm.h"
> +#include <linux/kvm.h>
>  
>  OBJECT_DECLARE_SIMPLE_TYPE(HostMemoryBackendMemfd, MEMORY_BACKEND_MEMFD)
>  
> @@ -28,6 +30,13 @@ struct HostMemoryBackendMemfd {
>      bool hugetlb;
>      uint64_t hugetlbsize;
>      bool seal;
> +    /*
> +     * NOTE: this differs from HostMemoryBackend's guest_memfd_private,
> +     * which represents a internally private guest-memfd that only backs
> +     * private pages.  Instead, this flag marks the memory backend will
> +     * 100% use the guest-memfd pages in-place.

I think there was previous discussion in v1 or v2 about reserving the
"in-place" naming for "in-place conversion of memory" rather than
mmap-able guest_memfd backends.

> +     */
> +    bool guest_memfd;
>  };
>  
>  static bool
> @@ -47,11 +56,26 @@ memfd_backend_memory_alloc(HostMemoryBackend *backend, 
> Error **errp)
>          goto have_fd;
>      }
>  
> -    fd = qemu_memfd_create(TYPE_MEMORY_BACKEND_MEMFD, backend->size,
> -                           m->hugetlb, m->hugetlbsize, m->seal ?
> -                           F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL : 0,
> -                           errp);
> -    if (fd == -1) {
> +    if (m->guest_memfd) {
> +        /* User choose to use fully shared guest-memfd to back the VM.. */
> +        if (!backend->share) {
> +            error_setg(errp, "Guest-memfd=on must be used with share=on");
> +            return false;
> +        }
> +
> +        /* TODO: add huge page support */

Until that's added, the related options should be disabled. m->seal as
well doesn't seem to be applicable for guest_memfd case.

-Mike

> +        fd = kvm_create_guest_memfd(backend->size,
> +                                    GUEST_MEMFD_FLAG_MMAP |
> +                                    GUEST_MEMFD_FLAG_INIT_SHARED,
> +                                    errp);
> +    } else {
> +        fd = qemu_memfd_create(TYPE_MEMORY_BACKEND_MEMFD, backend->size,
> +                               m->hugetlb, m->hugetlbsize, m->seal ?
> +                               F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL : 0,
> +                               errp);
> +    }
> +
> +    if (fd < 0) {
>          return false;
>      }
>      cpr_save_fd(name, 0, fd);
> @@ -65,6 +89,18 @@ have_fd:
>                                            backend->size, ram_flags, fd, 0, 
> errp);
>  }
>  
> +static bool
> +memfd_backend_get_guest_memfd(Object *o, Error **errp)
> +{
> +    return MEMORY_BACKEND_MEMFD(o)->guest_memfd;
> +}
> +
> +static void
> +memfd_backend_set_guest_memfd(Object *o, bool value, Error **errp)
> +{
> +    MEMORY_BACKEND_MEMFD(o)->guest_memfd = value;
> +}
> +
>  static bool
>  memfd_backend_get_hugetlb(Object *o, Error **errp)
>  {
> @@ -152,6 +188,13 @@ memfd_backend_class_init(ObjectClass *oc, const void 
> *data)
>          object_class_property_set_description(oc, "hugetlbsize",
>                                                "Huge pages size (ex: 2M, 
> 1G)");
>      }
> +
> +    object_class_property_add_bool(oc, "guest-memfd",
> +                                   memfd_backend_get_guest_memfd,
> +                                   memfd_backend_set_guest_memfd);
> +    object_class_property_set_description(oc, "guest-memfd",
> +                                          "Use guest memfd");
> +
>      object_class_property_add_bool(oc, "seal",
>                                     memfd_backend_get_seal,
>                                     memfd_backend_set_seal);
> -- 
> 2.50.1
> 
> 

Reply via email to