]> git.itanic.dy.fi Git - linux-stable/commitdiff
KVM: selftests: Test Hyper-V invariant TSC control
authorVitaly Kuznetsov <vkuznets@redhat.com>
Thu, 13 Oct 2022 09:58:49 +0000 (11:58 +0200)
committerPaolo Bonzini <pbonzini@redhat.com>
Wed, 28 Dec 2022 11:10:19 +0000 (06:10 -0500)
Add a test for the newly introduced Hyper-V invariant TSC control feature:
- HV_X64_MSR_TSC_INVARIANT_CONTROL is not available without
 HV_ACCESS_TSC_INVARIANT CPUID bit set and available with it.
- BIT(0) of HV_X64_MSR_TSC_INVARIANT_CONTROL controls the filtering of
architectural invariant TSC (CPUID.80000007H:EDX[8]) bit.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Reviewed-by: Sean Christopherson <seanjc@google.com>
Message-Id: <20221013095849.705943-8-vkuznets@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
tools/testing/selftests/kvm/include/x86_64/hyperv.h
tools/testing/selftests/kvm/include/x86_64/processor.h
tools/testing/selftests/kvm/x86_64/hyperv_features.c

index ab455c4efc665d07cfe4e206f9eff3add6f900dd..28eb99046475e102206622dcf381dddd10bd217d 100644 (file)
@@ -335,4 +335,7 @@ struct hyperv_test_pages {
 struct hyperv_test_pages *vcpu_alloc_hyperv_test_pages(struct kvm_vm *vm,
                                                       vm_vaddr_t *p_hv_pages_gva);
 
+/* HV_X64_MSR_TSC_INVARIANT_CONTROL bits */
+#define HV_INVARIANT_TSC_EXPOSED               BIT_ULL(0)
+
 #endif /* !SELFTEST_KVM_HYPERV_H */
index b1a31de7108acca03ebe3086a7a5bd5b2ed9be09..2a5f47d513884a5d292100ed6f9fc267bee35450 100644 (file)
@@ -137,6 +137,7 @@ struct kvm_x86_cpu_feature {
 #define        X86_FEATURE_GBPAGES             KVM_X86_CPU_FEATURE(0x80000001, 0, EDX, 26)
 #define        X86_FEATURE_RDTSCP              KVM_X86_CPU_FEATURE(0x80000001, 0, EDX, 27)
 #define        X86_FEATURE_LM                  KVM_X86_CPU_FEATURE(0x80000001, 0, EDX, 29)
+#define        X86_FEATURE_INVTSC              KVM_X86_CPU_FEATURE(0x80000007, 0, EDX, 8)
 #define        X86_FEATURE_RDPRU               KVM_X86_CPU_FEATURE(0x80000008, 0, EBX, 4)
 #define        X86_FEATURE_AMD_IBPB            KVM_X86_CPU_FEATURE(0x80000008, 0, EBX, 12)
 #define        X86_FEATURE_NPT                 KVM_X86_CPU_FEATURE(0x8000000A, 0, EDX, 0)
index b0024096397491fd1e7f9b8bdb83b7df63994268..258267df8e2a62b49672720a7cc60376ffbc10cb 100644 (file)
@@ -63,6 +63,16 @@ static void guest_msr(struct msr_data *msr)
        if (msr->write)
                GUEST_ASSERT_3(msr_val == msr->write_val, msr->idx,
                               msr_val, msr->write_val);
+
+       /* Invariant TSC bit appears when TSC invariant control MSR is written to */
+       if (msr->idx == HV_X64_MSR_TSC_INVARIANT_CONTROL) {
+               if (!this_cpu_has(HV_ACCESS_TSC_INVARIANT))
+                       GUEST_ASSERT(this_cpu_has(X86_FEATURE_INVTSC));
+               else
+                       GUEST_ASSERT(this_cpu_has(X86_FEATURE_INVTSC) ==
+                                    !!(msr_val & HV_INVARIANT_TSC_EXPOSED));
+       }
+
 done:
        GUEST_DONE();
 }
@@ -118,6 +128,7 @@ static void guest_test_msrs_access(void)
        int stage = 0;
        vm_vaddr_t msr_gva;
        struct msr_data *msr;
+       bool has_invtsc = kvm_cpu_has(X86_FEATURE_INVTSC);
 
        while (true) {
                vm = vm_create_with_one_vcpu(&vcpu, guest_msr);
@@ -435,6 +446,42 @@ static void guest_test_msrs_access(void)
                        break;
 
                case 44:
+                       /* MSR is not available when CPUID feature bit is unset */
+                       if (!has_invtsc)
+                               continue;
+                       msr->idx = HV_X64_MSR_TSC_INVARIANT_CONTROL;
+                       msr->write = false;
+                       msr->fault_expected = true;
+                       break;
+               case 45:
+                       /* MSR is vailable when CPUID feature bit is set */
+                       if (!has_invtsc)
+                               continue;
+                       vcpu_set_cpuid_feature(vcpu, HV_ACCESS_TSC_INVARIANT);
+                       msr->idx = HV_X64_MSR_TSC_INVARIANT_CONTROL;
+                       msr->write = false;
+                       msr->fault_expected = false;
+                       break;
+               case 46:
+                       /* Writing bits other than 0 is forbidden */
+                       if (!has_invtsc)
+                               continue;
+                       msr->idx = HV_X64_MSR_TSC_INVARIANT_CONTROL;
+                       msr->write = true;
+                       msr->write_val = 0xdeadbeef;
+                       msr->fault_expected = true;
+                       break;
+               case 47:
+                       /* Setting bit 0 enables the feature */
+                       if (!has_invtsc)
+                               continue;
+                       msr->idx = HV_X64_MSR_TSC_INVARIANT_CONTROL;
+                       msr->write = true;
+                       msr->write_val = 1;
+                       msr->fault_expected = false;
+                       break;
+
+               default:
                        kvm_vm_free(vm);
                        return;
                }