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

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

KVM selftests changes for 6.3:

- Cache the CPU vendor (AMD vs. Intel) and use the info to emit the correct
hypercall instruction instead of relying on KVM to patch in VMMCALL

- A variety of one-off cleanups and fixes

+63 -62
+26 -4
tools/testing/selftests/kvm/include/x86_64/processor.h
··· 19 19 20 20 #include "../kvm_util.h" 21 21 22 + extern bool host_cpu_is_intel; 23 + extern bool host_cpu_is_amd; 24 + 22 25 #define NMI_VECTOR 0x02 23 26 24 27 #define X86_EFLAGS_FIXED (1u << 1) ··· 558 555 return x86_model(this_cpu_fms()); 559 556 } 560 557 558 + static inline bool this_cpu_vendor_string_is(const char *vendor) 559 + { 560 + const uint32_t *chunk = (const uint32_t *)vendor; 561 + uint32_t eax, ebx, ecx, edx; 562 + 563 + cpuid(0, &eax, &ebx, &ecx, &edx); 564 + return (ebx == chunk[0] && edx == chunk[1] && ecx == chunk[2]); 565 + } 566 + 567 + static inline bool this_cpu_is_intel(void) 568 + { 569 + return this_cpu_vendor_string_is("GenuineIntel"); 570 + } 571 + 572 + /* 573 + * Exclude early K5 samples with a vendor string of "AMDisbetter!" 574 + */ 575 + static inline bool this_cpu_is_amd(void) 576 + { 577 + return this_cpu_vendor_string_is("AuthenticAMD"); 578 + } 579 + 561 580 static inline uint32_t __this_cpu_has(uint32_t function, uint32_t index, 562 581 uint8_t reg, uint8_t lo, uint8_t hi) 563 582 { ··· 716 691 "hlt\n" \ 717 692 ) 718 693 719 - bool is_intel_cpu(void); 720 - bool is_amd_cpu(void); 721 - 722 694 struct kvm_x86_state *vcpu_save_state(struct kvm_vcpu *vcpu); 723 695 void vcpu_load_state(struct kvm_vcpu *vcpu, struct kvm_x86_state *state); 724 696 void kvm_x86_state_cleanup(struct kvm_x86_state *state); ··· 739 717 int r = __vcpu_ioctl(vcpu, KVM_SET_MSRS, msrs); 740 718 741 719 TEST_ASSERT(r == msrs->nmsrs, 742 - "KVM_GET_MSRS failed, r: %i (failed on MSR %x)", 720 + "KVM_SET_MSRS failed, r: %i (failed on MSR %x)", 743 721 r, r < 0 || r >= msrs->nmsrs ? -1 : msrs->entries[r].index); 744 722 } 745 723 static inline void vcpu_debugregs_get(struct kvm_vcpu *vcpu,
+1 -9
tools/testing/selftests/kvm/kvm_binary_stats_test.c
··· 134 134 "Bucket size of stats (%s) is not zero", 135 135 pdesc->name); 136 136 } 137 - size_data += pdesc->size * sizeof(*stats_data); 137 + size_data = max(size_data, pdesc->offset + pdesc->size * sizeof(*stats_data)); 138 138 } 139 139 140 140 /* ··· 148 148 /* Check validity of all stats data size */ 149 149 TEST_ASSERT(size_data >= header.num_desc * sizeof(*stats_data), 150 150 "Data size is not correct"); 151 - 152 - /* Check stats offset */ 153 - for (i = 0; i < header.num_desc; ++i) { 154 - pdesc = get_stats_descriptor(stats_desc, i, &header); 155 - TEST_ASSERT(pdesc->offset < size_data, 156 - "Invalid offset (%u) for stats: %s", 157 - pdesc->offset, pdesc->name); 158 - } 159 151 160 152 /* Allocate memory for stats data */ 161 153 stats_data = malloc(size_data);
+2
tools/testing/selftests/kvm/lib/elf.c
··· 90 90 " hdrp->e_shentsize: %x\n" 91 91 " expected: %zx", 92 92 hdrp->e_shentsize, sizeof(Elf64_Shdr)); 93 + close(fd); 93 94 } 94 95 95 96 /* VM ELF Load ··· 191 190 phdr.p_filesz); 192 191 } 193 192 } 193 + close(fd); 194 194 }
+1 -1
tools/testing/selftests/kvm/lib/guest_modes.c
··· 127 127 mode_selected = true; 128 128 } 129 129 130 - mode = strtoul(optarg, NULL, 10); 130 + mode = atoi_non_negative("Guest mode ID", arg); 131 131 TEST_ASSERT(mode < NUM_VM_MODES, "Guest mode ID %d too big", mode); 132 132 guest_modes[mode].enabled = true; 133 133 }
-3
tools/testing/selftests/kvm/lib/kvm_util.c
··· 1942 1942 return vm_phy_pages_alloc(vm, 1, paddr_min, memslot); 1943 1943 } 1944 1944 1945 - /* Arbitrary minimum physical address used for virtual translation tables. */ 1946 - #define KVM_GUEST_PAGE_TABLE_MIN_PADDR 0x180000 1947 - 1948 1945 vm_paddr_t vm_alloc_page_table(struct kvm_vm *vm) 1949 1946 { 1950 1947 return vm_phy_page_alloc(vm, KVM_GUEST_PAGE_TABLE_MIN_PADDR,
+20 -26
tools/testing/selftests/kvm/lib/x86_64/processor.c
··· 19 19 #define MAX_NR_CPUID_ENTRIES 100 20 20 21 21 vm_vaddr_t exception_handlers; 22 + bool host_cpu_is_amd; 23 + bool host_cpu_is_intel; 22 24 23 25 static void regs_dump(FILE *stream, struct kvm_regs *regs, uint8_t indent) 24 26 { ··· 115 113 116 114 bool kvm_is_tdp_enabled(void) 117 115 { 118 - if (is_intel_cpu()) 116 + if (host_cpu_is_intel) 119 117 return get_kvm_intel_param_bool("ept"); 120 118 else 121 119 return get_kvm_amd_param_bool("npt"); ··· 557 555 void kvm_arch_vm_post_create(struct kvm_vm *vm) 558 556 { 559 557 vm_create_irqchip(vm); 558 + sync_global_to_guest(vm, host_cpu_is_intel); 559 + sync_global_to_guest(vm, host_cpu_is_amd); 560 560 } 561 561 562 562 struct kvm_vcpu *vm_arch_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id, ··· 1010 1006 free(state); 1011 1007 } 1012 1008 1013 - static bool cpu_vendor_string_is(const char *vendor) 1014 - { 1015 - const uint32_t *chunk = (const uint32_t *)vendor; 1016 - uint32_t eax, ebx, ecx, edx; 1017 - 1018 - cpuid(0, &eax, &ebx, &ecx, &edx); 1019 - return (ebx == chunk[0] && edx == chunk[1] && ecx == chunk[2]); 1020 - } 1021 - 1022 - bool is_intel_cpu(void) 1023 - { 1024 - return cpu_vendor_string_is("GenuineIntel"); 1025 - } 1026 - 1027 - /* 1028 - * Exclude early K5 samples with a vendor string of "AMDisbetter!" 1029 - */ 1030 - bool is_amd_cpu(void) 1031 - { 1032 - return cpu_vendor_string_is("AuthenticAMD"); 1033 - } 1034 - 1035 1009 void kvm_get_cpu_address_width(unsigned int *pa_bits, unsigned int *va_bits) 1036 1010 { 1037 1011 if (!kvm_cpu_has_p(X86_PROPERTY_MAX_PHY_ADDR)) { ··· 1144 1162 { 1145 1163 uint64_t r; 1146 1164 1147 - asm volatile("vmcall" 1165 + asm volatile("test %[use_vmmcall], %[use_vmmcall]\n\t" 1166 + "jnz 1f\n\t" 1167 + "vmcall\n\t" 1168 + "jmp 2f\n\t" 1169 + "1: vmmcall\n\t" 1170 + "2:" 1148 1171 : "=a"(r) 1149 - : "a"(nr), "b"(a0), "c"(a1), "d"(a2), "S"(a3)); 1172 + : "a"(nr), "b"(a0), "c"(a1), "d"(a2), "S"(a3), 1173 + [use_vmmcall] "r" (host_cpu_is_amd)); 1150 1174 return r; 1151 1175 } 1152 1176 ··· 1224 1236 max_gfn = (1ULL << (vm->pa_bits - vm->page_shift)) - 1; 1225 1237 1226 1238 /* Avoid reserved HyperTransport region on AMD processors. */ 1227 - if (!is_amd_cpu()) 1239 + if (!host_cpu_is_amd) 1228 1240 return max_gfn; 1229 1241 1230 1242 /* On parts with <40 physical address bits, the area is fully hidden */ ··· 1263 1275 close(open_kvm_dev_path_or_exit()); 1264 1276 1265 1277 return get_kvm_intel_param_bool("unrestricted_guest"); 1278 + } 1279 + 1280 + void kvm_selftest_arch_init(void) 1281 + { 1282 + host_cpu_is_intel = this_cpu_is_intel(); 1283 + host_cpu_is_amd = this_cpu_is_amd(); 1266 1284 }
+1 -4
tools/testing/selftests/kvm/memslot_perf_test.c
··· 308 308 data->hva_slots = malloc(sizeof(*data->hva_slots) * data->nslots); 309 309 TEST_ASSERT(data->hva_slots, "malloc() fail"); 310 310 311 - data->vm = __vm_create_with_one_vcpu(&data->vcpu, mempages, guest_code); 312 - 313 311 pr_info_v("Adding slots 1..%i, each slot with %"PRIu64" pages + %"PRIu64" extra pages last\n", 314 312 data->nslots, data->pages_per_slot, rempages); 315 313 ··· 347 349 virt_map(data->vm, MEM_GPA, MEM_GPA, data->npages); 348 350 349 351 sync = (typeof(sync))vm_gpa2hva(data, MEM_SYNC_GPA, NULL); 352 + sync->guest_page_size = data->vm->page_size; 350 353 atomic_init(&sync->start_flag, false); 351 354 atomic_init(&sync->exit_flag, false); 352 355 atomic_init(&sync->sync_flag, false); ··· 809 810 } 810 811 811 812 sync = (typeof(sync))vm_gpa2hva(data, MEM_SYNC_GPA, NULL); 812 - 813 - sync->guest_page_size = data->vm->page_size; 814 813 if (tdata->prepare && 815 814 !tdata->prepare(data, sync, maxslots)) { 816 815 ret = false;
+2 -2
tools/testing/selftests/kvm/x86_64/fix_hypercall_test.c
··· 48 48 const uint8_t *other_hypercall_insn; 49 49 uint64_t ret; 50 50 51 - if (is_intel_cpu()) { 51 + if (host_cpu_is_intel) { 52 52 native_hypercall_insn = vmx_vmcall; 53 53 other_hypercall_insn = svm_vmmcall; 54 - } else if (is_amd_cpu()) { 54 + } else if (host_cpu_is_amd) { 55 55 native_hypercall_insn = svm_vmmcall; 56 56 other_hypercall_insn = vmx_vmcall; 57 57 } else {
+1 -1
tools/testing/selftests/kvm/x86_64/mmio_warning_test.c
··· 93 93 { 94 94 int warnings_before, warnings_after; 95 95 96 - TEST_REQUIRE(is_intel_cpu()); 96 + TEST_REQUIRE(host_cpu_is_intel); 97 97 98 98 TEST_REQUIRE(!vm_is_unrestricted_guest(NULL)); 99 99
+2 -2
tools/testing/selftests/kvm/x86_64/pmu_event_filter_test.c
··· 364 364 */ 365 365 static bool use_intel_pmu(void) 366 366 { 367 - return is_intel_cpu() && 367 + return host_cpu_is_intel && 368 368 kvm_cpu_property(X86_PROPERTY_PMU_VERSION) && 369 369 kvm_cpu_property(X86_PROPERTY_PMU_NR_GP_COUNTERS) && 370 370 kvm_pmu_has(X86_PMU_FEATURE_BRANCH_INSNS_RETIRED); ··· 398 398 uint32_t family = kvm_cpu_family(); 399 399 uint32_t model = kvm_cpu_model(); 400 400 401 - return is_amd_cpu() && 401 + return host_cpu_is_amd && 402 402 (is_zen1(family, model) || 403 403 is_zen2(family, model) || 404 404 is_zen3(family, model));
+1 -1
tools/testing/selftests/kvm/x86_64/vmx_exception_with_invalid_guest_state.c
··· 111 111 struct kvm_vcpu *vcpu; 112 112 struct kvm_vm *vm; 113 113 114 - TEST_REQUIRE(is_intel_cpu()); 114 + TEST_REQUIRE(host_cpu_is_intel); 115 115 TEST_REQUIRE(!vm_is_unrestricted_guest(NULL)); 116 116 117 117 vm = vm_create_with_one_vcpu(&vcpu, guest_code);
+6 -9
tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c
··· 19 19 20 20 #include <sys/eventfd.h> 21 21 22 - /* Defined in include/linux/kvm_types.h */ 23 - #define GPA_INVALID (~(ulong)0) 24 - 25 22 #define SHINFO_REGION_GVA 0xc0000000ULL 26 23 #define SHINFO_REGION_GPA 0xc0000000ULL 27 24 #define SHINFO_REGION_SLOT 10 ··· 409 412 { 410 413 struct kvm_vm *vm = (struct kvm_vm *)arg; 411 414 412 - struct kvm_xen_hvm_attr cache_init = { 415 + struct kvm_xen_hvm_attr cache_activate = { 413 416 .type = KVM_XEN_ATTR_TYPE_SHARED_INFO, 414 417 .u.shared_info.gfn = SHINFO_REGION_GPA / PAGE_SIZE 415 418 }; 416 419 417 - struct kvm_xen_hvm_attr cache_destroy = { 420 + struct kvm_xen_hvm_attr cache_deactivate = { 418 421 .type = KVM_XEN_ATTR_TYPE_SHARED_INFO, 419 - .u.shared_info.gfn = GPA_INVALID 422 + .u.shared_info.gfn = KVM_XEN_INVALID_GFN 420 423 }; 421 424 422 425 for (;;) { 423 - __vm_ioctl(vm, KVM_XEN_HVM_SET_ATTR, &cache_init); 424 - __vm_ioctl(vm, KVM_XEN_HVM_SET_ATTR, &cache_destroy); 426 + __vm_ioctl(vm, KVM_XEN_HVM_SET_ATTR, &cache_activate); 427 + __vm_ioctl(vm, KVM_XEN_HVM_SET_ATTR, &cache_deactivate); 425 428 pthread_testcancel(); 426 - }; 429 + } 427 430 428 431 return NULL; 429 432 }