History

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.

Sean Christopherson committed 1 year ago

Commit d2042d81 parent 034417c4 files · +19 −13Browse files

Unified · Split

4 files
  1. Documentation/virt/kvm/api.rst +7 −3
  2. include/uapi/linux/kvm.h +1 −1
  3. tools/testing/selftests/kvm/guest_memfd_test.c +6 −7
  4. virt/kvm/kvm_main.c +5 −2
Documentation/virt/kvm/api.rst+7−3
@@ -6432,9 +6432,13 @@ most one mapping per page, i.e. binding multiple memory regions to a single · 6431 unmodified lines
6432guest_memfd range is not allowed (any number of memory regions can be bound to6432guest_memfd range is not allowed (any number of memory regions can be bound to
6433a single guest_memfd file, but the bound ranges must not overlap).6433a single guest_memfd file, but the bound ranges must not overlap).
6434 6434
6435When the capability KVM_CAP_GUEST_MEMFD_MMAP is supported, the 'flags' field6435The capability KVM_CAP_GUEST_MEMFD_FLAGS enumerates the `flags` that can be
6436supports GUEST_MEMFD_FLAG_MMAP. Setting this flag on guest_memfd creation6436specified via KVM_CREATE_GUEST_MEMFD. Currently defined flags:
6437enables mmap() and faulting of guest_memfd memory to host userspace.6437
6438 ============================ ================================================
6439 GUEST_MEMFD_FLAG_MMAP Enable using mmap() on the guest_memfd file
6440 descriptor.
6441 ============================ ================================================
6438 6442
6439When the KVM MMU performs a PFN lookup to service a guest fault and the backing6443When the KVM MMU performs a PFN lookup to service a guest fault and the backing
6440guest_memfd has the GUEST_MEMFD_FLAG_MMAP set, then the fault will always be6444guest_memfd has the GUEST_MEMFD_FLAG_MMAP set, then the fault will always be
include/uapi/linux/kvm.h+1−1
@@ -962,7 +962,7 @@ struct kvm_enable_cap { · 961 unmodified lines
962#define KVM_CAP_ARM_EL2_E2H0 241962#define KVM_CAP_ARM_EL2_E2H0 241
963#define KVM_CAP_RISCV_MP_STATE_RESET 242963#define KVM_CAP_RISCV_MP_STATE_RESET 242
964#define KVM_CAP_ARM_CACHEABLE_PFNMAP_SUPPORTED 243964#define KVM_CAP_ARM_CACHEABLE_PFNMAP_SUPPORTED 243
965#define KVM_CAP_GUEST_MEMFD_MMAP 244965#define KVM_CAP_GUEST_MEMFD_FLAGS 244
966 966
967struct kvm_irq_routing_irqchip {967struct kvm_irq_routing_irqchip {
968 __u32 irqchip;968 __u32 irqchip;
tools/testing/selftests/kvm/guest_memfd_test.c+6−7
@@ -262,19 +262,17 @@ static void test_guest_memfd_flags(struct kvm_vm *vm, uint64_t valid_flags) · 261 unmodified lines
262 262
263static void test_guest_memfd(unsigned long vm_type)263static void test_guest_memfd(unsigned long vm_type)
264{264{
265 uint64_t flags = 0;
266 struct kvm_vm *vm;265 struct kvm_vm *vm;
267 size_t total_size;266 size_t total_size;
268 size_t page_size;267 size_t page_size;
268 uint64_t flags;
269 int fd;269 int fd;
270 270
271 page_size = getpagesize();271 page_size = getpagesize();
272 total_size = page_size * 4;272 total_size = page_size * 4;
273 273
274 vm = vm_create_barebones_type(vm_type);274 vm = vm_create_barebones_type(vm_type);
275 275 flags = vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_FLAGS);
276 if (vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_MMAP))
277 flags |= GUEST_MEMFD_FLAG_MMAP;
278 276
279 test_create_guest_memfd_multiple(vm);277 test_create_guest_memfd_multiple(vm);
280 test_create_guest_memfd_invalid_sizes(vm, flags, page_size);278 test_create_guest_memfd_invalid_sizes(vm, flags, page_size);
@@ -328,13 +326,14 @@ static void test_guest_memfd_guest(void) · 47 unmodified lines
328 size_t size;326 size_t size;
329 int fd, i;327 int fd, i;
330 328
331 if (!kvm_has_cap(KVM_CAP_GUEST_MEMFD_MMAP))329 if (!kvm_check_cap(KVM_CAP_GUEST_MEMFD_FLAGS))
332 return;330 return;
333 331
334 vm = __vm_create_shape_with_one_vcpu(VM_SHAPE_DEFAULT, &vcpu, 1, guest_code);332 vm = __vm_create_shape_with_one_vcpu(VM_SHAPE_DEFAULT, &vcpu, 1, guest_code);
335 333
336 TEST_ASSERT(vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_MMAP),334 TEST_ASSERT(vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_FLAGS) & GUEST_MEMFD_FLAG_MMAP,
337 "Default VM type should always support guest_memfd mmap()");335 "Default VM type should support MMAP, supported flags = 0x%x",
336 vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_FLAGS));
338 337
339 size = vm->page_size;338 size = vm->page_size;
340 fd = vm_create_guest_memfd(vm, size, GUEST_MEMFD_FLAG_MMAP);339 fd = vm_create_guest_memfd(vm, size, GUEST_MEMFD_FLAG_MMAP);
virt/kvm/kvm_main.c+5−2
@@ -4928,8 +4928,11 @@ static int kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg) · 4927 unmodified lines
4928#ifdef CONFIG_KVM_GUEST_MEMFD4928#ifdef CONFIG_KVM_GUEST_MEMFD
4929 case KVM_CAP_GUEST_MEMFD:4929 case KVM_CAP_GUEST_MEMFD:
4930 return 1;4930 return 1;
4931 case KVM_CAP_GUEST_MEMFD_MMAP:4931 case KVM_CAP_GUEST_MEMFD_FLAGS:
4932 return !kvm || kvm_arch_supports_gmem_mmap(kvm);4932 if (!kvm || kvm_arch_supports_gmem_mmap(kvm))
4933 return GUEST_MEMFD_FLAG_MMAP;
4934
4935 return 0;
4933#endif4936#endif
4934 default:4937 default:
4935 break;4938 break;