]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: guest_memfd: Allow mmap() on guest_memfd for x86 VMs with private memory
authorSean Christopherson <seanjc@google.com>
Fri, 3 Oct 2025 23:25:58 +0000 (16:25 -0700)
committerSean Christopherson <seanjc@google.com>
Fri, 10 Oct 2025 21:25:25 +0000 (14:25 -0700)
Allow mmap() on guest_memfd instances for x86 VMs with private memory as
the need to track private vs. shared state in the guest_memfd instance is
only pertinent to INIT_SHARED.  Doing mmap() on private memory isn't
terrible useful (yet!), but it's now possible, and will be desirable when
guest_memfd gains support for other VMA-based syscalls, e.g. mbind() to
set NUMA policy.

Lift the restriction now, before MMAP support is officially released, so
that KVM doesn't need to add another capability to enumerate support for
mmap() on private memory.

Fixes: 3d3a04fad25a ("KVM: Allow and advertise support for host mmap() on guest_memfd files")
Reviewed-by: Ackerley Tng <ackerleytng@google.com>
Tested-by: Ackerley Tng <ackerleytng@google.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Link: https://lore.kernel.org/r/20251003232606.4070510-6-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/kvm/x86.c
include/linux/kvm_host.h
virt/kvm/guest_memfd.c
virt/kvm/kvm_main.c

index 4b8138bd48572fd161eda73d2dbdc1dcd0bcbcac..fe3dc3eb433127c4f5810ce7d023538bc3337db9 100644 (file)
@@ -13942,10 +13942,11 @@ bool kvm_arch_no_poll(struct kvm_vcpu *vcpu)
 
 #ifdef CONFIG_KVM_GUEST_MEMFD
 /*
- * KVM doesn't yet support mmap() on guest_memfd for VMs with private memory
- * (the private vs. shared tracking needs to be moved into guest_memfd).
+ * KVM doesn't yet support initializing guest_memfd memory as shared for VMs
+ * with private memory (the private vs. shared tracking needs to be moved into
+ * guest_memfd).
  */
-bool kvm_arch_supports_gmem_mmap(struct kvm *kvm)
+bool kvm_arch_supports_gmem_init_shared(struct kvm *kvm)
 {
        return !kvm_arch_has_private_mem(kvm);
 }
index 19b8c4bebb9c3cf5c79ab9bb30319db3a8d44ae8..680ca838f0181833e08584447bf323ed1af807d8 100644 (file)
@@ -729,7 +729,17 @@ static inline bool kvm_arch_has_private_mem(struct kvm *kvm)
 #endif
 
 #ifdef CONFIG_KVM_GUEST_MEMFD
-bool kvm_arch_supports_gmem_mmap(struct kvm *kvm);
+bool kvm_arch_supports_gmem_init_shared(struct kvm *kvm);
+
+static inline u64 kvm_gmem_get_supported_flags(struct kvm *kvm)
+{
+       u64 flags = GUEST_MEMFD_FLAG_MMAP;
+
+       if (!kvm || kvm_arch_supports_gmem_init_shared(kvm))
+               flags |= GUEST_MEMFD_FLAG_INIT_SHARED;
+
+       return flags;
+}
 #endif
 
 #ifndef kvm_arch_has_readonly_mem
index e10d2c71e78c458a52f20ae6db8f2d486781ef50..fbca8c0972da6e64e4b3a8418dd22e822ad4dc04 100644 (file)
@@ -485,7 +485,7 @@ static const struct inode_operations kvm_gmem_iops = {
        .setattr        = kvm_gmem_setattr,
 };
 
-bool __weak kvm_arch_supports_gmem_mmap(struct kvm *kvm)
+bool __weak kvm_arch_supports_gmem_init_shared(struct kvm *kvm)
 {
        return true;
 }
@@ -549,13 +549,8 @@ int kvm_gmem_create(struct kvm *kvm, struct kvm_create_guest_memfd *args)
 {
        loff_t size = args->size;
        u64 flags = args->flags;
-       u64 valid_flags = 0;
 
-       if (kvm_arch_supports_gmem_mmap(kvm))
-               valid_flags |= GUEST_MEMFD_FLAG_MMAP |
-                              GUEST_MEMFD_FLAG_INIT_SHARED;
-
-       if (flags & ~valid_flags)
+       if (flags & ~kvm_gmem_get_supported_flags(kvm))
                return -EINVAL;
 
        if (size <= 0 || !PAGE_ALIGNED(size))
index 5f644ca54af3530bc706512ad07ccf35d2780169..b7a0ae2a7b205c014cd9ddac7194ab93aecfad5a 100644 (file)
@@ -4929,11 +4929,7 @@ static int kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg)
        case KVM_CAP_GUEST_MEMFD:
                return 1;
        case KVM_CAP_GUEST_MEMFD_FLAGS:
-               if (!kvm || kvm_arch_supports_gmem_mmap(kvm))
-                       return GUEST_MEMFD_FLAG_MMAP |
-                              GUEST_MEMFD_FLAG_INIT_SHARED;
-
-               return 0;
+               return kvm_gmem_get_supported_flags(kvm);
 #endif
        default:
                break;