1*2ae41f5dSLike Xu #include "x86/msr.h" 2*2ae41f5dSLike Xu #include "x86/processor.h" 3*2ae41f5dSLike Xu #include "x86/pmu.h" 4*2ae41f5dSLike Xu #include "x86/isr.h" 5*2ae41f5dSLike Xu #include "x86/apic.h" 6*2ae41f5dSLike Xu #include "x86/apic-defs.h" 7*2ae41f5dSLike Xu #include "x86/desc.h" 8*2ae41f5dSLike Xu #include "alloc.h" 9*2ae41f5dSLike Xu 10*2ae41f5dSLike Xu #include "vm.h" 11*2ae41f5dSLike Xu #include "types.h" 12*2ae41f5dSLike Xu #include "processor.h" 13*2ae41f5dSLike Xu #include "vmalloc.h" 14*2ae41f5dSLike Xu #include "alloc_page.h" 15*2ae41f5dSLike Xu 16*2ae41f5dSLike Xu /* bits [63:48] provides the size of the current record in bytes */ 17*2ae41f5dSLike Xu #define RECORD_SIZE_OFFSET 48 18*2ae41f5dSLike Xu 19*2ae41f5dSLike Xu static unsigned int max_nr_gp_events; 20*2ae41f5dSLike Xu static unsigned long *ds_bufer; 21*2ae41f5dSLike Xu static unsigned long *pebs_buffer; 22*2ae41f5dSLike Xu static u64 ctr_start_val; 23*2ae41f5dSLike Xu static bool has_baseline; 24*2ae41f5dSLike Xu 25*2ae41f5dSLike Xu struct debug_store { 26*2ae41f5dSLike Xu u64 bts_buffer_base; 27*2ae41f5dSLike Xu u64 bts_index; 28*2ae41f5dSLike Xu u64 bts_absolute_maximum; 29*2ae41f5dSLike Xu u64 bts_interrupt_threshold; 30*2ae41f5dSLike Xu u64 pebs_buffer_base; 31*2ae41f5dSLike Xu u64 pebs_index; 32*2ae41f5dSLike Xu u64 pebs_absolute_maximum; 33*2ae41f5dSLike Xu u64 pebs_interrupt_threshold; 34*2ae41f5dSLike Xu u64 pebs_event_reset[64]; 35*2ae41f5dSLike Xu }; 36*2ae41f5dSLike Xu 37*2ae41f5dSLike Xu struct pebs_basic { 38*2ae41f5dSLike Xu u64 format_size; 39*2ae41f5dSLike Xu u64 ip; 40*2ae41f5dSLike Xu u64 applicable_counters; 41*2ae41f5dSLike Xu u64 tsc; 42*2ae41f5dSLike Xu }; 43*2ae41f5dSLike Xu 44*2ae41f5dSLike Xu struct pebs_meminfo { 45*2ae41f5dSLike Xu u64 address; 46*2ae41f5dSLike Xu u64 aux; 47*2ae41f5dSLike Xu u64 latency; 48*2ae41f5dSLike Xu u64 tsx_tuning; 49*2ae41f5dSLike Xu }; 50*2ae41f5dSLike Xu 51*2ae41f5dSLike Xu struct pebs_gprs { 52*2ae41f5dSLike Xu u64 flags, ip, ax, cx, dx, bx, sp, bp, si, di; 53*2ae41f5dSLike Xu u64 r8, r9, r10, r11, r12, r13, r14, r15; 54*2ae41f5dSLike Xu }; 55*2ae41f5dSLike Xu 56*2ae41f5dSLike Xu struct pebs_xmm { 57*2ae41f5dSLike Xu u64 xmm[16*2]; /* two entries for each register */ 58*2ae41f5dSLike Xu }; 59*2ae41f5dSLike Xu 60*2ae41f5dSLike Xu struct lbr_entry { 61*2ae41f5dSLike Xu u64 from; 62*2ae41f5dSLike Xu u64 to; 63*2ae41f5dSLike Xu u64 info; 64*2ae41f5dSLike Xu }; 65*2ae41f5dSLike Xu 66*2ae41f5dSLike Xu enum pmc_type { 67*2ae41f5dSLike Xu GP = 0, 68*2ae41f5dSLike Xu FIXED, 69*2ae41f5dSLike Xu }; 70*2ae41f5dSLike Xu 71*2ae41f5dSLike Xu static uint32_t intel_arch_events[] = { 72*2ae41f5dSLike Xu 0x00c4, /* PERF_COUNT_HW_BRANCH_INSTRUCTIONS */ 73*2ae41f5dSLike Xu 0x00c5, /* PERF_COUNT_HW_BRANCH_MISSES */ 74*2ae41f5dSLike Xu 0x0300, /* PERF_COUNT_HW_REF_CPU_CYCLES */ 75*2ae41f5dSLike Xu 0x003c, /* PERF_COUNT_HW_CPU_CYCLES */ 76*2ae41f5dSLike Xu 0x00c0, /* PERF_COUNT_HW_INSTRUCTIONS */ 77*2ae41f5dSLike Xu 0x013c, /* PERF_COUNT_HW_BUS_CYCLES */ 78*2ae41f5dSLike Xu 0x4f2e, /* PERF_COUNT_HW_CACHE_REFERENCES */ 79*2ae41f5dSLike Xu 0x412e, /* PERF_COUNT_HW_CACHE_MISSES */ 80*2ae41f5dSLike Xu }; 81*2ae41f5dSLike Xu 82*2ae41f5dSLike Xu static u64 pebs_data_cfgs[] = { 83*2ae41f5dSLike Xu PEBS_DATACFG_MEMINFO, 84*2ae41f5dSLike Xu PEBS_DATACFG_GP, 85*2ae41f5dSLike Xu PEBS_DATACFG_XMMS, 86*2ae41f5dSLike Xu PEBS_DATACFG_LBRS | ((MAX_NUM_LBR_ENTRY -1) << PEBS_DATACFG_LBR_SHIFT), 87*2ae41f5dSLike Xu }; 88*2ae41f5dSLike Xu 89*2ae41f5dSLike Xu /* Iterating each counter value is a waste of time, pick a few typical values. */ 90*2ae41f5dSLike Xu static u64 counter_start_values[] = { 91*2ae41f5dSLike Xu /* if PEBS counter doesn't overflow at all */ 92*2ae41f5dSLike Xu 0, 93*2ae41f5dSLike Xu 0xfffffffffff0, 94*2ae41f5dSLike Xu /* normal counter overflow to have PEBS records */ 95*2ae41f5dSLike Xu 0xfffffffffffe, 96*2ae41f5dSLike Xu /* test whether emulated instructions should trigger PEBS */ 97*2ae41f5dSLike Xu 0xffffffffffff, 98*2ae41f5dSLike Xu }; 99*2ae41f5dSLike Xu 100*2ae41f5dSLike Xu static unsigned int get_adaptive_pebs_record_size(u64 pebs_data_cfg) 101*2ae41f5dSLike Xu { 102*2ae41f5dSLike Xu unsigned int sz = sizeof(struct pebs_basic); 103*2ae41f5dSLike Xu 104*2ae41f5dSLike Xu if (!has_baseline) 105*2ae41f5dSLike Xu return sz; 106*2ae41f5dSLike Xu 107*2ae41f5dSLike Xu if (pebs_data_cfg & PEBS_DATACFG_MEMINFO) 108*2ae41f5dSLike Xu sz += sizeof(struct pebs_meminfo); 109*2ae41f5dSLike Xu if (pebs_data_cfg & PEBS_DATACFG_GP) 110*2ae41f5dSLike Xu sz += sizeof(struct pebs_gprs); 111*2ae41f5dSLike Xu if (pebs_data_cfg & PEBS_DATACFG_XMMS) 112*2ae41f5dSLike Xu sz += sizeof(struct pebs_xmm); 113*2ae41f5dSLike Xu if (pebs_data_cfg & PEBS_DATACFG_LBRS) 114*2ae41f5dSLike Xu sz += MAX_NUM_LBR_ENTRY * sizeof(struct lbr_entry); 115*2ae41f5dSLike Xu 116*2ae41f5dSLike Xu return sz; 117*2ae41f5dSLike Xu } 118*2ae41f5dSLike Xu 119*2ae41f5dSLike Xu static void cnt_overflow(isr_regs_t *regs) 120*2ae41f5dSLike Xu { 121*2ae41f5dSLike Xu apic_write(APIC_EOI, 0); 122*2ae41f5dSLike Xu } 123*2ae41f5dSLike Xu 124*2ae41f5dSLike Xu static inline void workload(void) 125*2ae41f5dSLike Xu { 126*2ae41f5dSLike Xu asm volatile( 127*2ae41f5dSLike Xu "mov $0x0, %%eax\n" 128*2ae41f5dSLike Xu "cmp $0x0, %%eax\n" 129*2ae41f5dSLike Xu "jne label2\n" 130*2ae41f5dSLike Xu "jne label2\n" 131*2ae41f5dSLike Xu "jne label2\n" 132*2ae41f5dSLike Xu "jne label2\n" 133*2ae41f5dSLike Xu "mov $0x0, %%eax\n" 134*2ae41f5dSLike Xu "cmp $0x0, %%eax\n" 135*2ae41f5dSLike Xu "jne label2\n" 136*2ae41f5dSLike Xu "jne label2\n" 137*2ae41f5dSLike Xu "jne label2\n" 138*2ae41f5dSLike Xu "jne label2\n" 139*2ae41f5dSLike Xu "mov $0xa, %%eax\n" 140*2ae41f5dSLike Xu "cpuid\n" 141*2ae41f5dSLike Xu "mov $0xa, %%eax\n" 142*2ae41f5dSLike Xu "cpuid\n" 143*2ae41f5dSLike Xu "mov $0xa, %%eax\n" 144*2ae41f5dSLike Xu "cpuid\n" 145*2ae41f5dSLike Xu "mov $0xa, %%eax\n" 146*2ae41f5dSLike Xu "cpuid\n" 147*2ae41f5dSLike Xu "mov $0xa, %%eax\n" 148*2ae41f5dSLike Xu "cpuid\n" 149*2ae41f5dSLike Xu "mov $0xa, %%eax\n" 150*2ae41f5dSLike Xu "cpuid\n" 151*2ae41f5dSLike Xu "label2:\n" 152*2ae41f5dSLike Xu : 153*2ae41f5dSLike Xu : 154*2ae41f5dSLike Xu : "eax", "ebx", "ecx", "edx"); 155*2ae41f5dSLike Xu } 156*2ae41f5dSLike Xu 157*2ae41f5dSLike Xu static inline void workload2(void) 158*2ae41f5dSLike Xu { 159*2ae41f5dSLike Xu asm volatile( 160*2ae41f5dSLike Xu "mov $0x0, %%eax\n" 161*2ae41f5dSLike Xu "cmp $0x0, %%eax\n" 162*2ae41f5dSLike Xu "jne label3\n" 163*2ae41f5dSLike Xu "jne label3\n" 164*2ae41f5dSLike Xu "jne label3\n" 165*2ae41f5dSLike Xu "jne label3\n" 166*2ae41f5dSLike Xu "mov $0x0, %%eax\n" 167*2ae41f5dSLike Xu "cmp $0x0, %%eax\n" 168*2ae41f5dSLike Xu "jne label3\n" 169*2ae41f5dSLike Xu "jne label3\n" 170*2ae41f5dSLike Xu "jne label3\n" 171*2ae41f5dSLike Xu "jne label3\n" 172*2ae41f5dSLike Xu "mov $0xa, %%eax\n" 173*2ae41f5dSLike Xu "cpuid\n" 174*2ae41f5dSLike Xu "mov $0xa, %%eax\n" 175*2ae41f5dSLike Xu "cpuid\n" 176*2ae41f5dSLike Xu "mov $0xa, %%eax\n" 177*2ae41f5dSLike Xu "cpuid\n" 178*2ae41f5dSLike Xu "mov $0xa, %%eax\n" 179*2ae41f5dSLike Xu "cpuid\n" 180*2ae41f5dSLike Xu "mov $0xa, %%eax\n" 181*2ae41f5dSLike Xu "cpuid\n" 182*2ae41f5dSLike Xu "mov $0xa, %%eax\n" 183*2ae41f5dSLike Xu "cpuid\n" 184*2ae41f5dSLike Xu "label3:\n" 185*2ae41f5dSLike Xu : 186*2ae41f5dSLike Xu : 187*2ae41f5dSLike Xu : "eax", "ebx", "ecx", "edx"); 188*2ae41f5dSLike Xu } 189*2ae41f5dSLike Xu 190*2ae41f5dSLike Xu static void alloc_buffers(void) 191*2ae41f5dSLike Xu { 192*2ae41f5dSLike Xu ds_bufer = alloc_page(); 193*2ae41f5dSLike Xu force_4k_page(ds_bufer); 194*2ae41f5dSLike Xu memset(ds_bufer, 0x0, PAGE_SIZE); 195*2ae41f5dSLike Xu 196*2ae41f5dSLike Xu pebs_buffer = alloc_page(); 197*2ae41f5dSLike Xu force_4k_page(pebs_buffer); 198*2ae41f5dSLike Xu memset(pebs_buffer, 0x0, PAGE_SIZE); 199*2ae41f5dSLike Xu } 200*2ae41f5dSLike Xu 201*2ae41f5dSLike Xu static void free_buffers(void) 202*2ae41f5dSLike Xu { 203*2ae41f5dSLike Xu if (ds_bufer) 204*2ae41f5dSLike Xu free_page(ds_bufer); 205*2ae41f5dSLike Xu 206*2ae41f5dSLike Xu if (pebs_buffer) 207*2ae41f5dSLike Xu free_page(pebs_buffer); 208*2ae41f5dSLike Xu } 209*2ae41f5dSLike Xu 210*2ae41f5dSLike Xu static void pebs_enable(u64 bitmask, u64 pebs_data_cfg) 211*2ae41f5dSLike Xu { 212*2ae41f5dSLike Xu static struct debug_store *ds; 213*2ae41f5dSLike Xu u64 baseline_extra_ctrl = 0, fixed_ctr_ctrl = 0; 214*2ae41f5dSLike Xu unsigned int idx; 215*2ae41f5dSLike Xu 216*2ae41f5dSLike Xu if (has_baseline) 217*2ae41f5dSLike Xu wrmsr(MSR_PEBS_DATA_CFG, pebs_data_cfg); 218*2ae41f5dSLike Xu 219*2ae41f5dSLike Xu ds = (struct debug_store *)ds_bufer; 220*2ae41f5dSLike Xu ds->pebs_index = ds->pebs_buffer_base = (unsigned long)pebs_buffer; 221*2ae41f5dSLike Xu ds->pebs_absolute_maximum = (unsigned long)pebs_buffer + PAGE_SIZE; 222*2ae41f5dSLike Xu ds->pebs_interrupt_threshold = ds->pebs_buffer_base + 223*2ae41f5dSLike Xu get_adaptive_pebs_record_size(pebs_data_cfg); 224*2ae41f5dSLike Xu 225*2ae41f5dSLike Xu for (idx = 0; idx < pmu.nr_fixed_counters; idx++) { 226*2ae41f5dSLike Xu if (!(BIT_ULL(FIXED_CNT_INDEX + idx) & bitmask)) 227*2ae41f5dSLike Xu continue; 228*2ae41f5dSLike Xu if (has_baseline) 229*2ae41f5dSLike Xu baseline_extra_ctrl = BIT(FIXED_CNT_INDEX + idx * 4); 230*2ae41f5dSLike Xu wrmsr(MSR_PERF_FIXED_CTRx(idx), ctr_start_val); 231*2ae41f5dSLike Xu fixed_ctr_ctrl |= (0xbULL << (idx * 4) | baseline_extra_ctrl); 232*2ae41f5dSLike Xu } 233*2ae41f5dSLike Xu if (fixed_ctr_ctrl) 234*2ae41f5dSLike Xu wrmsr(MSR_CORE_PERF_FIXED_CTR_CTRL, fixed_ctr_ctrl); 235*2ae41f5dSLike Xu 236*2ae41f5dSLike Xu for (idx = 0; idx < max_nr_gp_events; idx++) { 237*2ae41f5dSLike Xu if (!(BIT_ULL(idx) & bitmask)) 238*2ae41f5dSLike Xu continue; 239*2ae41f5dSLike Xu if (has_baseline) 240*2ae41f5dSLike Xu baseline_extra_ctrl = ICL_EVENTSEL_ADAPTIVE; 241*2ae41f5dSLike Xu wrmsr(MSR_GP_EVENT_SELECTx(idx), EVNTSEL_EN | EVNTSEL_OS | EVNTSEL_USR | 242*2ae41f5dSLike Xu intel_arch_events[idx] | baseline_extra_ctrl); 243*2ae41f5dSLike Xu wrmsr(MSR_GP_COUNTERx(idx), ctr_start_val); 244*2ae41f5dSLike Xu } 245*2ae41f5dSLike Xu 246*2ae41f5dSLike Xu wrmsr(MSR_IA32_DS_AREA, (unsigned long)ds_bufer); 247*2ae41f5dSLike Xu wrmsr(MSR_IA32_PEBS_ENABLE, bitmask); 248*2ae41f5dSLike Xu wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, bitmask); 249*2ae41f5dSLike Xu } 250*2ae41f5dSLike Xu 251*2ae41f5dSLike Xu static void reset_pebs(void) 252*2ae41f5dSLike Xu { 253*2ae41f5dSLike Xu memset(ds_bufer, 0x0, PAGE_SIZE); 254*2ae41f5dSLike Xu memset(pebs_buffer, 0x0, PAGE_SIZE); 255*2ae41f5dSLike Xu wrmsr(MSR_IA32_PEBS_ENABLE, 0); 256*2ae41f5dSLike Xu wrmsr(MSR_IA32_DS_AREA, 0); 257*2ae41f5dSLike Xu if (has_baseline) 258*2ae41f5dSLike Xu wrmsr(MSR_PEBS_DATA_CFG, 0); 259*2ae41f5dSLike Xu 260*2ae41f5dSLike Xu wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, 0); 261*2ae41f5dSLike Xu wrmsr(MSR_CORE_PERF_GLOBAL_OVF_CTRL, rdmsr(MSR_CORE_PERF_GLOBAL_STATUS)); 262*2ae41f5dSLike Xu 263*2ae41f5dSLike Xu pmu_reset_all_counters(); 264*2ae41f5dSLike Xu } 265*2ae41f5dSLike Xu 266*2ae41f5dSLike Xu static void pebs_disable(unsigned int idx) 267*2ae41f5dSLike Xu { 268*2ae41f5dSLike Xu /* 269*2ae41f5dSLike Xu * If we only clear the PEBS_ENABLE bit, the counter will continue to increment. 270*2ae41f5dSLike Xu * In this very tiny time window, if the counter overflows no pebs record will be generated, 271*2ae41f5dSLike Xu * but a normal counter irq. Test this fully with two ways. 272*2ae41f5dSLike Xu */ 273*2ae41f5dSLike Xu if (idx % 2) 274*2ae41f5dSLike Xu wrmsr(MSR_IA32_PEBS_ENABLE, 0); 275*2ae41f5dSLike Xu 276*2ae41f5dSLike Xu wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, 0); 277*2ae41f5dSLike Xu } 278*2ae41f5dSLike Xu 279*2ae41f5dSLike Xu static void check_pebs_records(u64 bitmask, u64 pebs_data_cfg) 280*2ae41f5dSLike Xu { 281*2ae41f5dSLike Xu struct pebs_basic *pebs_rec = (struct pebs_basic *)pebs_buffer; 282*2ae41f5dSLike Xu struct debug_store *ds = (struct debug_store *)ds_bufer; 283*2ae41f5dSLike Xu unsigned int pebs_record_size = get_adaptive_pebs_record_size(pebs_data_cfg); 284*2ae41f5dSLike Xu unsigned int count = 0; 285*2ae41f5dSLike Xu bool expected, pebs_idx_match, pebs_size_match, data_cfg_match; 286*2ae41f5dSLike Xu void *cur_record; 287*2ae41f5dSLike Xu 288*2ae41f5dSLike Xu expected = (ds->pebs_index == ds->pebs_buffer_base) && !pebs_rec->format_size; 289*2ae41f5dSLike Xu if (!(rdmsr(MSR_CORE_PERF_GLOBAL_STATUS) & GLOBAL_STATUS_BUFFER_OVF)) { 290*2ae41f5dSLike Xu report(expected, "No OVF irq, none PEBS records."); 291*2ae41f5dSLike Xu return; 292*2ae41f5dSLike Xu } 293*2ae41f5dSLike Xu 294*2ae41f5dSLike Xu if (expected) { 295*2ae41f5dSLike Xu report(!expected, "A OVF irq, but none PEBS records."); 296*2ae41f5dSLike Xu return; 297*2ae41f5dSLike Xu } 298*2ae41f5dSLike Xu 299*2ae41f5dSLike Xu expected = ds->pebs_index >= ds->pebs_interrupt_threshold; 300*2ae41f5dSLike Xu cur_record = (void *)pebs_buffer; 301*2ae41f5dSLike Xu do { 302*2ae41f5dSLike Xu pebs_rec = (struct pebs_basic *)cur_record; 303*2ae41f5dSLike Xu pebs_record_size = pebs_rec->format_size >> RECORD_SIZE_OFFSET; 304*2ae41f5dSLike Xu pebs_idx_match = 305*2ae41f5dSLike Xu pebs_rec->applicable_counters & bitmask; 306*2ae41f5dSLike Xu pebs_size_match = 307*2ae41f5dSLike Xu pebs_record_size == get_adaptive_pebs_record_size(pebs_data_cfg); 308*2ae41f5dSLike Xu data_cfg_match = 309*2ae41f5dSLike Xu (pebs_rec->format_size & GENMASK_ULL(47, 0)) == pebs_data_cfg; 310*2ae41f5dSLike Xu expected = pebs_idx_match && pebs_size_match && data_cfg_match; 311*2ae41f5dSLike Xu report(expected, 312*2ae41f5dSLike Xu "PEBS record (written seq %d) is verified (inclduing size, counters and cfg).", count); 313*2ae41f5dSLike Xu cur_record = cur_record + pebs_record_size; 314*2ae41f5dSLike Xu count++; 315*2ae41f5dSLike Xu } while (expected && (void *)cur_record < (void *)ds->pebs_index); 316*2ae41f5dSLike Xu 317*2ae41f5dSLike Xu if (!expected) { 318*2ae41f5dSLike Xu if (!pebs_idx_match) 319*2ae41f5dSLike Xu printf("FAIL: The applicable_counters (0x%lx) doesn't match with pmc_bitmask (0x%lx).\n", 320*2ae41f5dSLike Xu pebs_rec->applicable_counters, bitmask); 321*2ae41f5dSLike Xu if (!pebs_size_match) 322*2ae41f5dSLike Xu printf("FAIL: The pebs_record_size (%d) doesn't match with MSR_PEBS_DATA_CFG (%d).\n", 323*2ae41f5dSLike Xu pebs_record_size, get_adaptive_pebs_record_size(pebs_data_cfg)); 324*2ae41f5dSLike Xu if (!data_cfg_match) 325*2ae41f5dSLike Xu printf("FAIL: The pebs_data_cfg (0x%lx) doesn't match with MSR_PEBS_DATA_CFG (0x%lx).\n", 326*2ae41f5dSLike Xu pebs_rec->format_size & 0xffffffffffff, pebs_data_cfg); 327*2ae41f5dSLike Xu } 328*2ae41f5dSLike Xu } 329*2ae41f5dSLike Xu 330*2ae41f5dSLike Xu static void check_one_counter(enum pmc_type type, 331*2ae41f5dSLike Xu unsigned int idx, u64 pebs_data_cfg) 332*2ae41f5dSLike Xu { 333*2ae41f5dSLike Xu int pebs_bit = BIT_ULL(type == FIXED ? FIXED_CNT_INDEX + idx : idx); 334*2ae41f5dSLike Xu 335*2ae41f5dSLike Xu report_prefix_pushf("%s counter %d (0x%lx)", 336*2ae41f5dSLike Xu type == FIXED ? "Extended Fixed" : "GP", idx, ctr_start_val); 337*2ae41f5dSLike Xu reset_pebs(); 338*2ae41f5dSLike Xu pebs_enable(pebs_bit, pebs_data_cfg); 339*2ae41f5dSLike Xu workload(); 340*2ae41f5dSLike Xu pebs_disable(idx); 341*2ae41f5dSLike Xu check_pebs_records(pebs_bit, pebs_data_cfg); 342*2ae41f5dSLike Xu report_prefix_pop(); 343*2ae41f5dSLike Xu } 344*2ae41f5dSLike Xu 345*2ae41f5dSLike Xu /* more than one PEBS records will be generated. */ 346*2ae41f5dSLike Xu static void check_multiple_counters(u64 bitmask, u64 pebs_data_cfg) 347*2ae41f5dSLike Xu { 348*2ae41f5dSLike Xu reset_pebs(); 349*2ae41f5dSLike Xu pebs_enable(bitmask, pebs_data_cfg); 350*2ae41f5dSLike Xu workload2(); 351*2ae41f5dSLike Xu pebs_disable(0); 352*2ae41f5dSLike Xu check_pebs_records(bitmask, pebs_data_cfg); 353*2ae41f5dSLike Xu } 354*2ae41f5dSLike Xu 355*2ae41f5dSLike Xu static void check_pebs_counters(u64 pebs_data_cfg) 356*2ae41f5dSLike Xu { 357*2ae41f5dSLike Xu unsigned int idx; 358*2ae41f5dSLike Xu u64 bitmask = 0; 359*2ae41f5dSLike Xu 360*2ae41f5dSLike Xu for (idx = 0; idx < pmu.nr_fixed_counters; idx++) 361*2ae41f5dSLike Xu check_one_counter(FIXED, idx, pebs_data_cfg); 362*2ae41f5dSLike Xu 363*2ae41f5dSLike Xu for (idx = 0; idx < max_nr_gp_events; idx++) 364*2ae41f5dSLike Xu check_one_counter(GP, idx, pebs_data_cfg); 365*2ae41f5dSLike Xu 366*2ae41f5dSLike Xu for (idx = 0; idx < pmu.nr_fixed_counters; idx++) 367*2ae41f5dSLike Xu bitmask |= BIT_ULL(FIXED_CNT_INDEX + idx); 368*2ae41f5dSLike Xu for (idx = 0; idx < max_nr_gp_events; idx += 2) 369*2ae41f5dSLike Xu bitmask |= BIT_ULL(idx); 370*2ae41f5dSLike Xu report_prefix_pushf("Multiple (0x%lx)", bitmask); 371*2ae41f5dSLike Xu check_multiple_counters(bitmask, pebs_data_cfg); 372*2ae41f5dSLike Xu report_prefix_pop(); 373*2ae41f5dSLike Xu } 374*2ae41f5dSLike Xu 375*2ae41f5dSLike Xu /* 376*2ae41f5dSLike Xu * Known reasons for none PEBS records: 377*2ae41f5dSLike Xu * 1. The selected event does not support PEBS; 378*2ae41f5dSLike Xu * 2. From a core pmu perspective, the vCPU and pCPU models are not same; 379*2ae41f5dSLike Xu * 3. Guest counter has not yet overflowed or been cross-mapped by the host; 380*2ae41f5dSLike Xu */ 381*2ae41f5dSLike Xu int main(int ac, char **av) 382*2ae41f5dSLike Xu { 383*2ae41f5dSLike Xu unsigned int i, j; 384*2ae41f5dSLike Xu 385*2ae41f5dSLike Xu setup_vm(); 386*2ae41f5dSLike Xu 387*2ae41f5dSLike Xu max_nr_gp_events = MIN(pmu.nr_gp_counters, ARRAY_SIZE(intel_arch_events)); 388*2ae41f5dSLike Xu 389*2ae41f5dSLike Xu printf("PMU version: %d\n", pmu.version); 390*2ae41f5dSLike Xu 391*2ae41f5dSLike Xu has_baseline = pmu_has_pebs_baseline(); 392*2ae41f5dSLike Xu if (pmu_has_full_writes()) 393*2ae41f5dSLike Xu pmu_activate_full_writes(); 394*2ae41f5dSLike Xu 395*2ae41f5dSLike Xu if (!is_intel()) { 396*2ae41f5dSLike Xu report_skip("PEBS requires Intel ICX or later, non-Intel detected"); 397*2ae41f5dSLike Xu return report_summary(); 398*2ae41f5dSLike Xu } else if (!pmu_has_pebs()) { 399*2ae41f5dSLike Xu report_skip("PEBS required PMU version 2, reported version is %d", pmu.version); 400*2ae41f5dSLike Xu return report_summary(); 401*2ae41f5dSLike Xu } else if (!pmu_pebs_format()) { 402*2ae41f5dSLike Xu report_skip("PEBS not enumerated in PERF_CAPABILITIES"); 403*2ae41f5dSLike Xu return report_summary(); 404*2ae41f5dSLike Xu } else if (rdmsr(MSR_IA32_MISC_ENABLE) & MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL) { 405*2ae41f5dSLike Xu report_skip("PEBS unavailable according to MISC_ENABLE"); 406*2ae41f5dSLike Xu return report_summary(); 407*2ae41f5dSLike Xu } 408*2ae41f5dSLike Xu 409*2ae41f5dSLike Xu printf("PEBS format: %d\n", pmu_pebs_format()); 410*2ae41f5dSLike Xu printf("PEBS GP counters: %d\n", pmu.nr_gp_counters); 411*2ae41f5dSLike Xu printf("PEBS Fixed counters: %d\n", pmu.nr_fixed_counters); 412*2ae41f5dSLike Xu printf("PEBS baseline (Adaptive PEBS): %d\n", has_baseline); 413*2ae41f5dSLike Xu 414*2ae41f5dSLike Xu handle_irq(PMI_VECTOR, cnt_overflow); 415*2ae41f5dSLike Xu alloc_buffers(); 416*2ae41f5dSLike Xu 417*2ae41f5dSLike Xu for (i = 0; i < ARRAY_SIZE(counter_start_values); i++) { 418*2ae41f5dSLike Xu ctr_start_val = counter_start_values[i]; 419*2ae41f5dSLike Xu check_pebs_counters(0); 420*2ae41f5dSLike Xu if (!has_baseline) 421*2ae41f5dSLike Xu continue; 422*2ae41f5dSLike Xu 423*2ae41f5dSLike Xu for (j = 0; j < ARRAY_SIZE(pebs_data_cfgs); j++) { 424*2ae41f5dSLike Xu report_prefix_pushf("Adaptive (0x%lx)", pebs_data_cfgs[j]); 425*2ae41f5dSLike Xu check_pebs_counters(pebs_data_cfgs[j]); 426*2ae41f5dSLike Xu report_prefix_pop(); 427*2ae41f5dSLike Xu } 428*2ae41f5dSLike Xu } 429*2ae41f5dSLike Xu 430*2ae41f5dSLike Xu free_buffers(); 431*2ae41f5dSLike Xu 432*2ae41f5dSLike Xu return report_summary(); 433*2ae41f5dSLike Xu } 434