History

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.

Paolo Bonzini committed 1 year ago

Commit 4361f5a2 parents 5d26eaa 505f52217 files · +375 −185Browse files

Unified · Split

17 files
  1. Documentation/virt/kvm/api.rst +12 −3
  2. arch/x86/kvm/pmu.c +5 −3
  3. arch/x86/kvm/x86.c +4 −3
  4. include/linux/kvm_host.h +11 −1
  5. include/uapi/linux/kvm.h +3 −2
  6. tools/testing/selftests/kvm/guest_memfd_test.c +91 −78
  7. tools/testing/selftests/kvm/include/kvm_util.h +25 −0
  8. tools/testing/selftests/kvm/include/test_util.h +19 −0
  9. tools/testing/selftests/kvm/lib/kvm_util.c +15 −29
  10. tools/testing/selftests/kvm/lib/test_util.c +7 −0
  11. tools/testing/selftests/kvm/mmu_stress_test.c +2 −3
  12. tools/testing/selftests/kvm/pre_fault_memory_test.c +114 −17
  13. tools/testing/selftests/kvm/s390/ucontrol_test.c +7 −9
  14. tools/testing/selftests/kvm/set_memory_region_test.c +8 −9
  15. virt/kvm/Kconfig +1 −0
  16. virt/kvm/guest_memfd.c +49 −26
  17. virt/kvm/kvm_main.c +2 −2
Documentation/virt/kvm/api.rst+12−3
@@ -6437,9 +6437,18 @@ most one mapping per page, i.e. binding multiple memory regions to a single · 6436 unmodified lines
64376437 guest_memfd range is not allowed (any number of memory regions can be bound to
64386438 a single guest_memfd file, but the bound ranges must not overlap).
64396439
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+ ============================ ================================================
64436452
64446453 When the KVM MMU performs a PFN lookup to service a guest fault and the backing
64456454 guest_memfd has the GUEST_MEMFD_FLAG_MMAP set, then the fault will always be
arch/x86/kvm/pmu.c+5−3
@@ -108,16 +108,18 @@ void kvm_init_pmu_capability(const struct kvm_pmu_ops *pmu_ops) · 107 unmodified lines
108108 bool is_intel = boot_cpu_data.x86_vendor == X86_VENDOR_INTEL;
109109 int min_nr_gp_ctrs = pmu_ops->MIN_NR_GP_COUNTERS;
110110
111− perf_get_x86_pmu_capability(&kvm_host_pmu);
112−
113111 /*
114112 * Hybrid PMUs don't play nice with virtualization without careful
115113 * configuration by userspace, and KVM's APIs for reporting supported
116114 * vPMU features do not account for hybrid PMUs. Disable vPMU support
117115 * for hybrid PMUs until KVM gains a way to let userspace opt-in.
118116 */
119− if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU))
117+ if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU)) {
120118 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+ }
121123
122124 if (enable_pmu) {
123125 /*
arch/x86/kvm/x86.c+4−3
@@ -13941,10 +13941,11 @@ bool kvm_arch_no_poll(struct kvm_vcpu *vcpu) · 13940 unmodified lines
1394113941
1394213942 #ifdef CONFIG_KVM_GUEST_MEMFD
1394313943 /*
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).
1394613947 */
13947−bool kvm_arch_supports_gmem_mmap(struct kvm *kvm)
13948+bool kvm_arch_supports_gmem_init_shared(struct kvm *kvm)
1394813949 {
1394913950 return !kvm_arch_has_private_mem(kvm);
1395013951 }
include/linux/kvm_host.h+11−1
@@ -729,7 +729,17 @@ static inline bool kvm_arch_has_private_mem(struct kvm *kvm) · 728 unmodified lines
729729 #endif
730730
731731 #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+}
733743 #endif
734744
735745 #ifndef kvm_arch_has_readonly_mem
include/uapi/linux/kvm.h+3−2
@@ -962,7 +962,7 @@ struct kvm_enable_cap { · 961 unmodified lines
962962 #define KVM_CAP_ARM_EL2_E2H0 241
963963 #define KVM_CAP_RISCV_MP_STATE_RESET 242
964964 #define KVM_CAP_ARM_CACHEABLE_PFNMAP_SUPPORTED 243
965−#define KVM_CAP_GUEST_MEMFD_MMAP 244
965+#define KVM_CAP_GUEST_MEMFD_FLAGS 244
966966
967967 struct kvm_irq_routing_irqchip {
968968 __u32 irqchip;
@@ -1599,7 +1599,8 @@ struct kvm_memory_attributes { · 630 unmodified lines
15991599 #define KVM_MEMORY_ATTRIBUTE_PRIVATE (1ULL << 3)
16001600
16011601 #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)
16031604
16041605 struct kvm_create_guest_memfd {
16051606 __u64 size;
tools/testing/selftests/kvm/guest_memfd_test.c+91−78
@@ -14,8 +14,6 @@ · 13 unmodified lines
1414 #include <linux/bitmap.h>
1515 #include <linux/falloc.h>
1616 #include <linux/sizes.h>
17−#include <setjmp.h>
18−#include <signal.h>
1917 #include <sys/mman.h>
2018 #include <sys/types.h>
2119 #include <sys/stat.h>
@@ -24,7 +22,9 @@ · 2 unmodified lines
2422 #include "test_util.h"
2523 #include "ucall_common.h"
2624
27−static void test_file_read_write(int fd)
25+static size_t page_size;
26+
27+static void test_file_read_write(int fd, size_t total_size)
2828 {
2929 char buf[64];
3030
@@ -38,18 +38,22 @@ static void test_file_read_write(int fd) · 7 unmodified lines
3838 "pwrite on a guest_mem fd should fail");
3939 }
4040
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)
4250 {
4351 const char val = 0xaa;
4452 char *mem;
4553 size_t i;
4654 int ret;
4755
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);
5357
5458 memset(mem, val, total_size);
5559 for (i = 0; i < total_size; i++)
@@ -68,45 +72,37 @@ static void test_mmap_supported(int fd, size_t page_size, size_t total_size) · 12 unmodified lines
6872 for (i = 0; i < total_size; i++)
6973 TEST_ASSERT_EQ(READ_ONCE(mem[i]), val);
7074
71− ret = munmap(mem, total_size);
72− TEST_ASSERT(!ret, "munmap() should succeed.");
73−}
74−
75−static sigjmp_buf jmpbuf;
76−void fault_sigbus_handler(int signum)
77−{
78− siglongjmp(jmpbuf, 1);
75+ kvm_munmap(mem, total_size);
7976 }
8077
81−static void test_fault_overflow(int fd, size_t page_size, size_t total_size)
78+static void test_fault_sigbus(int fd, size_t accessible_size, size_t map_size)
8279 {
83− struct sigaction sa_old, sa_new = {
84− .sa_handler = fault_sigbus_handler,
85− };
86− size_t map_size = total_size * 4;
8780 const char val = 0xaa;
8881 char *mem;
8982 size_t i;
90− int ret;
9183
92− mem = mmap(NULL, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
93− TEST_ASSERT(mem != MAP_FAILED, "mmap() for guest_memfd should succeed.");
84+ mem = kvm_mmap(map_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd);
9485
95− sigaction(SIGBUS, &sa_new, &sa_old);
96− if (sigsetjmp(jmpbuf, 1) == 0) {
97− memset(mem, 0xaa, map_size);
98− TEST_ASSERT(false, "memset() should have triggered SIGBUS.");
99− }
100− sigaction(SIGBUS, &sa_old, NULL);
86+ TEST_EXPECT_SIGBUS(memset(mem, val, map_size));
87+ TEST_EXPECT_SIGBUS((void)READ_ONCE(mem[accessible_size]));
10188
102− for (i = 0; i < total_size; i++)
89+ for (i = 0; i < accessible_size; i++)
10390 TEST_ASSERT_EQ(READ_ONCE(mem[i]), val);
10491
105− ret = munmap(mem, map_size);
106− TEST_ASSERT(!ret, "munmap() should succeed.");
92+ kvm_munmap(mem, map_size);
93+}
94+
95+static void test_fault_overflow(int fd, size_t total_size)
96+{
97+ test_fault_sigbus(fd, total_size, total_size * 4);
98+}
99+
100+static void test_fault_private(int fd, size_t total_size)
101+{
102+ test_fault_sigbus(fd, 0, total_size);
107103 }
108104
109−static void test_mmap_not_supported(int fd, size_t page_size, size_t total_size)
105+static void test_mmap_not_supported(int fd, size_t total_size)
110106 {
111107 char *mem;
112108
@@ -117,7 +113,7 @@ static void test_mmap_not_supported(int fd, size_t page_size, size_t total_size) · 4 unmodified lines
117113 TEST_ASSERT_EQ(mem, MAP_FAILED);
118114 }
119115
120−static void test_file_size(int fd, size_t page_size, size_t total_size)
116+static void test_file_size(int fd, size_t total_size)
121117 {
122118 struct stat sb;
123119 int ret;
@@ -128,7 +124,7 @@ static void test_file_size(int fd, size_t page_size, size_t total_size) · 4 unmodified lines
128124 TEST_ASSERT_EQ(sb.st_blksize, page_size);
129125 }
130126
131−static void test_fallocate(int fd, size_t page_size, size_t total_size)
127+static void test_fallocate(int fd, size_t total_size)
132128 {
133129 int ret;
134130
@@ -165,7 +161,7 @@ static void test_fallocate(int fd, size_t page_size, size_t total_size) · 30 unmodified lines
165161 TEST_ASSERT(!ret, "fallocate to restore punched hole should succeed");
166162 }
167163
168−static void test_invalid_punch_hole(int fd, size_t page_size, size_t total_size)
164+static void test_invalid_punch_hole(int fd, size_t total_size)
169165 {
170166 struct {
171167 off_t offset;
@@ -196,8 +192,7 @@ static void test_invalid_punch_hole(int fd, size_t page_size, size_t total_size) · 24 unmodified lines
196192 }
197193
198194 static void test_create_guest_memfd_invalid_sizes(struct kvm_vm *vm,
199− uint64_t guest_memfd_flags,
200− size_t page_size)
195+ uint64_t guest_memfd_flags)
201196 {
202197 size_t size;
203198 int fd;
@@ -214,7 +209,6 @@ static void test_create_guest_memfd_multiple(struct kvm_vm *vm) · 10 unmodified lines
214209 {
215210 int fd1, fd2, ret;
216211 struct stat st1, st2;
217− size_t page_size = getpagesize();
218212
219213 fd1 = __vm_create_guest_memfd(vm, page_size, 0);
220214 TEST_ASSERT(fd1 != -1, "memfd creation should succeed");
@@ -239,9 +233,9 @@ static void test_create_guest_memfd_multiple(struct kvm_vm *vm) · 18 unmodified lines
239233 close(fd1);
240234 }
241235
242−static void test_guest_memfd_flags(struct kvm_vm *vm, uint64_t valid_flags)
236+static void test_guest_memfd_flags(struct kvm_vm *vm)
243237 {
244− size_t page_size = getpagesize();
238+ uint64_t valid_flags = vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_FLAGS);
245239 uint64_t flag;
246240 int fd;
247241
@@ -260,43 +254,57 @@ static void test_guest_memfd_flags(struct kvm_vm *vm, uint64_t valid_flags) · 12 unmodified lines
260254 }
261255 }
262256
263−static void test_guest_memfd(unsigned long vm_type)
257+#define gmem_test(__test, __vm, __flags) \
258+do { \
259+ int fd = vm_create_guest_memfd(__vm, page_size * 4, __flags); \
260+ \
261+ test_##__test(fd, page_size * 4); \
262+ close(fd); \
263+} while (0)
264+
265+static void __test_guest_memfd(struct kvm_vm *vm, uint64_t flags)
264266 {
265− uint64_t flags = 0;
266− struct kvm_vm *vm;
267− size_t total_size;
268− size_t page_size;
269− int fd;
267+ test_create_guest_memfd_multiple(vm);
268+ test_create_guest_memfd_invalid_sizes(vm, flags);
270269
271− page_size = getpagesize();
272− total_size = page_size * 4;
270+ gmem_test(file_read_write, vm, flags);
273271
274− vm = vm_create_barebones_type(vm_type);
272+ if (flags & GUEST_MEMFD_FLAG_MMAP) {
273+ if (flags & GUEST_MEMFD_FLAG_INIT_SHARED) {
274+ gmem_test(mmap_supported, vm, flags);
275+ gmem_test(fault_overflow, vm, flags);
276+ } else {
277+ gmem_test(fault_private, vm, flags);
278+ }
275279
276− if (vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_MMAP))
277− flags |= GUEST_MEMFD_FLAG_MMAP;
280+ gmem_test(mmap_cow, vm, flags);
281+ } else {
282+ gmem_test(mmap_not_supported, vm, flags);
283+ }
278284
279− test_create_guest_memfd_multiple(vm);
280− test_create_guest_memfd_invalid_sizes(vm, flags, page_size);
285+ gmem_test(file_size, vm, flags);
286+ gmem_test(fallocate, vm, flags);
287+ gmem_test(invalid_punch_hole, vm, flags);
288+}
281289
282− fd = vm_create_guest_memfd(vm, total_size, flags);
290+static void test_guest_memfd(unsigned long vm_type)
291+{
292+ struct kvm_vm *vm = vm_create_barebones_type(vm_type);
293+ uint64_t flags;
283294
284− test_file_read_write(fd);
295+ test_guest_memfd_flags(vm);
285296
286− if (flags & GUEST_MEMFD_FLAG_MMAP) {
287− test_mmap_supported(fd, page_size, total_size);
288− test_fault_overflow(fd, page_size, total_size);
289− } else {
290− test_mmap_not_supported(fd, page_size, total_size);
291− }
297+ __test_guest_memfd(vm, 0);
292298
293− test_file_size(fd, page_size, total_size);
294− test_fallocate(fd, page_size, total_size);
295− test_invalid_punch_hole(fd, page_size, total_size);
299+ flags = vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_FLAGS);
300+ if (flags & GUEST_MEMFD_FLAG_MMAP)
301+ __test_guest_memfd(vm, GUEST_MEMFD_FLAG_MMAP);
296302
297− test_guest_memfd_flags(vm, flags);
303+ /* MMAP should always be supported if INIT_SHARED is supported. */
304+ if (flags & GUEST_MEMFD_FLAG_INIT_SHARED)
305+ __test_guest_memfd(vm, GUEST_MEMFD_FLAG_MMAP |
306+ GUEST_MEMFD_FLAG_INIT_SHARED);
298307
299− close(fd);
300308 kvm_vm_free(vm);
301309 }
302310
@@ -328,22 +336,26 @@ static void test_guest_memfd_guest(void) · 25 unmodified lines
328336 size_t size;
329337 int fd, i;
330338
331− if (!kvm_has_cap(KVM_CAP_GUEST_MEMFD_MMAP))
339+ if (!kvm_check_cap(KVM_CAP_GUEST_MEMFD_FLAGS))
332340 return;
333341
334342 vm = __vm_create_shape_with_one_vcpu(VM_SHAPE_DEFAULT, &vcpu, 1, guest_code);
335343
336− TEST_ASSERT(vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_MMAP),
337− "Default VM type should always support guest_memfd mmap()");
344+ TEST_ASSERT(vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_FLAGS) & GUEST_MEMFD_FLAG_MMAP,
345+ "Default VM type should support MMAP, supported flags = 0x%x",
346+ vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_FLAGS));
347+ TEST_ASSERT(vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_FLAGS) & GUEST_MEMFD_FLAG_INIT_SHARED,
348+ "Default VM type should support INIT_SHARED, supported flags = 0x%x",
349+ vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_FLAGS));
338350
339351 size = vm->page_size;
340− fd = vm_create_guest_memfd(vm, size, GUEST_MEMFD_FLAG_MMAP);
352+ fd = vm_create_guest_memfd(vm, size, GUEST_MEMFD_FLAG_MMAP |
353+ GUEST_MEMFD_FLAG_INIT_SHARED);
341354 vm_set_user_memory_region2(vm, slot, KVM_MEM_GUEST_MEMFD, gpa, size, NULL, fd, 0);
342355
343− mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
344− TEST_ASSERT(mem != MAP_FAILED, "mmap() on guest_memfd failed");
356+ mem = kvm_mmap(size, PROT_READ | PROT_WRITE, MAP_SHARED, fd);
345357 memset(mem, 0xaa, size);
346− munmap(mem, size);
358+ kvm_munmap(mem, size);
347359
348360 virt_pg_map(vm, gpa, gpa);
349361 vcpu_args_set(vcpu, 2, gpa, size);
@@ -351,8 +363,7 @@ static void test_guest_memfd_guest(void) · 1 unmodified line
351363
352364 TEST_ASSERT_EQ(get_ucall(vcpu, NULL), UCALL_DONE);
353365
354− mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
355− TEST_ASSERT(mem != MAP_FAILED, "mmap() on guest_memfd failed");
366+ mem = kvm_mmap(size, PROT_READ | PROT_WRITE, MAP_SHARED, fd);
356367 for (i = 0; i < size; i++)
357368 TEST_ASSERT_EQ(mem[i], 0xff);
358369
@@ -366,6 +377,8 @@ int main(int argc, char *argv[]) · 7 unmodified lines
366377
367378 TEST_REQUIRE(kvm_has_cap(KVM_CAP_GUEST_MEMFD));
368379
380+ page_size = getpagesize();
381+
369382 /*
370383 * Not all architectures support KVM_CAP_VM_TYPES. However, those that
371384 * support guest_memfd have that support for the default VM type.
tools/testing/selftests/kvm/include/kvm_util.h+25−0
@@ -286,6 +286,31 @@ static inline bool kvm_has_cap(long cap) · 285 unmodified lines
286286 #define __KVM_SYSCALL_ERROR(_name, _ret) \
287287 "%s failed, rc: %i errno: %i (%s)", (_name), (_ret), errno, strerror(errno)
288288
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+
289314 /*
290315 * Use the "inner", double-underscore macro when reporting errors from within
291316 * other macros so that the name of ioctl() and not its literal numeric value
tools/testing/selftests/kvm/include/test_util.h+19−0
@@ -8,6 +8,8 @@ · 7 unmodified lines
88 #ifndef SELFTEST_KVM_TEST_UTIL_H
99 #define SELFTEST_KVM_TEST_UTIL_H
1010
11+#include <setjmp.h>
12+#include <signal.h>
1113 #include <stdlib.h>
1214 #include <stdarg.h>
1315 #include <stdbool.h>
@@ -78,6 +80,23 @@ do { \ · 64 unmodified lines
7880 __builtin_unreachable(); \
7981 } while (0)
8082
83+extern sigjmp_buf expect_sigbus_jmpbuf;
84+void expect_sigbus_handler(int signum);
85+
86+#define TEST_EXPECT_SIGBUS(action) \
87+do { \
88+ struct sigaction sa_old, sa_new = { \
89+ .sa_handler = expect_sigbus_handler, \
90+ }; \
91+ \
92+ sigaction(SIGBUS, &sa_new, &sa_old); \
93+ if (sigsetjmp(expect_sigbus_jmpbuf, 1) == 0) { \
94+ action; \
95+ TEST_FAIL("'%s' should have triggered SIGBUS", #action); \
96+ } \
97+ sigaction(SIGBUS, &sa_old, NULL); \
98+} while (0)
99+
81100 size_t parse_size(const char *size);
82101
83102 int64_t timespec_to_ns(struct timespec ts);
tools/testing/selftests/kvm/lib/kvm_util.c+15−29
@@ -741,13 +741,11 @@ static void vm_vcpu_rm(struct kvm_vm *vm, struct kvm_vcpu *vcpu) · 740 unmodified lines
741741 int ret;
742742
743743 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);
746745 vcpu->dirty_gfns = NULL;
747746 }
748747
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());
751749
752750 ret = close(vcpu->fd);
753751 TEST_ASSERT(!ret, __KVM_SYSCALL_ERROR("close()", ret));
@@ -783,20 +781,16 @@ void kvm_vm_release(struct kvm_vm *vmp) · 29 unmodified lines
783781 static void __vm_mem_region_delete(struct kvm_vm *vm,
784782 struct userspace_mem_region *region)
785783 {
786− int ret;
787−
788784 rb_erase(&region->gpa_node, &vm->regions.gpa_tree);
789785 rb_erase(&region->hva_node, &vm->regions.hva_tree);
790786 hash_del(&region->slot_node);
791787
792788 sparsebit_free(&region->unused_phy_pages);
793789 sparsebit_free(&region->protected_phy_pages);
794− ret = munmap(region->mmap_start, region->mmap_size);
795− TEST_ASSERT(!ret, __KVM_SYSCALL_ERROR("munmap()", ret));
790+ kvm_munmap(region->mmap_start, region->mmap_size);
796791 if (region->fd >= 0) {
797792 /* There's an extra map when using shared memory. */
798− ret = munmap(region->mmap_alias, region->mmap_size);
799− TEST_ASSERT(!ret, __KVM_SYSCALL_ERROR("munmap()", ret));
793+ kvm_munmap(region->mmap_alias, region->mmap_size);
800794 close(region->fd);
801795 }
802796 if (region->region.guest_memfd >= 0)
@@ -1053,12 +1047,9 @@ void vm_mem_add(struct kvm_vm *vm, enum vm_mem_backing_src_type src_type, · 250 unmodified lines
10531047 region->fd = kvm_memfd_alloc(region->mmap_size,
10541048 src_type == VM_MEM_SRC_SHARED_HUGETLB);
10551049
1056− region->mmap_start = mmap(NULL, region->mmap_size,
1057− PROT_READ | PROT_WRITE,
1058− vm_mem_backing_src_alias(src_type)->flag,
1059− region->fd, 0);
1060− TEST_ASSERT(region->mmap_start != MAP_FAILED,
1061− __KVM_SYSCALL_ERROR("mmap()", (int)(unsigned long)MAP_FAILED));
1050+ region->mmap_start = kvm_mmap(region->mmap_size, PROT_READ | PROT_WRITE,
1051+ vm_mem_backing_src_alias(src_type)->flag,
1052+ region->fd);
10621053
10631054 TEST_ASSERT(!is_backing_src_hugetlb(src_type) ||
10641055 region->mmap_start == align_ptr_up(region->mmap_start, backing_src_pagesz),
@@ -1129,12 +1120,10 @@ void vm_mem_add(struct kvm_vm *vm, enum vm_mem_backing_src_type src_type, · 64 unmodified lines
11291120
11301121 /* If shared memory, create an alias. */
11311122 if (region->fd >= 0) {
1132− region->mmap_alias = mmap(NULL, region->mmap_size,
1133− PROT_READ | PROT_WRITE,
1134− vm_mem_backing_src_alias(src_type)->flag,
1135− region->fd, 0);
1136− TEST_ASSERT(region->mmap_alias != MAP_FAILED,
1137− __KVM_SYSCALL_ERROR("mmap()", (int)(unsigned long)MAP_FAILED));
1123+ region->mmap_alias = kvm_mmap(region->mmap_size,
1124+ PROT_READ | PROT_WRITE,
1125+ vm_mem_backing_src_alias(src_type)->flag,
1126+ region->fd);
11381127
11391128 /* Align host alias address */
11401129 region->host_alias = align_ptr_up(region->mmap_alias, alignment);
@@ -1344,10 +1333,8 @@ struct kvm_vcpu *__vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id) · 203 unmodified lines
13441333 TEST_ASSERT(vcpu_mmap_sz() >= sizeof(*vcpu->run), "vcpu mmap size "
13451334 "smaller than expected, vcpu_mmap_sz: %zi expected_min: %zi",
13461335 vcpu_mmap_sz(), sizeof(*vcpu->run));
1347− vcpu->run = (struct kvm_run *) mmap(NULL, vcpu_mmap_sz(),
1348− PROT_READ | PROT_WRITE, MAP_SHARED, vcpu->fd, 0);
1349− TEST_ASSERT(vcpu->run != MAP_FAILED,
1350− __KVM_SYSCALL_ERROR("mmap()", (int)(unsigned long)MAP_FAILED));
1336+ vcpu->run = kvm_mmap(vcpu_mmap_sz(), PROT_READ | PROT_WRITE,
1337+ MAP_SHARED, vcpu->fd);
13511338
13521339 if (kvm_has_cap(KVM_CAP_BINARY_STATS_FD))
13531340 vcpu->stats.fd = vcpu_get_stats_fd(vcpu);
@@ -1794,9 +1781,8 @@ void *vcpu_map_dirty_ring(struct kvm_vcpu *vcpu) · 440 unmodified lines
17941781 page_size * KVM_DIRTY_LOG_PAGE_OFFSET);
17951782 TEST_ASSERT(addr == MAP_FAILED, "Dirty ring mapped exec");
17961783
1797− addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, vcpu->fd,
1798− page_size * KVM_DIRTY_LOG_PAGE_OFFSET);
1799− TEST_ASSERT(addr != MAP_FAILED, "Dirty ring map failed");
1784+ addr = __kvm_mmap(size, PROT_READ | PROT_WRITE, MAP_SHARED, vcpu->fd,
1785+ page_size * KVM_DIRTY_LOG_PAGE_OFFSET);
18001786
18011787 vcpu->dirty_gfns = addr;
18021788 vcpu->dirty_gfns_count = size / sizeof(struct kvm_dirty_gfn);
tools/testing/selftests/kvm/lib/test_util.c+7−0
@@ -18,6 +18,13 @@ · 17 unmodified lines
1818
1919 #include "test_util.h"
2020
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+
2128 /*
2229 * Random number generator that is usable from guest code. This is the
2330 * Park-Miller LCG using standard constants.
tools/testing/selftests/kvm/mmu_stress_test.c+2−3
@@ -339,8 +339,7 @@ int main(int argc, char *argv[]) · 338 unmodified lines
339339 TEST_ASSERT(max_gpa > (4 * slot_size), "MAXPHYADDR <4gb ");
340340
341341 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);
344343
345344 TEST_ASSERT(!madvise(mem, slot_size, MADV_NOHUGEPAGE), "madvise() failed");
346345
@@ -413,7 +412,7 @@ int main(int argc, char *argv[]) · 66 unmodified lines
413412 for (slot = (slot - 1) & ~1ull; slot >= first_slot; slot -= 2)
414413 vm_set_user_memory_region(vm, slot, 0, 0, 0, NULL);
415414
416− munmap(mem, slot_size / 2);
415+ kvm_munmap(mem, slot_size / 2);
417416
418417 /* Sanity check that the vCPUs actually ran. */
419418 for (i = 0; i < nr_vcpus; i++)
tools/testing/selftests/kvm/pre_fault_memory_test.c+114−17
@@ -10,6 +10,7 @@ · 9 unmodified lines
1010 #include <test_util.h>
1111 #include <kvm_util.h>
1212 #include <processor.h>
13+#include <pthread.h>
1314
1415 /* Arbitrarily chosen values */
1516 #define TEST_SIZE (SZ_2M + PAGE_SIZE)
@@ -30,18 +31,66 @@ static void guest_code(uint64_t base_gpa) · 14 unmodified lines
3031 GUEST_DONE();
3132 }
3233
33−static void pre_fault_memory(struct kvm_vcpu *vcpu, u64 gpa, u64 size,
34− u64 left)
34+struct slot_worker_data {
35+ struct kvm_vm *vm;
36+ u64 gpa;
37+ uint32_t flags;
38+ bool worker_ready;
39+ bool prefault_ready;
40+ bool recreate_slot;
41+};
42+
43+static void *delete_slot_worker(void *__data)
44+{
45+ struct slot_worker_data *data = __data;
46+ struct kvm_vm *vm = data->vm;
47+
48+ WRITE_ONCE(data->worker_ready, true);
49+
50+ while (!READ_ONCE(data->prefault_ready))
51+ cpu_relax();
52+
53+ vm_mem_region_delete(vm, TEST_SLOT);
54+
55+ while (!READ_ONCE(data->recreate_slot))
56+ cpu_relax();
57+
58+ vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, data->gpa,
59+ TEST_SLOT, TEST_NPAGES, data->flags);
60+
61+ return NULL;
62+}
63+
64+static void pre_fault_memory(struct kvm_vcpu *vcpu, u64 base_gpa, u64 offset,
65+ u64 size, u64 expected_left, bool private)
3566 {
3667 struct kvm_pre_fault_memory range = {
37− .gpa = gpa,
68+ .gpa = base_gpa + offset,
3869 .size = size,
3970 .flags = 0,
4071 };
41− u64 prev;
72+ struct slot_worker_data data = {
73+ .vm = vcpu->vm,
74+ .gpa = base_gpa,
75+ .flags = private ? KVM_MEM_GUEST_MEMFD : 0,
76+ };
77+ bool slot_recreated = false;
78+ pthread_t slot_worker;
4279 int ret, save_errno;
80+ u64 prev;
81+
82+ /*
83+ * Concurrently delete (and recreate) the slot to test KVM's handling
84+ * of a racing memslot deletion with prefaulting.
85+ */
86+ pthread_create(&slot_worker, NULL, delete_slot_worker, &data);
4387
44− do {
88+ while (!READ_ONCE(data.worker_ready))
89+ cpu_relax();
90+
91+ WRITE_ONCE(data.prefault_ready, true);
92+
93+ for (;;) {
4594 prev = range.size;
4695 ret = __vcpu_ioctl(vcpu, KVM_PRE_FAULT_MEMORY, &range);
4796 save_errno = errno;
@@ -49,18 +98,65 @@ static void pre_fault_memory(struct kvm_vcpu *vcpu, u64 gpa, u64 size, · 1 unmodified line
4998 "%sexpecting range.size to change on %s",
5099 ret < 0 ? "not " : "",
51100 ret < 0 ? "failure" : "success");
52− } while (ret >= 0 ? range.size : save_errno == EINTR);
53101
54− TEST_ASSERT(range.size == left,
55− "Completed with %lld bytes left, expected %" PRId64,
56− range.size, left);
102+ /*
103+ * Immediately retry prefaulting if KVM was interrupted by an
104+ * unrelated signal/event.
105+ */
106+ if (ret < 0 && save_errno == EINTR)
107+ continue;
108+
109+ /*
110+ * Tell the worker to recreate the slot in order to complete
111+ * prefaulting (if prefault didn't already succeed before the
112+ * slot was deleted) and/or to prepare for the next testcase.
113+ * Wait for the worker to exit so that the next invocation of
114+ * prefaulting is guaranteed to complete (assuming no KVM bugs).
115+ */
116+ if (!slot_recreated) {
117+ WRITE_ONCE(data.recreate_slot, true);
118+ pthread_join(slot_worker, NULL);
119+ slot_recreated = true;
120+
121+ /*
122+ * Retry prefaulting to get a stable result, i.e. to
123+ * avoid seeing random EAGAIN failures. Don't retry if
124+ * prefaulting already succeeded, as KVM disallows
125+ * prefaulting with size=0, i.e. blindly retrying would
126+ * result in test failures due to EINVAL. KVM should
127+ * always return success if all bytes are prefaulted,
128+ * i.e. there is no need to guard against EAGAIN being
129+ * returned.
130+ */
131+ if (range.size)
132+ continue;
133+ }
134+
135+ /*
136+ * All done if there are no remaining bytes to prefault, or if
137+ * prefaulting failed (EINTR was handled above, and EAGAIN due
138+ * to prefaulting a memslot that's being actively deleted should
139+ * be impossible since the memslot has already been recreated).
140+ */
141+ if (!range.size || ret < 0)
142+ break;
143+ }
57144
58− if (left == 0)
59− __TEST_ASSERT_VM_VCPU_IOCTL(!ret, "KVM_PRE_FAULT_MEMORY", ret, vcpu->vm);
145+ TEST_ASSERT(range.size == expected_left,
146+ "Completed with %llu bytes left, expected %lu",
147+ range.size, expected_left);
148+
149+ /*
150+ * Assert success if prefaulting the entire range should succeed, i.e.
151+ * complete with no bytes remaining. Otherwise prefaulting should have
152+ * failed due to ENOENT (due to RET_PF_EMULATE for emulated MMIO when
153+ * no memslot exists).
154+ */
155+ if (!expected_left)
156+ TEST_ASSERT_VM_VCPU_IOCTL(!ret, KVM_PRE_FAULT_MEMORY, ret, vcpu->vm);
60157 else
61− /* No memory slot causes RET_PF_EMULATE. it results in -ENOENT. */
62− __TEST_ASSERT_VM_VCPU_IOCTL(ret && save_errno == ENOENT,
63− "KVM_PRE_FAULT_MEMORY", ret, vcpu->vm);
158+ TEST_ASSERT_VM_VCPU_IOCTL(ret && save_errno == ENOENT,
159+ KVM_PRE_FAULT_MEMORY, ret, vcpu->vm);
64160 }
65161
66162 static void __test_pre_fault_memory(unsigned long vm_type, bool private)
@@ -97,9 +193,10 @@ static void __test_pre_fault_memory(unsigned long vm_type, bool private) · 30 unmodified lines
97193
98194 if (private)
99195 vm_mem_set_private(vm, guest_test_phys_mem, TEST_SIZE);
100− pre_fault_memory(vcpu, guest_test_phys_mem, SZ_2M, 0);
101− pre_fault_memory(vcpu, guest_test_phys_mem + SZ_2M, PAGE_SIZE * 2, PAGE_SIZE);
102− pre_fault_memory(vcpu, guest_test_phys_mem + TEST_SIZE, PAGE_SIZE, PAGE_SIZE);
196+
197+ pre_fault_memory(vcpu, guest_test_phys_mem, 0, SZ_2M, 0, private);
198+ pre_fault_memory(vcpu, guest_test_phys_mem, SZ_2M, PAGE_SIZE * 2, PAGE_SIZE, private);
199+ pre_fault_memory(vcpu, guest_test_phys_mem, TEST_SIZE, PAGE_SIZE, PAGE_SIZE, private);
103200
104201 vcpu_args_set(vcpu, 1, guest_test_virt_mem);
105202 vcpu_run(vcpu);
tools/testing/selftests/kvm/s390/ucontrol_test.c+7−9
@@ -142,19 +142,17 @@ FIXTURE_SETUP(uc_kvm) · 141 unmodified lines
142142 self->kvm_run_size = ioctl(self->kvm_fd, KVM_GET_VCPU_MMAP_SIZE, NULL);
143143 ASSERT_GE(self->kvm_run_size, sizeof(struct kvm_run))
144144 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);
148147 /**
149148 * For virtual cpus that have been created with S390 user controlled
150149 * virtual machines, the resulting vcpu fd can be memory mapped at page
151150 * offset KVM_S390_SIE_PAGE_OFFSET in order to obtain a memory map of
152151 * the virtual cpu's hardware control block.
153152 */
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);
158156
159157 TH_LOG("VM created %p %p", self->run, self->sie_block);
160158
@@ -186,8 +184,8 @@ FIXTURE_SETUP(uc_kvm) · 25 unmodified lines
186184
187185 FIXTURE_TEARDOWN(uc_kvm)
188186 {
189− munmap(self->sie_block, PAGE_SIZE);
190− munmap(self->run, self->kvm_run_size);
187+ kvm_munmap(self->sie_block, PAGE_SIZE);
188+ kvm_munmap(self->run, self->kvm_run_size);
191189 close(self->vcpu_fd);
192190 close(self->vm_fd);
193191 close(self->kvm_fd);
tools/testing/selftests/kvm/set_memory_region_test.c+8−9
@@ -433,10 +433,10 @@ static void test_add_max_memory_regions(void) · 432 unmodified lines
433433 pr_info("Adding slots 0..%i, each memory region with %dK size\n",
434434 (max_mem_slots - 1), MEM_REGION_SIZE >> 10);
435435
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);
440440 mem_aligned = (void *)(((size_t) mem + alignment - 1) & ~(alignment - 1));
441441
442442 for (slot = 0; slot < max_mem_slots; slot++)
@@ -446,9 +446,8 @@ static void test_add_max_memory_regions(void) · 3 unmodified lines
446446 mem_aligned + (uint64_t)slot * MEM_REGION_SIZE);
447447
448448 /* 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);
452451
453452 ret = __vm_set_user_memory_region(vm, max_mem_slots, 0,
454453 (uint64_t)max_mem_slots * MEM_REGION_SIZE,
@@ -456,8 +455,8 @@ static void test_add_max_memory_regions(void) · 1 unmodified line
456455 TEST_ASSERT(ret == -1 && errno == EINVAL,
457456 "Adding one more memory slot should fail with EINVAL");
458457
459− munmap(mem, (size_t)max_mem_slots * MEM_REGION_SIZE + alignment);
460− munmap(mem_extra, MEM_REGION_SIZE);
458+ kvm_munmap(mem, (size_t)max_mem_slots * MEM_REGION_SIZE + alignment);
459+ kvm_munmap(mem_extra, MEM_REGION_SIZE);
461460 kvm_vm_free(vm);
462461 }
463462
virt/kvm/Kconfig+1−0
@@ -113,6 +113,7 @@ config KVM_GENERIC_MEMORY_ATTRIBUTES · 112 unmodified lines
113113 bool
114114
115115 config KVM_GUEST_MEMFD
116+ depends on KVM_GENERIC_MMU_NOTIFIER
116117 select XARRAY_MULTI
117118 bool
118119
virt/kvm/guest_memfd.c+49−26
@@ -102,8 +102,17 @@ static struct folio *kvm_gmem_get_folio(struct inode *inode, pgoff_t index) · 101 unmodified lines
102102 return filemap_grab_folio(inode->i_mapping, index);
103103 }
104104
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)
107116 {
108117 bool flush = false, found_memslot = false;
109118 struct kvm_memory_slot *slot;
@@ -118,8 +127,7 @@ static void kvm_gmem_invalidate_begin(struct kvm_gmem *gmem, pgoff_t start, · 8 unmodified lines
118127 .end = slot->base_gfn + min(pgoff + slot->npages, end) - pgoff,
119128 .slot = slot,
120129 .may_block = true,
121− /* guest memfd is relevant to only private mappings. */
122− .attr_filter = KVM_FILTER_PRIVATE,
130+ .attr_filter = attr_filter,
123131 };
124132
125133 if (!found_memslot) {
@@ -139,8 +147,21 @@ static void kvm_gmem_invalidate_begin(struct kvm_gmem *gmem, pgoff_t start, · 13 unmodified lines
139147 KVM_MMU_UNLOCK(kvm);
140148 }
141149
142−static void kvm_gmem_invalidate_end(struct kvm_gmem *gmem, pgoff_t start,
143− pgoff_t end)
150+static void kvm_gmem_invalidate_begin(struct inode *inode, pgoff_t start,
151+ pgoff_t end)
152+{
153+ struct list_head *gmem_list = &inode->i_mapping->i_private_list;
154+ enum kvm_gfn_range_filter attr_filter;
155+ struct kvm_gmem *gmem;
156+
157+ attr_filter = kvm_gmem_get_invalidate_filter(inode);
158+
159+ list_for_each_entry(gmem, gmem_list, entry)
160+ __kvm_gmem_invalidate_begin(gmem, start, end, attr_filter);
161+}
162+
163+static void __kvm_gmem_invalidate_end(struct kvm_gmem *gmem, pgoff_t start,
164+ pgoff_t end)
144165 {
145166 struct kvm *kvm = gmem->kvm;
146167
@@ -151,12 +172,20 @@ static void kvm_gmem_invalidate_end(struct kvm_gmem *gmem, pgoff_t start, · 4 unmodified lines
151172 }
152173 }
153174
154−static long kvm_gmem_punch_hole(struct inode *inode, loff_t offset, loff_t len)
175+static void kvm_gmem_invalidate_end(struct inode *inode, pgoff_t start,
176+ pgoff_t end)
155177 {
156178 struct list_head *gmem_list = &inode->i_mapping->i_private_list;
179+ struct kvm_gmem *gmem;
180+
181+ list_for_each_entry(gmem, gmem_list, entry)
182+ __kvm_gmem_invalidate_end(gmem, start, end);
183+}
184+
185+static long kvm_gmem_punch_hole(struct inode *inode, loff_t offset, loff_t len)
186+{
157187 pgoff_t start = offset >> PAGE_SHIFT;
158188 pgoff_t end = (offset + len) >> PAGE_SHIFT;
159− struct kvm_gmem *gmem;
160189
161190 /*
162191 * Bindings must be stable across invalidation to ensure the start+end
@@ -164,13 +193,11 @@ static long kvm_gmem_punch_hole(struct inode *inode, loff_t offset, loff_t len) · 1 unmodified line
164193 */
165194 filemap_invalidate_lock(inode->i_mapping);
166195
167− list_for_each_entry(gmem, gmem_list, entry)
168− kvm_gmem_invalidate_begin(gmem, start, end);
196+ kvm_gmem_invalidate_begin(inode, start, end);
169197
170198 truncate_inode_pages_range(inode->i_mapping, offset, offset + len - 1);
171199
172− list_for_each_entry(gmem, gmem_list, entry)
173− kvm_gmem_invalidate_end(gmem, start, end);
200+ kvm_gmem_invalidate_end(inode, start, end);
174201
175202 filemap_invalidate_unlock(inode->i_mapping);
176203
@@ -280,8 +307,9 @@ static int kvm_gmem_release(struct inode *inode, struct file *file) · 103 unmodified lines
280307 * Zap all SPTEs pointed at by this file. Do not free the backing
281308 * memory, as its lifetime is associated with the inode, not the file.
282309 */
283− kvm_gmem_invalidate_begin(gmem, 0, -1ul);
284− kvm_gmem_invalidate_end(gmem, 0, -1ul);
310+ __kvm_gmem_invalidate_begin(gmem, 0, -1ul,
311+ kvm_gmem_get_invalidate_filter(inode));
312+ __kvm_gmem_invalidate_end(gmem, 0, -1ul);
285313
286314 list_del(&gmem->entry);
287315
@@ -328,6 +356,9 @@ static vm_fault_t kvm_gmem_fault_user_mapping(struct vm_fault *vmf) · 40 unmodified lines
328356 if (((loff_t)vmf->pgoff << PAGE_SHIFT) >= i_size_read(inode))
329357 return VM_FAULT_SIGBUS;
330358
359+ if (!((u64)inode->i_private & GUEST_MEMFD_FLAG_INIT_SHARED))
360+ return VM_FAULT_SIGBUS;
361+
331362 folio = kvm_gmem_get_folio(inode, vmf->pgoff);
332363 if (IS_ERR(folio)) {
333364 int err = PTR_ERR(folio);
@@ -400,8 +431,6 @@ static int kvm_gmem_migrate_folio(struct address_space *mapping, · 66 unmodified lines
400431
401432 static int kvm_gmem_error_folio(struct address_space *mapping, struct folio *folio)
402433 {
403− struct list_head *gmem_list = &mapping->i_private_list;
404− struct kvm_gmem *gmem;
405434 pgoff_t start, end;
406435
407436 filemap_invalidate_lock_shared(mapping);
@@ -409,8 +438,7 @@ static int kvm_gmem_error_folio(struct address_space *mapping, struct folio *fol · 1 unmodified line
409438 start = folio->index;
410439 end = start + folio_nr_pages(folio);
411440
412− list_for_each_entry(gmem, gmem_list, entry)
413− kvm_gmem_invalidate_begin(gmem, start, end);
441+ kvm_gmem_invalidate_begin(mapping->host, start, end);
414442
415443 /*
416444 * Do not truncate the range, what action is taken in response to the
@@ -421,8 +449,7 @@ static int kvm_gmem_error_folio(struct address_space *mapping, struct folio *fol · 4 unmodified lines
421449 * error to userspace.
422450 */
423451
424− list_for_each_entry(gmem, gmem_list, entry)
425− kvm_gmem_invalidate_end(gmem, start, end);
452+ kvm_gmem_invalidate_end(mapping->host, start, end);
426453
427454 filemap_invalidate_unlock_shared(mapping);
428455
@@ -458,7 +485,7 @@ static const struct inode_operations kvm_gmem_iops = { · 29 unmodified lines
458485 .setattr = kvm_gmem_setattr,
459486 };
460487
461−bool __weak kvm_arch_supports_gmem_mmap(struct kvm *kvm)
488+bool __weak kvm_arch_supports_gmem_init_shared(struct kvm *kvm)
462489 {
463490 return true;
464491 }
@@ -522,12 +549,8 @@ int kvm_gmem_create(struct kvm *kvm, struct kvm_create_guest_memfd *args) · 57 unmodified lines
522549 {
523550 loff_t size = args->size;
524551 u64 flags = args->flags;
525− u64 valid_flags = 0;
526−
527− if (kvm_arch_supports_gmem_mmap(kvm))
528− valid_flags |= GUEST_MEMFD_FLAG_MMAP;
529552
530− if (flags & ~valid_flags)
553+ if (flags & ~kvm_gmem_get_supported_flags(kvm))
531554 return -EINVAL;
532555
533556 if (size <= 0 || !PAGE_ALIGNED(size))
virt/kvm/kvm_main.c+2−2
@@ -4928,8 +4928,8 @@ static int kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg) · 4927 unmodified lines
49284928 #ifdef CONFIG_KVM_GUEST_MEMFD
49294929 case KVM_CAP_GUEST_MEMFD:
49304930 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);
49334933 #endif
49344934 default:
49354935 break;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t