[PATCH 2/8] kvm: Allow kvm_guest_memfd_supported for non-private use case

Peter Xu posted 8 patches 3 days, 16 hours ago
Maintainers: Paolo Bonzini <pbonzini@redhat.com>, David Hildenbrand <david@redhat.com>, Igor Mammedov <imammedo@redhat.com>, "Michael S. Tsirkin" <mst@redhat.com>, Cornelia Huck <cohuck@redhat.com>, Peter Xu <peterx@redhat.com>, "Philippe Mathieu-Daudé" <philmd@linaro.org>, Eric Blake <eblake@redhat.com>, Markus Armbruster <armbru@redhat.com>, "Daniel P. Berrangé" <berrange@redhat.com>, Eduardo Habkost <eduardo@habkost.net>
[PATCH 2/8] kvm: Allow kvm_guest_memfd_supported for non-private use case
Posted by Peter Xu 3 days, 16 hours ago
Guest-memfd is not 100% attached to private, it's a VM-specific memory
provider.  Allow it to be created even without private attributes, for
example, when the VM can use the guest-memfd memory completely shared.

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

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index f9254ae654..1425dfd8b3 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -2779,10 +2779,8 @@ 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_guest_memfd_supported = kvm_vm_check_extension(s, KVM_CAP_GUEST_MEMFD) &&
+        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) {
-- 
2.50.1
Re: [PATCH 2/8] kvm: Allow kvm_guest_memfd_supported for non-private use case
Posted by Xiaoyao Li 3 days, 8 hours ago
On 10/24/2025 2:59 AM, Peter Xu wrote:
> Guest-memfd is not 100% attached to private, it's a VM-specific memory
> provider.  Allow it to be created even without private attributes, for
> example, when the VM can use the guest-memfd memory completely shared.
> 
> Signed-off-by: Peter Xu <peterx@redhat.com>
> ---
>   accel/kvm/kvm-all.c | 6 ++----
>   1 file changed, 2 insertions(+), 4 deletions(-)
> 
> diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
> index f9254ae654..1425dfd8b3 100644
> --- a/accel/kvm/kvm-all.c
> +++ b/accel/kvm/kvm-all.c
> @@ -2779,10 +2779,8 @@ 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_guest_memfd_supported = kvm_vm_check_extension(s, KVM_CAP_GUEST_MEMFD) &&
> +        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) {


The check on KVM_MEMORY_ATTRIBUTE_PRIVATE is dropped silently. But using 
guest memfd to serve as private memory does requires the support of 
KVM_MEMORY_ATTRIBUTE_PRIVATE.

My version of the patch was


Author: Xiaoyao Li <xiaoyao.li@intel.com>
Date:   Sat Jul 19 00:56:57 2025 +0800

     kvm: Decouple memory attribute check from kvm_guest_memfd_supported

     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>

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index f9254ae65466..96c194ce54cd 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 68cd33ba9735..73f04eb589ef 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/include/system/kvm.h b/include/system/kvm.h
index 8f9eecf044c2..b5811c90f1cc 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/system/physmem.c b/system/physmem.c
index a340ca3e6166..7704572a5745 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);