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