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.
Unified · Split
| @@ -6432,9 +6432,13 @@ most one mapping per page, i.e. binding multiple memory regions to a single · 6431 unmodified lines | |||
| 6432 | guest_memfd range is not allowed (any number of memory regions can be bound to | 6432 | guest_memfd range is not allowed (any number of memory regions can be bound to |
| 6433 | a single guest_memfd file, but the bound ranges must not overlap). | 6433 | a single guest_memfd file, but the bound ranges must not overlap). |
| 6434 | 6434 | ||
| 6435 | When the capability KVM_CAP_GUEST_MEMFD_MMAP is supported, the 'flags' field | 6435 | The capability KVM_CAP_GUEST_MEMFD_FLAGS enumerates the `flags` that can be |
| 6436 | supports GUEST_MEMFD_FLAG_MMAP. Setting this flag on guest_memfd creation | 6436 | specified via KVM_CREATE_GUEST_MEMFD. Currently defined flags: |
| 6437 | enables 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 | ||
| 6439 | When the KVM MMU performs a PFN lookup to service a guest fault and the backing | 6443 | When the KVM MMU performs a PFN lookup to service a guest fault and the backing |
| 6440 | guest_memfd has the GUEST_MEMFD_FLAG_MMAP set, then the fault will always be | 6444 | guest_memfd has the GUEST_MEMFD_FLAG_MMAP set, then the fault will always be |
| @@ -962,7 +962,7 @@ struct kvm_enable_cap { · 961 unmodified lines | |||
| 962 | #define KVM_CAP_ARM_EL2_E2H0 241 | 962 | #define KVM_CAP_ARM_EL2_E2H0 241 |
| 963 | #define KVM_CAP_RISCV_MP_STATE_RESET 242 | 963 | #define KVM_CAP_RISCV_MP_STATE_RESET 242 |
| 964 | #define KVM_CAP_ARM_CACHEABLE_PFNMAP_SUPPORTED 243 | 964 | #define KVM_CAP_ARM_CACHEABLE_PFNMAP_SUPPORTED 243 |
| 965 | #define KVM_CAP_GUEST_MEMFD_MMAP 244 | 965 | #define KVM_CAP_GUEST_MEMFD_FLAGS 244 |
| 966 | 966 | ||
| 967 | struct kvm_irq_routing_irqchip { | 967 | struct kvm_irq_routing_irqchip { |
| 968 | __u32 irqchip; | 968 | __u32 irqchip; |
| @@ -262,19 +262,17 @@ static void test_guest_memfd_flags(struct kvm_vm *vm, uint64_t valid_flags) · 261 unmodified lines | |||
| 262 | 262 | ||
| 263 | static void test_guest_memfd(unsigned long vm_type) | 263 | static 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); |
| @@ -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_MEMFD | 4928 | #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 | #endif | 4936 | #endif |
| 4934 | default: | 4937 | default: |
| 4935 | break; | 4938 | break; |