diff mbox series

[v2,3/3] kvm/selftests: update tsc_msrs_test to cover KVM_X86_QUIRK_TSC_HOST_ACCESS

Message ID 20201203171118.372391-4-mlevitsk@redhat.com (mailing list archive)
State New, archived
Headers show
Series RFC: Precise TSC migration | expand

Commit Message

Maxim Levitsky Dec. 3, 2020, 5:11 p.m. UTC
Run the test once with quirk enabled and once disabled,
and adjust the expected values accordingly.

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

Patch

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;
 }