Assert that clearing the "load IA32_PERF_GLOBAL_CTRL" VM-{Entry,Exit} capability bits is preserved across KVM_SET_CPUID2. Signed-off-by: Oliver Upton <oupton@xxxxxxxxxx> --- tools/testing/selftests/kvm/.gitignore | 1 + tools/testing/selftests/kvm/Makefile | 1 + .../kvm/x86_64/vmx_capability_msrs_test.c | 82 +++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86_64/vmx_capability_msrs_test.c diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore index dce7de7755e6..d1e6757aed2f 100644 --- a/tools/testing/selftests/kvm/.gitignore +++ b/tools/testing/selftests/kvm/.gitignore @@ -36,6 +36,7 @@ /x86_64/userspace_io_test /x86_64/userspace_msr_exit_test /x86_64/vmx_apic_access_test +/x86_64/vmx_capability_msrs_test /x86_64/vmx_close_while_nested_test /x86_64/vmx_dirty_log_test /x86_64/vmx_exception_with_invalid_guest_state diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 0e4926bc9a58..083c437a852f 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -68,6 +68,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/sync_regs_test TEST_GEN_PROGS_x86_64 += x86_64/userspace_io_test TEST_GEN_PROGS_x86_64 += x86_64/userspace_msr_exit_test TEST_GEN_PROGS_x86_64 += x86_64/vmx_apic_access_test +TEST_GEN_PROGS_x86_64 += x86_64/vmx_capability_msrs_test TEST_GEN_PROGS_x86_64 += x86_64/vmx_close_while_nested_test TEST_GEN_PROGS_x86_64 += x86_64/vmx_dirty_log_test TEST_GEN_PROGS_x86_64 += x86_64/vmx_exception_with_invalid_guest_state diff --git a/tools/testing/selftests/kvm/x86_64/vmx_capability_msrs_test.c b/tools/testing/selftests/kvm/x86_64/vmx_capability_msrs_test.c new file mode 100644 index 000000000000..8a1a545e658b --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/vmx_capability_msrs_test.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * VMX capability MSRs test + * + * Copyright (C) 2022 Google LLC + * + * Regression tests to check that updates to guest CPUID do not affect the + * values of VMX capability MSRs. + */ + +#include "kvm_util.h" +#include "vmx.h" + +#define VCPU_ID 0 + +static void get_vmx_capability_msr(struct kvm_vm *vm, uint32_t msr_index, + uint32_t *low, uint32_t *high) +{ + uint64_t val; + + val = vcpu_get_msr(vm, VCPU_ID, msr_index); + *low = val; + *high = val >> 32; +} + +static void set_vmx_capability_msr(struct kvm_vm *vm, uint32_t msr_index, + uint32_t low, uint32_t high) +{ + uint64_t val = (((uint64_t) high) << 32) | low; + + vcpu_set_msr(vm, VCPU_ID, msr_index, val); +} + +/* + * Test to assert that clearing the "load IA32_PERF_GLOBAL_CTRL" VM-{Entry,Exit} + * control capability bits is preserved across a KVM_SET_CPUID2. + */ +static void load_perf_global_ctrl_test(struct kvm_vm *vm) +{ + uint32_t entry_low, entry_high, exit_low, exit_high; + struct kvm_cpuid2 *cpuid; + + get_vmx_capability_msr(vm, MSR_IA32_VMX_TRUE_ENTRY_CTLS, &entry_low, &entry_high); + get_vmx_capability_msr(vm, MSR_IA32_VMX_TRUE_EXIT_CTLS, &exit_low, &exit_high); + + if (!(entry_high & VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL) || + !(exit_high & VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL)) { + print_skip("\"load IA32_PERF_GLOBAL_CTRL\" VM-{Entry,Exit} control not supported"); + return; + } + + entry_high &= ~VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL; + exit_high &= ~VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL; + + set_vmx_capability_msr(vm, MSR_IA32_VMX_TRUE_ENTRY_CTLS, entry_low, entry_high); + set_vmx_capability_msr(vm, MSR_IA32_VMX_TRUE_EXIT_CTLS, exit_low, exit_high); + + cpuid = kvm_get_supported_cpuid(); + vcpu_set_cpuid(vm, VCPU_ID, cpuid); + + get_vmx_capability_msr(vm, MSR_IA32_VMX_TRUE_ENTRY_CTLS, &entry_low, &entry_high); + get_vmx_capability_msr(vm, MSR_IA32_VMX_TRUE_EXIT_CTLS, &exit_low, &exit_high); + + TEST_ASSERT(!(entry_high & VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL), + "\"load IA32_PERF_GLOBAL_CTRL\" VM-Entry bit set"); + TEST_ASSERT(!(exit_high & VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL), + "\"load IA32_PERF_GLOBAL_CTRL\" VM-Exit bit set"); +} + +int main(void) +{ + struct kvm_vm *vm; + + nested_vmx_check_supported(); + + /* No need to run a guest for these tests */ + vm = vm_create_default(VCPU_ID, 0, NULL); + + load_perf_global_ctrl_test(vm); + + kvm_vm_free(vm); +} -- 2.35.0.rc2.247.g8bbb082509-goog