Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'kvm-x86-fixes-6.18-rc2' of https://github.com/kvm-x86/linux into HEAD

KVM x86 fixes for 6.18:

- Expand the KVM_PRE_FAULT_MEMORY selftest to add a regression test for the
bug fixed by commit 3ccbf6f47098 ("KVM: x86/mmu: Return -EAGAIN if userspace
deletes/moves memslot during prefault")

- Don't try to get PMU capabbilities from perf when running a CPU with hybrid
CPUs/PMUs, as perf will rightly WARN.

- Rework KVM_CAP_GUEST_MEMFD_MMAP (newly introduced in 6.18) into a more
generic KVM_CAP_GUEST_MEMFD_FLAGS

- Add a guest_memfd INIT_SHARED flag and require userspace to explicitly set
said flag to initialize memory as SHARED, irrespective of MMAP. The
behavior merged in 6.18 is that enabling mmap() implicitly initializes
memory as SHARED, which would result in an ABI collision for x86 CoCo VMs
as their memory is currently always initialized PRIVATE.

- Allow mmap() on guest_memfd for x86 CoCo VMs, i.e. on VMs with private
memory, to enable testing such setups, i.e. to hopefully flush out any
other lurking ABI issues before 6.18 is officially released.

- Add testcases to the guest_memfd selftest to cover guest_memfd without MMAP,
and host userspace accesses to mmap()'d private memory.

+376 -186
+12 -3
Documentation/virt/kvm/api.rst
··· 6437 6437 guest_memfd range is not allowed (any number of memory regions can be bound to 6438 6438 a single guest_memfd file, but the bound ranges must not overlap). 6439 6439 6440 - When the capability KVM_CAP_GUEST_MEMFD_MMAP is supported, the 'flags' field 6441 - supports GUEST_MEMFD_FLAG_MMAP. Setting this flag on guest_memfd creation 6442 - enables mmap() and faulting of guest_memfd memory to host userspace. 6440 + The capability KVM_CAP_GUEST_MEMFD_FLAGS enumerates the `flags` that can be 6441 + specified via KVM_CREATE_GUEST_MEMFD. Currently defined flags: 6442 + 6443 + ============================ ================================================ 6444 + GUEST_MEMFD_FLAG_MMAP Enable using mmap() on the guest_memfd file 6445 + descriptor. 6446 + GUEST_MEMFD_FLAG_INIT_SHARED Make all memory in the file shared during 6447 + KVM_CREATE_GUEST_MEMFD (memory files created 6448 + without INIT_SHARED will be marked private). 6449 + Shared memory can be faulted into host userspace 6450 + page tables. Private memory cannot. 6451 + ============================ ================================================ 6443 6452 6444 6453 When the KVM MMU performs a PFN lookup to service a guest fault and the backing 6445 6454 guest_memfd has the GUEST_MEMFD_FLAG_MMAP set, then the fault will always be
+5 -3
arch/x86/kvm/pmu.c
··· 108 108 bool is_intel = boot_cpu_data.x86_vendor == X86_VENDOR_INTEL; 109 109 int min_nr_gp_ctrs = pmu_ops->MIN_NR_GP_COUNTERS; 110 110 111 - perf_get_x86_pmu_capability(&kvm_host_pmu); 112 - 113 111 /* 114 112 * Hybrid PMUs don't play nice with virtualization without careful 115 113 * configuration by userspace, and KVM's APIs for reporting supported 116 114 * vPMU features do not account for hybrid PMUs. Disable vPMU support 117 115 * for hybrid PMUs until KVM gains a way to let userspace opt-in. 118 116 */ 119 - if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU)) 117 + if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU)) { 120 118 enable_pmu = false; 119 + memset(&kvm_host_pmu, 0, sizeof(kvm_host_pmu)); 120 + } else { 121 + perf_get_x86_pmu_capability(&kvm_host_pmu); 122 + } 121 123 122 124 if (enable_pmu) { 123 125 /*
+4 -3
arch/x86/kvm/x86.c
··· 13941 13941 13942 13942 #ifdef CONFIG_KVM_GUEST_MEMFD 13943 13943 /* 13944 - * KVM doesn't yet support mmap() on guest_memfd for VMs with private memory 13945 - * (the private vs. shared tracking needs to be moved into guest_memfd). 13944 + * KVM doesn't yet support initializing guest_memfd memory as shared for VMs 13945 + * with private memory (the private vs. shared tracking needs to be moved into 13946 + * guest_memfd). 13946 13947 */ 13947 - bool kvm_arch_supports_gmem_mmap(struct kvm *kvm) 13948 + bool kvm_arch_supports_gmem_init_shared(struct kvm *kvm) 13948 13949 { 13949 13950 return !kvm_arch_has_private_mem(kvm); 13950 13951 }
+11 -1
include/linux/kvm_host.h
··· 729 729 #endif 730 730 731 731 #ifdef CONFIG_KVM_GUEST_MEMFD 732 - bool kvm_arch_supports_gmem_mmap(struct kvm *kvm); 732 + bool kvm_arch_supports_gmem_init_shared(struct kvm *kvm); 733 + 734 + static inline u64 kvm_gmem_get_supported_flags(struct kvm *kvm) 735 + { 736 + u64 flags = GUEST_MEMFD_FLAG_MMAP; 737 + 738 + if (!kvm || kvm_arch_supports_gmem_init_shared(kvm)) 739 + flags |= GUEST_MEMFD_FLAG_INIT_SHARED; 740 + 741 + return flags; 742 + } 733 743 #endif 734 744 735 745 #ifndef kvm_arch_has_readonly_mem
+3 -2
include/uapi/linux/kvm.h
··· 962 962 #define KVM_CAP_ARM_EL2_E2H0 241 963 963 #define KVM_CAP_RISCV_MP_STATE_RESET 242 964 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 967 struct kvm_irq_routing_irqchip { 968 968 __u32 irqchip; ··· 1599 1599 #define KVM_MEMORY_ATTRIBUTE_PRIVATE (1ULL << 3) 1600 1600 1601 1601 #define KVM_CREATE_GUEST_MEMFD _IOWR(KVMIO, 0xd4, struct kvm_create_guest_memfd) 1602 - #define GUEST_MEMFD_FLAG_MMAP (1ULL << 0) 1602 + #define GUEST_MEMFD_FLAG_MMAP (1ULL << 0) 1603 + #define GUEST_MEMFD_FLAG_INIT_SHARED (1ULL << 1) 1603 1604 1604 1605 struct kvm_create_guest_memfd { 1605 1606 __u64 size;
+92 -79
tools/testing/selftests/kvm/guest_memfd_test.c
··· 14 14 #include <linux/bitmap.h> 15 15 #include <linux/falloc.h> 16 16 #include <linux/sizes.h> 17 - #include <setjmp.h> 18 - #include <signal.h> 19 17 #include <sys/mman.h> 20 18 #include <sys/types.h> 21 19 #include <sys/stat.h> ··· 22 24 #include "test_util.h" 23 25 #include "ucall_common.h" 24 26 25 - static void test_file_read_write(int fd) 27 + static size_t page_size; 28 + 29 + static void test_file_read_write(int fd, size_t total_size) 26 30 { 27 31 char buf[64]; 28 32 ··· 38 38 "pwrite on a guest_mem fd should fail"); 39 39 } 40 40 41 - static void test_mmap_supported(int fd, size_t page_size, size_t total_size) 41 + static void test_mmap_cow(int fd, size_t size) 42 + { 43 + void *mem; 44 + 45 + mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); 46 + TEST_ASSERT(mem == MAP_FAILED, "Copy-on-write not allowed by guest_memfd."); 47 + } 48 + 49 + static void test_mmap_supported(int fd, size_t total_size) 42 50 { 43 51 const char val = 0xaa; 44 52 char *mem; 45 53 size_t i; 46 54 int ret; 47 55 48 - mem = mmap(NULL, total_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); 49 - TEST_ASSERT(mem == MAP_FAILED, "Copy-on-write not allowed by guest_memfd."); 50 - 51 - mem = mmap(NULL, total_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 52 - TEST_ASSERT(mem != MAP_FAILED, "mmap() for guest_memfd should succeed."); 56 + mem = kvm_mmap(total_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd); 53 57 54 58 memset(mem, val, total_size); 55 59 for (i = 0; i < total_size; i++) ··· 72 68 for (i = 0; i < total_size; i++) 73 69 TEST_ASSERT_EQ(READ_ONCE(mem[i]), val); 74 70 75 - ret = munmap(mem, total_size); 76 - TEST_ASSERT(!ret, "munmap() should succeed."); 71 + kvm_munmap(mem, total_size); 77 72 } 78 73 79 - static sigjmp_buf jmpbuf; 80 - void fault_sigbus_handler(int signum) 74 + static void test_fault_sigbus(int fd, size_t accessible_size, size_t map_size) 81 75 { 82 - siglongjmp(jmpbuf, 1); 83 - } 84 - 85 - static void test_fault_overflow(int fd, size_t page_size, size_t total_size) 86 - { 87 - struct sigaction sa_old, sa_new = { 88 - .sa_handler = fault_sigbus_handler, 89 - }; 90 - size_t map_size = total_size * 4; 91 76 const char val = 0xaa; 92 77 char *mem; 93 78 size_t i; 94 - int ret; 95 79 96 - mem = mmap(NULL, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 97 - TEST_ASSERT(mem != MAP_FAILED, "mmap() for guest_memfd should succeed."); 80 + mem = kvm_mmap(map_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd); 98 81 99 - sigaction(SIGBUS, &sa_new, &sa_old); 100 - if (sigsetjmp(jmpbuf, 1) == 0) { 101 - memset(mem, 0xaa, map_size); 102 - TEST_ASSERT(false, "memset() should have triggered SIGBUS."); 103 - } 104 - sigaction(SIGBUS, &sa_old, NULL); 82 + TEST_EXPECT_SIGBUS(memset(mem, val, map_size)); 83 + TEST_EXPECT_SIGBUS((void)READ_ONCE(mem[accessible_size])); 105 84 106 - for (i = 0; i < total_size; i++) 85 + for (i = 0; i < accessible_size; i++) 107 86 TEST_ASSERT_EQ(READ_ONCE(mem[i]), val); 108 87 109 - ret = munmap(mem, map_size); 110 - TEST_ASSERT(!ret, "munmap() should succeed."); 88 + kvm_munmap(mem, map_size); 111 89 } 112 90 113 - static void test_mmap_not_supported(int fd, size_t page_size, size_t total_size) 91 + static void test_fault_overflow(int fd, size_t total_size) 92 + { 93 + test_fault_sigbus(fd, total_size, total_size * 4); 94 + } 95 + 96 + static void test_fault_private(int fd, size_t total_size) 97 + { 98 + test_fault_sigbus(fd, 0, total_size); 99 + } 100 + 101 + static void test_mmap_not_supported(int fd, size_t total_size) 114 102 { 115 103 char *mem; 116 104 ··· 113 117 TEST_ASSERT_EQ(mem, MAP_FAILED); 114 118 } 115 119 116 - static void test_file_size(int fd, size_t page_size, size_t total_size) 120 + static void test_file_size(int fd, size_t total_size) 117 121 { 118 122 struct stat sb; 119 123 int ret; ··· 124 128 TEST_ASSERT_EQ(sb.st_blksize, page_size); 125 129 } 126 130 127 - static void test_fallocate(int fd, size_t page_size, size_t total_size) 131 + static void test_fallocate(int fd, size_t total_size) 128 132 { 129 133 int ret; 130 134 ··· 161 165 TEST_ASSERT(!ret, "fallocate to restore punched hole should succeed"); 162 166 } 163 167 164 - static void test_invalid_punch_hole(int fd, size_t page_size, size_t total_size) 168 + static void test_invalid_punch_hole(int fd, size_t total_size) 165 169 { 166 170 struct { 167 171 off_t offset; ··· 192 196 } 193 197 194 198 static void test_create_guest_memfd_invalid_sizes(struct kvm_vm *vm, 195 - uint64_t guest_memfd_flags, 196 - size_t page_size) 199 + uint64_t guest_memfd_flags) 197 200 { 198 201 size_t size; 199 202 int fd; ··· 209 214 { 210 215 int fd1, fd2, ret; 211 216 struct stat st1, st2; 212 - size_t page_size = getpagesize(); 213 217 214 218 fd1 = __vm_create_guest_memfd(vm, page_size, 0); 215 219 TEST_ASSERT(fd1 != -1, "memfd creation should succeed"); ··· 233 239 close(fd1); 234 240 } 235 241 236 - static void test_guest_memfd_flags(struct kvm_vm *vm, uint64_t valid_flags) 242 + static void test_guest_memfd_flags(struct kvm_vm *vm) 237 243 { 238 - size_t page_size = getpagesize(); 244 + uint64_t valid_flags = vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_FLAGS); 239 245 uint64_t flag; 240 246 int fd; 241 247 ··· 254 260 } 255 261 } 256 262 257 - static void test_guest_memfd(unsigned long vm_type) 263 + #define gmem_test(__test, __vm, __flags) \ 264 + do { \ 265 + int fd = vm_create_guest_memfd(__vm, page_size * 4, __flags); \ 266 + \ 267 + test_##__test(fd, page_size * 4); \ 268 + close(fd); \ 269 + } while (0) 270 + 271 + static void __test_guest_memfd(struct kvm_vm *vm, uint64_t flags) 258 272 { 259 - uint64_t flags = 0; 260 - struct kvm_vm *vm; 261 - size_t total_size; 262 - size_t page_size; 263 - int fd; 264 - 265 - page_size = getpagesize(); 266 - total_size = page_size * 4; 267 - 268 - vm = vm_create_barebones_type(vm_type); 269 - 270 - if (vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_MMAP)) 271 - flags |= GUEST_MEMFD_FLAG_MMAP; 272 - 273 273 test_create_guest_memfd_multiple(vm); 274 - test_create_guest_memfd_invalid_sizes(vm, flags, page_size); 274 + test_create_guest_memfd_invalid_sizes(vm, flags); 275 275 276 - fd = vm_create_guest_memfd(vm, total_size, flags); 277 - 278 - test_file_read_write(fd); 276 + gmem_test(file_read_write, vm, flags); 279 277 280 278 if (flags & GUEST_MEMFD_FLAG_MMAP) { 281 - test_mmap_supported(fd, page_size, total_size); 282 - test_fault_overflow(fd, page_size, total_size); 279 + if (flags & GUEST_MEMFD_FLAG_INIT_SHARED) { 280 + gmem_test(mmap_supported, vm, flags); 281 + gmem_test(fault_overflow, vm, flags); 282 + } else { 283 + gmem_test(fault_private, vm, flags); 284 + } 285 + 286 + gmem_test(mmap_cow, vm, flags); 283 287 } else { 284 - test_mmap_not_supported(fd, page_size, total_size); 288 + gmem_test(mmap_not_supported, vm, flags); 285 289 } 286 290 287 - test_file_size(fd, page_size, total_size); 288 - test_fallocate(fd, page_size, total_size); 289 - test_invalid_punch_hole(fd, page_size, total_size); 291 + gmem_test(file_size, vm, flags); 292 + gmem_test(fallocate, vm, flags); 293 + gmem_test(invalid_punch_hole, vm, flags); 294 + } 290 295 291 - test_guest_memfd_flags(vm, flags); 296 + static void test_guest_memfd(unsigned long vm_type) 297 + { 298 + struct kvm_vm *vm = vm_create_barebones_type(vm_type); 299 + uint64_t flags; 292 300 293 - close(fd); 301 + test_guest_memfd_flags(vm); 302 + 303 + __test_guest_memfd(vm, 0); 304 + 305 + flags = vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_FLAGS); 306 + if (flags & GUEST_MEMFD_FLAG_MMAP) 307 + __test_guest_memfd(vm, GUEST_MEMFD_FLAG_MMAP); 308 + 309 + /* MMAP should always be supported if INIT_SHARED is supported. */ 310 + if (flags & GUEST_MEMFD_FLAG_INIT_SHARED) 311 + __test_guest_memfd(vm, GUEST_MEMFD_FLAG_MMAP | 312 + GUEST_MEMFD_FLAG_INIT_SHARED); 313 + 294 314 kvm_vm_free(vm); 295 315 } 296 316 ··· 336 328 size_t size; 337 329 int fd, i; 338 330 339 - if (!kvm_has_cap(KVM_CAP_GUEST_MEMFD_MMAP)) 331 + if (!kvm_check_cap(KVM_CAP_GUEST_MEMFD_FLAGS)) 340 332 return; 341 333 342 334 vm = __vm_create_shape_with_one_vcpu(VM_SHAPE_DEFAULT, &vcpu, 1, guest_code); 343 335 344 - TEST_ASSERT(vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_MMAP), 345 - "Default VM type should always support guest_memfd mmap()"); 336 + TEST_ASSERT(vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_FLAGS) & GUEST_MEMFD_FLAG_MMAP, 337 + "Default VM type should support MMAP, supported flags = 0x%x", 338 + vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_FLAGS)); 339 + TEST_ASSERT(vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_FLAGS) & GUEST_MEMFD_FLAG_INIT_SHARED, 340 + "Default VM type should support INIT_SHARED, supported flags = 0x%x", 341 + vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_FLAGS)); 346 342 347 343 size = vm->page_size; 348 - fd = vm_create_guest_memfd(vm, size, GUEST_MEMFD_FLAG_MMAP); 344 + fd = vm_create_guest_memfd(vm, size, GUEST_MEMFD_FLAG_MMAP | 345 + GUEST_MEMFD_FLAG_INIT_SHARED); 349 346 vm_set_user_memory_region2(vm, slot, KVM_MEM_GUEST_MEMFD, gpa, size, NULL, fd, 0); 350 347 351 - mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 352 - TEST_ASSERT(mem != MAP_FAILED, "mmap() on guest_memfd failed"); 348 + mem = kvm_mmap(size, PROT_READ | PROT_WRITE, MAP_SHARED, fd); 353 349 memset(mem, 0xaa, size); 354 - munmap(mem, size); 350 + kvm_munmap(mem, size); 355 351 356 352 virt_pg_map(vm, gpa, gpa); 357 353 vcpu_args_set(vcpu, 2, gpa, size); ··· 363 351 364 352 TEST_ASSERT_EQ(get_ucall(vcpu, NULL), UCALL_DONE); 365 353 366 - mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 367 - TEST_ASSERT(mem != MAP_FAILED, "mmap() on guest_memfd failed"); 354 + mem = kvm_mmap(size, PROT_READ | PROT_WRITE, MAP_SHARED, fd); 368 355 for (i = 0; i < size; i++) 369 356 TEST_ASSERT_EQ(mem[i], 0xff); 370 357 ··· 376 365 unsigned long vm_types, vm_type; 377 366 378 367 TEST_REQUIRE(kvm_has_cap(KVM_CAP_GUEST_MEMFD)); 368 + 369 + page_size = getpagesize(); 379 370 380 371 /* 381 372 * Not all architectures support KVM_CAP_VM_TYPES. However, those that
+25
tools/testing/selftests/kvm/include/kvm_util.h
··· 286 286 #define __KVM_SYSCALL_ERROR(_name, _ret) \ 287 287 "%s failed, rc: %i errno: %i (%s)", (_name), (_ret), errno, strerror(errno) 288 288 289 + static inline void *__kvm_mmap(size_t size, int prot, int flags, int fd, 290 + off_t offset) 291 + { 292 + void *mem; 293 + 294 + mem = mmap(NULL, size, prot, flags, fd, offset); 295 + TEST_ASSERT(mem != MAP_FAILED, __KVM_SYSCALL_ERROR("mmap()", 296 + (int)(unsigned long)MAP_FAILED)); 297 + 298 + return mem; 299 + } 300 + 301 + static inline void *kvm_mmap(size_t size, int prot, int flags, int fd) 302 + { 303 + return __kvm_mmap(size, prot, flags, fd, 0); 304 + } 305 + 306 + static inline void kvm_munmap(void *mem, size_t size) 307 + { 308 + int ret; 309 + 310 + ret = munmap(mem, size); 311 + TEST_ASSERT(!ret, __KVM_SYSCALL_ERROR("munmap()", ret)); 312 + } 313 + 289 314 /* 290 315 * Use the "inner", double-underscore macro when reporting errors from within 291 316 * other macros so that the name of ioctl() and not its literal numeric value
+19
tools/testing/selftests/kvm/include/test_util.h
··· 8 8 #ifndef SELFTEST_KVM_TEST_UTIL_H 9 9 #define SELFTEST_KVM_TEST_UTIL_H 10 10 11 + #include <setjmp.h> 12 + #include <signal.h> 11 13 #include <stdlib.h> 12 14 #include <stdarg.h> 13 15 #include <stdbool.h> ··· 78 76 #define TEST_FAIL(fmt, ...) do { \ 79 77 TEST_ASSERT(false, fmt, ##__VA_ARGS__); \ 80 78 __builtin_unreachable(); \ 79 + } while (0) 80 + 81 + extern sigjmp_buf expect_sigbus_jmpbuf; 82 + void expect_sigbus_handler(int signum); 83 + 84 + #define TEST_EXPECT_SIGBUS(action) \ 85 + do { \ 86 + struct sigaction sa_old, sa_new = { \ 87 + .sa_handler = expect_sigbus_handler, \ 88 + }; \ 89 + \ 90 + sigaction(SIGBUS, &sa_new, &sa_old); \ 91 + if (sigsetjmp(expect_sigbus_jmpbuf, 1) == 0) { \ 92 + action; \ 93 + TEST_FAIL("'%s' should have triggered SIGBUS", #action); \ 94 + } \ 95 + sigaction(SIGBUS, &sa_old, NULL); \ 81 96 } while (0) 82 97 83 98 size_t parse_size(const char *size);
+15 -29
tools/testing/selftests/kvm/lib/kvm_util.c
··· 741 741 int ret; 742 742 743 743 if (vcpu->dirty_gfns) { 744 - ret = munmap(vcpu->dirty_gfns, vm->dirty_ring_size); 745 - TEST_ASSERT(!ret, __KVM_SYSCALL_ERROR("munmap()", ret)); 744 + kvm_munmap(vcpu->dirty_gfns, vm->dirty_ring_size); 746 745 vcpu->dirty_gfns = NULL; 747 746 } 748 747 749 - ret = munmap(vcpu->run, vcpu_mmap_sz()); 750 - TEST_ASSERT(!ret, __KVM_SYSCALL_ERROR("munmap()", ret)); 748 + kvm_munmap(vcpu->run, vcpu_mmap_sz()); 751 749 752 750 ret = close(vcpu->fd); 753 751 TEST_ASSERT(!ret, __KVM_SYSCALL_ERROR("close()", ret)); ··· 781 783 static void __vm_mem_region_delete(struct kvm_vm *vm, 782 784 struct userspace_mem_region *region) 783 785 { 784 - int ret; 785 - 786 786 rb_erase(&region->gpa_node, &vm->regions.gpa_tree); 787 787 rb_erase(&region->hva_node, &vm->regions.hva_tree); 788 788 hash_del(&region->slot_node); 789 789 790 790 sparsebit_free(&region->unused_phy_pages); 791 791 sparsebit_free(&region->protected_phy_pages); 792 - ret = munmap(region->mmap_start, region->mmap_size); 793 - TEST_ASSERT(!ret, __KVM_SYSCALL_ERROR("munmap()", ret)); 792 + kvm_munmap(region->mmap_start, region->mmap_size); 794 793 if (region->fd >= 0) { 795 794 /* There's an extra map when using shared memory. */ 796 - ret = munmap(region->mmap_alias, region->mmap_size); 797 - TEST_ASSERT(!ret, __KVM_SYSCALL_ERROR("munmap()", ret)); 795 + kvm_munmap(region->mmap_alias, region->mmap_size); 798 796 close(region->fd); 799 797 } 800 798 if (region->region.guest_memfd >= 0) ··· 1047 1053 region->fd = kvm_memfd_alloc(region->mmap_size, 1048 1054 src_type == VM_MEM_SRC_SHARED_HUGETLB); 1049 1055 1050 - region->mmap_start = mmap(NULL, region->mmap_size, 1051 - PROT_READ | PROT_WRITE, 1052 - vm_mem_backing_src_alias(src_type)->flag, 1053 - region->fd, 0); 1054 - TEST_ASSERT(region->mmap_start != MAP_FAILED, 1055 - __KVM_SYSCALL_ERROR("mmap()", (int)(unsigned long)MAP_FAILED)); 1056 + region->mmap_start = kvm_mmap(region->mmap_size, PROT_READ | PROT_WRITE, 1057 + vm_mem_backing_src_alias(src_type)->flag, 1058 + region->fd); 1056 1059 1057 1060 TEST_ASSERT(!is_backing_src_hugetlb(src_type) || 1058 1061 region->mmap_start == align_ptr_up(region->mmap_start, backing_src_pagesz), ··· 1120 1129 1121 1130 /* If shared memory, create an alias. */ 1122 1131 if (region->fd >= 0) { 1123 - region->mmap_alias = mmap(NULL, region->mmap_size, 1124 - PROT_READ | PROT_WRITE, 1125 - vm_mem_backing_src_alias(src_type)->flag, 1126 - region->fd, 0); 1127 - TEST_ASSERT(region->mmap_alias != MAP_FAILED, 1128 - __KVM_SYSCALL_ERROR("mmap()", (int)(unsigned long)MAP_FAILED)); 1132 + region->mmap_alias = kvm_mmap(region->mmap_size, 1133 + PROT_READ | PROT_WRITE, 1134 + vm_mem_backing_src_alias(src_type)->flag, 1135 + region->fd); 1129 1136 1130 1137 /* Align host alias address */ 1131 1138 region->host_alias = align_ptr_up(region->mmap_alias, alignment); ··· 1333 1344 TEST_ASSERT(vcpu_mmap_sz() >= sizeof(*vcpu->run), "vcpu mmap size " 1334 1345 "smaller than expected, vcpu_mmap_sz: %zi expected_min: %zi", 1335 1346 vcpu_mmap_sz(), sizeof(*vcpu->run)); 1336 - vcpu->run = (struct kvm_run *) mmap(NULL, vcpu_mmap_sz(), 1337 - PROT_READ | PROT_WRITE, MAP_SHARED, vcpu->fd, 0); 1338 - TEST_ASSERT(vcpu->run != MAP_FAILED, 1339 - __KVM_SYSCALL_ERROR("mmap()", (int)(unsigned long)MAP_FAILED)); 1347 + vcpu->run = kvm_mmap(vcpu_mmap_sz(), PROT_READ | PROT_WRITE, 1348 + MAP_SHARED, vcpu->fd); 1340 1349 1341 1350 if (kvm_has_cap(KVM_CAP_BINARY_STATS_FD)) 1342 1351 vcpu->stats.fd = vcpu_get_stats_fd(vcpu); ··· 1781 1794 page_size * KVM_DIRTY_LOG_PAGE_OFFSET); 1782 1795 TEST_ASSERT(addr == MAP_FAILED, "Dirty ring mapped exec"); 1783 1796 1784 - addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, vcpu->fd, 1785 - page_size * KVM_DIRTY_LOG_PAGE_OFFSET); 1786 - TEST_ASSERT(addr != MAP_FAILED, "Dirty ring map failed"); 1797 + addr = __kvm_mmap(size, PROT_READ | PROT_WRITE, MAP_SHARED, vcpu->fd, 1798 + page_size * KVM_DIRTY_LOG_PAGE_OFFSET); 1787 1799 1788 1800 vcpu->dirty_gfns = addr; 1789 1801 vcpu->dirty_gfns_count = size / sizeof(struct kvm_dirty_gfn);
+7
tools/testing/selftests/kvm/lib/test_util.c
··· 18 18 19 19 #include "test_util.h" 20 20 21 + sigjmp_buf expect_sigbus_jmpbuf; 22 + 23 + void __attribute__((used)) expect_sigbus_handler(int signum) 24 + { 25 + siglongjmp(expect_sigbus_jmpbuf, 1); 26 + } 27 + 21 28 /* 22 29 * Random number generator that is usable from guest code. This is the 23 30 * Park-Miller LCG using standard constants.
+2 -3
tools/testing/selftests/kvm/mmu_stress_test.c
··· 339 339 TEST_ASSERT(max_gpa > (4 * slot_size), "MAXPHYADDR <4gb "); 340 340 341 341 fd = kvm_memfd_alloc(slot_size, hugepages); 342 - mem = mmap(NULL, slot_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 343 - TEST_ASSERT(mem != MAP_FAILED, "mmap() failed"); 342 + mem = kvm_mmap(slot_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd); 344 343 345 344 TEST_ASSERT(!madvise(mem, slot_size, MADV_NOHUGEPAGE), "madvise() failed"); 346 345 ··· 412 413 for (slot = (slot - 1) & ~1ull; slot >= first_slot; slot -= 2) 413 414 vm_set_user_memory_region(vm, slot, 0, 0, 0, NULL); 414 415 415 - munmap(mem, slot_size / 2); 416 + kvm_munmap(mem, slot_size / 2); 416 417 417 418 /* Sanity check that the vCPUs actually ran. */ 418 419 for (i = 0; i < nr_vcpus; i++)
+114 -17
tools/testing/selftests/kvm/pre_fault_memory_test.c
··· 10 10 #include <test_util.h> 11 11 #include <kvm_util.h> 12 12 #include <processor.h> 13 + #include <pthread.h> 13 14 14 15 /* Arbitrarily chosen values */ 15 16 #define TEST_SIZE (SZ_2M + PAGE_SIZE) ··· 31 30 GUEST_DONE(); 32 31 } 33 32 34 - static void pre_fault_memory(struct kvm_vcpu *vcpu, u64 gpa, u64 size, 35 - u64 left) 33 + struct slot_worker_data { 34 + struct kvm_vm *vm; 35 + u64 gpa; 36 + uint32_t flags; 37 + bool worker_ready; 38 + bool prefault_ready; 39 + bool recreate_slot; 40 + }; 41 + 42 + static void *delete_slot_worker(void *__data) 43 + { 44 + struct slot_worker_data *data = __data; 45 + struct kvm_vm *vm = data->vm; 46 + 47 + WRITE_ONCE(data->worker_ready, true); 48 + 49 + while (!READ_ONCE(data->prefault_ready)) 50 + cpu_relax(); 51 + 52 + vm_mem_region_delete(vm, TEST_SLOT); 53 + 54 + while (!READ_ONCE(data->recreate_slot)) 55 + cpu_relax(); 56 + 57 + vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, data->gpa, 58 + TEST_SLOT, TEST_NPAGES, data->flags); 59 + 60 + return NULL; 61 + } 62 + 63 + static void pre_fault_memory(struct kvm_vcpu *vcpu, u64 base_gpa, u64 offset, 64 + u64 size, u64 expected_left, bool private) 36 65 { 37 66 struct kvm_pre_fault_memory range = { 38 - .gpa = gpa, 67 + .gpa = base_gpa + offset, 39 68 .size = size, 40 69 .flags = 0, 41 70 }; 42 - u64 prev; 71 + struct slot_worker_data data = { 72 + .vm = vcpu->vm, 73 + .gpa = base_gpa, 74 + .flags = private ? KVM_MEM_GUEST_MEMFD : 0, 75 + }; 76 + bool slot_recreated = false; 77 + pthread_t slot_worker; 43 78 int ret, save_errno; 79 + u64 prev; 44 80 45 - do { 81 + /* 82 + * Concurrently delete (and recreate) the slot to test KVM's handling 83 + * of a racing memslot deletion with prefaulting. 84 + */ 85 + pthread_create(&slot_worker, NULL, delete_slot_worker, &data); 86 + 87 + while (!READ_ONCE(data.worker_ready)) 88 + cpu_relax(); 89 + 90 + WRITE_ONCE(data.prefault_ready, true); 91 + 92 + for (;;) { 46 93 prev = range.size; 47 94 ret = __vcpu_ioctl(vcpu, KVM_PRE_FAULT_MEMORY, &range); 48 95 save_errno = errno; ··· 98 49 "%sexpecting range.size to change on %s", 99 50 ret < 0 ? "not " : "", 100 51 ret < 0 ? "failure" : "success"); 101 - } while (ret >= 0 ? range.size : save_errno == EINTR); 102 52 103 - TEST_ASSERT(range.size == left, 104 - "Completed with %lld bytes left, expected %" PRId64, 105 - range.size, left); 53 + /* 54 + * Immediately retry prefaulting if KVM was interrupted by an 55 + * unrelated signal/event. 56 + */ 57 + if (ret < 0 && save_errno == EINTR) 58 + continue; 106 59 107 - if (left == 0) 108 - __TEST_ASSERT_VM_VCPU_IOCTL(!ret, "KVM_PRE_FAULT_MEMORY", ret, vcpu->vm); 60 + /* 61 + * Tell the worker to recreate the slot in order to complete 62 + * prefaulting (if prefault didn't already succeed before the 63 + * slot was deleted) and/or to prepare for the next testcase. 64 + * Wait for the worker to exit so that the next invocation of 65 + * prefaulting is guaranteed to complete (assuming no KVM bugs). 66 + */ 67 + if (!slot_recreated) { 68 + WRITE_ONCE(data.recreate_slot, true); 69 + pthread_join(slot_worker, NULL); 70 + slot_recreated = true; 71 + 72 + /* 73 + * Retry prefaulting to get a stable result, i.e. to 74 + * avoid seeing random EAGAIN failures. Don't retry if 75 + * prefaulting already succeeded, as KVM disallows 76 + * prefaulting with size=0, i.e. blindly retrying would 77 + * result in test failures due to EINVAL. KVM should 78 + * always return success if all bytes are prefaulted, 79 + * i.e. there is no need to guard against EAGAIN being 80 + * returned. 81 + */ 82 + if (range.size) 83 + continue; 84 + } 85 + 86 + /* 87 + * All done if there are no remaining bytes to prefault, or if 88 + * prefaulting failed (EINTR was handled above, and EAGAIN due 89 + * to prefaulting a memslot that's being actively deleted should 90 + * be impossible since the memslot has already been recreated). 91 + */ 92 + if (!range.size || ret < 0) 93 + break; 94 + } 95 + 96 + TEST_ASSERT(range.size == expected_left, 97 + "Completed with %llu bytes left, expected %lu", 98 + range.size, expected_left); 99 + 100 + /* 101 + * Assert success if prefaulting the entire range should succeed, i.e. 102 + * complete with no bytes remaining. Otherwise prefaulting should have 103 + * failed due to ENOENT (due to RET_PF_EMULATE for emulated MMIO when 104 + * no memslot exists). 105 + */ 106 + if (!expected_left) 107 + TEST_ASSERT_VM_VCPU_IOCTL(!ret, KVM_PRE_FAULT_MEMORY, ret, vcpu->vm); 109 108 else 110 - /* No memory slot causes RET_PF_EMULATE. it results in -ENOENT. */ 111 - __TEST_ASSERT_VM_VCPU_IOCTL(ret && save_errno == ENOENT, 112 - "KVM_PRE_FAULT_MEMORY", ret, vcpu->vm); 109 + TEST_ASSERT_VM_VCPU_IOCTL(ret && save_errno == ENOENT, 110 + KVM_PRE_FAULT_MEMORY, ret, vcpu->vm); 113 111 } 114 112 115 113 static void __test_pre_fault_memory(unsigned long vm_type, bool private) ··· 193 97 194 98 if (private) 195 99 vm_mem_set_private(vm, guest_test_phys_mem, TEST_SIZE); 196 - pre_fault_memory(vcpu, guest_test_phys_mem, SZ_2M, 0); 197 - pre_fault_memory(vcpu, guest_test_phys_mem + SZ_2M, PAGE_SIZE * 2, PAGE_SIZE); 198 - pre_fault_memory(vcpu, guest_test_phys_mem + TEST_SIZE, PAGE_SIZE, PAGE_SIZE); 100 + 101 + pre_fault_memory(vcpu, guest_test_phys_mem, 0, SZ_2M, 0, private); 102 + pre_fault_memory(vcpu, guest_test_phys_mem, SZ_2M, PAGE_SIZE * 2, PAGE_SIZE, private); 103 + pre_fault_memory(vcpu, guest_test_phys_mem, TEST_SIZE, PAGE_SIZE, PAGE_SIZE, private); 199 104 200 105 vcpu_args_set(vcpu, 1, guest_test_virt_mem); 201 106 vcpu_run(vcpu);
+7 -9
tools/testing/selftests/kvm/s390/ucontrol_test.c
··· 142 142 self->kvm_run_size = ioctl(self->kvm_fd, KVM_GET_VCPU_MMAP_SIZE, NULL); 143 143 ASSERT_GE(self->kvm_run_size, sizeof(struct kvm_run)) 144 144 TH_LOG(KVM_IOCTL_ERROR(KVM_GET_VCPU_MMAP_SIZE, self->kvm_run_size)); 145 - self->run = (struct kvm_run *)mmap(NULL, self->kvm_run_size, 146 - PROT_READ | PROT_WRITE, MAP_SHARED, self->vcpu_fd, 0); 147 - ASSERT_NE(self->run, MAP_FAILED); 145 + self->run = kvm_mmap(self->kvm_run_size, PROT_READ | PROT_WRITE, 146 + MAP_SHARED, self->vcpu_fd); 148 147 /** 149 148 * For virtual cpus that have been created with S390 user controlled 150 149 * virtual machines, the resulting vcpu fd can be memory mapped at page 151 150 * offset KVM_S390_SIE_PAGE_OFFSET in order to obtain a memory map of 152 151 * the virtual cpu's hardware control block. 153 152 */ 154 - self->sie_block = (struct kvm_s390_sie_block *)mmap(NULL, PAGE_SIZE, 155 - PROT_READ | PROT_WRITE, MAP_SHARED, 156 - self->vcpu_fd, KVM_S390_SIE_PAGE_OFFSET << PAGE_SHIFT); 157 - ASSERT_NE(self->sie_block, MAP_FAILED); 153 + self->sie_block = __kvm_mmap(PAGE_SIZE, PROT_READ | PROT_WRITE, 154 + MAP_SHARED, self->vcpu_fd, 155 + KVM_S390_SIE_PAGE_OFFSET << PAGE_SHIFT); 158 156 159 157 TH_LOG("VM created %p %p", self->run, self->sie_block); 160 158 ··· 184 186 185 187 FIXTURE_TEARDOWN(uc_kvm) 186 188 { 187 - munmap(self->sie_block, PAGE_SIZE); 188 - munmap(self->run, self->kvm_run_size); 189 + kvm_munmap(self->sie_block, PAGE_SIZE); 190 + kvm_munmap(self->run, self->kvm_run_size); 189 191 close(self->vcpu_fd); 190 192 close(self->vm_fd); 191 193 close(self->kvm_fd);
+8 -9
tools/testing/selftests/kvm/set_memory_region_test.c
··· 433 433 pr_info("Adding slots 0..%i, each memory region with %dK size\n", 434 434 (max_mem_slots - 1), MEM_REGION_SIZE >> 10); 435 435 436 - mem = mmap(NULL, (size_t)max_mem_slots * MEM_REGION_SIZE + alignment, 437 - PROT_READ | PROT_WRITE, 438 - MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); 439 - TEST_ASSERT(mem != MAP_FAILED, "Failed to mmap() host"); 436 + 437 + mem = kvm_mmap((size_t)max_mem_slots * MEM_REGION_SIZE + alignment, 438 + PROT_READ | PROT_WRITE, 439 + MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1); 440 440 mem_aligned = (void *)(((size_t) mem + alignment - 1) & ~(alignment - 1)); 441 441 442 442 for (slot = 0; slot < max_mem_slots; slot++) ··· 446 446 mem_aligned + (uint64_t)slot * MEM_REGION_SIZE); 447 447 448 448 /* Check it cannot be added memory slots beyond the limit */ 449 - mem_extra = mmap(NULL, MEM_REGION_SIZE, PROT_READ | PROT_WRITE, 450 - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 451 - TEST_ASSERT(mem_extra != MAP_FAILED, "Failed to mmap() host"); 449 + mem_extra = kvm_mmap(MEM_REGION_SIZE, PROT_READ | PROT_WRITE, 450 + MAP_PRIVATE | MAP_ANONYMOUS, -1); 452 451 453 452 ret = __vm_set_user_memory_region(vm, max_mem_slots, 0, 454 453 (uint64_t)max_mem_slots * MEM_REGION_SIZE, ··· 455 456 TEST_ASSERT(ret == -1 && errno == EINVAL, 456 457 "Adding one more memory slot should fail with EINVAL"); 457 458 458 - munmap(mem, (size_t)max_mem_slots * MEM_REGION_SIZE + alignment); 459 - munmap(mem_extra, MEM_REGION_SIZE); 459 + kvm_munmap(mem, (size_t)max_mem_slots * MEM_REGION_SIZE + alignment); 460 + kvm_munmap(mem_extra, MEM_REGION_SIZE); 460 461 kvm_vm_free(vm); 461 462 } 462 463
+1
virt/kvm/Kconfig
··· 113 113 bool 114 114 115 115 config KVM_GUEST_MEMFD 116 + depends on KVM_GENERIC_MMU_NOTIFIER 116 117 select XARRAY_MULTI 117 118 bool 118 119
+49 -26
virt/kvm/guest_memfd.c
··· 102 102 return filemap_grab_folio(inode->i_mapping, index); 103 103 } 104 104 105 - static void kvm_gmem_invalidate_begin(struct kvm_gmem *gmem, pgoff_t start, 106 - pgoff_t end) 105 + static enum kvm_gfn_range_filter kvm_gmem_get_invalidate_filter(struct inode *inode) 106 + { 107 + if ((u64)inode->i_private & GUEST_MEMFD_FLAG_INIT_SHARED) 108 + return KVM_FILTER_SHARED; 109 + 110 + return KVM_FILTER_PRIVATE; 111 + } 112 + 113 + static void __kvm_gmem_invalidate_begin(struct kvm_gmem *gmem, pgoff_t start, 114 + pgoff_t end, 115 + enum kvm_gfn_range_filter attr_filter) 107 116 { 108 117 bool flush = false, found_memslot = false; 109 118 struct kvm_memory_slot *slot; ··· 127 118 .end = slot->base_gfn + min(pgoff + slot->npages, end) - pgoff, 128 119 .slot = slot, 129 120 .may_block = true, 130 - /* guest memfd is relevant to only private mappings. */ 131 - .attr_filter = KVM_FILTER_PRIVATE, 121 + .attr_filter = attr_filter, 132 122 }; 133 123 134 124 if (!found_memslot) { ··· 147 139 KVM_MMU_UNLOCK(kvm); 148 140 } 149 141 150 - static void kvm_gmem_invalidate_end(struct kvm_gmem *gmem, pgoff_t start, 151 - pgoff_t end) 142 + static void kvm_gmem_invalidate_begin(struct inode *inode, pgoff_t start, 143 + pgoff_t end) 144 + { 145 + struct list_head *gmem_list = &inode->i_mapping->i_private_list; 146 + enum kvm_gfn_range_filter attr_filter; 147 + struct kvm_gmem *gmem; 148 + 149 + attr_filter = kvm_gmem_get_invalidate_filter(inode); 150 + 151 + list_for_each_entry(gmem, gmem_list, entry) 152 + __kvm_gmem_invalidate_begin(gmem, start, end, attr_filter); 153 + } 154 + 155 + static void __kvm_gmem_invalidate_end(struct kvm_gmem *gmem, pgoff_t start, 156 + pgoff_t end) 152 157 { 153 158 struct kvm *kvm = gmem->kvm; 154 159 ··· 172 151 } 173 152 } 174 153 175 - static long kvm_gmem_punch_hole(struct inode *inode, loff_t offset, loff_t len) 154 + static void kvm_gmem_invalidate_end(struct inode *inode, pgoff_t start, 155 + pgoff_t end) 176 156 { 177 157 struct list_head *gmem_list = &inode->i_mapping->i_private_list; 158 + struct kvm_gmem *gmem; 159 + 160 + list_for_each_entry(gmem, gmem_list, entry) 161 + __kvm_gmem_invalidate_end(gmem, start, end); 162 + } 163 + 164 + static long kvm_gmem_punch_hole(struct inode *inode, loff_t offset, loff_t len) 165 + { 178 166 pgoff_t start = offset >> PAGE_SHIFT; 179 167 pgoff_t end = (offset + len) >> PAGE_SHIFT; 180 - struct kvm_gmem *gmem; 181 168 182 169 /* 183 170 * Bindings must be stable across invalidation to ensure the start+end ··· 193 164 */ 194 165 filemap_invalidate_lock(inode->i_mapping); 195 166 196 - list_for_each_entry(gmem, gmem_list, entry) 197 - kvm_gmem_invalidate_begin(gmem, start, end); 167 + kvm_gmem_invalidate_begin(inode, start, end); 198 168 199 169 truncate_inode_pages_range(inode->i_mapping, offset, offset + len - 1); 200 170 201 - list_for_each_entry(gmem, gmem_list, entry) 202 - kvm_gmem_invalidate_end(gmem, start, end); 171 + kvm_gmem_invalidate_end(inode, start, end); 203 172 204 173 filemap_invalidate_unlock(inode->i_mapping); 205 174 ··· 307 280 * Zap all SPTEs pointed at by this file. Do not free the backing 308 281 * memory, as its lifetime is associated with the inode, not the file. 309 282 */ 310 - kvm_gmem_invalidate_begin(gmem, 0, -1ul); 311 - kvm_gmem_invalidate_end(gmem, 0, -1ul); 283 + __kvm_gmem_invalidate_begin(gmem, 0, -1ul, 284 + kvm_gmem_get_invalidate_filter(inode)); 285 + __kvm_gmem_invalidate_end(gmem, 0, -1ul); 312 286 313 287 list_del(&gmem->entry); 314 288 ··· 354 326 vm_fault_t ret = VM_FAULT_LOCKED; 355 327 356 328 if (((loff_t)vmf->pgoff << PAGE_SHIFT) >= i_size_read(inode)) 329 + return VM_FAULT_SIGBUS; 330 + 331 + if (!((u64)inode->i_private & GUEST_MEMFD_FLAG_INIT_SHARED)) 357 332 return VM_FAULT_SIGBUS; 358 333 359 334 folio = kvm_gmem_get_folio(inode, vmf->pgoff); ··· 431 400 432 401 static int kvm_gmem_error_folio(struct address_space *mapping, struct folio *folio) 433 402 { 434 - struct list_head *gmem_list = &mapping->i_private_list; 435 - struct kvm_gmem *gmem; 436 403 pgoff_t start, end; 437 404 438 405 filemap_invalidate_lock_shared(mapping); ··· 438 409 start = folio->index; 439 410 end = start + folio_nr_pages(folio); 440 411 441 - list_for_each_entry(gmem, gmem_list, entry) 442 - kvm_gmem_invalidate_begin(gmem, start, end); 412 + kvm_gmem_invalidate_begin(mapping->host, start, end); 443 413 444 414 /* 445 415 * Do not truncate the range, what action is taken in response to the ··· 449 421 * error to userspace. 450 422 */ 451 423 452 - list_for_each_entry(gmem, gmem_list, entry) 453 - kvm_gmem_invalidate_end(gmem, start, end); 424 + kvm_gmem_invalidate_end(mapping->host, start, end); 454 425 455 426 filemap_invalidate_unlock_shared(mapping); 456 427 ··· 485 458 .setattr = kvm_gmem_setattr, 486 459 }; 487 460 488 - bool __weak kvm_arch_supports_gmem_mmap(struct kvm *kvm) 461 + bool __weak kvm_arch_supports_gmem_init_shared(struct kvm *kvm) 489 462 { 490 463 return true; 491 464 } ··· 549 522 { 550 523 loff_t size = args->size; 551 524 u64 flags = args->flags; 552 - u64 valid_flags = 0; 553 525 554 - if (kvm_arch_supports_gmem_mmap(kvm)) 555 - valid_flags |= GUEST_MEMFD_FLAG_MMAP; 556 - 557 - if (flags & ~valid_flags) 526 + if (flags & ~kvm_gmem_get_supported_flags(kvm)) 558 527 return -EINVAL; 559 528 560 529 if (size <= 0 || !PAGE_ALIGNED(size))
+2 -2
virt/kvm/kvm_main.c
··· 4928 4928 #ifdef CONFIG_KVM_GUEST_MEMFD 4929 4929 case KVM_CAP_GUEST_MEMFD: 4930 4930 return 1; 4931 - case KVM_CAP_GUEST_MEMFD_MMAP: 4932 - return !kvm || kvm_arch_supports_gmem_mmap(kvm); 4931 + case KVM_CAP_GUEST_MEMFD_FLAGS: 4932 + return kvm_gmem_get_supported_flags(kvm); 4933 4933 #endif 4934 4934 default: 4935 4935 break;