]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: Rework KVM_CAP_GUEST_MEMFD_MMAP into KVM_CAP_GUEST_MEMFD_FLAGS
authorSean Christopherson <seanjc@google.com>
Fri, 3 Oct 2025 23:25:54 +0000 (16:25 -0700)
committerSean Christopherson <seanjc@google.com>
Fri, 10 Oct 2025 21:25:22 +0000 (14:25 -0700)
Rework the not-yet-released KVM_CAP_GUEST_MEMFD_MMAP into a more generic
KVM_CAP_GUEST_MEMFD_FLAGS capability so that adding new flags doesn't
require a new capability, and so that developers aren't tempted to bundle
multiple flags into a single capability.

Note, kvm_vm_ioctl_check_extension_generic() can only return a 32-bit
value, but that limitation can be easily circumvented by adding e.g.
KVM_CAP_GUEST_MEMFD_FLAGS2 in the unlikely event guest_memfd supports more
than 32 flags.

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-2-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
Documentation/virt/kvm/api.rst
include/uapi/linux/kvm.h
tools/testing/selftests/kvm/guest_memfd_test.c
virt/kvm/kvm_main.c

index 6ae24c5ca5598f0e302f5de569217afa15528108..7ba92f2ced3867459a8703dd9b39fb5c635cc611 100644 (file)
@@ -6432,9 +6432,13 @@ most one mapping per page, i.e. binding multiple memory regions to a single
 guest_memfd range is not allowed (any number of memory regions can be bound to
 a single guest_memfd file, but the bound ranges must not overlap).
 
-When the capability KVM_CAP_GUEST_MEMFD_MMAP is supported, the 'flags' field
-supports GUEST_MEMFD_FLAG_MMAP.  Setting this flag on guest_memfd creation
-enables mmap() and faulting of guest_memfd memory to host userspace.
+The capability KVM_CAP_GUEST_MEMFD_FLAGS enumerates the `flags` that can be
+specified via KVM_CREATE_GUEST_MEMFD.  Currently defined flags:
+
+  ============================ ================================================
+  GUEST_MEMFD_FLAG_MMAP        Enable using mmap() on the guest_memfd file
+                               descriptor.
+  ============================ ================================================
 
 When the KVM MMU performs a PFN lookup to service a guest fault and the backing
 guest_memfd has the GUEST_MEMFD_FLAG_MMAP set, then the fault will always be
index 6efa98a57ec1156a13fd98b3178bda7ff2cd7606..b1d52d0c56ec45c48a88e8955e9794082ca2e563 100644 (file)
@@ -962,7 +962,7 @@ struct kvm_enable_cap {
 #define KVM_CAP_ARM_EL2_E2H0 241
 #define KVM_CAP_RISCV_MP_STATE_RESET 242
 #define KVM_CAP_ARM_CACHEABLE_PFNMAP_SUPPORTED 243
-#define KVM_CAP_GUEST_MEMFD_MMAP 244
+#define KVM_CAP_GUEST_MEMFD_FLAGS 244
 
 struct kvm_irq_routing_irqchip {
        __u32 irqchip;
index b3ca6737f3044f961415ad3dab040bec74d27bb0..3e58bd49610446327322207fb78a277a8fcb53df 100644 (file)
@@ -262,19 +262,17 @@ static void test_guest_memfd_flags(struct kvm_vm *vm, uint64_t valid_flags)
 
 static void test_guest_memfd(unsigned long vm_type)
 {
-       uint64_t flags = 0;
        struct kvm_vm *vm;
        size_t total_size;
        size_t page_size;
+       uint64_t flags;
        int fd;
 
        page_size = getpagesize();
        total_size = page_size * 4;
 
        vm = vm_create_barebones_type(vm_type);
-
-       if (vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_MMAP))
-               flags |= GUEST_MEMFD_FLAG_MMAP;
+       flags = vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_FLAGS);
 
        test_create_guest_memfd_multiple(vm);
        test_create_guest_memfd_invalid_sizes(vm, flags, page_size);
@@ -328,13 +326,14 @@ static void test_guest_memfd_guest(void)
        size_t size;
        int fd, i;
 
-       if (!kvm_has_cap(KVM_CAP_GUEST_MEMFD_MMAP))
+       if (!kvm_check_cap(KVM_CAP_GUEST_MEMFD_FLAGS))
                return;
 
        vm = __vm_create_shape_with_one_vcpu(VM_SHAPE_DEFAULT, &vcpu, 1, guest_code);
 
-       TEST_ASSERT(vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_MMAP),
-                   "Default VM type should always support guest_memfd mmap()");
+       TEST_ASSERT(vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_FLAGS) & GUEST_MEMFD_FLAG_MMAP,
+                   "Default VM type should support MMAP, supported flags = 0x%x",
+                   vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_FLAGS));
 
        size = vm->page_size;
        fd = vm_create_guest_memfd(vm, size, GUEST_MEMFD_FLAG_MMAP);
index 226faeaa8e5692c5a889f5a9345f756c9846ba6c..e3a268757621c6ffb2c21e70724a9944c888bb0b 100644 (file)
@@ -4928,8 +4928,11 @@ static int kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg)
 #ifdef CONFIG_KVM_GUEST_MEMFD
        case KVM_CAP_GUEST_MEMFD:
                return 1;
-       case KVM_CAP_GUEST_MEMFD_MMAP:
-               return !kvm || kvm_arch_supports_gmem_mmap(kvm);
+       case KVM_CAP_GUEST_MEMFD_FLAGS:
+               if (!kvm || kvm_arch_supports_gmem_mmap(kvm))
+                       return GUEST_MEMFD_FLAG_MMAP;
+
+               return 0;
 #endif
        default:
                break;