]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
KVM: Allow and advertise support for host mmap() on guest_memfd files
authorFuad Tabba <tabba@google.com>
Tue, 29 Jul 2025 22:54:52 +0000 (15:54 -0700)
committerPaolo Bonzini <pbonzini@redhat.com>
Wed, 27 Aug 2025 08:37:03 +0000 (04:37 -0400)
Now that all the x86 and arm64 plumbing for mmap() on guest_memfd is in
place, allow userspace to set GUEST_MEMFD_FLAG_MMAP and advertise support
via a new capability, KVM_CAP_GUEST_MEMFD_MMAP.

The availability of this capability is determined per architecture, and
its enablement for a specific guest_memfd instance is controlled by the
GUEST_MEMFD_FLAG_MMAP flag at creation time.

Update the KVM API documentation to detail the KVM_CAP_GUEST_MEMFD_MMAP
capability, the associated GUEST_MEMFD_FLAG_MMAP, and provide essential
information regarding support for mmap in guest_memfd.

Reviewed-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Gavin Shan <gshan@redhat.com>
Reviewed-by: Shivank Garg <shivankg@amd.com>
Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>
Signed-off-by: Fuad Tabba <tabba@google.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-ID: <20250729225455.670324-22-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Documentation/virt/kvm/api.rst
include/uapi/linux/kvm.h
virt/kvm/guest_memfd.c
virt/kvm/kvm_main.c

index 6aa40ee05a4ae075d4a18ca2c9b420d4d8ad512e..c17a87a0a5acb9a8d6c5f4066eb532ca4eedefb8 100644 (file)
@@ -6414,6 +6414,15 @@ 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.
+
+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
+consumed from guest_memfd, regardless of whether it is a shared or a private
+fault.
+
 See KVM_SET_USER_MEMORY_REGION2 for additional details.
 
 4.143 KVM_PRE_FAULT_MEMORY
index f0f0d49d254435523bd75efcabaa7e112c64f7ee..6efa98a57ec1156a13fd98b3178bda7ff2cd7606 100644 (file)
@@ -962,6 +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
 
 struct kvm_irq_routing_irqchip {
        __u32 irqchip;
@@ -1598,6 +1599,7 @@ struct kvm_memory_attributes {
 #define KVM_MEMORY_ATTRIBUTE_PRIVATE           (1ULL << 3)
 
 #define KVM_CREATE_GUEST_MEMFD _IOWR(KVMIO,  0xd4, struct kvm_create_guest_memfd)
+#define GUEST_MEMFD_FLAG_MMAP  (1ULL << 0)
 
 struct kvm_create_guest_memfd {
        __u64 size;
index d5b445548af428c91f0149b9144b592c3fe13ebd..08a6bc7d25b60a27cb8bdf92330cceed71a1d3d7 100644 (file)
@@ -314,7 +314,9 @@ static pgoff_t kvm_gmem_get_index(struct kvm_memory_slot *slot, gfn_t gfn)
 
 static bool kvm_gmem_supports_mmap(struct inode *inode)
 {
-       return false;
+       const u64 flags = (u64)inode->i_private;
+
+       return flags & GUEST_MEMFD_FLAG_MMAP;
 }
 
 static vm_fault_t kvm_gmem_fault_user_mapping(struct vm_fault *vmf)
@@ -522,6 +524,9 @@ int kvm_gmem_create(struct kvm *kvm, struct kvm_create_guest_memfd *args)
        u64 flags = args->flags;
        u64 valid_flags = 0;
 
+       if (kvm_arch_supports_gmem_mmap(kvm))
+               valid_flags |= GUEST_MEMFD_FLAG_MMAP;
+
        if (flags & ~valid_flags)
                return -EINVAL;
 
index 4f57cb92e10912c97ce7851e4ecdf7b67e9cf081..18f29ef9354372ab05a33c23a90f36454df2c555 100644 (file)
@@ -4918,6 +4918,8 @@ 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);
 #endif
        default:
                break;