Commit 3d3a04fa authored by Fuad Tabba's avatar Fuad Tabba Committed by Paolo Bonzini
Browse files

KVM: Allow and advertise support for host mmap() on guest_memfd files



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: default avatarDavid Hildenbrand <david@redhat.com>
Reviewed-by: default avatarGavin Shan <gshan@redhat.com>
Reviewed-by: default avatarShivank Garg <shivankg@amd.com>
Reviewed-by: default avatarXiaoyao Li <xiaoyao.li@intel.com>
Signed-off-by: default avatarFuad Tabba <tabba@google.com>
Signed-off-by: default avatarSean Christopherson <seanjc@google.com>
Message-ID: <20250729225455.670324-22-seanjc@google.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 32e200bd
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -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
+2 −0
Original line number Diff line number Diff line
@@ -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;
+6 −1
Original line number Diff line number Diff line
@@ -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;

+2 −0
Original line number Diff line number Diff line
@@ -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;