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