qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/9] KVM/hostmem: Support init-shared guest-memfd as VM backends
@ 2025-11-19 17:29 Peter Xu
  2025-11-19 17:29 ` [PATCH v2 1/9] kvm: Decouple memory attribute check from kvm_guest_memfd_supported Peter Xu
                   ` (8 more replies)
  0 siblings, 9 replies; 23+ messages in thread
From: Peter Xu @ 2025-11-19 17:29 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, David Hildenbrand, Alexey Kardashevskiy, peterx,
	Chenyi Qiang, Juraj Marcin, Li Xiaoyao, Fabiano Rosas

NOTE: The test cases of this series needs a dependency small series:

Based-on: <20251117223908.415965-1-peterx@redhat.com>

[PATCH 0/4] tests/migration-test: Introduce mem_type
https://lore.kernel.org/r/20251117223908.415965-1-peterx@redhat.com

v2 changelog:
- Linux-header update patch dropped because a similar version has landed
- Replaced old patch 2 with a similar but better one from Xiaoyao Li
- Target this series for QEMU 11.0 (hence, update in qapi/ "Since:")
- Added a qtest covering guest-memfd boot and basic precopy migration
- Fix checkpatch issues

=========8<===========

This series allows QEMU to consume init-shared guest-memfd to be a common
memory backend. Before this series, guest-memfd was only used in CoCo and
the fds will be created implicitly whenever CoCo environment is detected.
When used in init-shared mode, the guest-memfd will be specified in the
command lines directly just like other types of memory backends.

In the current patchset, I reused the memory-backend-memfd object, rather
than creating a new type of object.  After all, guest-memfd (at least from
userspace POV) works similarly like a memfd, except that it was tailored
for VM's use case.

This approach so far also does not involve gmem bindings to KVM instances,
hence it is not prone to issues when the same chunk of RAM will be attached
to more than one KVM memslots.

Now, instead of using a normal memfd backend using:

  -object memory-backend-memfd,id=ID,size=SIZE,share=on

One can also boot a VM with guest-memfd:

  -object memory-backend-memfd,id=ID,size=SIZE,share=on,guest-memfd=on

The init-shared guest-memfd relies on almost the latest linux, as the
mmap() support just landed v6.18-rc2.  When run it on an older qemu, we'll
see errors like:

  qemu-system-x86_64: KVM does not support guest_memfd

One thing to mention is live migration is by default supported, however
postcopy is still currently not supported.  The postcopy support will have
some kernel dependency work to be merged in Linux first.

Thanks,

Peter Xu (8):
  kvm: Detect guest-memfd flags supported
  memory: Rename RAM_GUEST_MEMFD to RAM_GUEST_MEMFD_PRIVATE
  memory: Rename memory_region_has_guest_memfd() to *_private()
  ramblock: Rename guest_memfd to guest_memfd_private
  hostmem: Rename guest_memfd to guest_memfd_private
  hostmem: Support in-place guest memfd to back a VM
  tests/migration-test: Support guest-memfd init shared mem type
  tests/migration-test: Add a precopy test for guest-memfd

Xiaoyao Li (1):
  kvm: Decouple memory attribute check from kvm_guest_memfd_supported

 qapi/qom.json                         |  6 ++-
 include/system/hostmem.h              |  2 +-
 include/system/kvm.h                  |  1 +
 include/system/memory.h               | 17 +++----
 include/system/ram_addr.h             |  2 +-
 include/system/ramblock.h             |  7 ++-
 tests/qtest/migration/framework.h     |  4 ++
 accel/kvm/kvm-all.c                   | 27 ++++++++---
 accel/stubs/kvm-stub.c                |  5 ++
 backends/hostmem-file.c               |  2 +-
 backends/hostmem-memfd.c              | 68 +++++++++++++++++++++++++--
 backends/hostmem-ram.c                |  2 +-
 backends/hostmem-shm.c                |  2 +-
 backends/hostmem.c                    |  2 +-
 system/memory.c                       |  7 +--
 system/physmem.c                      | 37 +++++++++------
 tests/qtest/migration/framework.c     | 60 +++++++++++++++++++++++
 tests/qtest/migration/precopy-tests.c | 12 +++++
 18 files changed, 219 insertions(+), 44 deletions(-)

-- 
2.50.1



^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH v2 1/9] kvm: Decouple memory attribute check from kvm_guest_memfd_supported
  2025-11-19 17:29 [PATCH v2 0/9] KVM/hostmem: Support init-shared guest-memfd as VM backends Peter Xu
@ 2025-11-19 17:29 ` Peter Xu
  2025-11-19 17:29 ` [PATCH v2 2/9] kvm: Detect guest-memfd flags supported Peter Xu
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 23+ messages in thread
From: Peter Xu @ 2025-11-19 17:29 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, David Hildenbrand, Alexey Kardashevskiy, peterx,
	Chenyi Qiang, Juraj Marcin, Li Xiaoyao, Fabiano Rosas

From: Xiaoyao Li <xiaoyao.li@intel.com>

With the mmap support of guest memfd, KVM allows usersapce to create
guest memfd serving as normal non-private memory for X86 DEFEAULT VM.
However, KVM doesn't support private memory attriute for X86 DEFAULT
VM.

Make kvm_guest_memfd_supported not rely on KVM_MEMORY_ATTRIBUTE_PRIVATE
and check KVM_MEMORY_ATTRIBUTE_PRIVATE separately when the machine
requires guest_memfd to serve as private memory.

This allows QMEU to create guest memfd with mmap to serve as the memory
backend for X86 DEFAULT VM.

Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
---
 include/system/kvm.h   | 1 +
 accel/kvm/kvm-all.c    | 8 ++++++--
 accel/stubs/kvm-stub.c | 5 +++++
 system/physmem.c       | 8 ++++++++
 4 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/include/system/kvm.h b/include/system/kvm.h
index 8f9eecf044..b5811c90f1 100644
--- a/include/system/kvm.h
+++ b/include/system/kvm.h
@@ -561,6 +561,7 @@ int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp);
 
 int kvm_set_memory_attributes_private(hwaddr start, uint64_t size);
 int kvm_set_memory_attributes_shared(hwaddr start, uint64_t size);
+bool kvm_private_memory_attribute_supported(void);
 
 int kvm_convert_memory(hwaddr start, hwaddr size, bool to_private);
 
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index f9254ae654..96c194ce54 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -1501,6 +1501,11 @@ int kvm_set_memory_attributes_shared(hwaddr start, uint64_t size)
     return kvm_set_memory_attributes(start, size, 0);
 }
 
+bool kvm_private_memory_attribute_supported(void)
+{
+    return !!(kvm_supported_memory_attributes & KVM_MEMORY_ATTRIBUTE_PRIVATE);
+}
+
 /* Called with KVMMemoryListener.slots_lock held */
 static void kvm_set_phys_mem(KVMMemoryListener *kml,
                              MemoryRegionSection *section, bool add)
@@ -2781,8 +2786,7 @@ static int kvm_init(AccelState *as, MachineState *ms)
     kvm_supported_memory_attributes = kvm_vm_check_extension(s, KVM_CAP_MEMORY_ATTRIBUTES);
     kvm_guest_memfd_supported =
         kvm_vm_check_extension(s, KVM_CAP_GUEST_MEMFD) &&
-        kvm_vm_check_extension(s, KVM_CAP_USER_MEMORY2) &&
-        (kvm_supported_memory_attributes & KVM_MEMORY_ATTRIBUTE_PRIVATE);
+        kvm_vm_check_extension(s, KVM_CAP_USER_MEMORY2);
     kvm_pre_fault_memory_supported = kvm_vm_check_extension(s, KVM_CAP_PRE_FAULT_MEMORY);
 
     if (s->kernel_irqchip_split == ON_OFF_AUTO_AUTO) {
diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c
index 68cd33ba97..73f04eb589 100644
--- a/accel/stubs/kvm-stub.c
+++ b/accel/stubs/kvm-stub.c
@@ -125,3 +125,8 @@ int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp)
 {
     return -ENOSYS;
 }
+
+bool kvm_private_memory_attribute_supported(void)
+{
+    return false;
+}
diff --git a/system/physmem.c b/system/physmem.c
index c9869e4049..3555d2f6f7 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -2211,6 +2211,14 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
                        object_get_typename(OBJECT(current_machine->cgs)));
             goto out_free;
         }
+
+        if (!kvm_private_memory_attribute_supported()) {
+            error_setg(errp, "cannot set up private guest memory for %s: "
+                       " KVM does not support private memory attribute",
+                       object_get_typename(OBJECT(current_machine->cgs)));
+            goto out_free;
+        }
+
         assert(new_block->guest_memfd < 0);
 
         ret = ram_block_coordinated_discard_require(true);
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 2/9] kvm: Detect guest-memfd flags supported
  2025-11-19 17:29 [PATCH v2 0/9] KVM/hostmem: Support init-shared guest-memfd as VM backends Peter Xu
  2025-11-19 17:29 ` [PATCH v2 1/9] kvm: Decouple memory attribute check from kvm_guest_memfd_supported Peter Xu
@ 2025-11-19 17:29 ` Peter Xu
  2025-12-11  6:56   ` Xiaoyao Li
  2025-12-12  3:10   ` Xiaoyao Li
  2025-11-19 17:29 ` [PATCH v2 3/9] memory: Rename RAM_GUEST_MEMFD to RAM_GUEST_MEMFD_PRIVATE Peter Xu
                   ` (6 subsequent siblings)
  8 siblings, 2 replies; 23+ messages in thread
From: Peter Xu @ 2025-11-19 17:29 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, David Hildenbrand, Alexey Kardashevskiy, peterx,
	Chenyi Qiang, Juraj Marcin, Li Xiaoyao, Fabiano Rosas

Detect supported guest-memfd flags by the current kernel, and reject
creations of guest-memfd using invalid flags.  When the cap isn't
available, then no flag is supported.

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 accel/kvm/kvm-all.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 96c194ce54..f477014126 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -108,6 +108,7 @@ static int kvm_sstep_flags;
 static bool kvm_immediate_exit;
 static uint64_t kvm_supported_memory_attributes;
 static bool kvm_guest_memfd_supported;
+static uint64_t kvm_guest_memfd_flags_supported;
 static hwaddr kvm_max_slot_size = ~0;
 
 static const KVMCapabilityInfo kvm_required_capabilites[] = {
@@ -2787,6 +2788,10 @@ static int kvm_init(AccelState *as, MachineState *ms)
     kvm_guest_memfd_supported =
         kvm_vm_check_extension(s, KVM_CAP_GUEST_MEMFD) &&
         kvm_vm_check_extension(s, KVM_CAP_USER_MEMORY2);
+
+    ret = kvm_vm_check_extension(s, KVM_CAP_GUEST_MEMFD_FLAGS);
+    kvm_guest_memfd_flags_supported = ret > 0 ? ret : 0;
+
     kvm_pre_fault_memory_supported = kvm_vm_check_extension(s, KVM_CAP_PRE_FAULT_MEMORY);
 
     if (s->kernel_irqchip_split == ON_OFF_AUTO_AUTO) {
@@ -4492,6 +4497,12 @@ int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp)
         return -1;
     }
 
+    if (flags & ~kvm_guest_memfd_flags_supported) {
+        error_setg(errp, "KVM does not support guest-memfd flag: 0x%"PRIx64,
+                   flags & ~kvm_guest_memfd_flags_supported);
+        return -1;
+    }
+
     fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_GUEST_MEMFD, &guest_memfd);
     if (fd < 0) {
         error_setg_errno(errp, errno, "Error creating KVM guest_memfd");
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 3/9] memory: Rename RAM_GUEST_MEMFD to RAM_GUEST_MEMFD_PRIVATE
  2025-11-19 17:29 [PATCH v2 0/9] KVM/hostmem: Support init-shared guest-memfd as VM backends Peter Xu
  2025-11-19 17:29 ` [PATCH v2 1/9] kvm: Decouple memory attribute check from kvm_guest_memfd_supported Peter Xu
  2025-11-19 17:29 ` [PATCH v2 2/9] kvm: Detect guest-memfd flags supported Peter Xu
@ 2025-11-19 17:29 ` Peter Xu
  2025-12-11  7:05   ` Xiaoyao Li
  2025-11-19 17:29 ` [PATCH v2 4/9] memory: Rename memory_region_has_guest_memfd() to *_private() Peter Xu
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Peter Xu @ 2025-11-19 17:29 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, David Hildenbrand, Alexey Kardashevskiy, peterx,
	Chenyi Qiang, Juraj Marcin, Li Xiaoyao, Fabiano Rosas

This name is too generic, and can conflict with in-place guest-memfd
support.  Add a _PRIVATE suffix to show what it really means: it is always
silently using an internal guest-memfd to back a shared host backend,
rather than used in-place.

This paves way for in-place guest-memfd, which means we can have a ramblock
that allocates pages completely from guest-memfd (private or shared).

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 include/system/memory.h   | 8 ++++----
 include/system/ram_addr.h | 2 +-
 backends/hostmem-file.c   | 2 +-
 backends/hostmem-memfd.c  | 2 +-
 backends/hostmem-ram.c    | 2 +-
 backends/hostmem-shm.c    | 2 +-
 system/memory.c           | 3 ++-
 system/physmem.c          | 8 ++++----
 8 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/include/system/memory.h b/include/system/memory.h
index 3bd5ffa5e0..2c1a5e06b4 100644
--- a/include/system/memory.h
+++ b/include/system/memory.h
@@ -263,7 +263,7 @@ typedef struct IOMMUTLBEvent {
 #define RAM_READONLY_FD (1 << 11)
 
 /* RAM can be private that has kvm guest memfd backend */
-#define RAM_GUEST_MEMFD   (1 << 12)
+#define RAM_GUEST_MEMFD_PRIVATE   (1 << 12)
 
 /*
  * In RAMBlock creation functions, if MAP_SHARED is 0 in the flags parameter,
@@ -1401,7 +1401,7 @@ bool memory_region_init_ram_nomigrate(MemoryRegion *mr,
  *        must be unique within any device
  * @size: size of the region.
  * @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_NORESERVE,
- *             RAM_GUEST_MEMFD.
+ *             RAM_GUEST_MEMFD_PRIVATE.
  * @errp: pointer to Error*, to store an error if it happens.
  *
  * Note that this function does not do anything to cause the data in the
@@ -1463,7 +1463,7 @@ bool memory_region_init_resizeable_ram(MemoryRegion *mr,
  *         (getpagesize()) will be used.
  * @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_PMEM,
  *             RAM_NORESERVE, RAM_PROTECTED, RAM_NAMED_FILE, RAM_READONLY,
- *             RAM_READONLY_FD, RAM_GUEST_MEMFD
+ *             RAM_READONLY_FD, RAM_GUEST_MEMFD_PRIVATE
  * @path: the path in which to allocate the RAM.
  * @offset: offset within the file referenced by path
  * @errp: pointer to Error*, to store an error if it happens.
@@ -1493,7 +1493,7 @@ bool memory_region_init_ram_from_file(MemoryRegion *mr,
  * @size: size of the region.
  * @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_PMEM,
  *             RAM_NORESERVE, RAM_PROTECTED, RAM_NAMED_FILE, RAM_READONLY,
- *             RAM_READONLY_FD, RAM_GUEST_MEMFD
+ *             RAM_READONLY_FD, RAM_GUEST_MEMFD_PRIVATE
  * @fd: the fd to mmap.
  * @offset: offset within the file referenced by fd
  * @errp: pointer to Error*, to store an error if it happens.
diff --git a/include/system/ram_addr.h b/include/system/ram_addr.h
index 683485980c..930d3824d7 100644
--- a/include/system/ram_addr.h
+++ b/include/system/ram_addr.h
@@ -92,7 +92,7 @@ static inline unsigned long int ramblock_recv_bitmap_offset(void *host_addr,
  *  @resized: callback after calls to qemu_ram_resize
  *  @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_PMEM,
  *              RAM_NORESERVE, RAM_PROTECTED, RAM_NAMED_FILE, RAM_READONLY,
- *              RAM_READONLY_FD, RAM_GUEST_MEMFD
+ *              RAM_READONLY_FD, RAM_GUEST_MEMFD_PRIVATE
  *  @mem_path or @fd: specify the backing file or device
  *  @offset: Offset into target file
  *  @grow: extend file if necessary (but an empty file is always extended).
diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c
index 8e3219c061..1f20cd8fd6 100644
--- a/backends/hostmem-file.c
+++ b/backends/hostmem-file.c
@@ -86,7 +86,7 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
     ram_flags |= fb->readonly ? RAM_READONLY_FD : 0;
     ram_flags |= fb->rom == ON_OFF_AUTO_ON ? RAM_READONLY : 0;
     ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
-    ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD : 0;
+    ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD_PRIVATE : 0;
     ram_flags |= fb->is_pmem ? RAM_PMEM : 0;
     ram_flags |= RAM_NAMED_FILE;
     return memory_region_init_ram_from_file(&backend->mr, OBJECT(backend), name,
diff --git a/backends/hostmem-memfd.c b/backends/hostmem-memfd.c
index 923239f9cf..3f3e485709 100644
--- a/backends/hostmem-memfd.c
+++ b/backends/hostmem-memfd.c
@@ -60,7 +60,7 @@ have_fd:
     backend->aligned = true;
     ram_flags = backend->share ? RAM_SHARED : RAM_PRIVATE;
     ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
-    ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD : 0;
+    ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD_PRIVATE : 0;
     return memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend), name,
                                           backend->size, ram_flags, fd, 0, errp);
 }
diff --git a/backends/hostmem-ram.c b/backends/hostmem-ram.c
index 062b1abb11..96ad29112d 100644
--- a/backends/hostmem-ram.c
+++ b/backends/hostmem-ram.c
@@ -30,7 +30,7 @@ ram_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
     name = host_memory_backend_get_name(backend);
     ram_flags = backend->share ? RAM_SHARED : RAM_PRIVATE;
     ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
-    ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD : 0;
+    ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD_PRIVATE : 0;
     return memory_region_init_ram_flags_nomigrate(&backend->mr, OBJECT(backend),
                                                   name, backend->size,
                                                   ram_flags, errp);
diff --git a/backends/hostmem-shm.c b/backends/hostmem-shm.c
index 806e2670e0..e86fb2e0aa 100644
--- a/backends/hostmem-shm.c
+++ b/backends/hostmem-shm.c
@@ -54,7 +54,7 @@ have_fd:
     /* Let's do the same as memory-backend-ram,share=on would do. */
     ram_flags = RAM_SHARED;
     ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
-    ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD : 0;
+    ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD_PRIVATE : 0;
 
     return memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend),
                                               backend_name, backend->size,
diff --git a/system/memory.c b/system/memory.c
index 8b84661ae3..81b7bff42d 100644
--- a/system/memory.c
+++ b/system/memory.c
@@ -3755,7 +3755,8 @@ bool memory_region_init_ram_guest_memfd(MemoryRegion *mr,
     DeviceState *owner_dev;
 
     if (!memory_region_init_ram_flags_nomigrate(mr, owner, name, size,
-                                                RAM_GUEST_MEMFD, errp)) {
+                                                RAM_GUEST_MEMFD_PRIVATE,
+                                                errp)) {
         return false;
     }
     /* This will assert if owner is neither NULL nor a DeviceState.
diff --git a/system/physmem.c b/system/physmem.c
index 3555d2f6f7..25c800c9d3 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -2203,7 +2203,7 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
         }
     }
 
-    if (new_block->flags & RAM_GUEST_MEMFD) {
+    if (new_block->flags & RAM_GUEST_MEMFD_PRIVATE) {
         int ret;
 
         if (!kvm_enabled()) {
@@ -2341,7 +2341,7 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, ram_addr_t max_size,
     /* Just support these ram flags by now. */
     assert((ram_flags & ~(RAM_SHARED | RAM_PMEM | RAM_NORESERVE |
                           RAM_PROTECTED | RAM_NAMED_FILE | RAM_READONLY |
-                          RAM_READONLY_FD | RAM_GUEST_MEMFD |
+                          RAM_READONLY_FD | RAM_GUEST_MEMFD_PRIVATE |
                           RAM_RESIZEABLE)) == 0);
     assert(max_size >= size);
 
@@ -2498,7 +2498,7 @@ RAMBlock *qemu_ram_alloc_internal(ram_addr_t size, ram_addr_t max_size,
     ram_flags &= ~RAM_PRIVATE;
 
     assert((ram_flags & ~(RAM_SHARED | RAM_RESIZEABLE | RAM_PREALLOC |
-                          RAM_NORESERVE | RAM_GUEST_MEMFD)) == 0);
+                          RAM_NORESERVE | RAM_GUEST_MEMFD_PRIVATE)) == 0);
     assert(!host ^ (ram_flags & RAM_PREALLOC));
     assert(max_size >= size);
 
@@ -2581,7 +2581,7 @@ RAMBlock *qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
 RAMBlock *qemu_ram_alloc(ram_addr_t size, uint32_t ram_flags,
                          MemoryRegion *mr, Error **errp)
 {
-    assert((ram_flags & ~(RAM_SHARED | RAM_NORESERVE | RAM_GUEST_MEMFD |
+    assert((ram_flags & ~(RAM_SHARED | RAM_NORESERVE | RAM_GUEST_MEMFD_PRIVATE |
                           RAM_PRIVATE)) == 0);
     return qemu_ram_alloc_internal(size, size, NULL, NULL, ram_flags, mr, errp);
 }
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 4/9] memory: Rename memory_region_has_guest_memfd() to *_private()
  2025-11-19 17:29 [PATCH v2 0/9] KVM/hostmem: Support init-shared guest-memfd as VM backends Peter Xu
                   ` (2 preceding siblings ...)
  2025-11-19 17:29 ` [PATCH v2 3/9] memory: Rename RAM_GUEST_MEMFD to RAM_GUEST_MEMFD_PRIVATE Peter Xu
@ 2025-11-19 17:29 ` Peter Xu
  2025-12-11  7:10   ` Xiaoyao Li
  2025-11-19 17:29 ` [PATCH v2 5/9] ramblock: Rename guest_memfd to guest_memfd_private Peter Xu
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Peter Xu @ 2025-11-19 17:29 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, David Hildenbrand, Alexey Kardashevskiy, peterx,
	Chenyi Qiang, Juraj Marcin, Li Xiaoyao, Fabiano Rosas

Rename the function with "_private" suffix, to show that it returns true
only if it has an internal guest-memfd to back private pages (rather than
in-place guest-memfd).

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 include/system/memory.h | 6 +++---
 accel/kvm/kvm-all.c     | 6 +++---
 system/memory.c         | 2 +-
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/include/system/memory.h b/include/system/memory.h
index 2c1a5e06b4..4428701a9f 100644
--- a/include/system/memory.h
+++ b/include/system/memory.h
@@ -1823,14 +1823,14 @@ static inline bool memory_region_is_romd(MemoryRegion *mr)
 bool memory_region_is_protected(MemoryRegion *mr);
 
 /**
- * memory_region_has_guest_memfd: check whether a memory region has guest_memfd
- *     associated
+ * memory_region_has_guest_memfd_private: check whether a memory region has
+ *     guest_memfd associated
  *
  * Returns %true if a memory region's ram_block has valid guest_memfd assigned.
  *
  * @mr: the memory region being queried
  */
-bool memory_region_has_guest_memfd(MemoryRegion *mr);
+bool memory_region_has_guest_memfd_private(MemoryRegion *mr);
 
 /**
  * memory_region_get_iommu: check whether a memory region is an iommu
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index f477014126..320315f50c 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -666,7 +666,7 @@ static int kvm_mem_flags(MemoryRegion *mr)
     if (readonly && kvm_readonly_mem_allowed) {
         flags |= KVM_MEM_READONLY;
     }
-    if (memory_region_has_guest_memfd(mr)) {
+    if (memory_region_has_guest_memfd_private(mr)) {
         assert(kvm_guest_memfd_supported);
         flags |= KVM_MEM_GUEST_MEMFD;
     }
@@ -1615,7 +1615,7 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
             abort();
         }
 
-        if (memory_region_has_guest_memfd(mr)) {
+        if (memory_region_has_guest_memfd_private(mr)) {
             err = kvm_set_memory_attributes_private(start_addr, slot_size);
             if (err) {
                 error_report("%s: failed to set memory attribute private: %s",
@@ -3101,7 +3101,7 @@ int kvm_convert_memory(hwaddr start, hwaddr size, bool to_private)
         return ret;
     }
 
-    if (!memory_region_has_guest_memfd(mr)) {
+    if (!memory_region_has_guest_memfd_private(mr)) {
         /*
          * Because vMMIO region must be shared, guest TD may convert vMMIO
          * region to shared explicitly.  Don't complain such case.  See
diff --git a/system/memory.c b/system/memory.c
index 81b7bff42d..15964160ee 100644
--- a/system/memory.c
+++ b/system/memory.c
@@ -1897,7 +1897,7 @@ bool memory_region_is_protected(MemoryRegion *mr)
     return mr->ram && (mr->ram_block->flags & RAM_PROTECTED);
 }
 
-bool memory_region_has_guest_memfd(MemoryRegion *mr)
+bool memory_region_has_guest_memfd_private(MemoryRegion *mr)
 {
     return mr->ram_block && mr->ram_block->guest_memfd >= 0;
 }
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 5/9] ramblock: Rename guest_memfd to guest_memfd_private
  2025-11-19 17:29 [PATCH v2 0/9] KVM/hostmem: Support init-shared guest-memfd as VM backends Peter Xu
                   ` (3 preceding siblings ...)
  2025-11-19 17:29 ` [PATCH v2 4/9] memory: Rename memory_region_has_guest_memfd() to *_private() Peter Xu
@ 2025-11-19 17:29 ` Peter Xu
  2025-12-11  7:10   ` Xiaoyao Li
  2025-11-19 17:29 ` [PATCH v2 6/9] hostmem: " Peter Xu
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Peter Xu @ 2025-11-19 17:29 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, David Hildenbrand, Alexey Kardashevskiy, peterx,
	Chenyi Qiang, Juraj Marcin, Li Xiaoyao, Fabiano Rosas

Rename the field to reflect the fact that the guest_memfd in this case only
backs private portion of the ramblock rather than all of it.

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 include/system/memory.h   |  3 ++-
 include/system/ramblock.h |  7 ++++++-
 accel/kvm/kvm-all.c       |  2 +-
 system/memory.c           |  2 +-
 system/physmem.c          | 21 +++++++++++----------
 5 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/include/system/memory.h b/include/system/memory.h
index 4428701a9f..0aca241360 100644
--- a/include/system/memory.h
+++ b/include/system/memory.h
@@ -1826,7 +1826,8 @@ bool memory_region_is_protected(MemoryRegion *mr);
  * memory_region_has_guest_memfd_private: check whether a memory region has
  *     guest_memfd associated
  *
- * Returns %true if a memory region's ram_block has valid guest_memfd assigned.
+ * Returns %true if a memory region's ram_block has guest_memfd_private
+ * assigned.
  *
  * @mr: the memory region being queried
  */
diff --git a/include/system/ramblock.h b/include/system/ramblock.h
index 76694fe1b5..9ecf7f970c 100644
--- a/include/system/ramblock.h
+++ b/include/system/ramblock.h
@@ -40,7 +40,12 @@ struct RAMBlock {
     Error *cpr_blocker;
     int fd;
     uint64_t fd_offset;
-    int guest_memfd;
+    /*
+     * When RAM_GUEST_MEMFD_PRIVATE flag is set, this ramblock can have
+     * private pages backed by guest_memfd_private specified, while shared
+     * pages are backed by the ramblock on its own.
+     */
+    int guest_memfd_private;
     RamBlockAttributes *attributes;
     size_t page_size;
     /* dirty bitmap used during migration */
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 320315f50c..5942e17f7e 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -1603,7 +1603,7 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
         mem->ram_start_offset = ram_start_offset;
         mem->ram = ram;
         mem->flags = kvm_mem_flags(mr);
-        mem->guest_memfd = mr->ram_block->guest_memfd;
+        mem->guest_memfd = mr->ram_block->guest_memfd_private;
         mem->guest_memfd_offset = mem->guest_memfd >= 0 ?
                                   (uint8_t*)ram - mr->ram_block->host : 0;
 
diff --git a/system/memory.c b/system/memory.c
index 15964160ee..d70968c966 100644
--- a/system/memory.c
+++ b/system/memory.c
@@ -1899,7 +1899,7 @@ bool memory_region_is_protected(MemoryRegion *mr)
 
 bool memory_region_has_guest_memfd_private(MemoryRegion *mr)
 {
-    return mr->ram_block && mr->ram_block->guest_memfd >= 0;
+    return mr->ram_block && mr->ram_block->guest_memfd_private >= 0;
 }
 
 uint8_t memory_region_get_dirty_log_mask(MemoryRegion *mr)
diff --git a/system/physmem.c b/system/physmem.c
index 25c800c9d3..d30fd690d1 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -2219,7 +2219,7 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
             goto out_free;
         }
 
-        assert(new_block->guest_memfd < 0);
+        assert(new_block->guest_memfd_private < 0);
 
         ret = ram_block_coordinated_discard_require(true);
         if (ret < 0) {
@@ -2229,9 +2229,9 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
             goto out_free;
         }
 
-        new_block->guest_memfd = kvm_create_guest_memfd(new_block->max_length,
-                                                        0, errp);
-        if (new_block->guest_memfd < 0) {
+        new_block->guest_memfd_private =
+            kvm_create_guest_memfd(new_block->max_length, 0, errp);
+        if (new_block->guest_memfd_private < 0) {
             qemu_mutex_unlock_ramlist();
             goto out_free;
         }
@@ -2248,7 +2248,7 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
         new_block->attributes = ram_block_attributes_create(new_block);
         if (!new_block->attributes) {
             error_setg(errp, "Failed to create ram block attribute");
-            close(new_block->guest_memfd);
+            close(new_block->guest_memfd_private);
             ram_block_coordinated_discard_require(false);
             qemu_mutex_unlock_ramlist();
             goto out_free;
@@ -2385,7 +2385,7 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, ram_addr_t max_size,
     new_block->max_length = max_size;
     new_block->resized = resized;
     new_block->flags = ram_flags;
-    new_block->guest_memfd = -1;
+    new_block->guest_memfd_private = -1;
     new_block->host = file_ram_alloc(new_block, max_size, fd,
                                      file_size < offset + max_size,
                                      offset, errp);
@@ -2558,7 +2558,7 @@ RAMBlock *qemu_ram_alloc_internal(ram_addr_t size, ram_addr_t max_size,
     new_block->used_length = size;
     new_block->max_length = max_size;
     new_block->fd = -1;
-    new_block->guest_memfd = -1;
+    new_block->guest_memfd_private = -1;
     new_block->page_size = qemu_real_host_page_size();
     new_block->host = host;
     new_block->flags = ram_flags;
@@ -2609,9 +2609,9 @@ static void reclaim_ramblock(RAMBlock *block)
         qemu_anon_ram_free(block->host, block->max_length);
     }
 
-    if (block->guest_memfd >= 0) {
+    if (block->guest_memfd_private >= 0) {
         ram_block_attributes_destroy(block->attributes);
-        close(block->guest_memfd);
+        close(block->guest_memfd_private);
         ram_block_coordinated_discard_require(false);
     }
 
@@ -4222,7 +4222,8 @@ int ram_block_discard_guest_memfd_range(RAMBlock *rb, uint64_t offset,
 
 #ifdef CONFIG_FALLOCATE_PUNCH_HOLE
     /* ignore fd_offset with guest_memfd */
-    ret = fallocate(rb->guest_memfd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
+    ret = fallocate(rb->guest_memfd_private,
+                    FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
                     offset, length);
 
     if (ret) {
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 6/9] hostmem: Rename guest_memfd to guest_memfd_private
  2025-11-19 17:29 [PATCH v2 0/9] KVM/hostmem: Support init-shared guest-memfd as VM backends Peter Xu
                   ` (4 preceding siblings ...)
  2025-11-19 17:29 ` [PATCH v2 5/9] ramblock: Rename guest_memfd to guest_memfd_private Peter Xu
@ 2025-11-19 17:29 ` Peter Xu
  2025-12-11  7:16   ` Xiaoyao Li
  2025-11-19 17:29 ` [PATCH v2 7/9] hostmem: Support in-place guest memfd to back a VM Peter Xu
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Peter Xu @ 2025-11-19 17:29 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, David Hildenbrand, Alexey Kardashevskiy, peterx,
	Chenyi Qiang, Juraj Marcin, Li Xiaoyao, Fabiano Rosas

Rename the HostMemoryBackend.guest_memfd field to reflect what it really
means, on whether it needs guest_memfd to back its private portion of
mapping.  This will help on clearance when we introduce in-place
guest_memfd for hostmem.

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 include/system/hostmem.h | 2 +-
 backends/hostmem-file.c  | 2 +-
 backends/hostmem-memfd.c | 2 +-
 backends/hostmem-ram.c   | 2 +-
 backends/hostmem-shm.c   | 2 +-
 backends/hostmem.c       | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/include/system/hostmem.h b/include/system/hostmem.h
index 88fa791ac7..dcbf81aeae 100644
--- a/include/system/hostmem.h
+++ b/include/system/hostmem.h
@@ -76,7 +76,7 @@ struct HostMemoryBackend {
     uint64_t size;
     bool merge, dump, use_canonical_path;
     bool prealloc, is_mapped, share, reserve;
-    bool guest_memfd, aligned;
+    bool guest_memfd_private, aligned;
     uint32_t prealloc_threads;
     ThreadContext *prealloc_context;
     DECLARE_BITMAP(host_nodes, MAX_NODES + 1);
diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c
index 1f20cd8fd6..0e4cfd6dc6 100644
--- a/backends/hostmem-file.c
+++ b/backends/hostmem-file.c
@@ -86,7 +86,7 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
     ram_flags |= fb->readonly ? RAM_READONLY_FD : 0;
     ram_flags |= fb->rom == ON_OFF_AUTO_ON ? RAM_READONLY : 0;
     ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
-    ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD_PRIVATE : 0;
+    ram_flags |= backend->guest_memfd_private ? RAM_GUEST_MEMFD_PRIVATE : 0;
     ram_flags |= fb->is_pmem ? RAM_PMEM : 0;
     ram_flags |= RAM_NAMED_FILE;
     return memory_region_init_ram_from_file(&backend->mr, OBJECT(backend), name,
diff --git a/backends/hostmem-memfd.c b/backends/hostmem-memfd.c
index 3f3e485709..ea93f034e4 100644
--- a/backends/hostmem-memfd.c
+++ b/backends/hostmem-memfd.c
@@ -60,7 +60,7 @@ have_fd:
     backend->aligned = true;
     ram_flags = backend->share ? RAM_SHARED : RAM_PRIVATE;
     ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
-    ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD_PRIVATE : 0;
+    ram_flags |= backend->guest_memfd_private ? RAM_GUEST_MEMFD_PRIVATE : 0;
     return memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend), name,
                                           backend->size, ram_flags, fd, 0, errp);
 }
diff --git a/backends/hostmem-ram.c b/backends/hostmem-ram.c
index 96ad29112d..6a507fad77 100644
--- a/backends/hostmem-ram.c
+++ b/backends/hostmem-ram.c
@@ -30,7 +30,7 @@ ram_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
     name = host_memory_backend_get_name(backend);
     ram_flags = backend->share ? RAM_SHARED : RAM_PRIVATE;
     ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
-    ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD_PRIVATE : 0;
+    ram_flags |= backend->guest_memfd_private ? RAM_GUEST_MEMFD_PRIVATE : 0;
     return memory_region_init_ram_flags_nomigrate(&backend->mr, OBJECT(backend),
                                                   name, backend->size,
                                                   ram_flags, errp);
diff --git a/backends/hostmem-shm.c b/backends/hostmem-shm.c
index e86fb2e0aa..4766db6aad 100644
--- a/backends/hostmem-shm.c
+++ b/backends/hostmem-shm.c
@@ -54,7 +54,7 @@ have_fd:
     /* Let's do the same as memory-backend-ram,share=on would do. */
     ram_flags = RAM_SHARED;
     ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
-    ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD_PRIVATE : 0;
+    ram_flags |= backend->guest_memfd_private ? RAM_GUEST_MEMFD_PRIVATE : 0;
 
     return memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend),
                                               backend_name, backend->size,
diff --git a/backends/hostmem.c b/backends/hostmem.c
index 35734d6f4d..70450733db 100644
--- a/backends/hostmem.c
+++ b/backends/hostmem.c
@@ -288,7 +288,7 @@ static void host_memory_backend_init(Object *obj)
     /* TODO: convert access to globals to compat properties */
     backend->merge = machine_mem_merge(machine);
     backend->dump = machine_dump_guest_core(machine);
-    backend->guest_memfd = machine_require_guest_memfd(machine);
+    backend->guest_memfd_private = machine_require_guest_memfd(machine);
     backend->reserve = true;
     backend->prealloc_threads = machine->smp.cpus;
 }
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 7/9] hostmem: Support in-place guest memfd to back a VM
  2025-11-19 17:29 [PATCH v2 0/9] KVM/hostmem: Support init-shared guest-memfd as VM backends Peter Xu
                   ` (5 preceding siblings ...)
  2025-11-19 17:29 ` [PATCH v2 6/9] hostmem: " Peter Xu
@ 2025-11-19 17:29 ` Peter Xu
  2025-12-11  7:41   ` Xiaoyao Li
  2025-11-19 17:29 ` [PATCH v2 8/9] tests/migration-test: Support guest-memfd init shared mem type Peter Xu
  2025-11-19 17:29 ` [PATCH v2 9/9] tests/migration-test: Add a precopy test for guest-memfd Peter Xu
  8 siblings, 1 reply; 23+ messages in thread
From: Peter Xu @ 2025-11-19 17:29 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, David Hildenbrand, Alexey Kardashevskiy, peterx,
	Chenyi Qiang, Juraj Marcin, Li Xiaoyao, Fabiano Rosas

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 in-place.  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, in place), rather than
having another backend supporting the pages converted to shared.

To use the in-place 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 in-place guest_memfd.

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 qapi/qom.json            |  6 +++-
 backends/hostmem-memfd.c | 66 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 67 insertions(+), 5 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..1fa16c1e1d 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.
+     */
+    bool guest_memfd;
 };
 
 static bool
@@ -47,10 +56,40 @@ 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 (m->guest_memfd) {
+        /* User choose to use in-place guest-memfd to back the VM.. */
+        if (!backend->share) {
+            error_setg(errp, "In-place guest-memfd must be used with share=on");
+            return false;
+        }
+
+        /*
+         * This is the request to have a guest-memfd to back private pages.
+         * In-place guest-memfd doesn't work like that.  Disable it for now
+         * to make it simple, so that each memory backend can only have
+         * guest-memfd either as private, or fully shared.
+         */
+        if (backend->guest_memfd_private) {
+            error_setg(errp, "In-place guest-memfd cannot be used with another "
+                       "private guest-memfd");
+            return false;
+        }
+
+        /* TODO: add huge page support */
+        fd = kvm_create_guest_memfd(backend->size,
+                                    GUEST_MEMFD_FLAG_MMAP |
+                                    GUEST_MEMFD_FLAG_INIT_SHARED,
+                                    errp);
+        if (fd < 0) {
+            return false;
+        }
+    } 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 == -1) {
         return false;
     }
@@ -65,6 +104,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 +203,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



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 8/9] tests/migration-test: Support guest-memfd init shared mem type
  2025-11-19 17:29 [PATCH v2 0/9] KVM/hostmem: Support init-shared guest-memfd as VM backends Peter Xu
                   ` (6 preceding siblings ...)
  2025-11-19 17:29 ` [PATCH v2 7/9] hostmem: Support in-place guest memfd to back a VM Peter Xu
@ 2025-11-19 17:29 ` Peter Xu
  2025-11-19 17:29 ` [PATCH v2 9/9] tests/migration-test: Add a precopy test for guest-memfd Peter Xu
  8 siblings, 0 replies; 23+ messages in thread
From: Peter Xu @ 2025-11-19 17:29 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, David Hildenbrand, Alexey Kardashevskiy, peterx,
	Chenyi Qiang, Juraj Marcin, Li Xiaoyao, Fabiano Rosas

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 <peterx@redhat.com>
---
 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 81eae09c92..73536c8f29 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"
@@ -279,6 +283,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;
     case MEM_TYPE_ANON:
         backend = g_strdup("-object memory-backend-ram");
         share = false;
@@ -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)
+{
+    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) {
+        *reason = "KVM doesn't support KVM_CAP_GUEST_MEMFD_FLAGS";
+        goto out;
+    }
+
+    if (!(ret & GUEST_MEMFD_FLAG_INIT_SHARED)) {
+        *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;
     }
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 9/9] tests/migration-test: Add a precopy test for guest-memfd
  2025-11-19 17:29 [PATCH v2 0/9] KVM/hostmem: Support init-shared guest-memfd as VM backends Peter Xu
                   ` (7 preceding siblings ...)
  2025-11-19 17:29 ` [PATCH v2 8/9] tests/migration-test: Support guest-memfd init shared mem type Peter Xu
@ 2025-11-19 17:29 ` Peter Xu
  8 siblings, 0 replies; 23+ messages in thread
From: Peter Xu @ 2025-11-19 17:29 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, David Hildenbrand, Alexey Kardashevskiy, peterx,
	Chenyi Qiang, Juraj Marcin, Li Xiaoyao, Fabiano Rosas

Add a plain tcp test for guest-memfd.  Note that the test will be
automatically skipped whenever not supported (e.g. qemu compiled without
KVM, or host kernel doesn't support kvm, or old kernels, etc.).

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 tests/qtest/migration/precopy-tests.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/tests/qtest/migration/precopy-tests.c b/tests/qtest/migration/precopy-tests.c
index 57ca623de5..88d2627efd 100644
--- a/tests/qtest/migration/precopy-tests.c
+++ b/tests/qtest/migration/precopy-tests.c
@@ -215,6 +215,16 @@ static void test_precopy_tcp_plain(void)
     test_precopy_common(&args);
 }
 
+static void test_precopy_tcp_plain_gmemfd(void)
+{
+    MigrateCommon args = {
+        .listen_uri = "tcp:127.0.0.1:0",
+        .start.mem_type = MEM_TYPE_GUEST_MEMFD,
+    };
+
+    test_precopy_common(&args);
+}
+
 static void test_precopy_tcp_switchover_ack(void)
 {
     MigrateCommon args = {
@@ -1276,6 +1286,8 @@ void migration_test_add_precopy(MigrationTestEnv *env)
         return;
     }
 
+    migration_test_add("/migration/precopy/tcp/plain/guest-memfd",
+                       test_precopy_tcp_plain_gmemfd);
     migration_test_add("/migration/precopy/tcp/plain/switchover-ack",
                        test_precopy_tcp_switchover_ack);
 
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 2/9] kvm: Detect guest-memfd flags supported
  2025-11-19 17:29 ` [PATCH v2 2/9] kvm: Detect guest-memfd flags supported Peter Xu
@ 2025-12-11  6:56   ` Xiaoyao Li
  2025-12-12  3:10   ` Xiaoyao Li
  1 sibling, 0 replies; 23+ messages in thread
From: Xiaoyao Li @ 2025-12-11  6:56 UTC (permalink / raw)
  To: Peter Xu, qemu-devel
  Cc: Paolo Bonzini, David Hildenbrand, Alexey Kardashevskiy,
	Chenyi Qiang, Juraj Marcin, Fabiano Rosas

On 11/20/2025 1:29 AM, Peter Xu wrote:
> Detect supported guest-memfd flags by the current kernel, and reject
> creations of guest-memfd using invalid flags.  When the cap isn't
> available, then no flag is supported.
> 
> Signed-off-by: Peter Xu <peterx@redhat.com>

Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>

> ---
>   accel/kvm/kvm-all.c | 11 +++++++++++
>   1 file changed, 11 insertions(+)
> 
> diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
> index 96c194ce54..f477014126 100644
> --- a/accel/kvm/kvm-all.c
> +++ b/accel/kvm/kvm-all.c
> @@ -108,6 +108,7 @@ static int kvm_sstep_flags;
>   static bool kvm_immediate_exit;
>   static uint64_t kvm_supported_memory_attributes;
>   static bool kvm_guest_memfd_supported;
> +static uint64_t kvm_guest_memfd_flags_supported;
>   static hwaddr kvm_max_slot_size = ~0;
>   
>   static const KVMCapabilityInfo kvm_required_capabilites[] = {
> @@ -2787,6 +2788,10 @@ static int kvm_init(AccelState *as, MachineState *ms)
>       kvm_guest_memfd_supported =
>           kvm_vm_check_extension(s, KVM_CAP_GUEST_MEMFD) &&
>           kvm_vm_check_extension(s, KVM_CAP_USER_MEMORY2);
> +
> +    ret = kvm_vm_check_extension(s, KVM_CAP_GUEST_MEMFD_FLAGS);
> +    kvm_guest_memfd_flags_supported = ret > 0 ? ret : 0;
> +
>       kvm_pre_fault_memory_supported = kvm_vm_check_extension(s, KVM_CAP_PRE_FAULT_MEMORY);
>   
>       if (s->kernel_irqchip_split == ON_OFF_AUTO_AUTO) {
> @@ -4492,6 +4497,12 @@ int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp)
>           return -1;
>       }
>   
> +    if (flags & ~kvm_guest_memfd_flags_supported) {
> +        error_setg(errp, "KVM does not support guest-memfd flag: 0x%"PRIx64,
> +                   flags & ~kvm_guest_memfd_flags_supported);
> +        return -1;
> +    }
> +
>       fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_GUEST_MEMFD, &guest_memfd);
>       if (fd < 0) {
>           error_setg_errno(errp, errno, "Error creating KVM guest_memfd");



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 3/9] memory: Rename RAM_GUEST_MEMFD to RAM_GUEST_MEMFD_PRIVATE
  2025-11-19 17:29 ` [PATCH v2 3/9] memory: Rename RAM_GUEST_MEMFD to RAM_GUEST_MEMFD_PRIVATE Peter Xu
@ 2025-12-11  7:05   ` Xiaoyao Li
  0 siblings, 0 replies; 23+ messages in thread
From: Xiaoyao Li @ 2025-12-11  7:05 UTC (permalink / raw)
  To: Peter Xu, qemu-devel
  Cc: Paolo Bonzini, David Hildenbrand, Alexey Kardashevskiy,
	Chenyi Qiang, Juraj Marcin, Fabiano Rosas

On 11/20/2025 1:29 AM, Peter Xu wrote:
> This name is too generic, and can conflict with in-place guest-memfd
> support.  Add a _PRIVATE suffix to show what it really means: it is always
> silently using an internal guest-memfd to back a shared host backend,
> rather than used in-place.
> 
> This paves way for in-place guest-memfd, which means we can have a ramblock
> that allocates pages completely from guest-memfd (private or shared).
> 
> Signed-off-by: Peter Xu <peterx@redhat.com>

Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 4/9] memory: Rename memory_region_has_guest_memfd() to *_private()
  2025-11-19 17:29 ` [PATCH v2 4/9] memory: Rename memory_region_has_guest_memfd() to *_private() Peter Xu
@ 2025-12-11  7:10   ` Xiaoyao Li
  2025-12-11 15:45     ` Peter Xu
  0 siblings, 1 reply; 23+ messages in thread
From: Xiaoyao Li @ 2025-12-11  7:10 UTC (permalink / raw)
  To: Peter Xu, qemu-devel
  Cc: Paolo Bonzini, David Hildenbrand, Alexey Kardashevskiy,
	Chenyi Qiang, Juraj Marcin, Fabiano Rosas

On 11/20/2025 1:29 AM, Peter Xu wrote:
> Rename the function with "_private" suffix, to show that it returns true
> only if it has an internal guest-memfd to back private pages (rather than
> in-place guest-memfd).
> 
> Signed-off-by: Peter Xu <peterx@redhat.com>
> ---
>   include/system/memory.h | 6 +++---
>   accel/kvm/kvm-all.c     | 6 +++---
>   system/memory.c         | 2 +-
>   3 files changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/include/system/memory.h b/include/system/memory.h
> index 2c1a5e06b4..4428701a9f 100644
> --- a/include/system/memory.h
> +++ b/include/system/memory.h
> @@ -1823,14 +1823,14 @@ static inline bool memory_region_is_romd(MemoryRegion *mr)
>   bool memory_region_is_protected(MemoryRegion *mr);
>   
>   /**
> - * memory_region_has_guest_memfd: check whether a memory region has guest_memfd
> - *     associated
> + * memory_region_has_guest_memfd_private: check whether a memory region has
> + *     guest_memfd associated

Nit: maybe change it to "guest_memfd_private associated", and maybe put 
this patch after patch 5?

Otherwise,

Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>

>    *
>    * Returns %true if a memory region's ram_block has valid guest_memfd assigned.
>    *
>    * @mr: the memory region being queried
>    */
> -bool memory_region_has_guest_memfd(MemoryRegion *mr);
> +bool memory_region_has_guest_memfd_private(MemoryRegion *mr);
>   
>   /**
>    * memory_region_get_iommu: check whether a memory region is an iommu
> diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
> index f477014126..320315f50c 100644
> --- a/accel/kvm/kvm-all.c
> +++ b/accel/kvm/kvm-all.c
> @@ -666,7 +666,7 @@ static int kvm_mem_flags(MemoryRegion *mr)
>       if (readonly && kvm_readonly_mem_allowed) {
>           flags |= KVM_MEM_READONLY;
>       }
> -    if (memory_region_has_guest_memfd(mr)) {
> +    if (memory_region_has_guest_memfd_private(mr)) {
>           assert(kvm_guest_memfd_supported);
>           flags |= KVM_MEM_GUEST_MEMFD;
>       }
> @@ -1615,7 +1615,7 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
>               abort();
>           }
>   
> -        if (memory_region_has_guest_memfd(mr)) {
> +        if (memory_region_has_guest_memfd_private(mr)) {
>               err = kvm_set_memory_attributes_private(start_addr, slot_size);
>               if (err) {
>                   error_report("%s: failed to set memory attribute private: %s",
> @@ -3101,7 +3101,7 @@ int kvm_convert_memory(hwaddr start, hwaddr size, bool to_private)
>           return ret;
>       }
>   
> -    if (!memory_region_has_guest_memfd(mr)) {
> +    if (!memory_region_has_guest_memfd_private(mr)) {
>           /*
>            * Because vMMIO region must be shared, guest TD may convert vMMIO
>            * region to shared explicitly.  Don't complain such case.  See
> diff --git a/system/memory.c b/system/memory.c
> index 81b7bff42d..15964160ee 100644
> --- a/system/memory.c
> +++ b/system/memory.c
> @@ -1897,7 +1897,7 @@ bool memory_region_is_protected(MemoryRegion *mr)
>       return mr->ram && (mr->ram_block->flags & RAM_PROTECTED);
>   }
>   
> -bool memory_region_has_guest_memfd(MemoryRegion *mr)
> +bool memory_region_has_guest_memfd_private(MemoryRegion *mr)
>   {
>       return mr->ram_block && mr->ram_block->guest_memfd >= 0;
>   }



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 5/9] ramblock: Rename guest_memfd to guest_memfd_private
  2025-11-19 17:29 ` [PATCH v2 5/9] ramblock: Rename guest_memfd to guest_memfd_private Peter Xu
@ 2025-12-11  7:10   ` Xiaoyao Li
  0 siblings, 0 replies; 23+ messages in thread
From: Xiaoyao Li @ 2025-12-11  7:10 UTC (permalink / raw)
  To: Peter Xu, qemu-devel
  Cc: Paolo Bonzini, David Hildenbrand, Alexey Kardashevskiy,
	Chenyi Qiang, Juraj Marcin, Fabiano Rosas

On 11/20/2025 1:29 AM, Peter Xu wrote:
> Rename the field to reflect the fact that the guest_memfd in this case only
> backs private portion of the ramblock rather than all of it.
> 
> Signed-off-by: Peter Xu <peterx@redhat.com>

Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 6/9] hostmem: Rename guest_memfd to guest_memfd_private
  2025-11-19 17:29 ` [PATCH v2 6/9] hostmem: " Peter Xu
@ 2025-12-11  7:16   ` Xiaoyao Li
  2025-12-11 16:15     ` Peter Xu
  0 siblings, 1 reply; 23+ messages in thread
From: Xiaoyao Li @ 2025-12-11  7:16 UTC (permalink / raw)
  To: Peter Xu, qemu-devel
  Cc: Paolo Bonzini, David Hildenbrand, Alexey Kardashevskiy,
	Chenyi Qiang, Juraj Marcin, Fabiano Rosas

On 11/20/2025 1:29 AM, Peter Xu wrote:
> Rename the HostMemoryBackend.guest_memfd field to reflect what it really
> means, on whether it needs guest_memfd to back its private portion of
> mapping.  This will help on clearance when we introduce in-place
> guest_memfd for hostmem.
> 
> Signed-off-by: Peter Xu <peterx@redhat.com>

Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>

<...>

> diff --git a/backends/hostmem.c b/backends/hostmem.c
> index 35734d6f4d..70450733db 100644
> --- a/backends/hostmem.c
> +++ b/backends/hostmem.c
> @@ -288,7 +288,7 @@ static void host_memory_backend_init(Object *obj)
>       /* TODO: convert access to globals to compat properties */
>       backend->merge = machine_mem_merge(machine);
>       backend->dump = machine_dump_guest_core(machine);
> -    backend->guest_memfd = machine_require_guest_memfd(machine);
> +    backend->guest_memfd_private = machine_require_guest_memfd(machine);

btw, how about a separate patch to rename

machine_require_guest_memfd() to machine_require_guest_memfd_private()?

and another patch to rename memory_region_init_ram_guest_memfd()?

>       backend->reserve = true;
>       backend->prealloc_threads = machine->smp.cpus;
>   }



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 7/9] hostmem: Support in-place guest memfd to back a VM
  2025-11-19 17:29 ` [PATCH v2 7/9] hostmem: Support in-place guest memfd to back a VM Peter Xu
@ 2025-12-11  7:41   ` Xiaoyao Li
  2025-12-11 16:27     ` Peter Xu
  0 siblings, 1 reply; 23+ messages in thread
From: Xiaoyao Li @ 2025-12-11  7:41 UTC (permalink / raw)
  To: Peter Xu, qemu-devel
  Cc: Paolo Bonzini, David Hildenbrand, Alexey Kardashevskiy,
	Chenyi Qiang, Juraj Marcin, Fabiano Rosas

On 11/20/2025 1:29 AM, 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 in-place.  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, in place), rather than
> having another backend supporting the pages converted to shared.
> 
> To use the in-place 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 in-place guest_memfd.
> 
> Signed-off-by: Peter Xu <peterx@redhat.com>

overall looks good to me except a few comments below,

Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>

> ---
>   qapi/qom.json            |  6 +++-
>   backends/hostmem-memfd.c | 66 +++++++++++++++++++++++++++++++++++++---
>   2 files changed, 67 insertions(+), 5 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..1fa16c1e1d 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.
> +     */
> +    bool guest_memfd;
>   };
>   
>   static bool
> @@ -47,10 +56,40 @@ 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 (m->guest_memfd) {
> +        /* User choose to use in-place guest-memfd to back the VM.. */
> +        if (!backend->share) {
> +            error_setg(errp, "In-place guest-memfd must be used with share=on");
> +            return false;
> +        }
> +
> +        /*
> +         * This is the request to have a guest-memfd to back private pages.
> +         * In-place guest-memfd doesn't work like that.  Disable it for now

This seems not correct to me. I think in-place guest-memfd can work with 
guest_memfd_private. The former serves as shared memory and referenced 
by the userspace_addr while the latter serves as private memory 
referenced by the fd of guest_memfd.

While the argument of "disable it for now to make it simple" does make 
sense to me.

> +         * to make it simple, so that each memory backend can only have
> +         * guest-memfd either as private, or fully shared.
> +         */
> +        if (backend->guest_memfd_private) {
> +            error_setg(errp, "In-place guest-memfd cannot be used with another "
> +                       "private guest-memfd");
> +            return false;
> +        }

please add the following check as I commented in v1:

	if (!kvm_enabled()) {
		error_setg(errp, "in-place guest-memfd requires KVM");
		return false;
	}

> +        /* TODO: add huge page support */
> +        fd = kvm_create_guest_memfd(backend->size,
> +                                    GUEST_MEMFD_FLAG_MMAP |
> +                                    GUEST_MEMFD_FLAG_INIT_SHARED,
> +                                    errp);
> +        if (fd < 0) {
> +            return false;
> +        }

how about just removing the fd check here because ...

> +    } 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 == -1) {
>           return false;
>       }

... the existing check can work for the guest memfd as well.

> @@ -65,6 +104,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 +203,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);



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 4/9] memory: Rename memory_region_has_guest_memfd() to *_private()
  2025-12-11  7:10   ` Xiaoyao Li
@ 2025-12-11 15:45     ` Peter Xu
  0 siblings, 0 replies; 23+ messages in thread
From: Peter Xu @ 2025-12-11 15:45 UTC (permalink / raw)
  To: Xiaoyao Li
  Cc: qemu-devel, Paolo Bonzini, David Hildenbrand,
	Alexey Kardashevskiy, Chenyi Qiang, Juraj Marcin, Fabiano Rosas

On Thu, Dec 11, 2025 at 03:10:24PM +0800, Xiaoyao Li wrote:
> On 11/20/2025 1:29 AM, Peter Xu wrote:
> > Rename the function with "_private" suffix, to show that it returns true
> > only if it has an internal guest-memfd to back private pages (rather than
> > in-place guest-memfd).

PS: I forgot to update here, I'll use "fully shared" to replace "in-place".

> > 
> > Signed-off-by: Peter Xu <peterx@redhat.com>
> > ---
> >   include/system/memory.h | 6 +++---
> >   accel/kvm/kvm-all.c     | 6 +++---
> >   system/memory.c         | 2 +-
> >   3 files changed, 7 insertions(+), 7 deletions(-)
> > 
> > diff --git a/include/system/memory.h b/include/system/memory.h
> > index 2c1a5e06b4..4428701a9f 100644
> > --- a/include/system/memory.h
> > +++ b/include/system/memory.h
> > @@ -1823,14 +1823,14 @@ static inline bool memory_region_is_romd(MemoryRegion *mr)
> >   bool memory_region_is_protected(MemoryRegion *mr);
> >   /**
> > - * memory_region_has_guest_memfd: check whether a memory region has guest_memfd
> > - *     associated
> > + * memory_region_has_guest_memfd_private: check whether a memory region has
> > + *     guest_memfd associated
> 
> Nit: maybe change it to "guest_memfd_private associated", and maybe put this
> patch after patch 5?

Agree, though maybe I should do this change in the other ramblock patch
(and move that one before this)?

> 
> Otherwise,
> 
> Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>

Thanks,

-- 
Peter Xu



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 6/9] hostmem: Rename guest_memfd to guest_memfd_private
  2025-12-11  7:16   ` Xiaoyao Li
@ 2025-12-11 16:15     ` Peter Xu
  0 siblings, 0 replies; 23+ messages in thread
From: Peter Xu @ 2025-12-11 16:15 UTC (permalink / raw)
  To: Xiaoyao Li
  Cc: qemu-devel, Paolo Bonzini, David Hildenbrand,
	Alexey Kardashevskiy, Chenyi Qiang, Juraj Marcin, Fabiano Rosas

On Thu, Dec 11, 2025 at 03:16:52PM +0800, Xiaoyao Li wrote:
> On 11/20/2025 1:29 AM, Peter Xu wrote:
> > Rename the HostMemoryBackend.guest_memfd field to reflect what it really
> > means, on whether it needs guest_memfd to back its private portion of
> > mapping.  This will help on clearance when we introduce in-place
> > guest_memfd for hostmem.
> > 
> > Signed-off-by: Peter Xu <peterx@redhat.com>
> 
> Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>
> 
> <...>
> 
> > diff --git a/backends/hostmem.c b/backends/hostmem.c
> > index 35734d6f4d..70450733db 100644
> > --- a/backends/hostmem.c
> > +++ b/backends/hostmem.c
> > @@ -288,7 +288,7 @@ static void host_memory_backend_init(Object *obj)
> >       /* TODO: convert access to globals to compat properties */
> >       backend->merge = machine_mem_merge(machine);
> >       backend->dump = machine_dump_guest_core(machine);
> > -    backend->guest_memfd = machine_require_guest_memfd(machine);
> > +    backend->guest_memfd_private = machine_require_guest_memfd(machine);
> 
> btw, how about a separate patch to rename
> 
> machine_require_guest_memfd() to machine_require_guest_memfd_private()?
> 
> and another patch to rename memory_region_init_ram_guest_memfd()?

Sounds all reasonable, will do.

Thanks,

-- 
Peter Xu



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 7/9] hostmem: Support in-place guest memfd to back a VM
  2025-12-11  7:41   ` Xiaoyao Li
@ 2025-12-11 16:27     ` Peter Xu
  2025-12-12  3:05       ` Xiaoyao Li
  0 siblings, 1 reply; 23+ messages in thread
From: Peter Xu @ 2025-12-11 16:27 UTC (permalink / raw)
  To: Xiaoyao Li
  Cc: qemu-devel, Paolo Bonzini, David Hildenbrand,
	Alexey Kardashevskiy, Chenyi Qiang, Juraj Marcin, Fabiano Rosas

On Thu, Dec 11, 2025 at 03:41:46PM +0800, Xiaoyao Li wrote:
> On 11/20/2025 1:29 AM, 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 in-place.  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, in place), rather than
> > having another backend supporting the pages converted to shared.
> > 
> > To use the in-place 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 in-place guest_memfd.
> > 
> > Signed-off-by: Peter Xu <peterx@redhat.com>
> 
> overall looks good to me except a few comments below,
> 
> Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>
> 
> > ---
> >   qapi/qom.json            |  6 +++-
> >   backends/hostmem-memfd.c | 66 +++++++++++++++++++++++++++++++++++++---
> >   2 files changed, 67 insertions(+), 5 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..1fa16c1e1d 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.
> > +     */
> > +    bool guest_memfd;
> >   };
> >   static bool
> > @@ -47,10 +56,40 @@ 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 (m->guest_memfd) {
> > +        /* User choose to use in-place guest-memfd to back the VM.. */
> > +        if (!backend->share) {
> > +            error_setg(errp, "In-place guest-memfd must be used with share=on");
> > +            return false;
> > +        }
> > +
> > +        /*
> > +         * This is the request to have a guest-memfd to back private pages.
> > +         * In-place guest-memfd doesn't work like that.  Disable it for now
> 
> This seems not correct to me. I think in-place guest-memfd can work with
> guest_memfd_private. The former serves as shared memory and referenced by
> the userspace_addr while the latter serves as private memory referenced by
> the fd of guest_memfd.
> 
> While the argument of "disable it for now to make it simple" does make sense
> to me.

Oops, I forgot to touch up quite a few places that kept mentioning
in-place, sorry.

I'll squash this diff into this patch when repost:

diff --git a/backends/hostmem-memfd.c b/backends/hostmem-memfd.c
index 1fa16c1e1d..e9e288651e 100644
--- a/backends/hostmem-memfd.c
+++ b/backends/hostmem-memfd.c
@@ -57,16 +57,16 @@ memfd_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
     }
 
     if (m->guest_memfd) {
-        /* User choose to use in-place guest-memfd to back the VM.. */
+        /* User choose to use fully shared guest-memfd to back the VM.. */
         if (!backend->share) {
-            error_setg(errp, "In-place guest-memfd must be used with share=on");
+            error_setg(errp, "Guest-memfd=on must be used with share=on");
             return false;
         }
 
         /*
          * This is the request to have a guest-memfd to back private pages.
-         * In-place guest-memfd doesn't work like that.  Disable it for now
-         * to make it simple, so that each memory backend can only have
+         * Fully shared guest-memfd doesn't work like that.  Disable it for
+         * now to make it simple, so that each memory backend can only have
          * guest-memfd either as private, or fully shared.
          */
         if (backend->guest_memfd_private) {

I'll also fix the commit message on in-place, now the one to be reposted:

  hostmem: Support fully shared guest memfd to back a VM
  
  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), rather than
  having another backend supporting the pages converted to 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.

I'll not take your R-b as of now, please check and ack again if you see fit
after reading.

> 
> > +         * to make it simple, so that each memory backend can only have
> > +         * guest-memfd either as private, or fully shared.
> > +         */
> > +        if (backend->guest_memfd_private) {
> > +            error_setg(errp, "In-place guest-memfd cannot be used with another "
> > +                       "private guest-memfd");
> > +            return false;
> > +        }
> 
> please add the following check as I commented in v1:
> 
> 	if (!kvm_enabled()) {
> 		error_setg(errp, "in-place guest-memfd requires KVM");
> 		return false;
> 	}

IMHO it's redundant to set here, when kvm not enabled,
kvm_create_guest_memfd() should be a stub.

However indeed I found the stub didn't set an error, so how about add one
trivial patch to add a verbal error for it instead?

commit aeeaba6dfc68a1c89af90c12f36cb8fe48faecfd
Author: Peter Xu <peterx@redhat.com>
Date:   Thu Dec 11 11:19:44 2025 -0500

    kvm/stub: Provide explicit error for kvm_create_guest_memfd()
    
    So that there will be a verbal string returned when kvm not enabled.
    
    Signed-off-by: Peter Xu <peterx@redhat.com>
---
 accel/stubs/kvm-stub.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c
index 73f04eb589..01b1d6285e 100644
--- a/accel/stubs/kvm-stub.c
+++ b/accel/stubs/kvm-stub.c
@@ -123,6 +123,7 @@ bool kvm_hwpoisoned_mem(void)
 
 int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp)
 {
+    error_setg(errp, "KVM is not enabled");
     return -ENOSYS;
 }

IIUC it'll achieve the same goal with better layering.

> 
> > +        /* TODO: add huge page support */
> > +        fd = kvm_create_guest_memfd(backend->size,
> > +                                    GUEST_MEMFD_FLAG_MMAP |
> > +                                    GUEST_MEMFD_FLAG_INIT_SHARED,
> > +                                    errp);
> > +        if (fd < 0) {
> > +            return false;
> > +        }
> 
> how about just removing the fd check here because ...

We needed it because at least the stub returns -ENOSYS..

I can remove it, but I'll need to change below to "fd<0" check.  That I can
do.

Thanks,

> 
> > +    } 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 == -1) {
> >           return false;
> >       }
> 
> ... the existing check can work for the guest memfd as well.
> 
> > @@ -65,6 +104,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 +203,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);
> 

-- 
Peter Xu



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 7/9] hostmem: Support in-place guest memfd to back a VM
  2025-12-11 16:27     ` Peter Xu
@ 2025-12-12  3:05       ` Xiaoyao Li
  2025-12-12 17:41         ` Peter Xu
  0 siblings, 1 reply; 23+ messages in thread
From: Xiaoyao Li @ 2025-12-12  3:05 UTC (permalink / raw)
  To: Peter Xu
  Cc: qemu-devel, Paolo Bonzini, David Hildenbrand,
	Alexey Kardashevskiy, Chenyi Qiang, Juraj Marcin, Fabiano Rosas

On 12/12/2025 12:27 AM, Peter Xu wrote:
> On Thu, Dec 11, 2025 at 03:41:46PM +0800, Xiaoyao Li wrote:
>> On 11/20/2025 1:29 AM, 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 in-place.  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, in place), rather than
>>> having another backend supporting the pages converted to shared.
>>>
>>> To use the in-place 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 in-place guest_memfd.
>>>
>>> Signed-off-by: Peter Xu <peterx@redhat.com>
>>
>> overall looks good to me except a few comments below,
>>
>> Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>
>>
>>> ---
>>>    qapi/qom.json            |  6 +++-
>>>    backends/hostmem-memfd.c | 66 +++++++++++++++++++++++++++++++++++++---
>>>    2 files changed, 67 insertions(+), 5 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..1fa16c1e1d 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.
>>> +     */
>>> +    bool guest_memfd;
>>>    };
>>>    static bool
>>> @@ -47,10 +56,40 @@ 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 (m->guest_memfd) {
>>> +        /* User choose to use in-place guest-memfd to back the VM.. */
>>> +        if (!backend->share) {
>>> +            error_setg(errp, "In-place guest-memfd must be used with share=on");
>>> +            return false;
>>> +        }
>>> +
>>> +        /*
>>> +         * This is the request to have a guest-memfd to back private pages.
>>> +         * In-place guest-memfd doesn't work like that.  Disable it for now
>>
>> This seems not correct to me. I think in-place guest-memfd can work with
>> guest_memfd_private. The former serves as shared memory and referenced by
>> the userspace_addr while the latter serves as private memory referenced by
>> the fd of guest_memfd.
>>
>> While the argument of "disable it for now to make it simple" does make sense
>> to me.
> 
> Oops, I forgot to touch up quite a few places that kept mentioning
> in-place, sorry.
> 
> I'll squash this diff into this patch when repost:
> 
> diff --git a/backends/hostmem-memfd.c b/backends/hostmem-memfd.c
> index 1fa16c1e1d..e9e288651e 100644
> --- a/backends/hostmem-memfd.c
> +++ b/backends/hostmem-memfd.c
> @@ -57,16 +57,16 @@ memfd_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
>       }
>   
>       if (m->guest_memfd) {
> -        /* User choose to use in-place guest-memfd to back the VM.. */
> +        /* User choose to use fully shared guest-memfd to back the VM.. */
>           if (!backend->share) {
> -            error_setg(errp, "In-place guest-memfd must be used with share=on");
> +            error_setg(errp, "Guest-memfd=on must be used with share=on");

lower-case the guest-memfd? since it's the name of the property?

>               return false;
>           }
>   
>           /*
>            * This is the request to have a guest-memfd to back private pages.
> -         * In-place guest-memfd doesn't work like that.  Disable it for now
> -         * to make it simple, so that each memory backend can only have
> +         * Fully shared guest-memfd doesn't work like that.  Disable it for
> +         * now to make it simple, so that each memory backend can only have
>            * guest-memfd either as private, or fully shared.
>            */
>           if (backend->guest_memfd_private) {

After rethinking on it, I think we just remove the check. There is 
nothing from QEMU side to prevent such usage. It is KVM currently that 
doesn't support INIT_SHARED guest-memfd for confidential VMs.

If we change to KVM to allow it:

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 8bb8830561d4..a658b636a9cf 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -13957,7 +13957,8 @@ bool kvm_arch_no_poll(struct kvm_vcpu *vcpu)
   */
  bool kvm_arch_supports_gmem_init_shared(struct kvm *kvm)
  {
-       return !kvm_arch_has_private_mem(kvm);
+       return true;
+

and remove this check in QEMU, it can actually boot a TDX guest with
fully-shared guest-memfd back'ed as shared part.

> I'll also fix the commit message on in-place, now the one to be reposted:
> 
>    hostmem: Support fully shared guest memfd to back a VM
>    
>    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), rather than
>    having another backend supporting the pages converted to shared.

As above, I think what the patch achieves is to enable guest-memfd (with 
MMAP and INIT_SHARED) to back shared memory. And it is not conflicted 
with using another guest-memfd to back private memory.

>    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.
> 
> I'll not take your R-b as of now, please check and ack again if you see fit
> after reading.
> 
>>
>>> +         * to make it simple, so that each memory backend can only have
>>> +         * guest-memfd either as private, or fully shared.
>>> +         */
>>> +        if (backend->guest_memfd_private) {
>>> +            error_setg(errp, "In-place guest-memfd cannot be used with another "
>>> +                       "private guest-memfd");
>>> +            return false;
>>> +        }
>>
>> please add the following check as I commented in v1:
>>
>> 	if (!kvm_enabled()) {
>> 		error_setg(errp, "in-place guest-memfd requires KVM");
>> 		return false;
>> 	}
> 
> IMHO it's redundant to set here, when kvm not enabled,
> kvm_create_guest_memfd() should be a stub.

No. The KVM stub is for the case where KVM is disable at compile time.

The kvm_enabled() check here is for the case where users use different 
accelerators other than KVM, e.g., -accel tcg.

> However indeed I found the stub didn't set an error, so how about add one
> trivial patch to add a verbal error for it instead?
> 
> commit aeeaba6dfc68a1c89af90c12f36cb8fe48faecfd
> Author: Peter Xu <peterx@redhat.com>
> Date:   Thu Dec 11 11:19:44 2025 -0500
> 
>      kvm/stub: Provide explicit error for kvm_create_guest_memfd()
>      
>      So that there will be a verbal string returned when kvm not enabled.
>      
>      Signed-off-by: Peter Xu <peterx@redhat.com>
> ---
>   accel/stubs/kvm-stub.c | 1 +
>   1 file changed, 1 insertion(+)
> 
> diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c
> index 73f04eb589..01b1d6285e 100644
> --- a/accel/stubs/kvm-stub.c
> +++ b/accel/stubs/kvm-stub.c
> @@ -123,6 +123,7 @@ bool kvm_hwpoisoned_mem(void)
>   
>   int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp)
>   {
> +    error_setg(errp, "KVM is not enabled");
>       return -ENOSYS;
>   }
> 
> IIUC it'll achieve the same goal with better layering.
> 
>>
>>> +        /* TODO: add huge page support */
>>> +        fd = kvm_create_guest_memfd(backend->size,
>>> +                                    GUEST_MEMFD_FLAG_MMAP |
>>> +                                    GUEST_MEMFD_FLAG_INIT_SHARED,
>>> +                                    errp);
>>> +        if (fd < 0) {
>>> +            return false;
>>> +        }
>>
>> how about just removing the fd check here because ...
> 
> We needed it because at least the stub returns -ENOSYS..
> 
> I can remove it, but I'll need to change below to "fd<0" check.  That I can
> do.

yeah, change to "fd < 0" looks better.

> Thanks,
> 
>>
>>> +    } 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 == -1) {
>>>            return false;
>>>        }
>>
>> ... the existing check can work for the guest memfd as well.
>>


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 2/9] kvm: Detect guest-memfd flags supported
  2025-11-19 17:29 ` [PATCH v2 2/9] kvm: Detect guest-memfd flags supported Peter Xu
  2025-12-11  6:56   ` Xiaoyao Li
@ 2025-12-12  3:10   ` Xiaoyao Li
  2025-12-12 17:23     ` Peter Xu
  1 sibling, 1 reply; 23+ messages in thread
From: Xiaoyao Li @ 2025-12-12  3:10 UTC (permalink / raw)
  To: Peter Xu, qemu-devel
  Cc: Paolo Bonzini, David Hildenbrand, Alexey Kardashevskiy,
	Chenyi Qiang, Juraj Marcin, Fabiano Rosas

On 11/20/2025 1:29 AM, Peter Xu wrote:
> Detect supported guest-memfd flags by the current kernel, and reject
> creations of guest-memfd using invalid flags.  When the cap isn't
> available, then no flag is supported.
> 
> Signed-off-by: Peter Xu <peterx@redhat.com>
> ---
>   accel/kvm/kvm-all.c | 11 +++++++++++
>   1 file changed, 11 insertions(+)
> 
> diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
> index 96c194ce54..f477014126 100644
> --- a/accel/kvm/kvm-all.c
> +++ b/accel/kvm/kvm-all.c
> @@ -108,6 +108,7 @@ static int kvm_sstep_flags;
>   static bool kvm_immediate_exit;
>   static uint64_t kvm_supported_memory_attributes;
>   static bool kvm_guest_memfd_supported;
> +static uint64_t kvm_guest_memfd_flags_supported;
>   static hwaddr kvm_max_slot_size = ~0;
>   
>   static const KVMCapabilityInfo kvm_required_capabilites[] = {
> @@ -2787,6 +2788,10 @@ static int kvm_init(AccelState *as, MachineState *ms)
>       kvm_guest_memfd_supported =
>           kvm_vm_check_extension(s, KVM_CAP_GUEST_MEMFD) &&
>           kvm_vm_check_extension(s, KVM_CAP_USER_MEMORY2);
> +
> +    ret = kvm_vm_check_extension(s, KVM_CAP_GUEST_MEMFD_FLAGS);
> +    kvm_guest_memfd_flags_supported = ret > 0 ? ret : 0;
> +
>       kvm_pre_fault_memory_supported = kvm_vm_check_extension(s, KVM_CAP_PRE_FAULT_MEMORY);
>   
>       if (s->kernel_irqchip_split == ON_OFF_AUTO_AUTO) {
> @@ -4492,6 +4497,12 @@ int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp)
>           return -1;
>       }
>   
> +    if (flags & ~kvm_guest_memfd_flags_supported) {
> +        error_setg(errp, "KVM does not support guest-memfd flag: 0x%"PRIx64,

I'm thinking if need to add "for current VM" like:

	KVM does not support guest-memfd flag: xxx for current VM

because kvm_guest_memfd_flags_supported is got from VM-scope CAP and 
varies for different VM types.

> +                   flags & ~kvm_guest_memfd_flags_supported);
> +        return -1;
> +    }
> +
>       fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_GUEST_MEMFD, &guest_memfd);
>       if (fd < 0) {
>           error_setg_errno(errp, errno, "Error creating KVM guest_memfd");



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 2/9] kvm: Detect guest-memfd flags supported
  2025-12-12  3:10   ` Xiaoyao Li
@ 2025-12-12 17:23     ` Peter Xu
  0 siblings, 0 replies; 23+ messages in thread
From: Peter Xu @ 2025-12-12 17:23 UTC (permalink / raw)
  To: Xiaoyao Li
  Cc: qemu-devel, Paolo Bonzini, David Hildenbrand,
	Alexey Kardashevskiy, Chenyi Qiang, Juraj Marcin, Fabiano Rosas

On Fri, Dec 12, 2025 at 11:10:23AM +0800, Xiaoyao Li wrote:
> On 11/20/2025 1:29 AM, Peter Xu wrote:
> > Detect supported guest-memfd flags by the current kernel, and reject
> > creations of guest-memfd using invalid flags.  When the cap isn't
> > available, then no flag is supported.
> > 
> > Signed-off-by: Peter Xu <peterx@redhat.com>
> > ---
> >   accel/kvm/kvm-all.c | 11 +++++++++++
> >   1 file changed, 11 insertions(+)
> > 
> > diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
> > index 96c194ce54..f477014126 100644
> > --- a/accel/kvm/kvm-all.c
> > +++ b/accel/kvm/kvm-all.c
> > @@ -108,6 +108,7 @@ static int kvm_sstep_flags;
> >   static bool kvm_immediate_exit;
> >   static uint64_t kvm_supported_memory_attributes;
> >   static bool kvm_guest_memfd_supported;
> > +static uint64_t kvm_guest_memfd_flags_supported;
> >   static hwaddr kvm_max_slot_size = ~0;
> >   static const KVMCapabilityInfo kvm_required_capabilites[] = {
> > @@ -2787,6 +2788,10 @@ static int kvm_init(AccelState *as, MachineState *ms)
> >       kvm_guest_memfd_supported =
> >           kvm_vm_check_extension(s, KVM_CAP_GUEST_MEMFD) &&
> >           kvm_vm_check_extension(s, KVM_CAP_USER_MEMORY2);
> > +
> > +    ret = kvm_vm_check_extension(s, KVM_CAP_GUEST_MEMFD_FLAGS);
> > +    kvm_guest_memfd_flags_supported = ret > 0 ? ret : 0;
> > +
> >       kvm_pre_fault_memory_supported = kvm_vm_check_extension(s, KVM_CAP_PRE_FAULT_MEMORY);
> >       if (s->kernel_irqchip_split == ON_OFF_AUTO_AUTO) {
> > @@ -4492,6 +4497,12 @@ int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp)
> >           return -1;
> >       }
> > +    if (flags & ~kvm_guest_memfd_flags_supported) {
> > +        error_setg(errp, "KVM does not support guest-memfd flag: 0x%"PRIx64,
> 
> I'm thinking if need to add "for current VM" like:
> 
> 	KVM does not support guest-memfd flag: xxx for current VM
> 
> because kvm_guest_memfd_flags_supported is got from VM-scope CAP and varies
> for different VM types.

Sure I can amend it.  Though I plan to change the sentence slightly:

     if (flags & ~kvm_guest_memfd_flags_supported) {
-        error_setg(errp, "KVM does not support guest-memfd flag: 0x%"PRIx64,
+        error_setg(errp, "Current KVM instance does not support "
+                   "guest-memfd flag: 0x%"PRIx64,
                    flags & ~kvm_guest_memfd_flags_supported);
         return -1;
     }

Thanks,

> 
> > +                   flags & ~kvm_guest_memfd_flags_supported);
> > +        return -1;
> > +    }
> > +
> >       fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_GUEST_MEMFD, &guest_memfd);
> >       if (fd < 0) {
> >           error_setg_errno(errp, errno, "Error creating KVM guest_memfd");
> 

-- 
Peter Xu



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 7/9] hostmem: Support in-place guest memfd to back a VM
  2025-12-12  3:05       ` Xiaoyao Li
@ 2025-12-12 17:41         ` Peter Xu
  0 siblings, 0 replies; 23+ messages in thread
From: Peter Xu @ 2025-12-12 17:41 UTC (permalink / raw)
  To: Xiaoyao Li
  Cc: qemu-devel, Paolo Bonzini, David Hildenbrand,
	Alexey Kardashevskiy, Chenyi Qiang, Juraj Marcin, Fabiano Rosas

On Fri, Dec 12, 2025 at 11:05:44AM +0800, Xiaoyao Li wrote:
> On 12/12/2025 12:27 AM, Peter Xu wrote:
> > On Thu, Dec 11, 2025 at 03:41:46PM +0800, Xiaoyao Li wrote:
> > > On 11/20/2025 1:29 AM, 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 in-place.  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, in place), rather than
> > > > having another backend supporting the pages converted to shared.
> > > > 
> > > > To use the in-place 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 in-place guest_memfd.
> > > > 
> > > > Signed-off-by: Peter Xu <peterx@redhat.com>
> > > 
> > > overall looks good to me except a few comments below,
> > > 
> > > Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>
> > > 
> > > > ---
> > > >    qapi/qom.json            |  6 +++-
> > > >    backends/hostmem-memfd.c | 66 +++++++++++++++++++++++++++++++++++++---
> > > >    2 files changed, 67 insertions(+), 5 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..1fa16c1e1d 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.
> > > > +     */
> > > > +    bool guest_memfd;
> > > >    };
> > > >    static bool
> > > > @@ -47,10 +56,40 @@ 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 (m->guest_memfd) {
> > > > +        /* User choose to use in-place guest-memfd to back the VM.. */
> > > > +        if (!backend->share) {
> > > > +            error_setg(errp, "In-place guest-memfd must be used with share=on");
> > > > +            return false;
> > > > +        }
> > > > +
> > > > +        /*
> > > > +         * This is the request to have a guest-memfd to back private pages.
> > > > +         * In-place guest-memfd doesn't work like that.  Disable it for now
> > > 
> > > This seems not correct to me. I think in-place guest-memfd can work with
> > > guest_memfd_private. The former serves as shared memory and referenced by
> > > the userspace_addr while the latter serves as private memory referenced by
> > > the fd of guest_memfd.
> > > 
> > > While the argument of "disable it for now to make it simple" does make sense
> > > to me.
> > 
> > Oops, I forgot to touch up quite a few places that kept mentioning
> > in-place, sorry.
> > 
> > I'll squash this diff into this patch when repost:
> > 
> > diff --git a/backends/hostmem-memfd.c b/backends/hostmem-memfd.c
> > index 1fa16c1e1d..e9e288651e 100644
> > --- a/backends/hostmem-memfd.c
> > +++ b/backends/hostmem-memfd.c
> > @@ -57,16 +57,16 @@ memfd_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
> >       }
> >       if (m->guest_memfd) {
> > -        /* User choose to use in-place guest-memfd to back the VM.. */
> > +        /* User choose to use fully shared guest-memfd to back the VM.. */
> >           if (!backend->share) {
> > -            error_setg(errp, "In-place guest-memfd must be used with share=on");
> > +            error_setg(errp, "Guest-memfd=on must be used with share=on");
> 
> lower-case the guest-memfd? since it's the name of the property?

Sure.

> 
> >               return false;
> >           }
> >           /*
> >            * This is the request to have a guest-memfd to back private pages.
> > -         * In-place guest-memfd doesn't work like that.  Disable it for now
> > -         * to make it simple, so that each memory backend can only have
> > +         * Fully shared guest-memfd doesn't work like that.  Disable it for
> > +         * now to make it simple, so that each memory backend can only have
> >            * guest-memfd either as private, or fully shared.
> >            */
> >           if (backend->guest_memfd_private) {
> 
> After rethinking on it, I think we just remove the check. There is nothing
> from QEMU side to prevent such usage. It is KVM currently that doesn't
> support INIT_SHARED guest-memfd for confidential VMs.
> 
> If we change to KVM to allow it:
> 
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 8bb8830561d4..a658b636a9cf 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -13957,7 +13957,8 @@ bool kvm_arch_no_poll(struct kvm_vcpu *vcpu)
>   */
>  bool kvm_arch_supports_gmem_init_shared(struct kvm *kvm)
>  {
> -       return !kvm_arch_has_private_mem(kvm);
> +       return true;
> +
> 
> and remove this check in QEMU, it can actually boot a TDX guest with
> fully-shared guest-memfd back'ed as shared part.

Yes, logically I also don't see an issue with it.  I wanted to add more
restrictions because that's not an expected way of consuming fully shared.

But I don't see it a must indeed.  In practise, IIUC it's not triggerable
anyway with the current KVM (as IIUC the flags will report less when CoCo
is on..).  Let me drop it when repost.

> 
> > I'll also fix the commit message on in-place, now the one to be reposted:
> > 
> >    hostmem: Support fully shared guest memfd to back a VM
> >    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), rather than
> >    having another backend supporting the pages converted to shared.
> 
> As above, I think what the patch achieves is to enable guest-memfd (with
> MMAP and INIT_SHARED) to back shared memory. And it is not conflicted with
> using another guest-memfd to back private memory.

Sure.

> 
> >    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.
> > 
> > I'll not take your R-b as of now, please check and ack again if you see fit
> > after reading.
> > 
> > > 
> > > > +         * to make it simple, so that each memory backend can only have
> > > > +         * guest-memfd either as private, or fully shared.
> > > > +         */
> > > > +        if (backend->guest_memfd_private) {
> > > > +            error_setg(errp, "In-place guest-memfd cannot be used with another "
> > > > +                       "private guest-memfd");
> > > > +            return false;
> > > > +        }
> > > 
> > > please add the following check as I commented in v1:
> > > 
> > > 	if (!kvm_enabled()) {
> > > 		error_setg(errp, "in-place guest-memfd requires KVM");
> > > 		return false;
> > > 	}
> > 
> > IMHO it's redundant to set here, when kvm not enabled,
> > kvm_create_guest_memfd() should be a stub.
> 
> No. The KVM stub is for the case where KVM is disable at compile time.
> 
> The kvm_enabled() check here is for the case where users use different
> accelerators other than KVM, e.g., -accel tcg.

I thought the kvm-compiled case is already covered, at least the flags will
be 0 here:

    if (!kvm_guest_memfd_supported) {
        error_setg(errp, "KVM does not support guest_memfd");
        return -1;
    }

So I can change below stub patch into this one, would it look better (so
that we'll provide explicit errors for all cases)?

===8<===
commit 70012ceb70d3ffe624db33a8aeaaec581c7b4ccd
Author: Peter Xu <peterx@redhat.com>
Date:   Thu Dec 11 11:19:44 2025 -0500

    kvm: Provide explicit error for kvm_create_guest_memfd()
    
    So that there will be a verbal string returned when kvm not enabled, or kvm
    not compiled.
    
    Signed-off-by: Peter Xu <peterx@redhat.com>
---
 accel/kvm/kvm-all.c    | 5 +++++
 accel/stubs/kvm-stub.c | 1 +
 2 files changed, 6 insertions(+)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 68d57c1af0..c32fbcf9cc 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -4492,6 +4492,11 @@ int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp)
         .flags = flags,
     };
 
+    if (!kvm_enabled()) {
+        error_setg(errp, "guest-memfd requires KVM accelerator");
+        return -1;
+    }
+
     if (!kvm_guest_memfd_supported) {
         error_setg(errp, "KVM does not support guest_memfd");
         return -1;
diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c
index 73f04eb589..01b1d6285e 100644
--- a/accel/stubs/kvm-stub.c
+++ b/accel/stubs/kvm-stub.c
@@ -123,6 +123,7 @@ bool kvm_hwpoisoned_mem(void)
 
 int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp)
 {
+    error_setg(errp, "KVM is not enabled");
     return -ENOSYS;
 }
===8<===

Thanks,

> 
> > However indeed I found the stub didn't set an error, so how about add one
> > trivial patch to add a verbal error for it instead?
> > 
> > commit aeeaba6dfc68a1c89af90c12f36cb8fe48faecfd
> > Author: Peter Xu <peterx@redhat.com>
> > Date:   Thu Dec 11 11:19:44 2025 -0500
> > 
> >      kvm/stub: Provide explicit error for kvm_create_guest_memfd()
> >      So that there will be a verbal string returned when kvm not enabled.
> >      Signed-off-by: Peter Xu <peterx@redhat.com>
> > ---
> >   accel/stubs/kvm-stub.c | 1 +
> >   1 file changed, 1 insertion(+)
> > 
> > diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c
> > index 73f04eb589..01b1d6285e 100644
> > --- a/accel/stubs/kvm-stub.c
> > +++ b/accel/stubs/kvm-stub.c
> > @@ -123,6 +123,7 @@ bool kvm_hwpoisoned_mem(void)
> >   int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp)
> >   {
> > +    error_setg(errp, "KVM is not enabled");
> >       return -ENOSYS;
> >   }
> > 
> > IIUC it'll achieve the same goal with better layering.
> > 
> > > 
> > > > +        /* TODO: add huge page support */
> > > > +        fd = kvm_create_guest_memfd(backend->size,
> > > > +                                    GUEST_MEMFD_FLAG_MMAP |
> > > > +                                    GUEST_MEMFD_FLAG_INIT_SHARED,
> > > > +                                    errp);
> > > > +        if (fd < 0) {
> > > > +            return false;
> > > > +        }
> > > 
> > > how about just removing the fd check here because ...
> > 
> > We needed it because at least the stub returns -ENOSYS..
> > 
> > I can remove it, but I'll need to change below to "fd<0" check.  That I can
> > do.
> 
> yeah, change to "fd < 0" looks better.
> 
> > Thanks,
> > 
> > > 
> > > > +    } 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 == -1) {
> > > >            return false;
> > > >        }
> > > 
> > > ... the existing check can work for the guest memfd as well.
> > > 
> 

-- 
Peter Xu



^ permalink raw reply related	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2025-12-12 17:42 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-19 17:29 [PATCH v2 0/9] KVM/hostmem: Support init-shared guest-memfd as VM backends Peter Xu
2025-11-19 17:29 ` [PATCH v2 1/9] kvm: Decouple memory attribute check from kvm_guest_memfd_supported Peter Xu
2025-11-19 17:29 ` [PATCH v2 2/9] kvm: Detect guest-memfd flags supported Peter Xu
2025-12-11  6:56   ` Xiaoyao Li
2025-12-12  3:10   ` Xiaoyao Li
2025-12-12 17:23     ` Peter Xu
2025-11-19 17:29 ` [PATCH v2 3/9] memory: Rename RAM_GUEST_MEMFD to RAM_GUEST_MEMFD_PRIVATE Peter Xu
2025-12-11  7:05   ` Xiaoyao Li
2025-11-19 17:29 ` [PATCH v2 4/9] memory: Rename memory_region_has_guest_memfd() to *_private() Peter Xu
2025-12-11  7:10   ` Xiaoyao Li
2025-12-11 15:45     ` Peter Xu
2025-11-19 17:29 ` [PATCH v2 5/9] ramblock: Rename guest_memfd to guest_memfd_private Peter Xu
2025-12-11  7:10   ` Xiaoyao Li
2025-11-19 17:29 ` [PATCH v2 6/9] hostmem: " Peter Xu
2025-12-11  7:16   ` Xiaoyao Li
2025-12-11 16:15     ` Peter Xu
2025-11-19 17:29 ` [PATCH v2 7/9] hostmem: Support in-place guest memfd to back a VM Peter Xu
2025-12-11  7:41   ` Xiaoyao Li
2025-12-11 16:27     ` Peter Xu
2025-12-12  3:05       ` Xiaoyao Li
2025-12-12 17:41         ` Peter Xu
2025-11-19 17:29 ` [PATCH v2 8/9] tests/migration-test: Support guest-memfd init shared mem type Peter Xu
2025-11-19 17:29 ` [PATCH v2 9/9] tests/migration-test: Add a precopy test for guest-memfd Peter Xu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).