Commit bd827bd7 authored by Vitaly Kuznetsov's avatar Vitaly Kuznetsov Committed by Paolo Bonzini
Browse files

KVM: selftests: Test Hyper-V invariant TSC control



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: default avatarVitaly Kuznetsov <vkuznets@redhat.com>
Reviewed-by: default avatarSean Christopherson <seanjc@google.com>
Message-Id: <20221013095849.705943-8-vkuznets@redhat.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 91a0b547
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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 */
+1 −0
Original line number Diff line number Diff line
@@ -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)
+47 −0
Original line number Diff line number Diff line
@@ -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;
		}