xref: /kvm-unit-tests/x86/tsc_adjust.c (revision 5fecf5d8cad101e2a3ce7af85ed18bc44624e552)
1*5fecf5d8SWill Auld #include "libcflat.h"
2*5fecf5d8SWill Auld #include "processor.h"
3*5fecf5d8SWill Auld 
4*5fecf5d8SWill Auld #define IA32_TSC_ADJUST 0x3b
5*5fecf5d8SWill Auld 
6*5fecf5d8SWill Auld int main()
7*5fecf5d8SWill Auld {
8*5fecf5d8SWill Auld 	u64 t1, t2, t3, t4, t5;
9*5fecf5d8SWill Auld 	u64 est_delta_time;
10*5fecf5d8SWill Auld 	bool pass = true;
11*5fecf5d8SWill Auld 
12*5fecf5d8SWill Auld 	if (cpuid(7).b & (1 << 1)) { // IA32_TSC_ADJUST Feature is enabled?
13*5fecf5d8SWill Auld 		if ( rdmsr(IA32_TSC_ADJUST) != 0x0) {
14*5fecf5d8SWill Auld 			printf("failure: IA32_TSC_ADJUST msr was incorrectly"
15*5fecf5d8SWill Auld 				" initialized\n");
16*5fecf5d8SWill Auld 			pass = false;
17*5fecf5d8SWill Auld 		}
18*5fecf5d8SWill Auld 		t3 = 100000000000ull;
19*5fecf5d8SWill Auld 		t1 = rdtsc();
20*5fecf5d8SWill Auld 		wrmsr(IA32_TSC_ADJUST, t3);
21*5fecf5d8SWill Auld 		t2 = rdtsc();
22*5fecf5d8SWill Auld 		if (rdmsr(IA32_TSC_ADJUST) != t3) {
23*5fecf5d8SWill Auld 			printf("failure: IA32_TSC_ADJUST msr read / write"
24*5fecf5d8SWill Auld 				" incorrect\n");
25*5fecf5d8SWill Auld 			pass = false;
26*5fecf5d8SWill Auld 		}
27*5fecf5d8SWill Auld 		if (t2 - t1 < t3) {
28*5fecf5d8SWill Auld 			printf("failure: TSC did not adjust for IA32_TSC_ADJUST"
29*5fecf5d8SWill Auld 				" value\n");
30*5fecf5d8SWill Auld 			pass = false;
31*5fecf5d8SWill Auld 		}
32*5fecf5d8SWill Auld 		t3 = 0x0;
33*5fecf5d8SWill Auld 		wrmsr(IA32_TSC_ADJUST, t3);
34*5fecf5d8SWill Auld 		if (rdmsr(IA32_TSC_ADJUST) != t3) {
35*5fecf5d8SWill Auld 			printf("failure: IA32_TSC_ADJUST msr read / write"
36*5fecf5d8SWill Auld 				" incorrect\n");
37*5fecf5d8SWill Auld 			pass = false;
38*5fecf5d8SWill Auld 		}
39*5fecf5d8SWill Auld 		t4 = 100000000000ull;
40*5fecf5d8SWill Auld 		t1 = rdtsc();
41*5fecf5d8SWill Auld 		wrtsc(t4);
42*5fecf5d8SWill Auld 		t2 = rdtsc();
43*5fecf5d8SWill Auld 		t5 = rdmsr(IA32_TSC_ADJUST);
44*5fecf5d8SWill Auld 		// est of time between reading tsc and writing tsc,
45*5fecf5d8SWill Auld 		// (based on IA32_TSC_ADJUST msr value) should be small
46*5fecf5d8SWill Auld 		est_delta_time = t4 - t5 - t1;
47*5fecf5d8SWill Auld 		if (est_delta_time > 2 * (t2 - t4)) {
48*5fecf5d8SWill Auld 			// arbitray 2x latency (wrtsc->rdtsc) threshold
49*5fecf5d8SWill Auld 			printf("failure: IA32_TSC_ADJUST msr incorrectly"
50*5fecf5d8SWill Auld 				" adjusted on tsc write\n");
51*5fecf5d8SWill Auld 			pass = false;
52*5fecf5d8SWill Auld 		}
53*5fecf5d8SWill Auld 		if (pass) printf("success: IA32_TSC_ADJUST enabled and"
54*5fecf5d8SWill Auld 				" working correctly\n");
55*5fecf5d8SWill Auld 	}
56*5fecf5d8SWill Auld 	else {
57*5fecf5d8SWill Auld 		printf("success: IA32_TSC_ADJUST feature not enabled\n");
58*5fecf5d8SWill Auld 	}
59*5fecf5d8SWill Auld 	return pass?0:1;
60*5fecf5d8SWill Auld }
61