Commit d2042d8f authored by Sean Christopherson's avatar Sean Christopherson
Browse files

KVM: Rework KVM_CAP_GUEST_MEMFD_MMAP into KVM_CAP_GUEST_MEMFD_FLAGS



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: default avatarAckerley Tng <ackerleytng@google.com>
Tested-by: default avatarAckerley Tng <ackerleytng@google.com>
Reviewed-by: default avatarDavid Hildenbrand <david@redhat.com>
Link: https://lore.kernel.org/r/20251003232606.4070510-2-seanjc@google.com


Signed-off-by: default avatarSean Christopherson <seanjc@google.com>
parent 034417c1
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -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
+1 −1
Original line number Diff line number Diff line
@@ -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;
+6 −7
Original line number Diff line number Diff line
@@ -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);
+5 −2
Original line number Diff line number Diff line
@@ -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;