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 12 static noinline int compute_flag(int i) 13 { 14 if (i % 10 < 4) 15 return i + 1; 16 return 0; 17 } 18 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 34 static void init_lbr(void *index) 35 { 36 wrmsr(lbr_from + *(int *) index, 0); 37 wrmsr(lbr_to + *(int *)index, 0); 38 } 39 40 static bool test_init_lbr_from_exception(u64 index) 41 { 42 return test_for_exception(GP_VECTOR, init_lbr, &index); 43 } 44 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 report(rdmsr(MSR_LBR_TOS) != 0, "The guest LBR MSR_LBR_TOS value is good."); 102 for (i = 0; i < max; ++i) { 103 if (!rdmsr(lbr_to + i) || !rdmsr(lbr_from + i)) 104 break; 105 } 106 report(i == max, "The guest LBR FROM_IP/TO_IP values are good."); 107 108 return report_summary(); 109 } 110