Commit 26241579ef for qemu.org
commit 26241579ef88ccaf0d73d699e5f467243b350ad6
Author: Xiaoyao Li <xiaoyao.li@intel.com>
Date: Tue Sep 29 18:50:07 2026 -0500
kvm: Decouple memory attribute check from kvm_guest_memfd_supported
With the mmap support of guest memfd, KVM allows userspace to create
guest memfd serving as normal non-private memory for X86 DEFAULT VM.
However, KVM doesn't support private memory attribute 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 QEMU 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>
Reviewed-by: Fabiano Rosas <farosas@suse.de>
Reviewed-by: Michael Roth <michael.roth@amd.com>
Reviewed-by: David Hildenbrand <david@kernel.org>
Signed-off-by: Michael Roth <michael.roth@amd.com>
Link: https://lore.kernel.org/r/20260929235109.1398509-2-michael.roth@amd.com
Signed-off-by: Peter Xu <peterx@redhat.com>
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 83cbd120a8..cdc7554082 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -1627,6 +1627,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)
@@ -3058,8 +3063,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 32b4b07403..3d34e3b99d 100644
--- a/accel/stubs/kvm-stub.c
+++ b/accel/stubs/kvm-stub.c
@@ -143,3 +143,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/include/system/kvm.h b/include/system/kvm.h
index 714b8c7b01..d29624034c 100644
--- a/include/system/kvm.h
+++ b/include/system/kvm.h
@@ -551,6 +551,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/system/physmem.c b/system/physmem.c
index bd5f41cb02..1b3f327ed5 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -2192,6 +2192,15 @@ 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)));
+ qemu_mutex_unlock_ramlist();
+ goto out_free;
+ }
+
assert(new_block->guest_memfd < 0);
ret = ram_block_coordinated_discard_require(true);