Loading Documentation/virt/kvm/api.rst +383 −406 File changed.Preview size limit exceeded, changes collapsed. Show changes tools/testing/selftests/kvm/Makefile.kvm +15 −30 Original line number Diff line number Diff line Loading @@ -50,8 +50,18 @@ LIBKVM_riscv += lib/riscv/ucall.c # Non-compiled test targets TEST_PROGS_x86 += x86/nx_huge_pages_test.sh # Compiled test targets valid on all architectures with libkvm support TEST_GEN_PROGS_COMMON = demand_paging_test TEST_GEN_PROGS_COMMON += dirty_log_test TEST_GEN_PROGS_COMMON += guest_print_test TEST_GEN_PROGS_COMMON += kvm_binary_stats_test TEST_GEN_PROGS_COMMON += kvm_create_max_vcpus TEST_GEN_PROGS_COMMON += kvm_page_table_test TEST_GEN_PROGS_COMMON += set_memory_region_test # Compiled test targets TEST_GEN_PROGS_x86 = x86/cpuid_test TEST_GEN_PROGS_x86 = $(TEST_GEN_PROGS_COMMON) TEST_GEN_PROGS_x86 += x86/cpuid_test TEST_GEN_PROGS_x86 += x86/cr4_cpuid_sync_test TEST_GEN_PROGS_x86 += x86/dirty_log_page_splitting_test TEST_GEN_PROGS_x86 += x86/feature_msrs_test Loading Loading @@ -119,27 +129,21 @@ TEST_GEN_PROGS_x86 += x86/triple_fault_event_test TEST_GEN_PROGS_x86 += x86/recalc_apic_map_test TEST_GEN_PROGS_x86 += access_tracking_perf_test TEST_GEN_PROGS_x86 += coalesced_io_test TEST_GEN_PROGS_x86 += demand_paging_test TEST_GEN_PROGS_x86 += dirty_log_test TEST_GEN_PROGS_x86 += dirty_log_perf_test TEST_GEN_PROGS_x86 += guest_memfd_test TEST_GEN_PROGS_x86 += guest_print_test TEST_GEN_PROGS_x86 += hardware_disable_test TEST_GEN_PROGS_x86 += kvm_create_max_vcpus TEST_GEN_PROGS_x86 += kvm_page_table_test TEST_GEN_PROGS_x86 += memslot_modification_stress_test TEST_GEN_PROGS_x86 += memslot_perf_test TEST_GEN_PROGS_x86 += mmu_stress_test TEST_GEN_PROGS_x86 += rseq_test TEST_GEN_PROGS_x86 += set_memory_region_test TEST_GEN_PROGS_x86 += steal_time TEST_GEN_PROGS_x86 += kvm_binary_stats_test TEST_GEN_PROGS_x86 += system_counter_offset_test TEST_GEN_PROGS_x86 += pre_fault_memory_test # Compiled outputs used by test targets TEST_GEN_PROGS_EXTENDED_x86 += x86/nx_huge_pages_test TEST_GEN_PROGS_arm64 = $(TEST_GEN_PROGS_COMMON) TEST_GEN_PROGS_arm64 += arm64/aarch32_id_regs TEST_GEN_PROGS_arm64 += arm64/arch_timer_edge_cases TEST_GEN_PROGS_arm64 += arm64/debug-exceptions Loading @@ -158,22 +162,16 @@ TEST_GEN_PROGS_arm64 += arm64/no-vgic-v3 TEST_GEN_PROGS_arm64 += access_tracking_perf_test TEST_GEN_PROGS_arm64 += arch_timer TEST_GEN_PROGS_arm64 += coalesced_io_test TEST_GEN_PROGS_arm64 += demand_paging_test TEST_GEN_PROGS_arm64 += dirty_log_test TEST_GEN_PROGS_arm64 += dirty_log_perf_test TEST_GEN_PROGS_arm64 += guest_print_test TEST_GEN_PROGS_arm64 += get-reg-list TEST_GEN_PROGS_arm64 += kvm_create_max_vcpus TEST_GEN_PROGS_arm64 += kvm_page_table_test TEST_GEN_PROGS_arm64 += memslot_modification_stress_test TEST_GEN_PROGS_arm64 += memslot_perf_test TEST_GEN_PROGS_arm64 += mmu_stress_test TEST_GEN_PROGS_arm64 += rseq_test TEST_GEN_PROGS_arm64 += set_memory_region_test TEST_GEN_PROGS_arm64 += steal_time TEST_GEN_PROGS_arm64 += kvm_binary_stats_test TEST_GEN_PROGS_s390 = s390/memop TEST_GEN_PROGS_s390 = $(TEST_GEN_PROGS_COMMON) TEST_GEN_PROGS_s390 += s390/memop TEST_GEN_PROGS_s390 += s390/resets TEST_GEN_PROGS_s390 += s390/sync_regs_test TEST_GEN_PROGS_s390 += s390/tprot Loading @@ -182,27 +180,14 @@ TEST_GEN_PROGS_s390 += s390/debug_test TEST_GEN_PROGS_s390 += s390/cpumodel_subfuncs_test TEST_GEN_PROGS_s390 += s390/shared_zeropage_test TEST_GEN_PROGS_s390 += s390/ucontrol_test TEST_GEN_PROGS_s390 += demand_paging_test TEST_GEN_PROGS_s390 += dirty_log_test TEST_GEN_PROGS_s390 += guest_print_test TEST_GEN_PROGS_s390 += kvm_create_max_vcpus TEST_GEN_PROGS_s390 += kvm_page_table_test TEST_GEN_PROGS_s390 += rseq_test TEST_GEN_PROGS_s390 += set_memory_region_test TEST_GEN_PROGS_s390 += kvm_binary_stats_test TEST_GEN_PROGS_riscv = $(TEST_GEN_PROGS_COMMON) TEST_GEN_PROGS_riscv += riscv/sbi_pmu_test TEST_GEN_PROGS_riscv += riscv/ebreak_test TEST_GEN_PROGS_riscv += arch_timer TEST_GEN_PROGS_riscv += coalesced_io_test TEST_GEN_PROGS_riscv += demand_paging_test TEST_GEN_PROGS_riscv += dirty_log_test TEST_GEN_PROGS_riscv += get-reg-list TEST_GEN_PROGS_riscv += guest_print_test TEST_GEN_PROGS_riscv += kvm_binary_stats_test TEST_GEN_PROGS_riscv += kvm_create_max_vcpus TEST_GEN_PROGS_riscv += kvm_page_table_test TEST_GEN_PROGS_riscv += set_memory_region_test TEST_GEN_PROGS_riscv += steal_time SPLIT_TESTS += arch_timer Loading tools/testing/selftests/kvm/lib/kvm_util.c +2 −3 Original line number Diff line number Diff line Loading @@ -2019,9 +2019,8 @@ static struct exit_reason { KVM_EXIT_STRING(RISCV_SBI), KVM_EXIT_STRING(RISCV_CSR), KVM_EXIT_STRING(NOTIFY), #ifdef KVM_EXIT_MEMORY_NOT_PRESENT KVM_EXIT_STRING(MEMORY_NOT_PRESENT), #endif KVM_EXIT_STRING(LOONGARCH_IOCSR), KVM_EXIT_STRING(MEMORY_FAULT), }; /* Loading tools/testing/selftests/kvm/x86/monitor_mwait_test.c +57 −51 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ #include "kvm_util.h" #include "processor.h" #include "kselftest.h" #define CPUID_MWAIT (1u << 3) Loading @@ -14,6 +15,8 @@ enum monitor_mwait_testcases { MWAIT_QUIRK_DISABLED = BIT(0), MISC_ENABLES_QUIRK_DISABLED = BIT(1), MWAIT_DISABLED = BIT(2), CPUID_DISABLED = BIT(3), TEST_MAX = CPUID_DISABLED * 2 - 1, }; /* Loading @@ -35,11 +38,19 @@ do { \ testcase, vector); \ } while (0) static void guest_monitor_wait(int testcase) static void guest_monitor_wait(void *arg) { int testcase = (int) (long) arg; u8 vector; GUEST_SYNC(testcase); u64 val = rdmsr(MSR_IA32_MISC_ENABLE) & ~MSR_IA32_MISC_ENABLE_MWAIT; if (!(testcase & MWAIT_DISABLED)) val |= MSR_IA32_MISC_ENABLE_MWAIT; wrmsr(MSR_IA32_MISC_ENABLE, val); __GUEST_ASSERT(this_cpu_has(X86_FEATURE_MWAIT) == !(testcase & MWAIT_DISABLED), "Expected CPUID.MWAIT %s\n", (testcase & MWAIT_DISABLED) ? "cleared" : "set"); /* * Arbitrarily MONITOR this function, SVM performs fault checks before Loading @@ -50,19 +61,6 @@ static void guest_monitor_wait(int testcase) vector = kvm_asm_safe("mwait", "a"(guest_monitor_wait), "c"(0), "d"(0)); GUEST_ASSERT_MONITOR_MWAIT("MWAIT", testcase, vector); } static void guest_code(void) { guest_monitor_wait(MWAIT_DISABLED); guest_monitor_wait(MWAIT_QUIRK_DISABLED | MWAIT_DISABLED); guest_monitor_wait(MISC_ENABLES_QUIRK_DISABLED | MWAIT_DISABLED); guest_monitor_wait(MISC_ENABLES_QUIRK_DISABLED); guest_monitor_wait(MISC_ENABLES_QUIRK_DISABLED | MWAIT_QUIRK_DISABLED | MWAIT_DISABLED); guest_monitor_wait(MISC_ENABLES_QUIRK_DISABLED | MWAIT_QUIRK_DISABLED); GUEST_DONE(); } Loading @@ -74,56 +72,64 @@ int main(int argc, char *argv[]) struct kvm_vm *vm; struct ucall uc; int testcase; char test[80]; TEST_REQUIRE(this_cpu_has(X86_FEATURE_MWAIT)); TEST_REQUIRE(kvm_has_cap(KVM_CAP_DISABLE_QUIRKS2)); vm = vm_create_with_one_vcpu(&vcpu, guest_code); ksft_print_header(); ksft_set_plan(12); for (testcase = 0; testcase <= TEST_MAX; testcase++) { vm = vm_create_with_one_vcpu(&vcpu, guest_monitor_wait); vcpu_args_set(vcpu, 1, (void *)(long)testcase); disabled_quirks = 0; if (testcase & MWAIT_QUIRK_DISABLED) { disabled_quirks |= KVM_X86_QUIRK_MWAIT_NEVER_UD_FAULTS; strcpy(test, "MWAIT can fault"); } else { strcpy(test, "MWAIT never faults"); } if (testcase & MISC_ENABLES_QUIRK_DISABLED) { disabled_quirks |= KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT; strcat(test, ", MISC_ENABLE updates CPUID"); } else { strcat(test, ", no CPUID updates"); } vm_enable_cap(vm, KVM_CAP_DISABLE_QUIRKS2, disabled_quirks); if (!(testcase & MISC_ENABLES_QUIRK_DISABLED) && (!!(testcase & CPUID_DISABLED) ^ !!(testcase & MWAIT_DISABLED))) continue; if (testcase & CPUID_DISABLED) { strcat(test, ", CPUID clear"); vcpu_clear_cpuid_feature(vcpu, X86_FEATURE_MWAIT); } else { strcat(test, ", CPUID set"); vcpu_set_cpuid_feature(vcpu, X86_FEATURE_MWAIT); } if (testcase & MWAIT_DISABLED) strcat(test, ", MWAIT disabled"); while (1) { vcpu_run(vcpu); TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_SYNC: testcase = uc.args[1]; break; case UCALL_ABORT: REPORT_GUEST_ASSERT(uc); goto done; /* Detected in vcpu_run */ break; case UCALL_DONE: goto done; ksft_test_result_pass("%s\n", test); break; default: TEST_FAIL("Unknown ucall %lu", uc.cmd); goto done; } disabled_quirks = 0; if (testcase & MWAIT_QUIRK_DISABLED) disabled_quirks |= KVM_X86_QUIRK_MWAIT_NEVER_UD_FAULTS; if (testcase & MISC_ENABLES_QUIRK_DISABLED) disabled_quirks |= KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT; vm_enable_cap(vm, KVM_CAP_DISABLE_QUIRKS2, disabled_quirks); /* * If the MISC_ENABLES quirk (KVM neglects to update CPUID to * enable/disable MWAIT) is disabled, toggle the ENABLE_MWAIT * bit in MISC_ENABLES accordingly. If the quirk is enabled, * the only valid configuration is MWAIT disabled, as CPUID * can't be manually changed after running the vCPU. */ if (!(testcase & MISC_ENABLES_QUIRK_DISABLED)) { TEST_ASSERT(testcase & MWAIT_DISABLED, "Can't toggle CPUID features after running vCPU"); continue; break; } vcpu_set_msr(vcpu, MSR_IA32_MISC_ENABLE, (testcase & MWAIT_DISABLED) ? 0 : MSR_IA32_MISC_ENABLE_MWAIT); kvm_vm_free(vm); } ksft_finished(); done: kvm_vm_free(vm); return 0; } Loading
Documentation/virt/kvm/api.rst +383 −406 File changed.Preview size limit exceeded, changes collapsed. Show changes
tools/testing/selftests/kvm/Makefile.kvm +15 −30 Original line number Diff line number Diff line Loading @@ -50,8 +50,18 @@ LIBKVM_riscv += lib/riscv/ucall.c # Non-compiled test targets TEST_PROGS_x86 += x86/nx_huge_pages_test.sh # Compiled test targets valid on all architectures with libkvm support TEST_GEN_PROGS_COMMON = demand_paging_test TEST_GEN_PROGS_COMMON += dirty_log_test TEST_GEN_PROGS_COMMON += guest_print_test TEST_GEN_PROGS_COMMON += kvm_binary_stats_test TEST_GEN_PROGS_COMMON += kvm_create_max_vcpus TEST_GEN_PROGS_COMMON += kvm_page_table_test TEST_GEN_PROGS_COMMON += set_memory_region_test # Compiled test targets TEST_GEN_PROGS_x86 = x86/cpuid_test TEST_GEN_PROGS_x86 = $(TEST_GEN_PROGS_COMMON) TEST_GEN_PROGS_x86 += x86/cpuid_test TEST_GEN_PROGS_x86 += x86/cr4_cpuid_sync_test TEST_GEN_PROGS_x86 += x86/dirty_log_page_splitting_test TEST_GEN_PROGS_x86 += x86/feature_msrs_test Loading Loading @@ -119,27 +129,21 @@ TEST_GEN_PROGS_x86 += x86/triple_fault_event_test TEST_GEN_PROGS_x86 += x86/recalc_apic_map_test TEST_GEN_PROGS_x86 += access_tracking_perf_test TEST_GEN_PROGS_x86 += coalesced_io_test TEST_GEN_PROGS_x86 += demand_paging_test TEST_GEN_PROGS_x86 += dirty_log_test TEST_GEN_PROGS_x86 += dirty_log_perf_test TEST_GEN_PROGS_x86 += guest_memfd_test TEST_GEN_PROGS_x86 += guest_print_test TEST_GEN_PROGS_x86 += hardware_disable_test TEST_GEN_PROGS_x86 += kvm_create_max_vcpus TEST_GEN_PROGS_x86 += kvm_page_table_test TEST_GEN_PROGS_x86 += memslot_modification_stress_test TEST_GEN_PROGS_x86 += memslot_perf_test TEST_GEN_PROGS_x86 += mmu_stress_test TEST_GEN_PROGS_x86 += rseq_test TEST_GEN_PROGS_x86 += set_memory_region_test TEST_GEN_PROGS_x86 += steal_time TEST_GEN_PROGS_x86 += kvm_binary_stats_test TEST_GEN_PROGS_x86 += system_counter_offset_test TEST_GEN_PROGS_x86 += pre_fault_memory_test # Compiled outputs used by test targets TEST_GEN_PROGS_EXTENDED_x86 += x86/nx_huge_pages_test TEST_GEN_PROGS_arm64 = $(TEST_GEN_PROGS_COMMON) TEST_GEN_PROGS_arm64 += arm64/aarch32_id_regs TEST_GEN_PROGS_arm64 += arm64/arch_timer_edge_cases TEST_GEN_PROGS_arm64 += arm64/debug-exceptions Loading @@ -158,22 +162,16 @@ TEST_GEN_PROGS_arm64 += arm64/no-vgic-v3 TEST_GEN_PROGS_arm64 += access_tracking_perf_test TEST_GEN_PROGS_arm64 += arch_timer TEST_GEN_PROGS_arm64 += coalesced_io_test TEST_GEN_PROGS_arm64 += demand_paging_test TEST_GEN_PROGS_arm64 += dirty_log_test TEST_GEN_PROGS_arm64 += dirty_log_perf_test TEST_GEN_PROGS_arm64 += guest_print_test TEST_GEN_PROGS_arm64 += get-reg-list TEST_GEN_PROGS_arm64 += kvm_create_max_vcpus TEST_GEN_PROGS_arm64 += kvm_page_table_test TEST_GEN_PROGS_arm64 += memslot_modification_stress_test TEST_GEN_PROGS_arm64 += memslot_perf_test TEST_GEN_PROGS_arm64 += mmu_stress_test TEST_GEN_PROGS_arm64 += rseq_test TEST_GEN_PROGS_arm64 += set_memory_region_test TEST_GEN_PROGS_arm64 += steal_time TEST_GEN_PROGS_arm64 += kvm_binary_stats_test TEST_GEN_PROGS_s390 = s390/memop TEST_GEN_PROGS_s390 = $(TEST_GEN_PROGS_COMMON) TEST_GEN_PROGS_s390 += s390/memop TEST_GEN_PROGS_s390 += s390/resets TEST_GEN_PROGS_s390 += s390/sync_regs_test TEST_GEN_PROGS_s390 += s390/tprot Loading @@ -182,27 +180,14 @@ TEST_GEN_PROGS_s390 += s390/debug_test TEST_GEN_PROGS_s390 += s390/cpumodel_subfuncs_test TEST_GEN_PROGS_s390 += s390/shared_zeropage_test TEST_GEN_PROGS_s390 += s390/ucontrol_test TEST_GEN_PROGS_s390 += demand_paging_test TEST_GEN_PROGS_s390 += dirty_log_test TEST_GEN_PROGS_s390 += guest_print_test TEST_GEN_PROGS_s390 += kvm_create_max_vcpus TEST_GEN_PROGS_s390 += kvm_page_table_test TEST_GEN_PROGS_s390 += rseq_test TEST_GEN_PROGS_s390 += set_memory_region_test TEST_GEN_PROGS_s390 += kvm_binary_stats_test TEST_GEN_PROGS_riscv = $(TEST_GEN_PROGS_COMMON) TEST_GEN_PROGS_riscv += riscv/sbi_pmu_test TEST_GEN_PROGS_riscv += riscv/ebreak_test TEST_GEN_PROGS_riscv += arch_timer TEST_GEN_PROGS_riscv += coalesced_io_test TEST_GEN_PROGS_riscv += demand_paging_test TEST_GEN_PROGS_riscv += dirty_log_test TEST_GEN_PROGS_riscv += get-reg-list TEST_GEN_PROGS_riscv += guest_print_test TEST_GEN_PROGS_riscv += kvm_binary_stats_test TEST_GEN_PROGS_riscv += kvm_create_max_vcpus TEST_GEN_PROGS_riscv += kvm_page_table_test TEST_GEN_PROGS_riscv += set_memory_region_test TEST_GEN_PROGS_riscv += steal_time SPLIT_TESTS += arch_timer Loading
tools/testing/selftests/kvm/lib/kvm_util.c +2 −3 Original line number Diff line number Diff line Loading @@ -2019,9 +2019,8 @@ static struct exit_reason { KVM_EXIT_STRING(RISCV_SBI), KVM_EXIT_STRING(RISCV_CSR), KVM_EXIT_STRING(NOTIFY), #ifdef KVM_EXIT_MEMORY_NOT_PRESENT KVM_EXIT_STRING(MEMORY_NOT_PRESENT), #endif KVM_EXIT_STRING(LOONGARCH_IOCSR), KVM_EXIT_STRING(MEMORY_FAULT), }; /* Loading
tools/testing/selftests/kvm/x86/monitor_mwait_test.c +57 −51 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ #include "kvm_util.h" #include "processor.h" #include "kselftest.h" #define CPUID_MWAIT (1u << 3) Loading @@ -14,6 +15,8 @@ enum monitor_mwait_testcases { MWAIT_QUIRK_DISABLED = BIT(0), MISC_ENABLES_QUIRK_DISABLED = BIT(1), MWAIT_DISABLED = BIT(2), CPUID_DISABLED = BIT(3), TEST_MAX = CPUID_DISABLED * 2 - 1, }; /* Loading @@ -35,11 +38,19 @@ do { \ testcase, vector); \ } while (0) static void guest_monitor_wait(int testcase) static void guest_monitor_wait(void *arg) { int testcase = (int) (long) arg; u8 vector; GUEST_SYNC(testcase); u64 val = rdmsr(MSR_IA32_MISC_ENABLE) & ~MSR_IA32_MISC_ENABLE_MWAIT; if (!(testcase & MWAIT_DISABLED)) val |= MSR_IA32_MISC_ENABLE_MWAIT; wrmsr(MSR_IA32_MISC_ENABLE, val); __GUEST_ASSERT(this_cpu_has(X86_FEATURE_MWAIT) == !(testcase & MWAIT_DISABLED), "Expected CPUID.MWAIT %s\n", (testcase & MWAIT_DISABLED) ? "cleared" : "set"); /* * Arbitrarily MONITOR this function, SVM performs fault checks before Loading @@ -50,19 +61,6 @@ static void guest_monitor_wait(int testcase) vector = kvm_asm_safe("mwait", "a"(guest_monitor_wait), "c"(0), "d"(0)); GUEST_ASSERT_MONITOR_MWAIT("MWAIT", testcase, vector); } static void guest_code(void) { guest_monitor_wait(MWAIT_DISABLED); guest_monitor_wait(MWAIT_QUIRK_DISABLED | MWAIT_DISABLED); guest_monitor_wait(MISC_ENABLES_QUIRK_DISABLED | MWAIT_DISABLED); guest_monitor_wait(MISC_ENABLES_QUIRK_DISABLED); guest_monitor_wait(MISC_ENABLES_QUIRK_DISABLED | MWAIT_QUIRK_DISABLED | MWAIT_DISABLED); guest_monitor_wait(MISC_ENABLES_QUIRK_DISABLED | MWAIT_QUIRK_DISABLED); GUEST_DONE(); } Loading @@ -74,56 +72,64 @@ int main(int argc, char *argv[]) struct kvm_vm *vm; struct ucall uc; int testcase; char test[80]; TEST_REQUIRE(this_cpu_has(X86_FEATURE_MWAIT)); TEST_REQUIRE(kvm_has_cap(KVM_CAP_DISABLE_QUIRKS2)); vm = vm_create_with_one_vcpu(&vcpu, guest_code); ksft_print_header(); ksft_set_plan(12); for (testcase = 0; testcase <= TEST_MAX; testcase++) { vm = vm_create_with_one_vcpu(&vcpu, guest_monitor_wait); vcpu_args_set(vcpu, 1, (void *)(long)testcase); disabled_quirks = 0; if (testcase & MWAIT_QUIRK_DISABLED) { disabled_quirks |= KVM_X86_QUIRK_MWAIT_NEVER_UD_FAULTS; strcpy(test, "MWAIT can fault"); } else { strcpy(test, "MWAIT never faults"); } if (testcase & MISC_ENABLES_QUIRK_DISABLED) { disabled_quirks |= KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT; strcat(test, ", MISC_ENABLE updates CPUID"); } else { strcat(test, ", no CPUID updates"); } vm_enable_cap(vm, KVM_CAP_DISABLE_QUIRKS2, disabled_quirks); if (!(testcase & MISC_ENABLES_QUIRK_DISABLED) && (!!(testcase & CPUID_DISABLED) ^ !!(testcase & MWAIT_DISABLED))) continue; if (testcase & CPUID_DISABLED) { strcat(test, ", CPUID clear"); vcpu_clear_cpuid_feature(vcpu, X86_FEATURE_MWAIT); } else { strcat(test, ", CPUID set"); vcpu_set_cpuid_feature(vcpu, X86_FEATURE_MWAIT); } if (testcase & MWAIT_DISABLED) strcat(test, ", MWAIT disabled"); while (1) { vcpu_run(vcpu); TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); switch (get_ucall(vcpu, &uc)) { case UCALL_SYNC: testcase = uc.args[1]; break; case UCALL_ABORT: REPORT_GUEST_ASSERT(uc); goto done; /* Detected in vcpu_run */ break; case UCALL_DONE: goto done; ksft_test_result_pass("%s\n", test); break; default: TEST_FAIL("Unknown ucall %lu", uc.cmd); goto done; } disabled_quirks = 0; if (testcase & MWAIT_QUIRK_DISABLED) disabled_quirks |= KVM_X86_QUIRK_MWAIT_NEVER_UD_FAULTS; if (testcase & MISC_ENABLES_QUIRK_DISABLED) disabled_quirks |= KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT; vm_enable_cap(vm, KVM_CAP_DISABLE_QUIRKS2, disabled_quirks); /* * If the MISC_ENABLES quirk (KVM neglects to update CPUID to * enable/disable MWAIT) is disabled, toggle the ENABLE_MWAIT * bit in MISC_ENABLES accordingly. If the quirk is enabled, * the only valid configuration is MWAIT disabled, as CPUID * can't be manually changed after running the vCPU. */ if (!(testcase & MISC_ENABLES_QUIRK_DISABLED)) { TEST_ASSERT(testcase & MWAIT_DISABLED, "Can't toggle CPUID features after running vCPU"); continue; break; } vcpu_set_msr(vcpu, MSR_IA32_MISC_ENABLE, (testcase & MWAIT_DISABLED) ? 0 : MSR_IA32_MISC_ENABLE_MWAIT); kvm_vm_free(vm); } ksft_finished(); done: kvm_vm_free(vm); return 0; }