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