Run the test once with quirk enabled and once disabled,
and adjust the expected values accordingly.

Signed-off-by: Maxim Levitsky <mlevi...@redhat.com>
---
 .../selftests/kvm/x86_64/tsc_msrs_test.c      | 79 ++++++++++++++++---
 1 file changed, 69 insertions(+), 10 deletions(-)

diff --git a/tools/testing/selftests/kvm/x86_64/tsc_msrs_test.c 
b/tools/testing/selftests/kvm/x86_64/tsc_msrs_test.c
index e357d8e222d47..3900c543a7ee1 100644
--- a/tools/testing/selftests/kvm/x86_64/tsc_msrs_test.c
+++ b/tools/testing/selftests/kvm/x86_64/tsc_msrs_test.c
@@ -79,8 +79,6 @@ static void run_vcpu(struct kvm_vm *vm, uint32_t vcpuid, int 
stage)
 {
        struct ucall uc;
 
-       vcpu_args_set(vm, vcpuid, 1, vcpuid);
-
        vcpu_ioctl(vm, vcpuid, KVM_RUN, NULL);
 
        switch (get_ucall(vm, vcpuid, &uc)) {
@@ -101,7 +99,7 @@ static void run_vcpu(struct kvm_vm *vm, uint32_t vcpuid, int 
stage)
        }
 }
 
-int main(void)
+void run_test(bool quirk_disabled)
 {
        struct kvm_vm *vm;
        uint64_t val;
@@ -109,6 +107,14 @@ int main(void)
        vm = vm_create_default(VCPU_ID, 0, guest_code);
 
        val = 0;
+       if (quirk_disabled) {
+               struct kvm_enable_cap cap = {
+                       .cap = KVM_CAP_DISABLE_QUIRKS,
+                       .args[0] = KVM_X86_QUIRK_TSC_HOST_ACCESS,
+               };
+               vm_enable_cap(vm, &cap);
+       }
+
        ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC), val);
        ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC_ADJUST), val);
 
@@ -124,20 +130,67 @@ int main(void)
        ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC), val);
        ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC_ADJUST), val);
 
-       /*
-        * Host: writes to MSR_IA32_TSC set the host-side offset
-        * and therefore do not change MSR_IA32_TSC_ADJUST.
-        */
-       vcpu_set_msr(vm, 0, MSR_IA32_TSC, HOST_ADJUST + val);
+       if (quirk_disabled) {
+               struct kvm_tsc_state state = {
+                       .tsc = HOST_ADJUST + val,
+                       .flags = 0
+               };
+               vcpu_ioctl(vm, VCPU_ID, KVM_SET_TSC_STATE, &state);
+       } else {
+               /*
+                * Host: writes to MSR_IA32_TSC set the host-side offset
+                * and therefore do not change MSR_IA32_TSC_ADJUST
+                */
+               vcpu_set_msr(vm, 0, MSR_IA32_TSC, HOST_ADJUST + val);
+       }
+
        ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC), HOST_ADJUST + val);
        ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC_ADJUST), val);
+
+       if (quirk_disabled) {
+               /*
+                * Host: writes to MSR_IA32_TSC work like in the guest
+                * when quirk is disabled
+                */
+               vcpu_set_msr(vm, 0, MSR_IA32_TSC, val);
+               ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC), val);
+               ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC_ADJUST), val - 
HOST_ADJUST);
+
+               /* Restore the value */
+               vcpu_set_msr(vm, 0, MSR_IA32_TSC, HOST_ADJUST + val);
+               ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC_ADJUST), val);
+       }
+
        run_vcpu(vm, VCPU_ID, 3);
 
-       /* Host: writes to MSR_IA32_TSC_ADJUST do not modify the TSC.  */
+       /*
+        * Host: writes to MSR_IA32_TSC_ADJUST do not modify the TSC,
+        * (unless the quirk is disabled)
+        */
        vcpu_set_msr(vm, 0, MSR_IA32_TSC_ADJUST, UNITY * 123456);
-       ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC), HOST_ADJUST + val);
+       ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC),
+                 quirk_disabled ? UNITY * 123456 + HOST_ADJUST : HOST_ADJUST + 
val);
        ASSERT_EQ(vcpu_get_msr(vm, 0, MSR_IA32_TSC_ADJUST), UNITY * 123456);
 
+       if (quirk_disabled) {
+               /*
+                * Host: writes via KVM_SET_TSC_STATE
+                * to MSR_IA32_TSC and MSR_IA32_TSC_ADJUST can be done
+                * independently
+                */
+               struct kvm_tsc_state state = {
+                       .tsc = UNITY * 42,
+                       .tsc_adjust = UNITY * 42 - HOST_ADJUST,
+                       .flags = KVM_TSC_STATE_TSC_ADJUST_VALID
+               };
+
+               vcpu_ioctl(vm, VCPU_ID, KVM_SET_TSC_STATE, &state);
+
+               ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC), UNITY * 42);
+               ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC_ADJUST),
+                         UNITY * 42 - HOST_ADJUST);
+       }
+
        /* Restore previous value.  */
        vcpu_set_msr(vm, 0, MSR_IA32_TSC_ADJUST, val);
        ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC), HOST_ADJUST + val);
@@ -162,6 +215,12 @@ int main(void)
        ASSERT_EQ(rounded_host_rdmsr(MSR_IA32_TSC_ADJUST), val - HOST_ADJUST);
 
        kvm_vm_free(vm);
+}
+
 
+int main(void)
+{
+       run_test(false);
+       run_test(true);
        return 0;
 }
-- 
2.26.2

Reply via email to