xref: /kvm-unit-tests/x86/pmu_lbr.c (revision dca3f4c041143c8e8dc70c6890a19a5730310230)
1 #include "x86/msr.h"
2 #include "x86/processor.h"
3 #include "x86/pmu.h"
4 #include "x86/desc.h"
5 #include "vmalloc.h"
6 
7 #define N 1000000
8 
9 volatile int count;
10 u32 lbr_from, lbr_to;
11 
compute_flag(int i)12 static noinline int compute_flag(int i)
13 {
14 	if (i % 10 < 4)
15 		return i + 1;
16 	return 0;
17 }
18 
lbr_test(void)19 static noinline int lbr_test(void)
20 {
21 	int i;
22 	int flag;
23 	volatile double x = 1212121212, y = 121212;
24 
25 	for (i = 0; i < 200000000; i++) {
26 		flag = compute_flag(i);
27 		count++;
28 		if (flag)
29 			x += x / y + y / x;
30 	}
31 	return 0;
32 }
33 
init_lbr(void * index)34 static void init_lbr(void *index)
35 {
36 	wrmsr(lbr_from + *(int *) index, 0);
37 	wrmsr(lbr_to + *(int *)index, 0);
38 }
39 
test_init_lbr_from_exception(u64 index)40 static bool test_init_lbr_from_exception(u64 index)
41 {
42 	return test_for_exception(GP_VECTOR, init_lbr, &index);
43 }
44 
main(int ac,char ** av)45 int main(int ac, char **av)
46 {
47 	int max, i;
48 
49 	setup_vm();
50 
51 	if (!pmu.is_intel) {
52 		report_skip("PMU_LBR test is for intel CPU's only");
53 		return report_summary();
54 	}
55 
56 	if (!this_cpu_has_pmu()) {
57 		report_skip("No pmu is detected!");
58 		return report_summary();
59 	}
60 
61 	if (!this_cpu_has(X86_FEATURE_PDCM)) {
62 		report_skip("Perfmon/Debug Capabilities MSR isn't supported.");
63 		return report_summary();
64 	}
65 
66 	if (!pmu_lbr_version()) {
67 		report_skip("(Architectural) LBR is not supported.");
68 		return report_summary();
69 	}
70 
71 	printf("PMU version:		 %d\n", pmu.version);
72 	printf("LBR version:		 %ld\n", pmu_lbr_version());
73 
74 	/* Look for LBR from and to MSRs */
75 	lbr_from = MSR_LBR_CORE_FROM;
76 	lbr_to = MSR_LBR_CORE_TO;
77 	if (test_init_lbr_from_exception(0)) {
78 		lbr_from = MSR_LBR_NHM_FROM;
79 		lbr_to = MSR_LBR_NHM_TO;
80 	}
81 
82 	if (test_init_lbr_from_exception(0)) {
83 		report_skip("LBR on this platform is not supported!");
84 		return report_summary();
85 	}
86 
87 	wrmsr(MSR_LBR_SELECT, 0);
88 	wrmsr(MSR_LBR_TOS, 0);
89 	for (max = 0; max < MAX_NUM_LBR_ENTRY; max++) {
90 		if (test_init_lbr_from_exception(max))
91 			break;
92 	}
93 
94 	report(max > 0, "The number of guest LBR entries is good.");
95 
96 	/* Do some branch instructions. */
97 	wrmsr(MSR_IA32_DEBUGCTLMSR, DEBUGCTLMSR_LBR);
98 	lbr_test();
99 	wrmsr(MSR_IA32_DEBUGCTLMSR, 0);
100 
101 	for (i = 0; i < max; ++i) {
102 		if (!rdmsr(lbr_to + i) || !rdmsr(lbr_from + i))
103 			break;
104 	}
105 	report(i == max, "The guest LBR FROM_IP/TO_IP values are good.");
106 
107 	return report_summary();
108 }
109