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
>
>