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