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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'kvm-x86-selftests-7.1' of https://github.com/kvm-x86/linux into HEAD

KVM selftests changes for 7.1

- Add support for Hygon CPUs in KVM selftests.

- Fix a bug in the MSR test where it would get false failures on AMD/Hygon
CPUs with exactly one of RDPID or RDTSCP.

- Add an MADV_COLLAPSE testcase for guest_memfd as a regression test for a
bug where the kernel would attempt to collapse guest_memfd folios against
KVM's will.

+92 -12
+67 -3
tools/testing/selftests/kvm/guest_memfd_test.c
··· 171 171 kvm_munmap(mem, total_size); 172 172 } 173 173 174 + static void test_collapse(int fd, uint64_t flags) 175 + { 176 + const size_t pmd_size = get_trans_hugepagesz(); 177 + void *reserved_addr; 178 + void *aligned_addr; 179 + char *mem; 180 + off_t i; 181 + 182 + /* 183 + * To even reach the point where the guest_memfd folios will 184 + * get collapsed, both the userspace address and the offset 185 + * within the guest_memfd have to be aligned to pmd_size. 186 + * 187 + * To achieve that alignment, reserve virtual address space 188 + * with regular mmap, then use MAP_FIXED to allocate memory 189 + * from a pmd_size-aligned offset (0) at a known, available 190 + * virtual address. 191 + */ 192 + reserved_addr = kvm_mmap(pmd_size * 2, PROT_NONE, 193 + MAP_PRIVATE | MAP_ANONYMOUS, -1); 194 + aligned_addr = align_ptr_up(reserved_addr, pmd_size); 195 + 196 + mem = mmap(aligned_addr, pmd_size, PROT_READ | PROT_WRITE, 197 + MAP_FIXED | MAP_SHARED, fd, 0); 198 + TEST_ASSERT(IS_ALIGNED((u64)mem, pmd_size), 199 + "Userspace address must be aligned to PMD size."); 200 + 201 + /* 202 + * Use reads to populate page table to avoid setting dirty 203 + * flag on page. 204 + */ 205 + for (i = 0; i < pmd_size; i += getpagesize()) 206 + READ_ONCE(mem[i]); 207 + 208 + /* 209 + * Advising the use of huge pages in guest_memfd should be 210 + * fine... 211 + */ 212 + kvm_madvise(mem, pmd_size, MADV_HUGEPAGE); 213 + 214 + /* 215 + * ... but collapsing folios must not be supported to avoid 216 + * mapping beyond shared ranges into host userspace page 217 + * tables. 218 + */ 219 + TEST_ASSERT_EQ(madvise(mem, pmd_size, MADV_COLLAPSE), -1); 220 + TEST_ASSERT_EQ(errno, EINVAL); 221 + 222 + /* 223 + * Removing from host page tables and re-faulting should be 224 + * fine; should not end up faulting in a collapsed/huge folio. 225 + */ 226 + kvm_madvise(mem, pmd_size, MADV_DONTNEED); 227 + READ_ONCE(mem[0]); 228 + 229 + kvm_munmap(reserved_addr, pmd_size * 2); 230 + } 231 + 174 232 static void test_fault_sigbus(int fd, size_t accessible_size, size_t map_size) 175 233 { 176 234 const char val = 0xaa; ··· 408 350 } 409 351 } 410 352 411 - #define gmem_test(__test, __vm, __flags) \ 353 + #define __gmem_test(__test, __vm, __flags, __gmem_size) \ 412 354 do { \ 413 - int fd = vm_create_guest_memfd(__vm, page_size * 4, __flags); \ 355 + int fd = vm_create_guest_memfd(__vm, __gmem_size, __flags); \ 414 356 \ 415 - test_##__test(fd, page_size * 4); \ 357 + test_##__test(fd, __gmem_size); \ 416 358 close(fd); \ 417 359 } while (0) 360 + 361 + #define gmem_test(__test, __vm, __flags) \ 362 + __gmem_test(__test, __vm, __flags, page_size * 4) 418 363 419 364 static void __test_guest_memfd(struct kvm_vm *vm, uint64_t flags) 420 365 { ··· 428 367 429 368 if (flags & GUEST_MEMFD_FLAG_MMAP) { 430 369 if (flags & GUEST_MEMFD_FLAG_INIT_SHARED) { 370 + size_t pmd_size = get_trans_hugepagesz(); 371 + 431 372 gmem_test(mmap_supported, vm, flags); 432 373 gmem_test(fault_overflow, vm, flags); 433 374 gmem_test(numa_allocation, vm, flags); 375 + __gmem_test(collapse, vm, flags, pmd_size); 434 376 } else { 435 377 gmem_test(fault_private, vm, flags); 436 378 }
+1
tools/testing/selftests/kvm/include/kvm_syscalls.h
··· 77 77 __KVM_SYSCALL_DEFINE(close, 1, int, fd); 78 78 __KVM_SYSCALL_DEFINE(fallocate, 4, int, fd, int, mode, loff_t, offset, loff_t, len); 79 79 __KVM_SYSCALL_DEFINE(ftruncate, 2, unsigned int, fd, off_t, length); 80 + __KVM_SYSCALL_DEFINE(madvise, 3, void *, addr, size_t, length, int, advice); 80 81 81 82 #endif /* SELFTEST_KVM_SYSCALLS_H */
+7
tools/testing/selftests/kvm/include/x86/processor.h
··· 21 21 22 22 extern bool host_cpu_is_intel; 23 23 extern bool host_cpu_is_amd; 24 + extern bool host_cpu_is_hygon; 25 + extern bool host_cpu_is_amd_compatible; 24 26 extern uint64_t guest_tsc_khz; 25 27 26 28 #ifndef MAX_NR_CPUID_ENTRIES ··· 717 715 static inline bool this_cpu_is_amd(void) 718 716 { 719 717 return this_cpu_vendor_string_is("AuthenticAMD"); 718 + } 719 + 720 + static inline bool this_cpu_is_hygon(void) 721 + { 722 + return this_cpu_vendor_string_is("HygonGenuine"); 720 723 } 721 724 722 725 static inline uint32_t __this_cpu_has(uint32_t function, uint32_t index,
+11 -4
tools/testing/selftests/kvm/lib/x86/processor.c
··· 24 24 vm_vaddr_t exception_handlers; 25 25 bool host_cpu_is_amd; 26 26 bool host_cpu_is_intel; 27 + bool host_cpu_is_hygon; 28 + bool host_cpu_is_amd_compatible; 27 29 bool is_forced_emulation_enabled; 28 30 uint64_t guest_tsc_khz; 29 31 ··· 795 793 796 794 sync_global_to_guest(vm, host_cpu_is_intel); 797 795 sync_global_to_guest(vm, host_cpu_is_amd); 796 + sync_global_to_guest(vm, host_cpu_is_hygon); 797 + sync_global_to_guest(vm, host_cpu_is_amd_compatible); 798 798 sync_global_to_guest(vm, is_forced_emulation_enabled); 799 799 sync_global_to_guest(vm, pmu_errata_mask); 800 800 ··· 1353 1349 "1: vmmcall\n\t" \ 1354 1350 "2:" \ 1355 1351 : "=a"(r) \ 1356 - : [use_vmmcall] "r" (host_cpu_is_amd), inputs); \ 1352 + : [use_vmmcall] "r" (host_cpu_is_amd_compatible), \ 1353 + inputs); \ 1357 1354 \ 1358 1355 r; \ 1359 1356 }) ··· 1394 1389 1395 1390 max_gfn = (1ULL << (guest_maxphyaddr - vm->page_shift)) - 1; 1396 1391 1397 - /* Avoid reserved HyperTransport region on AMD processors. */ 1398 - if (!host_cpu_is_amd) 1392 + /* Avoid reserved HyperTransport region on AMD or Hygon processors. */ 1393 + if (!host_cpu_is_amd_compatible) 1399 1394 return max_gfn; 1400 1395 1401 1396 /* On parts with <40 physical address bits, the area is fully hidden */ ··· 1409 1404 1410 1405 /* 1411 1406 * Otherwise it's at the top of the physical address space, possibly 1412 - * reduced due to SME by bits 11:6 of CPUID[0x8000001f].EBX. Use 1407 + * reduced due to SME or CSV by bits 11:6 of CPUID[0x8000001f].EBX. Use 1413 1408 * the old conservative value if MAXPHYADDR is not enumerated. 1414 1409 */ 1415 1410 if (!this_cpu_has_p(X86_PROPERTY_MAX_PHY_ADDR)) ··· 1430 1425 { 1431 1426 host_cpu_is_intel = this_cpu_is_intel(); 1432 1427 host_cpu_is_amd = this_cpu_is_amd(); 1428 + host_cpu_is_hygon = this_cpu_is_hygon(); 1429 + host_cpu_is_amd_compatible = host_cpu_is_amd || host_cpu_is_hygon; 1433 1430 is_forced_emulation_enabled = kvm_is_forced_emulation_enabled(); 1434 1431 1435 1432 kvm_init_pmu_errata();
+1 -1
tools/testing/selftests/kvm/x86/fix_hypercall_test.c
··· 52 52 if (host_cpu_is_intel) { 53 53 native_hypercall_insn = vmx_vmcall; 54 54 other_hypercall_insn = svm_vmmcall; 55 - } else if (host_cpu_is_amd) { 55 + } else if (host_cpu_is_amd_compatible) { 56 56 native_hypercall_insn = svm_vmmcall; 57 57 other_hypercall_insn = vmx_vmcall; 58 58 } else {
+2 -2
tools/testing/selftests/kvm/x86/msrs_test.c
··· 81 81 * is supposed to emulate that behavior based on guest vendor model 82 82 * (which is the same as the host vendor model for this test). 83 83 */ 84 - if (!host_cpu_is_amd) 84 + if (!host_cpu_is_amd_compatible) 85 85 return want; 86 86 87 87 switch (msr) { ··· 175 175 * If the CPU will truncate the written value (e.g. SYSENTER on AMD), 176 176 * expect success and a truncated value, not #GP. 177 177 */ 178 - if (!this_cpu_has(msr->feature) || 178 + if ((!this_cpu_has(msr->feature) && !this_cpu_has(msr->feature2)) || 179 179 msr->rsvd_val == fixup_rdmsr_val(msr->index, msr->rsvd_val)) { 180 180 u8 vec = wrmsr_safe(msr->index, msr->rsvd_val); 181 181
+2 -1
tools/testing/selftests/kvm/x86/pmu_event_filter_test.c
··· 361 361 */ 362 362 static bool use_amd_pmu(void) 363 363 { 364 - return host_cpu_is_amd && kvm_cpu_family() >= 0x17; 364 + return (host_cpu_is_amd && kvm_cpu_family() >= 0x17) || 365 + host_cpu_is_hygon; 365 366 } 366 367 367 368 /*
+1 -1
tools/testing/selftests/kvm/x86/xapic_state_test.c
··· 248 248 * drops writes, AMD does not). Account for the errata when checking 249 249 * that KVM reads back what was written. 250 250 */ 251 - x.has_xavic_errata = host_cpu_is_amd && 251 + x.has_xavic_errata = host_cpu_is_amd_compatible && 252 252 get_kvm_amd_param_bool("avic"); 253 253 254 254 vcpu_clear_cpuid_feature(x.vcpu, X86_FEATURE_X2APIC);