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.12' of https://github.com/kvm-x86/linux into HEAD

KVM selftests changes for 6.12:

- Fix a goof that caused some Hyper-V tests to be skipped when run on bare
metal, i.e. NOT in a VM.

- Add a regression test for KVM's handling of SHUTDOWN for an SEV-ES guest.

- Explicitly include one-off assets in .gitignore. Past Sean was completely
wrong about not being able to detect missing .gitignore entries.

- Verify userspace single-stepping works when KVM happens to handle a VM-Exit
in its fastpath.

- Misc cleanups

+140 -151
+3
tools/testing/selftests/kvm/.gitignore
··· 5 5 !*.h 6 6 !*.S 7 7 !*.sh 8 + !.gitignore 8 9 !config 10 + !settings 11 + !Makefile
-2
tools/testing/selftests/kvm/include/kvm_util.h
··· 428 428 void kvm_vm_free(struct kvm_vm *vmp); 429 429 void kvm_vm_restart(struct kvm_vm *vmp); 430 430 void kvm_vm_release(struct kvm_vm *vmp); 431 - int kvm_memcmp_hva_gva(void *hva, struct kvm_vm *vm, const vm_vaddr_t gva, 432 - size_t len); 433 431 void kvm_vm_elf_load(struct kvm_vm *vm, const char *filename); 434 432 int kvm_memfd_alloc(size_t size, bool hugepages); 435 433
+18
tools/testing/selftests/kvm/include/x86_64/hyperv.h
··· 186 186 #define HV_X64_ENLIGHTENED_VMCS_RECOMMENDED \ 187 187 KVM_X86_CPU_FEATURE(HYPERV_CPUID_ENLIGHTMENT_INFO, 0, EAX, 14) 188 188 189 + /* HYPERV_CPUID_NESTED_FEATURES.EAX */ 190 + #define HV_X64_NESTED_DIRECT_FLUSH \ 191 + KVM_X86_CPU_FEATURE(HYPERV_CPUID_NESTED_FEATURES, 0, EAX, 17) 192 + #define HV_X64_NESTED_GUEST_MAPPING_FLUSH \ 193 + KVM_X86_CPU_FEATURE(HYPERV_CPUID_NESTED_FEATURES, 0, EAX, 18) 194 + #define HV_X64_NESTED_MSR_BITMAP \ 195 + KVM_X86_CPU_FEATURE(HYPERV_CPUID_NESTED_FEATURES, 0, EAX, 19) 196 + 197 + /* HYPERV_CPUID_NESTED_FEATURES.EBX */ 198 + #define HV_X64_NESTED_EVMCS1_PERF_GLOBAL_CTRL \ 199 + KVM_X86_CPU_FEATURE(HYPERV_CPUID_NESTED_FEATURES, 0, EBX, 0) 200 + 189 201 /* HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES.EAX */ 190 202 #define HV_X64_SYNDBG_CAP_ALLOW_KERNEL_DEBUGGING \ 191 203 KVM_X86_CPU_FEATURE(HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES, 0, EAX, 1) ··· 354 342 355 343 /* HV_X64_MSR_TSC_INVARIANT_CONTROL bits */ 356 344 #define HV_INVARIANT_TSC_EXPOSED BIT_ULL(0) 345 + 346 + const struct kvm_cpuid2 *kvm_get_supported_hv_cpuid(void); 347 + const struct kvm_cpuid2 *vcpu_get_supported_hv_cpuid(struct kvm_vcpu *vcpu); 348 + void vcpu_set_hv_cpuid(struct kvm_vcpu *vcpu); 349 + 350 + bool kvm_hv_cpu_has(struct kvm_x86_cpu_feature feature); 357 351 358 352 #endif /* !SELFTEST_KVM_HYPERV_H */
+4 -3
tools/testing/selftests/kvm/include/x86_64/processor.h
··· 25 25 extern bool host_cpu_is_amd; 26 26 extern uint64_t guest_tsc_khz; 27 27 28 + #ifndef MAX_NR_CPUID_ENTRIES 29 + #define MAX_NR_CPUID_ENTRIES 100 30 + #endif 31 + 28 32 /* Forced emulation prefix, used to invoke the emulator unconditionally. */ 29 33 #define KVM_FEP "ud2; .byte 'k', 'v', 'm';" 30 34 ··· 912 908 const struct kvm_cpuid_entry2 *get_cpuid_entry(const struct kvm_cpuid2 *cpuid, 913 909 uint32_t function, uint32_t index); 914 910 const struct kvm_cpuid2 *kvm_get_supported_cpuid(void); 915 - const struct kvm_cpuid2 *kvm_get_supported_hv_cpuid(void); 916 - const struct kvm_cpuid2 *vcpu_get_supported_hv_cpuid(struct kvm_vcpu *vcpu); 917 911 918 912 static inline uint32_t kvm_cpu_fms(void) 919 913 { ··· 1011 1009 } 1012 1010 1013 1011 void vcpu_init_cpuid(struct kvm_vcpu *vcpu, const struct kvm_cpuid2 *cpuid); 1014 - void vcpu_set_hv_cpuid(struct kvm_vcpu *vcpu); 1015 1012 1016 1013 static inline struct kvm_cpuid_entry2 *__vcpu_get_cpuid_entry(struct kvm_vcpu *vcpu, 1017 1014 uint32_t function,
+6 -79
tools/testing/selftests/kvm/lib/kvm_util.c
··· 712 712 } 713 713 714 714 static void __vm_mem_region_delete(struct kvm_vm *vm, 715 - struct userspace_mem_region *region, 716 - bool unlink) 715 + struct userspace_mem_region *region) 717 716 { 718 717 int ret; 719 718 720 - if (unlink) { 721 - rb_erase(&region->gpa_node, &vm->regions.gpa_tree); 722 - rb_erase(&region->hva_node, &vm->regions.hva_tree); 723 - hash_del(&region->slot_node); 724 - } 719 + rb_erase(&region->gpa_node, &vm->regions.gpa_tree); 720 + rb_erase(&region->hva_node, &vm->regions.hva_tree); 721 + hash_del(&region->slot_node); 725 722 726 723 region->region.memory_size = 0; 727 724 vm_ioctl(vm, KVM_SET_USER_MEMORY_REGION2, &region->region); ··· 759 762 760 763 /* Free userspace_mem_regions. */ 761 764 hash_for_each_safe(vmp->regions.slot_hash, ctr, node, region, slot_node) 762 - __vm_mem_region_delete(vmp, region, false); 765 + __vm_mem_region_delete(vmp, region); 763 766 764 767 /* Free sparsebit arrays. */ 765 768 sparsebit_free(&vmp->vpages_valid); ··· 789 792 TEST_ASSERT(!r, __KVM_SYSCALL_ERROR("fallocate()", r)); 790 793 791 794 return fd; 792 - } 793 - 794 - /* 795 - * Memory Compare, host virtual to guest virtual 796 - * 797 - * Input Args: 798 - * hva - Starting host virtual address 799 - * vm - Virtual Machine 800 - * gva - Starting guest virtual address 801 - * len - number of bytes to compare 802 - * 803 - * Output Args: None 804 - * 805 - * Input/Output Args: None 806 - * 807 - * Return: 808 - * Returns 0 if the bytes starting at hva for a length of len 809 - * are equal the guest virtual bytes starting at gva. Returns 810 - * a value < 0, if bytes at hva are less than those at gva. 811 - * Otherwise a value > 0 is returned. 812 - * 813 - * Compares the bytes starting at the host virtual address hva, for 814 - * a length of len, to the guest bytes starting at the guest virtual 815 - * address given by gva. 816 - */ 817 - int kvm_memcmp_hva_gva(void *hva, struct kvm_vm *vm, vm_vaddr_t gva, size_t len) 818 - { 819 - size_t amt; 820 - 821 - /* 822 - * Compare a batch of bytes until either a match is found 823 - * or all the bytes have been compared. 824 - */ 825 - for (uintptr_t offset = 0; offset < len; offset += amt) { 826 - uintptr_t ptr1 = (uintptr_t)hva + offset; 827 - 828 - /* 829 - * Determine host address for guest virtual address 830 - * at offset. 831 - */ 832 - uintptr_t ptr2 = (uintptr_t)addr_gva2hva(vm, gva + offset); 833 - 834 - /* 835 - * Determine amount to compare on this pass. 836 - * Don't allow the comparsion to cross a page boundary. 837 - */ 838 - amt = len - offset; 839 - if ((ptr1 >> vm->page_shift) != ((ptr1 + amt) >> vm->page_shift)) 840 - amt = vm->page_size - (ptr1 % vm->page_size); 841 - if ((ptr2 >> vm->page_shift) != ((ptr2 + amt) >> vm->page_shift)) 842 - amt = vm->page_size - (ptr2 % vm->page_size); 843 - 844 - assert((ptr1 >> vm->page_shift) == ((ptr1 + amt - 1) >> vm->page_shift)); 845 - assert((ptr2 >> vm->page_shift) == ((ptr2 + amt - 1) >> vm->page_shift)); 846 - 847 - /* 848 - * Perform the comparison. If there is a difference 849 - * return that result to the caller, otherwise need 850 - * to continue on looking for a mismatch. 851 - */ 852 - int ret = memcmp((void *)ptr1, (void *)ptr2, amt); 853 - if (ret != 0) 854 - return ret; 855 - } 856 - 857 - /* 858 - * No mismatch found. Let the caller know the two memory 859 - * areas are equal. 860 - */ 861 - return 0; 862 795 } 863 796 864 797 static void vm_userspace_mem_region_gpa_insert(struct rb_root *gpa_tree, ··· 1197 1270 */ 1198 1271 void vm_mem_region_delete(struct kvm_vm *vm, uint32_t slot) 1199 1272 { 1200 - __vm_mem_region_delete(vm, memslot2region(vm, slot), true); 1273 + __vm_mem_region_delete(vm, memslot2region(vm, slot)); 1201 1274 } 1202 1275 1203 1276 void vm_guest_mem_fallocate(struct kvm_vm *vm, uint64_t base, uint64_t size,
+67
tools/testing/selftests/kvm/lib/x86_64/hyperv.c
··· 8 8 #include "processor.h" 9 9 #include "hyperv.h" 10 10 11 + const struct kvm_cpuid2 *kvm_get_supported_hv_cpuid(void) 12 + { 13 + static struct kvm_cpuid2 *cpuid; 14 + int kvm_fd; 15 + 16 + if (cpuid) 17 + return cpuid; 18 + 19 + cpuid = allocate_kvm_cpuid2(MAX_NR_CPUID_ENTRIES); 20 + kvm_fd = open_kvm_dev_path_or_exit(); 21 + 22 + kvm_ioctl(kvm_fd, KVM_GET_SUPPORTED_HV_CPUID, cpuid); 23 + 24 + close(kvm_fd); 25 + return cpuid; 26 + } 27 + 28 + void vcpu_set_hv_cpuid(struct kvm_vcpu *vcpu) 29 + { 30 + static struct kvm_cpuid2 *cpuid_full; 31 + const struct kvm_cpuid2 *cpuid_sys, *cpuid_hv; 32 + int i, nent = 0; 33 + 34 + if (!cpuid_full) { 35 + cpuid_sys = kvm_get_supported_cpuid(); 36 + cpuid_hv = kvm_get_supported_hv_cpuid(); 37 + 38 + cpuid_full = allocate_kvm_cpuid2(cpuid_sys->nent + cpuid_hv->nent); 39 + if (!cpuid_full) { 40 + perror("malloc"); 41 + abort(); 42 + } 43 + 44 + /* Need to skip KVM CPUID leaves 0x400000xx */ 45 + for (i = 0; i < cpuid_sys->nent; i++) { 46 + if (cpuid_sys->entries[i].function >= 0x40000000 && 47 + cpuid_sys->entries[i].function < 0x40000100) 48 + continue; 49 + cpuid_full->entries[nent] = cpuid_sys->entries[i]; 50 + nent++; 51 + } 52 + 53 + memcpy(&cpuid_full->entries[nent], cpuid_hv->entries, 54 + cpuid_hv->nent * sizeof(struct kvm_cpuid_entry2)); 55 + cpuid_full->nent = nent + cpuid_hv->nent; 56 + } 57 + 58 + vcpu_init_cpuid(vcpu, cpuid_full); 59 + } 60 + 61 + const struct kvm_cpuid2 *vcpu_get_supported_hv_cpuid(struct kvm_vcpu *vcpu) 62 + { 63 + struct kvm_cpuid2 *cpuid = allocate_kvm_cpuid2(MAX_NR_CPUID_ENTRIES); 64 + 65 + vcpu_ioctl(vcpu, KVM_GET_SUPPORTED_HV_CPUID, cpuid); 66 + 67 + return cpuid; 68 + } 69 + 70 + bool kvm_hv_cpu_has(struct kvm_x86_cpu_feature feature) 71 + { 72 + if (!kvm_has_cap(KVM_CAP_SYS_HYPERV_CPUID)) 73 + return false; 74 + 75 + return kvm_cpuid_has(kvm_get_supported_hv_cpuid(), feature); 76 + } 77 + 11 78 struct hyperv_test_pages *vcpu_alloc_hyperv_test_pages(struct kvm_vm *vm, 12 79 vm_vaddr_t *p_hv_pages_gva) 13 80 {
-61
tools/testing/selftests/kvm/lib/x86_64/processor.c
··· 19 19 #define KERNEL_DS 0x10 20 20 #define KERNEL_TSS 0x18 21 21 22 - #define MAX_NR_CPUID_ENTRIES 100 23 - 24 22 vm_vaddr_t exception_handlers; 25 23 bool host_cpu_is_amd; 26 24 bool host_cpu_is_intel; ··· 1189 1191 void xen_hypercall(uint64_t nr, uint64_t a0, void *a1) 1190 1192 { 1191 1193 GUEST_ASSERT(!__xen_hypercall(nr, a0, a1)); 1192 - } 1193 - 1194 - const struct kvm_cpuid2 *kvm_get_supported_hv_cpuid(void) 1195 - { 1196 - static struct kvm_cpuid2 *cpuid; 1197 - int kvm_fd; 1198 - 1199 - if (cpuid) 1200 - return cpuid; 1201 - 1202 - cpuid = allocate_kvm_cpuid2(MAX_NR_CPUID_ENTRIES); 1203 - kvm_fd = open_kvm_dev_path_or_exit(); 1204 - 1205 - kvm_ioctl(kvm_fd, KVM_GET_SUPPORTED_HV_CPUID, cpuid); 1206 - 1207 - close(kvm_fd); 1208 - return cpuid; 1209 - } 1210 - 1211 - void vcpu_set_hv_cpuid(struct kvm_vcpu *vcpu) 1212 - { 1213 - static struct kvm_cpuid2 *cpuid_full; 1214 - const struct kvm_cpuid2 *cpuid_sys, *cpuid_hv; 1215 - int i, nent = 0; 1216 - 1217 - if (!cpuid_full) { 1218 - cpuid_sys = kvm_get_supported_cpuid(); 1219 - cpuid_hv = kvm_get_supported_hv_cpuid(); 1220 - 1221 - cpuid_full = allocate_kvm_cpuid2(cpuid_sys->nent + cpuid_hv->nent); 1222 - if (!cpuid_full) { 1223 - perror("malloc"); 1224 - abort(); 1225 - } 1226 - 1227 - /* Need to skip KVM CPUID leaves 0x400000xx */ 1228 - for (i = 0; i < cpuid_sys->nent; i++) { 1229 - if (cpuid_sys->entries[i].function >= 0x40000000 && 1230 - cpuid_sys->entries[i].function < 0x40000100) 1231 - continue; 1232 - cpuid_full->entries[nent] = cpuid_sys->entries[i]; 1233 - nent++; 1234 - } 1235 - 1236 - memcpy(&cpuid_full->entries[nent], cpuid_hv->entries, 1237 - cpuid_hv->nent * sizeof(struct kvm_cpuid_entry2)); 1238 - cpuid_full->nent = nent + cpuid_hv->nent; 1239 - } 1240 - 1241 - vcpu_init_cpuid(vcpu, cpuid_full); 1242 - } 1243 - 1244 - const struct kvm_cpuid2 *vcpu_get_supported_hv_cpuid(struct kvm_vcpu *vcpu) 1245 - { 1246 - struct kvm_cpuid2 *cpuid = allocate_kvm_cpuid2(MAX_NR_CPUID_ENTRIES); 1247 - 1248 - vcpu_ioctl(vcpu, KVM_GET_SUPPORTED_HV_CPUID, cpuid); 1249 - 1250 - return cpuid; 1251 1194 } 1252 1195 1253 1196 unsigned long vm_compute_max_gfn(struct kvm_vm *vm)
+7 -4
tools/testing/selftests/kvm/x86_64/debug_regs.c
··· 47 47 /* 48 48 * Single step test, covers 2 basic instructions and 2 emulated 49 49 * 50 - * Enable interrupts during the single stepping to see that 51 - * pending interrupt we raised is not handled due to KVM_GUESTDBG_BLOCKIRQ 50 + * Enable interrupts during the single stepping to see that pending 51 + * interrupt we raised is not handled due to KVM_GUESTDBG_BLOCKIRQ. 52 + * 53 + * Write MSR_IA32_TSC_DEADLINE to verify that KVM's fastpath handler 54 + * exits to userspace due to single-step being enabled. 52 55 */ 53 56 asm volatile("ss_start: " 54 57 "sti\n\t" 55 58 "xor %%eax,%%eax\n\t" 56 59 "cpuid\n\t" 57 - "movl $0x1a0,%%ecx\n\t" 58 - "rdmsr\n\t" 60 + "movl $" __stringify(MSR_IA32_TSC_DEADLINE) ", %%ecx\n\t" 61 + "wrmsr\n\t" 59 62 "cli\n\t" 60 63 : : : "eax", "ebx", "ecx", "edx"); 61 64
+1 -1
tools/testing/selftests/kvm/x86_64/hyperv_evmcs.c
··· 242 242 TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX)); 243 243 TEST_REQUIRE(kvm_has_cap(KVM_CAP_NESTED_STATE)); 244 244 TEST_REQUIRE(kvm_has_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS)); 245 - TEST_REQUIRE(kvm_has_cap(KVM_CAP_HYPERV_DIRECT_TLBFLUSH)); 245 + TEST_REQUIRE(kvm_hv_cpu_has(HV_X64_NESTED_DIRECT_FLUSH)); 246 246 247 247 vm = vm_create_with_one_vcpu(&vcpu, guest_code); 248 248
+1 -1
tools/testing/selftests/kvm/x86_64/hyperv_svm_test.c
··· 157 157 int stage; 158 158 159 159 TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SVM)); 160 - TEST_REQUIRE(kvm_has_cap(KVM_CAP_HYPERV_DIRECT_TLBFLUSH)); 160 + TEST_REQUIRE(kvm_hv_cpu_has(HV_X64_NESTED_DIRECT_FLUSH)); 161 161 162 162 /* Create VM */ 163 163 vm = vm_create_with_one_vcpu(&vcpu, guest_code);
+32
tools/testing/selftests/kvm/x86_64/sev_smoke_test.c
··· 160 160 kvm_vm_free(vm); 161 161 } 162 162 163 + static void guest_shutdown_code(void) 164 + { 165 + struct desc_ptr idt; 166 + 167 + /* Clobber the IDT so that #UD is guaranteed to trigger SHUTDOWN. */ 168 + memset(&idt, 0, sizeof(idt)); 169 + __asm__ __volatile__("lidt %0" :: "m"(idt)); 170 + 171 + __asm__ __volatile__("ud2"); 172 + } 173 + 174 + static void test_sev_es_shutdown(void) 175 + { 176 + struct kvm_vcpu *vcpu; 177 + struct kvm_vm *vm; 178 + 179 + uint32_t type = KVM_X86_SEV_ES_VM; 180 + 181 + vm = vm_sev_create_with_one_vcpu(type, guest_shutdown_code, &vcpu); 182 + 183 + vm_sev_launch(vm, SEV_POLICY_ES, NULL); 184 + 185 + vcpu_run(vcpu); 186 + TEST_ASSERT(vcpu->run->exit_reason == KVM_EXIT_SHUTDOWN, 187 + "Wanted SHUTDOWN, got %s", 188 + exit_reason_str(vcpu->run->exit_reason)); 189 + 190 + kvm_vm_free(vm); 191 + } 192 + 163 193 int main(int argc, char *argv[]) 164 194 { 165 195 TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SEV)); ··· 200 170 if (kvm_cpu_has(X86_FEATURE_SEV_ES)) { 201 171 test_sev(guest_sev_es_code, SEV_POLICY_ES | SEV_POLICY_NO_DBG); 202 172 test_sev(guest_sev_es_code, SEV_POLICY_ES); 173 + 174 + test_sev_es_shutdown(); 203 175 204 176 if (kvm_has_cap(KVM_CAP_XCRS) && 205 177 (xgetbv(0) & XFEATURE_MASK_X87_AVX) == XFEATURE_MASK_X87_AVX) {
+1
tools/testing/selftests/kvm/x86_64/xen_vmcall_test.c
··· 10 10 #include "test_util.h" 11 11 #include "kvm_util.h" 12 12 #include "processor.h" 13 + #include "hyperv.h" 13 14 14 15 #define HCALL_REGION_GPA 0xc0000000ULL 15 16 #define HCALL_REGION_SLOT 10