18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include <linux/bitops.h> 38c2ecf20Sopenharmony_ci#include <linux/types.h> 48c2ecf20Sopenharmony_ci#include <linux/slab.h> 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <asm/cpu_entry_area.h> 78c2ecf20Sopenharmony_ci#include <asm/perf_event.h> 88c2ecf20Sopenharmony_ci#include <asm/tlbflush.h> 98c2ecf20Sopenharmony_ci#include <asm/insn.h> 108c2ecf20Sopenharmony_ci#include <asm/io.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include "../perf_event.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci/* Waste a full page so it can be mapped into the cpu_entry_area */ 158c2ecf20Sopenharmony_ciDEFINE_PER_CPU_PAGE_ALIGNED(struct debug_store, cpu_debug_store); 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci/* The size of a BTS record in bytes: */ 188c2ecf20Sopenharmony_ci#define BTS_RECORD_SIZE 24 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#define PEBS_FIXUP_SIZE PAGE_SIZE 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci/* 238c2ecf20Sopenharmony_ci * pebs_record_32 for p4 and core not supported 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistruct pebs_record_32 { 268c2ecf20Sopenharmony_ci u32 flags, ip; 278c2ecf20Sopenharmony_ci u32 ax, bc, cx, dx; 288c2ecf20Sopenharmony_ci u32 si, di, bp, sp; 298c2ecf20Sopenharmony_ci}; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ciunion intel_x86_pebs_dse { 348c2ecf20Sopenharmony_ci u64 val; 358c2ecf20Sopenharmony_ci struct { 368c2ecf20Sopenharmony_ci unsigned int ld_dse:4; 378c2ecf20Sopenharmony_ci unsigned int ld_stlb_miss:1; 388c2ecf20Sopenharmony_ci unsigned int ld_locked:1; 398c2ecf20Sopenharmony_ci unsigned int ld_reserved:26; 408c2ecf20Sopenharmony_ci }; 418c2ecf20Sopenharmony_ci struct { 428c2ecf20Sopenharmony_ci unsigned int st_l1d_hit:1; 438c2ecf20Sopenharmony_ci unsigned int st_reserved1:3; 448c2ecf20Sopenharmony_ci unsigned int st_stlb_miss:1; 458c2ecf20Sopenharmony_ci unsigned int st_locked:1; 468c2ecf20Sopenharmony_ci unsigned int st_reserved2:26; 478c2ecf20Sopenharmony_ci }; 488c2ecf20Sopenharmony_ci}; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci/* 528c2ecf20Sopenharmony_ci * Map PEBS Load Latency Data Source encodings to generic 538c2ecf20Sopenharmony_ci * memory data source information 548c2ecf20Sopenharmony_ci */ 558c2ecf20Sopenharmony_ci#define P(a, b) PERF_MEM_S(a, b) 568c2ecf20Sopenharmony_ci#define OP_LH (P(OP, LOAD) | P(LVL, HIT)) 578c2ecf20Sopenharmony_ci#define LEVEL(x) P(LVLNUM, x) 588c2ecf20Sopenharmony_ci#define REM P(REMOTE, REMOTE) 598c2ecf20Sopenharmony_ci#define SNOOP_NONE_MISS (P(SNOOP, NONE) | P(SNOOP, MISS)) 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci/* Version for Sandy Bridge and later */ 628c2ecf20Sopenharmony_cistatic u64 pebs_data_source[] = { 638c2ecf20Sopenharmony_ci P(OP, LOAD) | P(LVL, MISS) | LEVEL(L3) | P(SNOOP, NA),/* 0x00:ukn L3 */ 648c2ecf20Sopenharmony_ci OP_LH | P(LVL, L1) | LEVEL(L1) | P(SNOOP, NONE), /* 0x01: L1 local */ 658c2ecf20Sopenharmony_ci OP_LH | P(LVL, LFB) | LEVEL(LFB) | P(SNOOP, NONE), /* 0x02: LFB hit */ 668c2ecf20Sopenharmony_ci OP_LH | P(LVL, L2) | LEVEL(L2) | P(SNOOP, NONE), /* 0x03: L2 hit */ 678c2ecf20Sopenharmony_ci OP_LH | P(LVL, L3) | LEVEL(L3) | P(SNOOP, NONE), /* 0x04: L3 hit */ 688c2ecf20Sopenharmony_ci OP_LH | P(LVL, L3) | LEVEL(L3) | P(SNOOP, MISS), /* 0x05: L3 hit, snoop miss */ 698c2ecf20Sopenharmony_ci OP_LH | P(LVL, L3) | LEVEL(L3) | P(SNOOP, HIT), /* 0x06: L3 hit, snoop hit */ 708c2ecf20Sopenharmony_ci OP_LH | P(LVL, L3) | LEVEL(L3) | P(SNOOP, HITM), /* 0x07: L3 hit, snoop hitm */ 718c2ecf20Sopenharmony_ci OP_LH | P(LVL, REM_CCE1) | REM | LEVEL(L3) | P(SNOOP, HIT), /* 0x08: L3 miss snoop hit */ 728c2ecf20Sopenharmony_ci OP_LH | P(LVL, REM_CCE1) | REM | LEVEL(L3) | P(SNOOP, HITM), /* 0x09: L3 miss snoop hitm*/ 738c2ecf20Sopenharmony_ci OP_LH | P(LVL, LOC_RAM) | LEVEL(RAM) | P(SNOOP, HIT), /* 0x0a: L3 miss, shared */ 748c2ecf20Sopenharmony_ci OP_LH | P(LVL, REM_RAM1) | REM | LEVEL(L3) | P(SNOOP, HIT), /* 0x0b: L3 miss, shared */ 758c2ecf20Sopenharmony_ci OP_LH | P(LVL, LOC_RAM) | LEVEL(RAM) | SNOOP_NONE_MISS, /* 0x0c: L3 miss, excl */ 768c2ecf20Sopenharmony_ci OP_LH | P(LVL, REM_RAM1) | LEVEL(RAM) | REM | SNOOP_NONE_MISS, /* 0x0d: L3 miss, excl */ 778c2ecf20Sopenharmony_ci OP_LH | P(LVL, IO) | LEVEL(NA) | P(SNOOP, NONE), /* 0x0e: I/O */ 788c2ecf20Sopenharmony_ci OP_LH | P(LVL, UNC) | LEVEL(NA) | P(SNOOP, NONE), /* 0x0f: uncached */ 798c2ecf20Sopenharmony_ci}; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci/* Patch up minor differences in the bits */ 828c2ecf20Sopenharmony_civoid __init intel_pmu_pebs_data_source_nhm(void) 838c2ecf20Sopenharmony_ci{ 848c2ecf20Sopenharmony_ci pebs_data_source[0x05] = OP_LH | P(LVL, L3) | LEVEL(L3) | P(SNOOP, HIT); 858c2ecf20Sopenharmony_ci pebs_data_source[0x06] = OP_LH | P(LVL, L3) | LEVEL(L3) | P(SNOOP, HITM); 868c2ecf20Sopenharmony_ci pebs_data_source[0x07] = OP_LH | P(LVL, L3) | LEVEL(L3) | P(SNOOP, HITM); 878c2ecf20Sopenharmony_ci} 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_civoid __init intel_pmu_pebs_data_source_skl(bool pmem) 908c2ecf20Sopenharmony_ci{ 918c2ecf20Sopenharmony_ci u64 pmem_or_l4 = pmem ? LEVEL(PMEM) : LEVEL(L4); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci pebs_data_source[0x08] = OP_LH | pmem_or_l4 | P(SNOOP, HIT); 948c2ecf20Sopenharmony_ci pebs_data_source[0x09] = OP_LH | pmem_or_l4 | REM | P(SNOOP, HIT); 958c2ecf20Sopenharmony_ci pebs_data_source[0x0b] = OP_LH | LEVEL(RAM) | REM | P(SNOOP, NONE); 968c2ecf20Sopenharmony_ci pebs_data_source[0x0c] = OP_LH | LEVEL(ANY_CACHE) | REM | P(SNOOPX, FWD); 978c2ecf20Sopenharmony_ci pebs_data_source[0x0d] = OP_LH | LEVEL(ANY_CACHE) | REM | P(SNOOP, HITM); 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistatic u64 precise_store_data(u64 status) 1018c2ecf20Sopenharmony_ci{ 1028c2ecf20Sopenharmony_ci union intel_x86_pebs_dse dse; 1038c2ecf20Sopenharmony_ci u64 val = P(OP, STORE) | P(SNOOP, NA) | P(LVL, L1) | P(TLB, L2); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci dse.val = status; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci /* 1088c2ecf20Sopenharmony_ci * bit 4: TLB access 1098c2ecf20Sopenharmony_ci * 1 = stored missed 2nd level TLB 1108c2ecf20Sopenharmony_ci * 1118c2ecf20Sopenharmony_ci * so it either hit the walker or the OS 1128c2ecf20Sopenharmony_ci * otherwise hit 2nd level TLB 1138c2ecf20Sopenharmony_ci */ 1148c2ecf20Sopenharmony_ci if (dse.st_stlb_miss) 1158c2ecf20Sopenharmony_ci val |= P(TLB, MISS); 1168c2ecf20Sopenharmony_ci else 1178c2ecf20Sopenharmony_ci val |= P(TLB, HIT); 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci /* 1208c2ecf20Sopenharmony_ci * bit 0: hit L1 data cache 1218c2ecf20Sopenharmony_ci * if not set, then all we know is that 1228c2ecf20Sopenharmony_ci * it missed L1D 1238c2ecf20Sopenharmony_ci */ 1248c2ecf20Sopenharmony_ci if (dse.st_l1d_hit) 1258c2ecf20Sopenharmony_ci val |= P(LVL, HIT); 1268c2ecf20Sopenharmony_ci else 1278c2ecf20Sopenharmony_ci val |= P(LVL, MISS); 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci /* 1308c2ecf20Sopenharmony_ci * bit 5: Locked prefix 1318c2ecf20Sopenharmony_ci */ 1328c2ecf20Sopenharmony_ci if (dse.st_locked) 1338c2ecf20Sopenharmony_ci val |= P(LOCK, LOCKED); 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci return val; 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_cistatic u64 precise_datala_hsw(struct perf_event *event, u64 status) 1398c2ecf20Sopenharmony_ci{ 1408c2ecf20Sopenharmony_ci union perf_mem_data_src dse; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci dse.val = PERF_MEM_NA; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci if (event->hw.flags & PERF_X86_EVENT_PEBS_ST_HSW) 1458c2ecf20Sopenharmony_ci dse.mem_op = PERF_MEM_OP_STORE; 1468c2ecf20Sopenharmony_ci else if (event->hw.flags & PERF_X86_EVENT_PEBS_LD_HSW) 1478c2ecf20Sopenharmony_ci dse.mem_op = PERF_MEM_OP_LOAD; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci /* 1508c2ecf20Sopenharmony_ci * L1 info only valid for following events: 1518c2ecf20Sopenharmony_ci * 1528c2ecf20Sopenharmony_ci * MEM_UOPS_RETIRED.STLB_MISS_STORES 1538c2ecf20Sopenharmony_ci * MEM_UOPS_RETIRED.LOCK_STORES 1548c2ecf20Sopenharmony_ci * MEM_UOPS_RETIRED.SPLIT_STORES 1558c2ecf20Sopenharmony_ci * MEM_UOPS_RETIRED.ALL_STORES 1568c2ecf20Sopenharmony_ci */ 1578c2ecf20Sopenharmony_ci if (event->hw.flags & PERF_X86_EVENT_PEBS_ST_HSW) { 1588c2ecf20Sopenharmony_ci if (status & 1) 1598c2ecf20Sopenharmony_ci dse.mem_lvl = PERF_MEM_LVL_L1 | PERF_MEM_LVL_HIT; 1608c2ecf20Sopenharmony_ci else 1618c2ecf20Sopenharmony_ci dse.mem_lvl = PERF_MEM_LVL_L1 | PERF_MEM_LVL_MISS; 1628c2ecf20Sopenharmony_ci } 1638c2ecf20Sopenharmony_ci return dse.val; 1648c2ecf20Sopenharmony_ci} 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_cistatic u64 load_latency_data(u64 status) 1678c2ecf20Sopenharmony_ci{ 1688c2ecf20Sopenharmony_ci union intel_x86_pebs_dse dse; 1698c2ecf20Sopenharmony_ci u64 val; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci dse.val = status; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci /* 1748c2ecf20Sopenharmony_ci * use the mapping table for bit 0-3 1758c2ecf20Sopenharmony_ci */ 1768c2ecf20Sopenharmony_ci val = pebs_data_source[dse.ld_dse]; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci /* 1798c2ecf20Sopenharmony_ci * Nehalem models do not support TLB, Lock infos 1808c2ecf20Sopenharmony_ci */ 1818c2ecf20Sopenharmony_ci if (x86_pmu.pebs_no_tlb) { 1828c2ecf20Sopenharmony_ci val |= P(TLB, NA) | P(LOCK, NA); 1838c2ecf20Sopenharmony_ci return val; 1848c2ecf20Sopenharmony_ci } 1858c2ecf20Sopenharmony_ci /* 1868c2ecf20Sopenharmony_ci * bit 4: TLB access 1878c2ecf20Sopenharmony_ci * 0 = did not miss 2nd level TLB 1888c2ecf20Sopenharmony_ci * 1 = missed 2nd level TLB 1898c2ecf20Sopenharmony_ci */ 1908c2ecf20Sopenharmony_ci if (dse.ld_stlb_miss) 1918c2ecf20Sopenharmony_ci val |= P(TLB, MISS) | P(TLB, L2); 1928c2ecf20Sopenharmony_ci else 1938c2ecf20Sopenharmony_ci val |= P(TLB, HIT) | P(TLB, L1) | P(TLB, L2); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci /* 1968c2ecf20Sopenharmony_ci * bit 5: locked prefix 1978c2ecf20Sopenharmony_ci */ 1988c2ecf20Sopenharmony_ci if (dse.ld_locked) 1998c2ecf20Sopenharmony_ci val |= P(LOCK, LOCKED); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci return val; 2028c2ecf20Sopenharmony_ci} 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_cistruct pebs_record_core { 2058c2ecf20Sopenharmony_ci u64 flags, ip; 2068c2ecf20Sopenharmony_ci u64 ax, bx, cx, dx; 2078c2ecf20Sopenharmony_ci u64 si, di, bp, sp; 2088c2ecf20Sopenharmony_ci u64 r8, r9, r10, r11; 2098c2ecf20Sopenharmony_ci u64 r12, r13, r14, r15; 2108c2ecf20Sopenharmony_ci}; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_cistruct pebs_record_nhm { 2138c2ecf20Sopenharmony_ci u64 flags, ip; 2148c2ecf20Sopenharmony_ci u64 ax, bx, cx, dx; 2158c2ecf20Sopenharmony_ci u64 si, di, bp, sp; 2168c2ecf20Sopenharmony_ci u64 r8, r9, r10, r11; 2178c2ecf20Sopenharmony_ci u64 r12, r13, r14, r15; 2188c2ecf20Sopenharmony_ci u64 status, dla, dse, lat; 2198c2ecf20Sopenharmony_ci}; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci/* 2228c2ecf20Sopenharmony_ci * Same as pebs_record_nhm, with two additional fields. 2238c2ecf20Sopenharmony_ci */ 2248c2ecf20Sopenharmony_cistruct pebs_record_hsw { 2258c2ecf20Sopenharmony_ci u64 flags, ip; 2268c2ecf20Sopenharmony_ci u64 ax, bx, cx, dx; 2278c2ecf20Sopenharmony_ci u64 si, di, bp, sp; 2288c2ecf20Sopenharmony_ci u64 r8, r9, r10, r11; 2298c2ecf20Sopenharmony_ci u64 r12, r13, r14, r15; 2308c2ecf20Sopenharmony_ci u64 status, dla, dse, lat; 2318c2ecf20Sopenharmony_ci u64 real_ip, tsx_tuning; 2328c2ecf20Sopenharmony_ci}; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ciunion hsw_tsx_tuning { 2358c2ecf20Sopenharmony_ci struct { 2368c2ecf20Sopenharmony_ci u32 cycles_last_block : 32, 2378c2ecf20Sopenharmony_ci hle_abort : 1, 2388c2ecf20Sopenharmony_ci rtm_abort : 1, 2398c2ecf20Sopenharmony_ci instruction_abort : 1, 2408c2ecf20Sopenharmony_ci non_instruction_abort : 1, 2418c2ecf20Sopenharmony_ci retry : 1, 2428c2ecf20Sopenharmony_ci data_conflict : 1, 2438c2ecf20Sopenharmony_ci capacity_writes : 1, 2448c2ecf20Sopenharmony_ci capacity_reads : 1; 2458c2ecf20Sopenharmony_ci }; 2468c2ecf20Sopenharmony_ci u64 value; 2478c2ecf20Sopenharmony_ci}; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci#define PEBS_HSW_TSX_FLAGS 0xff00000000ULL 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci/* Same as HSW, plus TSC */ 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_cistruct pebs_record_skl { 2548c2ecf20Sopenharmony_ci u64 flags, ip; 2558c2ecf20Sopenharmony_ci u64 ax, bx, cx, dx; 2568c2ecf20Sopenharmony_ci u64 si, di, bp, sp; 2578c2ecf20Sopenharmony_ci u64 r8, r9, r10, r11; 2588c2ecf20Sopenharmony_ci u64 r12, r13, r14, r15; 2598c2ecf20Sopenharmony_ci u64 status, dla, dse, lat; 2608c2ecf20Sopenharmony_ci u64 real_ip, tsx_tuning; 2618c2ecf20Sopenharmony_ci u64 tsc; 2628c2ecf20Sopenharmony_ci}; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_civoid init_debug_store_on_cpu(int cpu) 2658c2ecf20Sopenharmony_ci{ 2668c2ecf20Sopenharmony_ci struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci if (!ds) 2698c2ecf20Sopenharmony_ci return; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci wrmsr_on_cpu(cpu, MSR_IA32_DS_AREA, 2728c2ecf20Sopenharmony_ci (u32)((u64)(unsigned long)ds), 2738c2ecf20Sopenharmony_ci (u32)((u64)(unsigned long)ds >> 32)); 2748c2ecf20Sopenharmony_ci} 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_civoid fini_debug_store_on_cpu(int cpu) 2778c2ecf20Sopenharmony_ci{ 2788c2ecf20Sopenharmony_ci if (!per_cpu(cpu_hw_events, cpu).ds) 2798c2ecf20Sopenharmony_ci return; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci wrmsr_on_cpu(cpu, MSR_IA32_DS_AREA, 0, 0); 2828c2ecf20Sopenharmony_ci} 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_cistatic DEFINE_PER_CPU(void *, insn_buffer); 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_cistatic void ds_update_cea(void *cea, void *addr, size_t size, pgprot_t prot) 2878c2ecf20Sopenharmony_ci{ 2888c2ecf20Sopenharmony_ci unsigned long start = (unsigned long)cea; 2898c2ecf20Sopenharmony_ci phys_addr_t pa; 2908c2ecf20Sopenharmony_ci size_t msz = 0; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci pa = virt_to_phys(addr); 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci preempt_disable(); 2958c2ecf20Sopenharmony_ci for (; msz < size; msz += PAGE_SIZE, pa += PAGE_SIZE, cea += PAGE_SIZE) 2968c2ecf20Sopenharmony_ci cea_set_pte(cea, pa, prot); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci /* 2998c2ecf20Sopenharmony_ci * This is a cross-CPU update of the cpu_entry_area, we must shoot down 3008c2ecf20Sopenharmony_ci * all TLB entries for it. 3018c2ecf20Sopenharmony_ci */ 3028c2ecf20Sopenharmony_ci flush_tlb_kernel_range(start, start + size); 3038c2ecf20Sopenharmony_ci preempt_enable(); 3048c2ecf20Sopenharmony_ci} 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_cistatic void ds_clear_cea(void *cea, size_t size) 3078c2ecf20Sopenharmony_ci{ 3088c2ecf20Sopenharmony_ci unsigned long start = (unsigned long)cea; 3098c2ecf20Sopenharmony_ci size_t msz = 0; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci preempt_disable(); 3128c2ecf20Sopenharmony_ci for (; msz < size; msz += PAGE_SIZE, cea += PAGE_SIZE) 3138c2ecf20Sopenharmony_ci cea_set_pte(cea, 0, PAGE_NONE); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci flush_tlb_kernel_range(start, start + size); 3168c2ecf20Sopenharmony_ci preempt_enable(); 3178c2ecf20Sopenharmony_ci} 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_cistatic void *dsalloc_pages(size_t size, gfp_t flags, int cpu) 3208c2ecf20Sopenharmony_ci{ 3218c2ecf20Sopenharmony_ci unsigned int order = get_order(size); 3228c2ecf20Sopenharmony_ci int node = cpu_to_node(cpu); 3238c2ecf20Sopenharmony_ci struct page *page; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci page = __alloc_pages_node(node, flags | __GFP_ZERO, order); 3268c2ecf20Sopenharmony_ci return page ? page_address(page) : NULL; 3278c2ecf20Sopenharmony_ci} 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_cistatic void dsfree_pages(const void *buffer, size_t size) 3308c2ecf20Sopenharmony_ci{ 3318c2ecf20Sopenharmony_ci if (buffer) 3328c2ecf20Sopenharmony_ci free_pages((unsigned long)buffer, get_order(size)); 3338c2ecf20Sopenharmony_ci} 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_cistatic int alloc_pebs_buffer(int cpu) 3368c2ecf20Sopenharmony_ci{ 3378c2ecf20Sopenharmony_ci struct cpu_hw_events *hwev = per_cpu_ptr(&cpu_hw_events, cpu); 3388c2ecf20Sopenharmony_ci struct debug_store *ds = hwev->ds; 3398c2ecf20Sopenharmony_ci size_t bsiz = x86_pmu.pebs_buffer_size; 3408c2ecf20Sopenharmony_ci int max, node = cpu_to_node(cpu); 3418c2ecf20Sopenharmony_ci void *buffer, *insn_buff, *cea; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci if (!x86_pmu.pebs) 3448c2ecf20Sopenharmony_ci return 0; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci buffer = dsalloc_pages(bsiz, GFP_KERNEL, cpu); 3478c2ecf20Sopenharmony_ci if (unlikely(!buffer)) 3488c2ecf20Sopenharmony_ci return -ENOMEM; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci /* 3518c2ecf20Sopenharmony_ci * HSW+ already provides us the eventing ip; no need to allocate this 3528c2ecf20Sopenharmony_ci * buffer then. 3538c2ecf20Sopenharmony_ci */ 3548c2ecf20Sopenharmony_ci if (x86_pmu.intel_cap.pebs_format < 2) { 3558c2ecf20Sopenharmony_ci insn_buff = kzalloc_node(PEBS_FIXUP_SIZE, GFP_KERNEL, node); 3568c2ecf20Sopenharmony_ci if (!insn_buff) { 3578c2ecf20Sopenharmony_ci dsfree_pages(buffer, bsiz); 3588c2ecf20Sopenharmony_ci return -ENOMEM; 3598c2ecf20Sopenharmony_ci } 3608c2ecf20Sopenharmony_ci per_cpu(insn_buffer, cpu) = insn_buff; 3618c2ecf20Sopenharmony_ci } 3628c2ecf20Sopenharmony_ci hwev->ds_pebs_vaddr = buffer; 3638c2ecf20Sopenharmony_ci /* Update the cpu entry area mapping */ 3648c2ecf20Sopenharmony_ci cea = &get_cpu_entry_area(cpu)->cpu_debug_buffers.pebs_buffer; 3658c2ecf20Sopenharmony_ci ds->pebs_buffer_base = (unsigned long) cea; 3668c2ecf20Sopenharmony_ci ds_update_cea(cea, buffer, bsiz, PAGE_KERNEL); 3678c2ecf20Sopenharmony_ci ds->pebs_index = ds->pebs_buffer_base; 3688c2ecf20Sopenharmony_ci max = x86_pmu.pebs_record_size * (bsiz / x86_pmu.pebs_record_size); 3698c2ecf20Sopenharmony_ci ds->pebs_absolute_maximum = ds->pebs_buffer_base + max; 3708c2ecf20Sopenharmony_ci return 0; 3718c2ecf20Sopenharmony_ci} 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_cistatic void release_pebs_buffer(int cpu) 3748c2ecf20Sopenharmony_ci{ 3758c2ecf20Sopenharmony_ci struct cpu_hw_events *hwev = per_cpu_ptr(&cpu_hw_events, cpu); 3768c2ecf20Sopenharmony_ci void *cea; 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci if (!x86_pmu.pebs) 3798c2ecf20Sopenharmony_ci return; 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci kfree(per_cpu(insn_buffer, cpu)); 3828c2ecf20Sopenharmony_ci per_cpu(insn_buffer, cpu) = NULL; 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci /* Clear the fixmap */ 3858c2ecf20Sopenharmony_ci cea = &get_cpu_entry_area(cpu)->cpu_debug_buffers.pebs_buffer; 3868c2ecf20Sopenharmony_ci ds_clear_cea(cea, x86_pmu.pebs_buffer_size); 3878c2ecf20Sopenharmony_ci dsfree_pages(hwev->ds_pebs_vaddr, x86_pmu.pebs_buffer_size); 3888c2ecf20Sopenharmony_ci hwev->ds_pebs_vaddr = NULL; 3898c2ecf20Sopenharmony_ci} 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_cistatic int alloc_bts_buffer(int cpu) 3928c2ecf20Sopenharmony_ci{ 3938c2ecf20Sopenharmony_ci struct cpu_hw_events *hwev = per_cpu_ptr(&cpu_hw_events, cpu); 3948c2ecf20Sopenharmony_ci struct debug_store *ds = hwev->ds; 3958c2ecf20Sopenharmony_ci void *buffer, *cea; 3968c2ecf20Sopenharmony_ci int max; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci if (!x86_pmu.bts) 3998c2ecf20Sopenharmony_ci return 0; 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci buffer = dsalloc_pages(BTS_BUFFER_SIZE, GFP_KERNEL | __GFP_NOWARN, cpu); 4028c2ecf20Sopenharmony_ci if (unlikely(!buffer)) { 4038c2ecf20Sopenharmony_ci WARN_ONCE(1, "%s: BTS buffer allocation failure\n", __func__); 4048c2ecf20Sopenharmony_ci return -ENOMEM; 4058c2ecf20Sopenharmony_ci } 4068c2ecf20Sopenharmony_ci hwev->ds_bts_vaddr = buffer; 4078c2ecf20Sopenharmony_ci /* Update the fixmap */ 4088c2ecf20Sopenharmony_ci cea = &get_cpu_entry_area(cpu)->cpu_debug_buffers.bts_buffer; 4098c2ecf20Sopenharmony_ci ds->bts_buffer_base = (unsigned long) cea; 4108c2ecf20Sopenharmony_ci ds_update_cea(cea, buffer, BTS_BUFFER_SIZE, PAGE_KERNEL); 4118c2ecf20Sopenharmony_ci ds->bts_index = ds->bts_buffer_base; 4128c2ecf20Sopenharmony_ci max = BTS_BUFFER_SIZE / BTS_RECORD_SIZE; 4138c2ecf20Sopenharmony_ci ds->bts_absolute_maximum = ds->bts_buffer_base + 4148c2ecf20Sopenharmony_ci max * BTS_RECORD_SIZE; 4158c2ecf20Sopenharmony_ci ds->bts_interrupt_threshold = ds->bts_absolute_maximum - 4168c2ecf20Sopenharmony_ci (max / 16) * BTS_RECORD_SIZE; 4178c2ecf20Sopenharmony_ci return 0; 4188c2ecf20Sopenharmony_ci} 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_cistatic void release_bts_buffer(int cpu) 4218c2ecf20Sopenharmony_ci{ 4228c2ecf20Sopenharmony_ci struct cpu_hw_events *hwev = per_cpu_ptr(&cpu_hw_events, cpu); 4238c2ecf20Sopenharmony_ci void *cea; 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci if (!x86_pmu.bts) 4268c2ecf20Sopenharmony_ci return; 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci /* Clear the fixmap */ 4298c2ecf20Sopenharmony_ci cea = &get_cpu_entry_area(cpu)->cpu_debug_buffers.bts_buffer; 4308c2ecf20Sopenharmony_ci ds_clear_cea(cea, BTS_BUFFER_SIZE); 4318c2ecf20Sopenharmony_ci dsfree_pages(hwev->ds_bts_vaddr, BTS_BUFFER_SIZE); 4328c2ecf20Sopenharmony_ci hwev->ds_bts_vaddr = NULL; 4338c2ecf20Sopenharmony_ci} 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_cistatic int alloc_ds_buffer(int cpu) 4368c2ecf20Sopenharmony_ci{ 4378c2ecf20Sopenharmony_ci struct debug_store *ds = &get_cpu_entry_area(cpu)->cpu_debug_store; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci memset(ds, 0, sizeof(*ds)); 4408c2ecf20Sopenharmony_ci per_cpu(cpu_hw_events, cpu).ds = ds; 4418c2ecf20Sopenharmony_ci return 0; 4428c2ecf20Sopenharmony_ci} 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_cistatic void release_ds_buffer(int cpu) 4458c2ecf20Sopenharmony_ci{ 4468c2ecf20Sopenharmony_ci per_cpu(cpu_hw_events, cpu).ds = NULL; 4478c2ecf20Sopenharmony_ci} 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_civoid release_ds_buffers(void) 4508c2ecf20Sopenharmony_ci{ 4518c2ecf20Sopenharmony_ci int cpu; 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci if (!x86_pmu.bts && !x86_pmu.pebs) 4548c2ecf20Sopenharmony_ci return; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci for_each_possible_cpu(cpu) 4578c2ecf20Sopenharmony_ci release_ds_buffer(cpu); 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci for_each_possible_cpu(cpu) { 4608c2ecf20Sopenharmony_ci /* 4618c2ecf20Sopenharmony_ci * Again, ignore errors from offline CPUs, they will no longer 4628c2ecf20Sopenharmony_ci * observe cpu_hw_events.ds and not program the DS_AREA when 4638c2ecf20Sopenharmony_ci * they come up. 4648c2ecf20Sopenharmony_ci */ 4658c2ecf20Sopenharmony_ci fini_debug_store_on_cpu(cpu); 4668c2ecf20Sopenharmony_ci } 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci for_each_possible_cpu(cpu) { 4698c2ecf20Sopenharmony_ci release_pebs_buffer(cpu); 4708c2ecf20Sopenharmony_ci release_bts_buffer(cpu); 4718c2ecf20Sopenharmony_ci } 4728c2ecf20Sopenharmony_ci} 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_civoid reserve_ds_buffers(void) 4758c2ecf20Sopenharmony_ci{ 4768c2ecf20Sopenharmony_ci int bts_err = 0, pebs_err = 0; 4778c2ecf20Sopenharmony_ci int cpu; 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci x86_pmu.bts_active = 0; 4808c2ecf20Sopenharmony_ci x86_pmu.pebs_active = 0; 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci if (!x86_pmu.bts && !x86_pmu.pebs) 4838c2ecf20Sopenharmony_ci return; 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci if (!x86_pmu.bts) 4868c2ecf20Sopenharmony_ci bts_err = 1; 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci if (!x86_pmu.pebs) 4898c2ecf20Sopenharmony_ci pebs_err = 1; 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci for_each_possible_cpu(cpu) { 4928c2ecf20Sopenharmony_ci if (alloc_ds_buffer(cpu)) { 4938c2ecf20Sopenharmony_ci bts_err = 1; 4948c2ecf20Sopenharmony_ci pebs_err = 1; 4958c2ecf20Sopenharmony_ci } 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci if (!bts_err && alloc_bts_buffer(cpu)) 4988c2ecf20Sopenharmony_ci bts_err = 1; 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci if (!pebs_err && alloc_pebs_buffer(cpu)) 5018c2ecf20Sopenharmony_ci pebs_err = 1; 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci if (bts_err && pebs_err) 5048c2ecf20Sopenharmony_ci break; 5058c2ecf20Sopenharmony_ci } 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci if (bts_err) { 5088c2ecf20Sopenharmony_ci for_each_possible_cpu(cpu) 5098c2ecf20Sopenharmony_ci release_bts_buffer(cpu); 5108c2ecf20Sopenharmony_ci } 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci if (pebs_err) { 5138c2ecf20Sopenharmony_ci for_each_possible_cpu(cpu) 5148c2ecf20Sopenharmony_ci release_pebs_buffer(cpu); 5158c2ecf20Sopenharmony_ci } 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci if (bts_err && pebs_err) { 5188c2ecf20Sopenharmony_ci for_each_possible_cpu(cpu) 5198c2ecf20Sopenharmony_ci release_ds_buffer(cpu); 5208c2ecf20Sopenharmony_ci } else { 5218c2ecf20Sopenharmony_ci if (x86_pmu.bts && !bts_err) 5228c2ecf20Sopenharmony_ci x86_pmu.bts_active = 1; 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci if (x86_pmu.pebs && !pebs_err) 5258c2ecf20Sopenharmony_ci x86_pmu.pebs_active = 1; 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci for_each_possible_cpu(cpu) { 5288c2ecf20Sopenharmony_ci /* 5298c2ecf20Sopenharmony_ci * Ignores wrmsr_on_cpu() errors for offline CPUs they 5308c2ecf20Sopenharmony_ci * will get this call through intel_pmu_cpu_starting(). 5318c2ecf20Sopenharmony_ci */ 5328c2ecf20Sopenharmony_ci init_debug_store_on_cpu(cpu); 5338c2ecf20Sopenharmony_ci } 5348c2ecf20Sopenharmony_ci } 5358c2ecf20Sopenharmony_ci} 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci/* 5388c2ecf20Sopenharmony_ci * BTS 5398c2ecf20Sopenharmony_ci */ 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_cistruct event_constraint bts_constraint = 5428c2ecf20Sopenharmony_ci EVENT_CONSTRAINT(0, 1ULL << INTEL_PMC_IDX_FIXED_BTS, 0); 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_civoid intel_pmu_enable_bts(u64 config) 5458c2ecf20Sopenharmony_ci{ 5468c2ecf20Sopenharmony_ci unsigned long debugctlmsr; 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci debugctlmsr = get_debugctlmsr(); 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci debugctlmsr |= DEBUGCTLMSR_TR; 5518c2ecf20Sopenharmony_ci debugctlmsr |= DEBUGCTLMSR_BTS; 5528c2ecf20Sopenharmony_ci if (config & ARCH_PERFMON_EVENTSEL_INT) 5538c2ecf20Sopenharmony_ci debugctlmsr |= DEBUGCTLMSR_BTINT; 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci if (!(config & ARCH_PERFMON_EVENTSEL_OS)) 5568c2ecf20Sopenharmony_ci debugctlmsr |= DEBUGCTLMSR_BTS_OFF_OS; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci if (!(config & ARCH_PERFMON_EVENTSEL_USR)) 5598c2ecf20Sopenharmony_ci debugctlmsr |= DEBUGCTLMSR_BTS_OFF_USR; 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci update_debugctlmsr(debugctlmsr); 5628c2ecf20Sopenharmony_ci} 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_civoid intel_pmu_disable_bts(void) 5658c2ecf20Sopenharmony_ci{ 5668c2ecf20Sopenharmony_ci struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 5678c2ecf20Sopenharmony_ci unsigned long debugctlmsr; 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci if (!cpuc->ds) 5708c2ecf20Sopenharmony_ci return; 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci debugctlmsr = get_debugctlmsr(); 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci debugctlmsr &= 5758c2ecf20Sopenharmony_ci ~(DEBUGCTLMSR_TR | DEBUGCTLMSR_BTS | DEBUGCTLMSR_BTINT | 5768c2ecf20Sopenharmony_ci DEBUGCTLMSR_BTS_OFF_OS | DEBUGCTLMSR_BTS_OFF_USR); 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci update_debugctlmsr(debugctlmsr); 5798c2ecf20Sopenharmony_ci} 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ciint intel_pmu_drain_bts_buffer(void) 5828c2ecf20Sopenharmony_ci{ 5838c2ecf20Sopenharmony_ci struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 5848c2ecf20Sopenharmony_ci struct debug_store *ds = cpuc->ds; 5858c2ecf20Sopenharmony_ci struct bts_record { 5868c2ecf20Sopenharmony_ci u64 from; 5878c2ecf20Sopenharmony_ci u64 to; 5888c2ecf20Sopenharmony_ci u64 flags; 5898c2ecf20Sopenharmony_ci }; 5908c2ecf20Sopenharmony_ci struct perf_event *event = cpuc->events[INTEL_PMC_IDX_FIXED_BTS]; 5918c2ecf20Sopenharmony_ci struct bts_record *at, *base, *top; 5928c2ecf20Sopenharmony_ci struct perf_output_handle handle; 5938c2ecf20Sopenharmony_ci struct perf_event_header header; 5948c2ecf20Sopenharmony_ci struct perf_sample_data data; 5958c2ecf20Sopenharmony_ci unsigned long skip = 0; 5968c2ecf20Sopenharmony_ci struct pt_regs regs; 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci if (!event) 5998c2ecf20Sopenharmony_ci return 0; 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci if (!x86_pmu.bts_active) 6028c2ecf20Sopenharmony_ci return 0; 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci base = (struct bts_record *)(unsigned long)ds->bts_buffer_base; 6058c2ecf20Sopenharmony_ci top = (struct bts_record *)(unsigned long)ds->bts_index; 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci if (top <= base) 6088c2ecf20Sopenharmony_ci return 0; 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci memset(®s, 0, sizeof(regs)); 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci ds->bts_index = ds->bts_buffer_base; 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci perf_sample_data_init(&data, 0, event->hw.last_period); 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci /* 6178c2ecf20Sopenharmony_ci * BTS leaks kernel addresses in branches across the cpl boundary, 6188c2ecf20Sopenharmony_ci * such as traps or system calls, so unless the user is asking for 6198c2ecf20Sopenharmony_ci * kernel tracing (and right now it's not possible), we'd need to 6208c2ecf20Sopenharmony_ci * filter them out. But first we need to count how many of those we 6218c2ecf20Sopenharmony_ci * have in the current batch. This is an extra O(n) pass, however, 6228c2ecf20Sopenharmony_ci * it's much faster than the other one especially considering that 6238c2ecf20Sopenharmony_ci * n <= 2560 (BTS_BUFFER_SIZE / BTS_RECORD_SIZE * 15/16; see the 6248c2ecf20Sopenharmony_ci * alloc_bts_buffer()). 6258c2ecf20Sopenharmony_ci */ 6268c2ecf20Sopenharmony_ci for (at = base; at < top; at++) { 6278c2ecf20Sopenharmony_ci /* 6288c2ecf20Sopenharmony_ci * Note that right now *this* BTS code only works if 6298c2ecf20Sopenharmony_ci * attr::exclude_kernel is set, but let's keep this extra 6308c2ecf20Sopenharmony_ci * check here in case that changes. 6318c2ecf20Sopenharmony_ci */ 6328c2ecf20Sopenharmony_ci if (event->attr.exclude_kernel && 6338c2ecf20Sopenharmony_ci (kernel_ip(at->from) || kernel_ip(at->to))) 6348c2ecf20Sopenharmony_ci skip++; 6358c2ecf20Sopenharmony_ci } 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci /* 6388c2ecf20Sopenharmony_ci * Prepare a generic sample, i.e. fill in the invariant fields. 6398c2ecf20Sopenharmony_ci * We will overwrite the from and to address before we output 6408c2ecf20Sopenharmony_ci * the sample. 6418c2ecf20Sopenharmony_ci */ 6428c2ecf20Sopenharmony_ci rcu_read_lock(); 6438c2ecf20Sopenharmony_ci perf_prepare_sample(&header, &data, event, ®s); 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci if (perf_output_begin(&handle, &data, event, 6468c2ecf20Sopenharmony_ci header.size * (top - base - skip))) 6478c2ecf20Sopenharmony_ci goto unlock; 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci for (at = base; at < top; at++) { 6508c2ecf20Sopenharmony_ci /* Filter out any records that contain kernel addresses. */ 6518c2ecf20Sopenharmony_ci if (event->attr.exclude_kernel && 6528c2ecf20Sopenharmony_ci (kernel_ip(at->from) || kernel_ip(at->to))) 6538c2ecf20Sopenharmony_ci continue; 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci data.ip = at->from; 6568c2ecf20Sopenharmony_ci data.addr = at->to; 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci perf_output_sample(&handle, &header, &data, event); 6598c2ecf20Sopenharmony_ci } 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci perf_output_end(&handle); 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci /* There's new data available. */ 6648c2ecf20Sopenharmony_ci event->hw.interrupts++; 6658c2ecf20Sopenharmony_ci event->pending_kill = POLL_IN; 6668c2ecf20Sopenharmony_ciunlock: 6678c2ecf20Sopenharmony_ci rcu_read_unlock(); 6688c2ecf20Sopenharmony_ci return 1; 6698c2ecf20Sopenharmony_ci} 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_cistatic inline void intel_pmu_drain_pebs_buffer(void) 6728c2ecf20Sopenharmony_ci{ 6738c2ecf20Sopenharmony_ci struct perf_sample_data data; 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci x86_pmu.drain_pebs(NULL, &data); 6768c2ecf20Sopenharmony_ci} 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci/* 6798c2ecf20Sopenharmony_ci * PEBS 6808c2ecf20Sopenharmony_ci */ 6818c2ecf20Sopenharmony_cistruct event_constraint intel_core2_pebs_event_constraints[] = { 6828c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */ 6838c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0xfec1, 0x1), /* X87_OPS_RETIRED.ANY */ 6848c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x00c5, 0x1), /* BR_INST_RETIRED.MISPRED */ 6858c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x1fc7, 0x1), /* SIMD_INST_RETURED.ANY */ 6868c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED.* */ 6878c2ecf20Sopenharmony_ci /* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */ 6888c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x108000c0, 0x01), 6898c2ecf20Sopenharmony_ci EVENT_CONSTRAINT_END 6908c2ecf20Sopenharmony_ci}; 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_cistruct event_constraint intel_atom_pebs_event_constraints[] = { 6938c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */ 6948c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x00c5, 0x1), /* MISPREDICTED_BRANCH_RETIRED */ 6958c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED.* */ 6968c2ecf20Sopenharmony_ci /* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */ 6978c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x108000c0, 0x01), 6988c2ecf20Sopenharmony_ci /* Allow all events as PEBS with no flags */ 6998c2ecf20Sopenharmony_ci INTEL_ALL_EVENT_CONSTRAINT(0, 0x1), 7008c2ecf20Sopenharmony_ci EVENT_CONSTRAINT_END 7018c2ecf20Sopenharmony_ci}; 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_cistruct event_constraint intel_slm_pebs_event_constraints[] = { 7048c2ecf20Sopenharmony_ci /* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */ 7058c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x108000c0, 0x1), 7068c2ecf20Sopenharmony_ci /* Allow all events as PEBS with no flags */ 7078c2ecf20Sopenharmony_ci INTEL_ALL_EVENT_CONSTRAINT(0, 0x1), 7088c2ecf20Sopenharmony_ci EVENT_CONSTRAINT_END 7098c2ecf20Sopenharmony_ci}; 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_cistruct event_constraint intel_glm_pebs_event_constraints[] = { 7128c2ecf20Sopenharmony_ci /* Allow all events as PEBS with no flags */ 7138c2ecf20Sopenharmony_ci INTEL_ALL_EVENT_CONSTRAINT(0, 0x1), 7148c2ecf20Sopenharmony_ci EVENT_CONSTRAINT_END 7158c2ecf20Sopenharmony_ci}; 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_cistruct event_constraint intel_nehalem_pebs_event_constraints[] = { 7188c2ecf20Sopenharmony_ci INTEL_PLD_CONSTRAINT(0x100b, 0xf), /* MEM_INST_RETIRED.* */ 7198c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT(0x0f, 0xf), /* MEM_UNCORE_RETIRED.* */ 7208c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */ 7218c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT(0xc0, 0xf), /* INST_RETIRED.ANY */ 7228c2ecf20Sopenharmony_ci INTEL_EVENT_CONSTRAINT(0xc2, 0xf), /* UOPS_RETIRED.* */ 7238c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT(0xc4, 0xf), /* BR_INST_RETIRED.* */ 7248c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x02c5, 0xf), /* BR_MISP_RETIRED.NEAR_CALL */ 7258c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT(0xc7, 0xf), /* SSEX_UOPS_RETIRED.* */ 7268c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x20c8, 0xf), /* ITLB_MISS_RETIRED */ 7278c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT(0xcb, 0xf), /* MEM_LOAD_RETIRED.* */ 7288c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT(0xf7, 0xf), /* FP_ASSIST.* */ 7298c2ecf20Sopenharmony_ci /* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */ 7308c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x108000c0, 0x0f), 7318c2ecf20Sopenharmony_ci EVENT_CONSTRAINT_END 7328c2ecf20Sopenharmony_ci}; 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_cistruct event_constraint intel_westmere_pebs_event_constraints[] = { 7358c2ecf20Sopenharmony_ci INTEL_PLD_CONSTRAINT(0x100b, 0xf), /* MEM_INST_RETIRED.* */ 7368c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT(0x0f, 0xf), /* MEM_UNCORE_RETIRED.* */ 7378c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */ 7388c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT(0xc0, 0xf), /* INSTR_RETIRED.* */ 7398c2ecf20Sopenharmony_ci INTEL_EVENT_CONSTRAINT(0xc2, 0xf), /* UOPS_RETIRED.* */ 7408c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT(0xc4, 0xf), /* BR_INST_RETIRED.* */ 7418c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT(0xc5, 0xf), /* BR_MISP_RETIRED.* */ 7428c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT(0xc7, 0xf), /* SSEX_UOPS_RETIRED.* */ 7438c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x20c8, 0xf), /* ITLB_MISS_RETIRED */ 7448c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT(0xcb, 0xf), /* MEM_LOAD_RETIRED.* */ 7458c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT(0xf7, 0xf), /* FP_ASSIST.* */ 7468c2ecf20Sopenharmony_ci /* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */ 7478c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x108000c0, 0x0f), 7488c2ecf20Sopenharmony_ci EVENT_CONSTRAINT_END 7498c2ecf20Sopenharmony_ci}; 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_cistruct event_constraint intel_snb_pebs_event_constraints[] = { 7528c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */ 7538c2ecf20Sopenharmony_ci INTEL_PLD_CONSTRAINT(0x01cd, 0x8), /* MEM_TRANS_RETIRED.LAT_ABOVE_THR */ 7548c2ecf20Sopenharmony_ci INTEL_PST_CONSTRAINT(0x02cd, 0x8), /* MEM_TRANS_RETIRED.PRECISE_STORES */ 7558c2ecf20Sopenharmony_ci /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */ 7568c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x108001c2, 0xf), 7578c2ecf20Sopenharmony_ci INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf), /* MEM_UOP_RETIRED.* */ 7588c2ecf20Sopenharmony_ci INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */ 7598c2ecf20Sopenharmony_ci INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */ 7608c2ecf20Sopenharmony_ci INTEL_EXCLEVT_CONSTRAINT(0xd3, 0xf), /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */ 7618c2ecf20Sopenharmony_ci /* Allow all events as PEBS with no flags */ 7628c2ecf20Sopenharmony_ci INTEL_ALL_EVENT_CONSTRAINT(0, 0xf), 7638c2ecf20Sopenharmony_ci EVENT_CONSTRAINT_END 7648c2ecf20Sopenharmony_ci}; 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_cistruct event_constraint intel_ivb_pebs_event_constraints[] = { 7678c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */ 7688c2ecf20Sopenharmony_ci INTEL_PLD_CONSTRAINT(0x01cd, 0x8), /* MEM_TRANS_RETIRED.LAT_ABOVE_THR */ 7698c2ecf20Sopenharmony_ci INTEL_PST_CONSTRAINT(0x02cd, 0x8), /* MEM_TRANS_RETIRED.PRECISE_STORES */ 7708c2ecf20Sopenharmony_ci /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */ 7718c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x108001c2, 0xf), 7728c2ecf20Sopenharmony_ci /* INST_RETIRED.PREC_DIST, inv=1, cmask=16 (cycles:ppp). */ 7738c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x108001c0, 0x2), 7748c2ecf20Sopenharmony_ci INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf), /* MEM_UOP_RETIRED.* */ 7758c2ecf20Sopenharmony_ci INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */ 7768c2ecf20Sopenharmony_ci INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */ 7778c2ecf20Sopenharmony_ci INTEL_EXCLEVT_CONSTRAINT(0xd3, 0xf), /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */ 7788c2ecf20Sopenharmony_ci /* Allow all events as PEBS with no flags */ 7798c2ecf20Sopenharmony_ci INTEL_ALL_EVENT_CONSTRAINT(0, 0xf), 7808c2ecf20Sopenharmony_ci EVENT_CONSTRAINT_END 7818c2ecf20Sopenharmony_ci}; 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_cistruct event_constraint intel_hsw_pebs_event_constraints[] = { 7848c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */ 7858c2ecf20Sopenharmony_ci INTEL_PLD_CONSTRAINT(0x01cd, 0xf), /* MEM_TRANS_RETIRED.* */ 7868c2ecf20Sopenharmony_ci /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */ 7878c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x108001c2, 0xf), 7888c2ecf20Sopenharmony_ci /* INST_RETIRED.PREC_DIST, inv=1, cmask=16 (cycles:ppp). */ 7898c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x108001c0, 0x2), 7908c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_NA(0x01c2, 0xf), /* UOPS_RETIRED.ALL */ 7918c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(0x11d0, 0xf), /* MEM_UOPS_RETIRED.STLB_MISS_LOADS */ 7928c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(0x21d0, 0xf), /* MEM_UOPS_RETIRED.LOCK_LOADS */ 7938c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(0x41d0, 0xf), /* MEM_UOPS_RETIRED.SPLIT_LOADS */ 7948c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(0x81d0, 0xf), /* MEM_UOPS_RETIRED.ALL_LOADS */ 7958c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XST(0x12d0, 0xf), /* MEM_UOPS_RETIRED.STLB_MISS_STORES */ 7968c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XST(0x42d0, 0xf), /* MEM_UOPS_RETIRED.SPLIT_STORES */ 7978c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XST(0x82d0, 0xf), /* MEM_UOPS_RETIRED.ALL_STORES */ 7988c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_XLD(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */ 7998c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_XLD(0xd2, 0xf), /* MEM_LOAD_UOPS_L3_HIT_RETIRED.* */ 8008c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_XLD(0xd3, 0xf), /* MEM_LOAD_UOPS_L3_MISS_RETIRED.* */ 8018c2ecf20Sopenharmony_ci /* Allow all events as PEBS with no flags */ 8028c2ecf20Sopenharmony_ci INTEL_ALL_EVENT_CONSTRAINT(0, 0xf), 8038c2ecf20Sopenharmony_ci EVENT_CONSTRAINT_END 8048c2ecf20Sopenharmony_ci}; 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_cistruct event_constraint intel_bdw_pebs_event_constraints[] = { 8078c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */ 8088c2ecf20Sopenharmony_ci INTEL_PLD_CONSTRAINT(0x01cd, 0xf), /* MEM_TRANS_RETIRED.* */ 8098c2ecf20Sopenharmony_ci /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */ 8108c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x108001c2, 0xf), 8118c2ecf20Sopenharmony_ci /* INST_RETIRED.PREC_DIST, inv=1, cmask=16 (cycles:ppp). */ 8128c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x108001c0, 0x2), 8138c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_NA(0x01c2, 0xf), /* UOPS_RETIRED.ALL */ 8148c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x11d0, 0xf), /* MEM_UOPS_RETIRED.STLB_MISS_LOADS */ 8158c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x21d0, 0xf), /* MEM_UOPS_RETIRED.LOCK_LOADS */ 8168c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x41d0, 0xf), /* MEM_UOPS_RETIRED.SPLIT_LOADS */ 8178c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x81d0, 0xf), /* MEM_UOPS_RETIRED.ALL_LOADS */ 8188c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x12d0, 0xf), /* MEM_UOPS_RETIRED.STLB_MISS_STORES */ 8198c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x42d0, 0xf), /* MEM_UOPS_RETIRED.SPLIT_STORES */ 8208c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x82d0, 0xf), /* MEM_UOPS_RETIRED.ALL_STORES */ 8218c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */ 8228c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(0xd2, 0xf), /* MEM_LOAD_UOPS_L3_HIT_RETIRED.* */ 8238c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(0xd3, 0xf), /* MEM_LOAD_UOPS_L3_MISS_RETIRED.* */ 8248c2ecf20Sopenharmony_ci /* Allow all events as PEBS with no flags */ 8258c2ecf20Sopenharmony_ci INTEL_ALL_EVENT_CONSTRAINT(0, 0xf), 8268c2ecf20Sopenharmony_ci EVENT_CONSTRAINT_END 8278c2ecf20Sopenharmony_ci}; 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_cistruct event_constraint intel_skl_pebs_event_constraints[] = { 8318c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x1c0, 0x2), /* INST_RETIRED.PREC_DIST */ 8328c2ecf20Sopenharmony_ci /* INST_RETIRED.PREC_DIST, inv=1, cmask=16 (cycles:ppp). */ 8338c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x108001c0, 0x2), 8348c2ecf20Sopenharmony_ci /* INST_RETIRED.TOTAL_CYCLES_PS (inv=1, cmask=16) (cycles:p). */ 8358c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x108000c0, 0x0f), 8368c2ecf20Sopenharmony_ci INTEL_PLD_CONSTRAINT(0x1cd, 0xf), /* MEM_TRANS_RETIRED.* */ 8378c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x11d0, 0xf), /* MEM_INST_RETIRED.STLB_MISS_LOADS */ 8388c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x12d0, 0xf), /* MEM_INST_RETIRED.STLB_MISS_STORES */ 8398c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x21d0, 0xf), /* MEM_INST_RETIRED.LOCK_LOADS */ 8408c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x22d0, 0xf), /* MEM_INST_RETIRED.LOCK_STORES */ 8418c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x41d0, 0xf), /* MEM_INST_RETIRED.SPLIT_LOADS */ 8428c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x42d0, 0xf), /* MEM_INST_RETIRED.SPLIT_STORES */ 8438c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x81d0, 0xf), /* MEM_INST_RETIRED.ALL_LOADS */ 8448c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x82d0, 0xf), /* MEM_INST_RETIRED.ALL_STORES */ 8458c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(0xd1, 0xf), /* MEM_LOAD_RETIRED.* */ 8468c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(0xd2, 0xf), /* MEM_LOAD_L3_HIT_RETIRED.* */ 8478c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(0xd3, 0xf), /* MEM_LOAD_L3_MISS_RETIRED.* */ 8488c2ecf20Sopenharmony_ci /* Allow all events as PEBS with no flags */ 8498c2ecf20Sopenharmony_ci INTEL_ALL_EVENT_CONSTRAINT(0, 0xf), 8508c2ecf20Sopenharmony_ci EVENT_CONSTRAINT_END 8518c2ecf20Sopenharmony_ci}; 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_cistruct event_constraint intel_icl_pebs_event_constraints[] = { 8548c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x1c0, 0x100000000ULL), /* INST_RETIRED.PREC_DIST */ 8558c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT(0x0400, 0x800000000ULL), /* SLOTS */ 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci INTEL_PLD_CONSTRAINT(0x1cd, 0xff), /* MEM_TRANS_RETIRED.LOAD_LATENCY */ 8588c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x11d0, 0xf), /* MEM_INST_RETIRED.STLB_MISS_LOADS */ 8598c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x12d0, 0xf), /* MEM_INST_RETIRED.STLB_MISS_STORES */ 8608c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x21d0, 0xf), /* MEM_INST_RETIRED.LOCK_LOADS */ 8618c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x41d0, 0xf), /* MEM_INST_RETIRED.SPLIT_LOADS */ 8628c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x42d0, 0xf), /* MEM_INST_RETIRED.SPLIT_STORES */ 8638c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x81d0, 0xf), /* MEM_INST_RETIRED.ALL_LOADS */ 8648c2ecf20Sopenharmony_ci INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x82d0, 0xf), /* MEM_INST_RETIRED.ALL_STORES */ 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD_RANGE(0xd1, 0xd4, 0xf), /* MEM_LOAD_*_RETIRED.* */ 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci INTEL_FLAGS_EVENT_CONSTRAINT(0xd0, 0xf), /* MEM_INST_RETIRED.* */ 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ci /* 8718c2ecf20Sopenharmony_ci * Everything else is handled by PMU_FL_PEBS_ALL, because we 8728c2ecf20Sopenharmony_ci * need the full constraints from the main table. 8738c2ecf20Sopenharmony_ci */ 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci EVENT_CONSTRAINT_END 8768c2ecf20Sopenharmony_ci}; 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_cistruct event_constraint *intel_pebs_constraints(struct perf_event *event) 8798c2ecf20Sopenharmony_ci{ 8808c2ecf20Sopenharmony_ci struct event_constraint *c; 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_ci if (!event->attr.precise_ip) 8838c2ecf20Sopenharmony_ci return NULL; 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci if (x86_pmu.pebs_constraints) { 8868c2ecf20Sopenharmony_ci for_each_event_constraint(c, x86_pmu.pebs_constraints) { 8878c2ecf20Sopenharmony_ci if (constraint_match(c, event->hw.config)) { 8888c2ecf20Sopenharmony_ci event->hw.flags |= c->flags; 8898c2ecf20Sopenharmony_ci return c; 8908c2ecf20Sopenharmony_ci } 8918c2ecf20Sopenharmony_ci } 8928c2ecf20Sopenharmony_ci } 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci /* 8958c2ecf20Sopenharmony_ci * Extended PEBS support 8968c2ecf20Sopenharmony_ci * Makes the PEBS code search the normal constraints. 8978c2ecf20Sopenharmony_ci */ 8988c2ecf20Sopenharmony_ci if (x86_pmu.flags & PMU_FL_PEBS_ALL) 8998c2ecf20Sopenharmony_ci return NULL; 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci return &emptyconstraint; 9028c2ecf20Sopenharmony_ci} 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci/* 9058c2ecf20Sopenharmony_ci * We need the sched_task callback even for per-cpu events when we use 9068c2ecf20Sopenharmony_ci * the large interrupt threshold, such that we can provide PID and TID 9078c2ecf20Sopenharmony_ci * to PEBS samples. 9088c2ecf20Sopenharmony_ci */ 9098c2ecf20Sopenharmony_cistatic inline bool pebs_needs_sched_cb(struct cpu_hw_events *cpuc) 9108c2ecf20Sopenharmony_ci{ 9118c2ecf20Sopenharmony_ci if (cpuc->n_pebs == cpuc->n_pebs_via_pt) 9128c2ecf20Sopenharmony_ci return false; 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci return cpuc->n_pebs && (cpuc->n_pebs == cpuc->n_large_pebs); 9158c2ecf20Sopenharmony_ci} 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_civoid intel_pmu_pebs_sched_task(struct perf_event_context *ctx, bool sched_in) 9188c2ecf20Sopenharmony_ci{ 9198c2ecf20Sopenharmony_ci struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci if (!sched_in && pebs_needs_sched_cb(cpuc)) 9228c2ecf20Sopenharmony_ci intel_pmu_drain_pebs_buffer(); 9238c2ecf20Sopenharmony_ci} 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_cistatic inline void pebs_update_threshold(struct cpu_hw_events *cpuc) 9268c2ecf20Sopenharmony_ci{ 9278c2ecf20Sopenharmony_ci struct debug_store *ds = cpuc->ds; 9288c2ecf20Sopenharmony_ci u64 threshold; 9298c2ecf20Sopenharmony_ci int reserved; 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci if (cpuc->n_pebs_via_pt) 9328c2ecf20Sopenharmony_ci return; 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_ci if (x86_pmu.flags & PMU_FL_PEBS_ALL) 9358c2ecf20Sopenharmony_ci reserved = x86_pmu.max_pebs_events + x86_pmu.num_counters_fixed; 9368c2ecf20Sopenharmony_ci else 9378c2ecf20Sopenharmony_ci reserved = x86_pmu.max_pebs_events; 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci if (cpuc->n_pebs == cpuc->n_large_pebs) { 9408c2ecf20Sopenharmony_ci threshold = ds->pebs_absolute_maximum - 9418c2ecf20Sopenharmony_ci reserved * cpuc->pebs_record_size; 9428c2ecf20Sopenharmony_ci } else { 9438c2ecf20Sopenharmony_ci threshold = ds->pebs_buffer_base + cpuc->pebs_record_size; 9448c2ecf20Sopenharmony_ci } 9458c2ecf20Sopenharmony_ci 9468c2ecf20Sopenharmony_ci ds->pebs_interrupt_threshold = threshold; 9478c2ecf20Sopenharmony_ci} 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_cistatic void adaptive_pebs_record_size_update(void) 9508c2ecf20Sopenharmony_ci{ 9518c2ecf20Sopenharmony_ci struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 9528c2ecf20Sopenharmony_ci u64 pebs_data_cfg = cpuc->pebs_data_cfg; 9538c2ecf20Sopenharmony_ci int sz = sizeof(struct pebs_basic); 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_ci if (pebs_data_cfg & PEBS_DATACFG_MEMINFO) 9568c2ecf20Sopenharmony_ci sz += sizeof(struct pebs_meminfo); 9578c2ecf20Sopenharmony_ci if (pebs_data_cfg & PEBS_DATACFG_GP) 9588c2ecf20Sopenharmony_ci sz += sizeof(struct pebs_gprs); 9598c2ecf20Sopenharmony_ci if (pebs_data_cfg & PEBS_DATACFG_XMMS) 9608c2ecf20Sopenharmony_ci sz += sizeof(struct pebs_xmm); 9618c2ecf20Sopenharmony_ci if (pebs_data_cfg & PEBS_DATACFG_LBRS) 9628c2ecf20Sopenharmony_ci sz += x86_pmu.lbr_nr * sizeof(struct lbr_entry); 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci cpuc->pebs_record_size = sz; 9658c2ecf20Sopenharmony_ci} 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci#define PERF_PEBS_MEMINFO_TYPE (PERF_SAMPLE_ADDR | PERF_SAMPLE_DATA_SRC | \ 9688c2ecf20Sopenharmony_ci PERF_SAMPLE_PHYS_ADDR | PERF_SAMPLE_WEIGHT | \ 9698c2ecf20Sopenharmony_ci PERF_SAMPLE_TRANSACTION) 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_cistatic u64 pebs_update_adaptive_cfg(struct perf_event *event) 9728c2ecf20Sopenharmony_ci{ 9738c2ecf20Sopenharmony_ci struct perf_event_attr *attr = &event->attr; 9748c2ecf20Sopenharmony_ci u64 sample_type = attr->sample_type; 9758c2ecf20Sopenharmony_ci u64 pebs_data_cfg = 0; 9768c2ecf20Sopenharmony_ci bool gprs, tsx_weight; 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ci if (!(sample_type & ~(PERF_SAMPLE_IP|PERF_SAMPLE_TIME)) && 9798c2ecf20Sopenharmony_ci attr->precise_ip > 1) 9808c2ecf20Sopenharmony_ci return pebs_data_cfg; 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci if (sample_type & PERF_PEBS_MEMINFO_TYPE) 9838c2ecf20Sopenharmony_ci pebs_data_cfg |= PEBS_DATACFG_MEMINFO; 9848c2ecf20Sopenharmony_ci 9858c2ecf20Sopenharmony_ci /* 9868c2ecf20Sopenharmony_ci * We need GPRs when: 9878c2ecf20Sopenharmony_ci * + user requested them 9888c2ecf20Sopenharmony_ci * + precise_ip < 2 for the non event IP 9898c2ecf20Sopenharmony_ci * + For RTM TSX weight we need GPRs for the abort code. 9908c2ecf20Sopenharmony_ci */ 9918c2ecf20Sopenharmony_ci gprs = (sample_type & PERF_SAMPLE_REGS_INTR) && 9928c2ecf20Sopenharmony_ci (attr->sample_regs_intr & PEBS_GP_REGS); 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci tsx_weight = (sample_type & PERF_SAMPLE_WEIGHT) && 9958c2ecf20Sopenharmony_ci ((attr->config & INTEL_ARCH_EVENT_MASK) == 9968c2ecf20Sopenharmony_ci x86_pmu.rtm_abort_event); 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ci if (gprs || (attr->precise_ip < 2) || tsx_weight) 9998c2ecf20Sopenharmony_ci pebs_data_cfg |= PEBS_DATACFG_GP; 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci if ((sample_type & PERF_SAMPLE_REGS_INTR) && 10028c2ecf20Sopenharmony_ci (attr->sample_regs_intr & PERF_REG_EXTENDED_MASK)) 10038c2ecf20Sopenharmony_ci pebs_data_cfg |= PEBS_DATACFG_XMMS; 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci if (sample_type & PERF_SAMPLE_BRANCH_STACK) { 10068c2ecf20Sopenharmony_ci /* 10078c2ecf20Sopenharmony_ci * For now always log all LBRs. Could configure this 10088c2ecf20Sopenharmony_ci * later. 10098c2ecf20Sopenharmony_ci */ 10108c2ecf20Sopenharmony_ci pebs_data_cfg |= PEBS_DATACFG_LBRS | 10118c2ecf20Sopenharmony_ci ((x86_pmu.lbr_nr-1) << PEBS_DATACFG_LBR_SHIFT); 10128c2ecf20Sopenharmony_ci } 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci return pebs_data_cfg; 10158c2ecf20Sopenharmony_ci} 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_cistatic void 10188c2ecf20Sopenharmony_cipebs_update_state(bool needed_cb, struct cpu_hw_events *cpuc, 10198c2ecf20Sopenharmony_ci struct perf_event *event, bool add) 10208c2ecf20Sopenharmony_ci{ 10218c2ecf20Sopenharmony_ci struct pmu *pmu = event->ctx->pmu; 10228c2ecf20Sopenharmony_ci /* 10238c2ecf20Sopenharmony_ci * Make sure we get updated with the first PEBS 10248c2ecf20Sopenharmony_ci * event. It will trigger also during removal, but 10258c2ecf20Sopenharmony_ci * that does not hurt: 10268c2ecf20Sopenharmony_ci */ 10278c2ecf20Sopenharmony_ci bool update = cpuc->n_pebs == 1; 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_ci if (needed_cb != pebs_needs_sched_cb(cpuc)) { 10308c2ecf20Sopenharmony_ci if (!needed_cb) 10318c2ecf20Sopenharmony_ci perf_sched_cb_inc(pmu); 10328c2ecf20Sopenharmony_ci else 10338c2ecf20Sopenharmony_ci perf_sched_cb_dec(pmu); 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci update = true; 10368c2ecf20Sopenharmony_ci } 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci /* 10398c2ecf20Sopenharmony_ci * The PEBS record doesn't shrink on pmu::del(). Doing so would require 10408c2ecf20Sopenharmony_ci * iterating all remaining PEBS events to reconstruct the config. 10418c2ecf20Sopenharmony_ci */ 10428c2ecf20Sopenharmony_ci if (x86_pmu.intel_cap.pebs_baseline && add) { 10438c2ecf20Sopenharmony_ci u64 pebs_data_cfg; 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ci /* Clear pebs_data_cfg and pebs_record_size for first PEBS. */ 10468c2ecf20Sopenharmony_ci if (cpuc->n_pebs == 1) { 10478c2ecf20Sopenharmony_ci cpuc->pebs_data_cfg = 0; 10488c2ecf20Sopenharmony_ci cpuc->pebs_record_size = sizeof(struct pebs_basic); 10498c2ecf20Sopenharmony_ci } 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_ci pebs_data_cfg = pebs_update_adaptive_cfg(event); 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_ci /* Update pebs_record_size if new event requires more data. */ 10548c2ecf20Sopenharmony_ci if (pebs_data_cfg & ~cpuc->pebs_data_cfg) { 10558c2ecf20Sopenharmony_ci cpuc->pebs_data_cfg |= pebs_data_cfg; 10568c2ecf20Sopenharmony_ci adaptive_pebs_record_size_update(); 10578c2ecf20Sopenharmony_ci update = true; 10588c2ecf20Sopenharmony_ci } 10598c2ecf20Sopenharmony_ci } 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci if (update) 10628c2ecf20Sopenharmony_ci pebs_update_threshold(cpuc); 10638c2ecf20Sopenharmony_ci} 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_civoid intel_pmu_pebs_add(struct perf_event *event) 10668c2ecf20Sopenharmony_ci{ 10678c2ecf20Sopenharmony_ci struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 10688c2ecf20Sopenharmony_ci struct hw_perf_event *hwc = &event->hw; 10698c2ecf20Sopenharmony_ci bool needed_cb = pebs_needs_sched_cb(cpuc); 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_ci cpuc->n_pebs++; 10728c2ecf20Sopenharmony_ci if (hwc->flags & PERF_X86_EVENT_LARGE_PEBS) 10738c2ecf20Sopenharmony_ci cpuc->n_large_pebs++; 10748c2ecf20Sopenharmony_ci if (hwc->flags & PERF_X86_EVENT_PEBS_VIA_PT) 10758c2ecf20Sopenharmony_ci cpuc->n_pebs_via_pt++; 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ci pebs_update_state(needed_cb, cpuc, event, true); 10788c2ecf20Sopenharmony_ci} 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_cistatic void intel_pmu_pebs_via_pt_disable(struct perf_event *event) 10818c2ecf20Sopenharmony_ci{ 10828c2ecf20Sopenharmony_ci struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_ci if (!is_pebs_pt(event)) 10858c2ecf20Sopenharmony_ci return; 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci if (!(cpuc->pebs_enabled & ~PEBS_VIA_PT_MASK)) 10888c2ecf20Sopenharmony_ci cpuc->pebs_enabled &= ~PEBS_VIA_PT_MASK; 10898c2ecf20Sopenharmony_ci} 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_cistatic void intel_pmu_pebs_via_pt_enable(struct perf_event *event) 10928c2ecf20Sopenharmony_ci{ 10938c2ecf20Sopenharmony_ci struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 10948c2ecf20Sopenharmony_ci struct hw_perf_event *hwc = &event->hw; 10958c2ecf20Sopenharmony_ci struct debug_store *ds = cpuc->ds; 10968c2ecf20Sopenharmony_ci 10978c2ecf20Sopenharmony_ci if (!is_pebs_pt(event)) 10988c2ecf20Sopenharmony_ci return; 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci if (!(event->hw.flags & PERF_X86_EVENT_LARGE_PEBS)) 11018c2ecf20Sopenharmony_ci cpuc->pebs_enabled |= PEBS_PMI_AFTER_EACH_RECORD; 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_ci cpuc->pebs_enabled |= PEBS_OUTPUT_PT; 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci wrmsrl(MSR_RELOAD_PMC0 + hwc->idx, ds->pebs_event_reset[hwc->idx]); 11068c2ecf20Sopenharmony_ci} 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_civoid intel_pmu_pebs_enable(struct perf_event *event) 11098c2ecf20Sopenharmony_ci{ 11108c2ecf20Sopenharmony_ci struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 11118c2ecf20Sopenharmony_ci struct hw_perf_event *hwc = &event->hw; 11128c2ecf20Sopenharmony_ci struct debug_store *ds = cpuc->ds; 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci hwc->config &= ~ARCH_PERFMON_EVENTSEL_INT; 11158c2ecf20Sopenharmony_ci 11168c2ecf20Sopenharmony_ci cpuc->pebs_enabled |= 1ULL << hwc->idx; 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_ci if ((event->hw.flags & PERF_X86_EVENT_PEBS_LDLAT) && (x86_pmu.version < 5)) 11198c2ecf20Sopenharmony_ci cpuc->pebs_enabled |= 1ULL << (hwc->idx + 32); 11208c2ecf20Sopenharmony_ci else if (event->hw.flags & PERF_X86_EVENT_PEBS_ST) 11218c2ecf20Sopenharmony_ci cpuc->pebs_enabled |= 1ULL << 63; 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci if (x86_pmu.intel_cap.pebs_baseline) { 11248c2ecf20Sopenharmony_ci hwc->config |= ICL_EVENTSEL_ADAPTIVE; 11258c2ecf20Sopenharmony_ci if (cpuc->pebs_data_cfg != cpuc->active_pebs_data_cfg) { 11268c2ecf20Sopenharmony_ci wrmsrl(MSR_PEBS_DATA_CFG, cpuc->pebs_data_cfg); 11278c2ecf20Sopenharmony_ci cpuc->active_pebs_data_cfg = cpuc->pebs_data_cfg; 11288c2ecf20Sopenharmony_ci } 11298c2ecf20Sopenharmony_ci } 11308c2ecf20Sopenharmony_ci 11318c2ecf20Sopenharmony_ci /* 11328c2ecf20Sopenharmony_ci * Use auto-reload if possible to save a MSR write in the PMI. 11338c2ecf20Sopenharmony_ci * This must be done in pmu::start(), because PERF_EVENT_IOC_PERIOD. 11348c2ecf20Sopenharmony_ci */ 11358c2ecf20Sopenharmony_ci if (hwc->flags & PERF_X86_EVENT_AUTO_RELOAD) { 11368c2ecf20Sopenharmony_ci unsigned int idx = hwc->idx; 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_ci if (idx >= INTEL_PMC_IDX_FIXED) 11398c2ecf20Sopenharmony_ci idx = MAX_PEBS_EVENTS + (idx - INTEL_PMC_IDX_FIXED); 11408c2ecf20Sopenharmony_ci ds->pebs_event_reset[idx] = 11418c2ecf20Sopenharmony_ci (u64)(-hwc->sample_period) & x86_pmu.cntval_mask; 11428c2ecf20Sopenharmony_ci } else { 11438c2ecf20Sopenharmony_ci ds->pebs_event_reset[hwc->idx] = 0; 11448c2ecf20Sopenharmony_ci } 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ci intel_pmu_pebs_via_pt_enable(event); 11478c2ecf20Sopenharmony_ci} 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_civoid intel_pmu_pebs_del(struct perf_event *event) 11508c2ecf20Sopenharmony_ci{ 11518c2ecf20Sopenharmony_ci struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 11528c2ecf20Sopenharmony_ci struct hw_perf_event *hwc = &event->hw; 11538c2ecf20Sopenharmony_ci bool needed_cb = pebs_needs_sched_cb(cpuc); 11548c2ecf20Sopenharmony_ci 11558c2ecf20Sopenharmony_ci cpuc->n_pebs--; 11568c2ecf20Sopenharmony_ci if (hwc->flags & PERF_X86_EVENT_LARGE_PEBS) 11578c2ecf20Sopenharmony_ci cpuc->n_large_pebs--; 11588c2ecf20Sopenharmony_ci if (hwc->flags & PERF_X86_EVENT_PEBS_VIA_PT) 11598c2ecf20Sopenharmony_ci cpuc->n_pebs_via_pt--; 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci pebs_update_state(needed_cb, cpuc, event, false); 11628c2ecf20Sopenharmony_ci} 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_civoid intel_pmu_pebs_disable(struct perf_event *event) 11658c2ecf20Sopenharmony_ci{ 11668c2ecf20Sopenharmony_ci struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 11678c2ecf20Sopenharmony_ci struct hw_perf_event *hwc = &event->hw; 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_ci if (cpuc->n_pebs == cpuc->n_large_pebs && 11708c2ecf20Sopenharmony_ci cpuc->n_pebs != cpuc->n_pebs_via_pt) 11718c2ecf20Sopenharmony_ci intel_pmu_drain_pebs_buffer(); 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ci cpuc->pebs_enabled &= ~(1ULL << hwc->idx); 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_ci if ((event->hw.flags & PERF_X86_EVENT_PEBS_LDLAT) && 11768c2ecf20Sopenharmony_ci (x86_pmu.version < 5)) 11778c2ecf20Sopenharmony_ci cpuc->pebs_enabled &= ~(1ULL << (hwc->idx + 32)); 11788c2ecf20Sopenharmony_ci else if (event->hw.flags & PERF_X86_EVENT_PEBS_ST) 11798c2ecf20Sopenharmony_ci cpuc->pebs_enabled &= ~(1ULL << 63); 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci intel_pmu_pebs_via_pt_disable(event); 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_ci if (cpuc->enabled) 11848c2ecf20Sopenharmony_ci wrmsrl(MSR_IA32_PEBS_ENABLE, cpuc->pebs_enabled); 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci hwc->config |= ARCH_PERFMON_EVENTSEL_INT; 11878c2ecf20Sopenharmony_ci} 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_civoid intel_pmu_pebs_enable_all(void) 11908c2ecf20Sopenharmony_ci{ 11918c2ecf20Sopenharmony_ci struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci if (cpuc->pebs_enabled) 11948c2ecf20Sopenharmony_ci wrmsrl(MSR_IA32_PEBS_ENABLE, cpuc->pebs_enabled); 11958c2ecf20Sopenharmony_ci} 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_civoid intel_pmu_pebs_disable_all(void) 11988c2ecf20Sopenharmony_ci{ 11998c2ecf20Sopenharmony_ci struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_ci if (cpuc->pebs_enabled) 12028c2ecf20Sopenharmony_ci wrmsrl(MSR_IA32_PEBS_ENABLE, 0); 12038c2ecf20Sopenharmony_ci} 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_cistatic int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) 12068c2ecf20Sopenharmony_ci{ 12078c2ecf20Sopenharmony_ci struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 12088c2ecf20Sopenharmony_ci unsigned long from = cpuc->lbr_entries[0].from; 12098c2ecf20Sopenharmony_ci unsigned long old_to, to = cpuc->lbr_entries[0].to; 12108c2ecf20Sopenharmony_ci unsigned long ip = regs->ip; 12118c2ecf20Sopenharmony_ci int is_64bit = 0; 12128c2ecf20Sopenharmony_ci void *kaddr; 12138c2ecf20Sopenharmony_ci int size; 12148c2ecf20Sopenharmony_ci 12158c2ecf20Sopenharmony_ci /* 12168c2ecf20Sopenharmony_ci * We don't need to fixup if the PEBS assist is fault like 12178c2ecf20Sopenharmony_ci */ 12188c2ecf20Sopenharmony_ci if (!x86_pmu.intel_cap.pebs_trap) 12198c2ecf20Sopenharmony_ci return 1; 12208c2ecf20Sopenharmony_ci 12218c2ecf20Sopenharmony_ci /* 12228c2ecf20Sopenharmony_ci * No LBR entry, no basic block, no rewinding 12238c2ecf20Sopenharmony_ci */ 12248c2ecf20Sopenharmony_ci if (!cpuc->lbr_stack.nr || !from || !to) 12258c2ecf20Sopenharmony_ci return 0; 12268c2ecf20Sopenharmony_ci 12278c2ecf20Sopenharmony_ci /* 12288c2ecf20Sopenharmony_ci * Basic blocks should never cross user/kernel boundaries 12298c2ecf20Sopenharmony_ci */ 12308c2ecf20Sopenharmony_ci if (kernel_ip(ip) != kernel_ip(to)) 12318c2ecf20Sopenharmony_ci return 0; 12328c2ecf20Sopenharmony_ci 12338c2ecf20Sopenharmony_ci /* 12348c2ecf20Sopenharmony_ci * unsigned math, either ip is before the start (impossible) or 12358c2ecf20Sopenharmony_ci * the basic block is larger than 1 page (sanity) 12368c2ecf20Sopenharmony_ci */ 12378c2ecf20Sopenharmony_ci if ((ip - to) > PEBS_FIXUP_SIZE) 12388c2ecf20Sopenharmony_ci return 0; 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_ci /* 12418c2ecf20Sopenharmony_ci * We sampled a branch insn, rewind using the LBR stack 12428c2ecf20Sopenharmony_ci */ 12438c2ecf20Sopenharmony_ci if (ip == to) { 12448c2ecf20Sopenharmony_ci set_linear_ip(regs, from); 12458c2ecf20Sopenharmony_ci return 1; 12468c2ecf20Sopenharmony_ci } 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci size = ip - to; 12498c2ecf20Sopenharmony_ci if (!kernel_ip(ip)) { 12508c2ecf20Sopenharmony_ci int bytes; 12518c2ecf20Sopenharmony_ci u8 *buf = this_cpu_read(insn_buffer); 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ci /* 'size' must fit our buffer, see above */ 12548c2ecf20Sopenharmony_ci bytes = copy_from_user_nmi(buf, (void __user *)to, size); 12558c2ecf20Sopenharmony_ci if (bytes != 0) 12568c2ecf20Sopenharmony_ci return 0; 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_ci kaddr = buf; 12598c2ecf20Sopenharmony_ci } else { 12608c2ecf20Sopenharmony_ci kaddr = (void *)to; 12618c2ecf20Sopenharmony_ci } 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_ci do { 12648c2ecf20Sopenharmony_ci struct insn insn; 12658c2ecf20Sopenharmony_ci 12668c2ecf20Sopenharmony_ci old_to = to; 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_64 12698c2ecf20Sopenharmony_ci is_64bit = kernel_ip(to) || !test_thread_flag(TIF_IA32); 12708c2ecf20Sopenharmony_ci#endif 12718c2ecf20Sopenharmony_ci insn_init(&insn, kaddr, size, is_64bit); 12728c2ecf20Sopenharmony_ci insn_get_length(&insn); 12738c2ecf20Sopenharmony_ci /* 12748c2ecf20Sopenharmony_ci * Make sure there was not a problem decoding the 12758c2ecf20Sopenharmony_ci * instruction and getting the length. This is 12768c2ecf20Sopenharmony_ci * doubly important because we have an infinite 12778c2ecf20Sopenharmony_ci * loop if insn.length=0. 12788c2ecf20Sopenharmony_ci */ 12798c2ecf20Sopenharmony_ci if (!insn.length) 12808c2ecf20Sopenharmony_ci break; 12818c2ecf20Sopenharmony_ci 12828c2ecf20Sopenharmony_ci to += insn.length; 12838c2ecf20Sopenharmony_ci kaddr += insn.length; 12848c2ecf20Sopenharmony_ci size -= insn.length; 12858c2ecf20Sopenharmony_ci } while (to < ip); 12868c2ecf20Sopenharmony_ci 12878c2ecf20Sopenharmony_ci if (to == ip) { 12888c2ecf20Sopenharmony_ci set_linear_ip(regs, old_to); 12898c2ecf20Sopenharmony_ci return 1; 12908c2ecf20Sopenharmony_ci } 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_ci /* 12938c2ecf20Sopenharmony_ci * Even though we decoded the basic block, the instruction stream 12948c2ecf20Sopenharmony_ci * never matched the given IP, either the TO or the IP got corrupted. 12958c2ecf20Sopenharmony_ci */ 12968c2ecf20Sopenharmony_ci return 0; 12978c2ecf20Sopenharmony_ci} 12988c2ecf20Sopenharmony_ci 12998c2ecf20Sopenharmony_cistatic inline u64 intel_get_tsx_weight(u64 tsx_tuning) 13008c2ecf20Sopenharmony_ci{ 13018c2ecf20Sopenharmony_ci if (tsx_tuning) { 13028c2ecf20Sopenharmony_ci union hsw_tsx_tuning tsx = { .value = tsx_tuning }; 13038c2ecf20Sopenharmony_ci return tsx.cycles_last_block; 13048c2ecf20Sopenharmony_ci } 13058c2ecf20Sopenharmony_ci return 0; 13068c2ecf20Sopenharmony_ci} 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_cistatic inline u64 intel_get_tsx_transaction(u64 tsx_tuning, u64 ax) 13098c2ecf20Sopenharmony_ci{ 13108c2ecf20Sopenharmony_ci u64 txn = (tsx_tuning & PEBS_HSW_TSX_FLAGS) >> 32; 13118c2ecf20Sopenharmony_ci 13128c2ecf20Sopenharmony_ci /* For RTM XABORTs also log the abort code from AX */ 13138c2ecf20Sopenharmony_ci if ((txn & PERF_TXN_TRANSACTION) && (ax & 1)) 13148c2ecf20Sopenharmony_ci txn |= ((ax >> 24) & 0xff) << PERF_TXN_ABORT_SHIFT; 13158c2ecf20Sopenharmony_ci return txn; 13168c2ecf20Sopenharmony_ci} 13178c2ecf20Sopenharmony_ci 13188c2ecf20Sopenharmony_cistatic inline u64 get_pebs_status(void *n) 13198c2ecf20Sopenharmony_ci{ 13208c2ecf20Sopenharmony_ci if (x86_pmu.intel_cap.pebs_format < 4) 13218c2ecf20Sopenharmony_ci return ((struct pebs_record_nhm *)n)->status; 13228c2ecf20Sopenharmony_ci return ((struct pebs_basic *)n)->applicable_counters; 13238c2ecf20Sopenharmony_ci} 13248c2ecf20Sopenharmony_ci 13258c2ecf20Sopenharmony_ci#define PERF_X86_EVENT_PEBS_HSW_PREC \ 13268c2ecf20Sopenharmony_ci (PERF_X86_EVENT_PEBS_ST_HSW | \ 13278c2ecf20Sopenharmony_ci PERF_X86_EVENT_PEBS_LD_HSW | \ 13288c2ecf20Sopenharmony_ci PERF_X86_EVENT_PEBS_NA_HSW) 13298c2ecf20Sopenharmony_ci 13308c2ecf20Sopenharmony_cistatic u64 get_data_src(struct perf_event *event, u64 aux) 13318c2ecf20Sopenharmony_ci{ 13328c2ecf20Sopenharmony_ci u64 val = PERF_MEM_NA; 13338c2ecf20Sopenharmony_ci int fl = event->hw.flags; 13348c2ecf20Sopenharmony_ci bool fst = fl & (PERF_X86_EVENT_PEBS_ST | PERF_X86_EVENT_PEBS_HSW_PREC); 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci if (fl & PERF_X86_EVENT_PEBS_LDLAT) 13378c2ecf20Sopenharmony_ci val = load_latency_data(aux); 13388c2ecf20Sopenharmony_ci else if (fst && (fl & PERF_X86_EVENT_PEBS_HSW_PREC)) 13398c2ecf20Sopenharmony_ci val = precise_datala_hsw(event, aux); 13408c2ecf20Sopenharmony_ci else if (fst) 13418c2ecf20Sopenharmony_ci val = precise_store_data(aux); 13428c2ecf20Sopenharmony_ci return val; 13438c2ecf20Sopenharmony_ci} 13448c2ecf20Sopenharmony_ci 13458c2ecf20Sopenharmony_cistatic void setup_pebs_fixed_sample_data(struct perf_event *event, 13468c2ecf20Sopenharmony_ci struct pt_regs *iregs, void *__pebs, 13478c2ecf20Sopenharmony_ci struct perf_sample_data *data, 13488c2ecf20Sopenharmony_ci struct pt_regs *regs) 13498c2ecf20Sopenharmony_ci{ 13508c2ecf20Sopenharmony_ci /* 13518c2ecf20Sopenharmony_ci * We cast to the biggest pebs_record but are careful not to 13528c2ecf20Sopenharmony_ci * unconditionally access the 'extra' entries. 13538c2ecf20Sopenharmony_ci */ 13548c2ecf20Sopenharmony_ci struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 13558c2ecf20Sopenharmony_ci struct pebs_record_skl *pebs = __pebs; 13568c2ecf20Sopenharmony_ci u64 sample_type; 13578c2ecf20Sopenharmony_ci int fll; 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_ci if (pebs == NULL) 13608c2ecf20Sopenharmony_ci return; 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_ci sample_type = event->attr.sample_type; 13638c2ecf20Sopenharmony_ci fll = event->hw.flags & PERF_X86_EVENT_PEBS_LDLAT; 13648c2ecf20Sopenharmony_ci 13658c2ecf20Sopenharmony_ci perf_sample_data_init(data, 0, event->hw.last_period); 13668c2ecf20Sopenharmony_ci 13678c2ecf20Sopenharmony_ci data->period = event->hw.last_period; 13688c2ecf20Sopenharmony_ci 13698c2ecf20Sopenharmony_ci /* 13708c2ecf20Sopenharmony_ci * Use latency for weight (only avail with PEBS-LL) 13718c2ecf20Sopenharmony_ci */ 13728c2ecf20Sopenharmony_ci if (fll && (sample_type & PERF_SAMPLE_WEIGHT)) 13738c2ecf20Sopenharmony_ci data->weight = pebs->lat; 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_ci /* 13768c2ecf20Sopenharmony_ci * data.data_src encodes the data source 13778c2ecf20Sopenharmony_ci */ 13788c2ecf20Sopenharmony_ci if (sample_type & PERF_SAMPLE_DATA_SRC) 13798c2ecf20Sopenharmony_ci data->data_src.val = get_data_src(event, pebs->dse); 13808c2ecf20Sopenharmony_ci 13818c2ecf20Sopenharmony_ci /* 13828c2ecf20Sopenharmony_ci * We must however always use iregs for the unwinder to stay sane; the 13838c2ecf20Sopenharmony_ci * record BP,SP,IP can point into thin air when the record is from a 13848c2ecf20Sopenharmony_ci * previous PMI context or an (I)RET happened between the record and 13858c2ecf20Sopenharmony_ci * PMI. 13868c2ecf20Sopenharmony_ci */ 13878c2ecf20Sopenharmony_ci if (sample_type & PERF_SAMPLE_CALLCHAIN) 13888c2ecf20Sopenharmony_ci data->callchain = perf_callchain(event, iregs); 13898c2ecf20Sopenharmony_ci 13908c2ecf20Sopenharmony_ci /* 13918c2ecf20Sopenharmony_ci * We use the interrupt regs as a base because the PEBS record does not 13928c2ecf20Sopenharmony_ci * contain a full regs set, specifically it seems to lack segment 13938c2ecf20Sopenharmony_ci * descriptors, which get used by things like user_mode(). 13948c2ecf20Sopenharmony_ci * 13958c2ecf20Sopenharmony_ci * In the simple case fix up only the IP for PERF_SAMPLE_IP. 13968c2ecf20Sopenharmony_ci */ 13978c2ecf20Sopenharmony_ci *regs = *iregs; 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci /* 14008c2ecf20Sopenharmony_ci * Initialize regs_>flags from PEBS, 14018c2ecf20Sopenharmony_ci * Clear exact bit (which uses x86 EFLAGS Reserved bit 3), 14028c2ecf20Sopenharmony_ci * i.e., do not rely on it being zero: 14038c2ecf20Sopenharmony_ci */ 14048c2ecf20Sopenharmony_ci regs->flags = pebs->flags & ~PERF_EFLAGS_EXACT; 14058c2ecf20Sopenharmony_ci 14068c2ecf20Sopenharmony_ci if (sample_type & PERF_SAMPLE_REGS_INTR) { 14078c2ecf20Sopenharmony_ci regs->ax = pebs->ax; 14088c2ecf20Sopenharmony_ci regs->bx = pebs->bx; 14098c2ecf20Sopenharmony_ci regs->cx = pebs->cx; 14108c2ecf20Sopenharmony_ci regs->dx = pebs->dx; 14118c2ecf20Sopenharmony_ci regs->si = pebs->si; 14128c2ecf20Sopenharmony_ci regs->di = pebs->di; 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_ci regs->bp = pebs->bp; 14158c2ecf20Sopenharmony_ci regs->sp = pebs->sp; 14168c2ecf20Sopenharmony_ci 14178c2ecf20Sopenharmony_ci#ifndef CONFIG_X86_32 14188c2ecf20Sopenharmony_ci regs->r8 = pebs->r8; 14198c2ecf20Sopenharmony_ci regs->r9 = pebs->r9; 14208c2ecf20Sopenharmony_ci regs->r10 = pebs->r10; 14218c2ecf20Sopenharmony_ci regs->r11 = pebs->r11; 14228c2ecf20Sopenharmony_ci regs->r12 = pebs->r12; 14238c2ecf20Sopenharmony_ci regs->r13 = pebs->r13; 14248c2ecf20Sopenharmony_ci regs->r14 = pebs->r14; 14258c2ecf20Sopenharmony_ci regs->r15 = pebs->r15; 14268c2ecf20Sopenharmony_ci#endif 14278c2ecf20Sopenharmony_ci } 14288c2ecf20Sopenharmony_ci 14298c2ecf20Sopenharmony_ci if (event->attr.precise_ip > 1) { 14308c2ecf20Sopenharmony_ci /* 14318c2ecf20Sopenharmony_ci * Haswell and later processors have an 'eventing IP' 14328c2ecf20Sopenharmony_ci * (real IP) which fixes the off-by-1 skid in hardware. 14338c2ecf20Sopenharmony_ci * Use it when precise_ip >= 2 : 14348c2ecf20Sopenharmony_ci */ 14358c2ecf20Sopenharmony_ci if (x86_pmu.intel_cap.pebs_format >= 2) { 14368c2ecf20Sopenharmony_ci set_linear_ip(regs, pebs->real_ip); 14378c2ecf20Sopenharmony_ci regs->flags |= PERF_EFLAGS_EXACT; 14388c2ecf20Sopenharmony_ci } else { 14398c2ecf20Sopenharmony_ci /* Otherwise, use PEBS off-by-1 IP: */ 14408c2ecf20Sopenharmony_ci set_linear_ip(regs, pebs->ip); 14418c2ecf20Sopenharmony_ci 14428c2ecf20Sopenharmony_ci /* 14438c2ecf20Sopenharmony_ci * With precise_ip >= 2, try to fix up the off-by-1 IP 14448c2ecf20Sopenharmony_ci * using the LBR. If successful, the fixup function 14458c2ecf20Sopenharmony_ci * corrects regs->ip and calls set_linear_ip() on regs: 14468c2ecf20Sopenharmony_ci */ 14478c2ecf20Sopenharmony_ci if (intel_pmu_pebs_fixup_ip(regs)) 14488c2ecf20Sopenharmony_ci regs->flags |= PERF_EFLAGS_EXACT; 14498c2ecf20Sopenharmony_ci } 14508c2ecf20Sopenharmony_ci } else { 14518c2ecf20Sopenharmony_ci /* 14528c2ecf20Sopenharmony_ci * When precise_ip == 1, return the PEBS off-by-1 IP, 14538c2ecf20Sopenharmony_ci * no fixup attempted: 14548c2ecf20Sopenharmony_ci */ 14558c2ecf20Sopenharmony_ci set_linear_ip(regs, pebs->ip); 14568c2ecf20Sopenharmony_ci } 14578c2ecf20Sopenharmony_ci 14588c2ecf20Sopenharmony_ci 14598c2ecf20Sopenharmony_ci if ((sample_type & (PERF_SAMPLE_ADDR | PERF_SAMPLE_PHYS_ADDR)) && 14608c2ecf20Sopenharmony_ci x86_pmu.intel_cap.pebs_format >= 1) 14618c2ecf20Sopenharmony_ci data->addr = pebs->dla; 14628c2ecf20Sopenharmony_ci 14638c2ecf20Sopenharmony_ci if (x86_pmu.intel_cap.pebs_format >= 2) { 14648c2ecf20Sopenharmony_ci /* Only set the TSX weight when no memory weight. */ 14658c2ecf20Sopenharmony_ci if ((sample_type & PERF_SAMPLE_WEIGHT) && !fll) 14668c2ecf20Sopenharmony_ci data->weight = intel_get_tsx_weight(pebs->tsx_tuning); 14678c2ecf20Sopenharmony_ci 14688c2ecf20Sopenharmony_ci if (sample_type & PERF_SAMPLE_TRANSACTION) 14698c2ecf20Sopenharmony_ci data->txn = intel_get_tsx_transaction(pebs->tsx_tuning, 14708c2ecf20Sopenharmony_ci pebs->ax); 14718c2ecf20Sopenharmony_ci } 14728c2ecf20Sopenharmony_ci 14738c2ecf20Sopenharmony_ci /* 14748c2ecf20Sopenharmony_ci * v3 supplies an accurate time stamp, so we use that 14758c2ecf20Sopenharmony_ci * for the time stamp. 14768c2ecf20Sopenharmony_ci * 14778c2ecf20Sopenharmony_ci * We can only do this for the default trace clock. 14788c2ecf20Sopenharmony_ci */ 14798c2ecf20Sopenharmony_ci if (x86_pmu.intel_cap.pebs_format >= 3 && 14808c2ecf20Sopenharmony_ci event->attr.use_clockid == 0) 14818c2ecf20Sopenharmony_ci data->time = native_sched_clock_from_tsc(pebs->tsc); 14828c2ecf20Sopenharmony_ci 14838c2ecf20Sopenharmony_ci if (has_branch_stack(event)) 14848c2ecf20Sopenharmony_ci data->br_stack = &cpuc->lbr_stack; 14858c2ecf20Sopenharmony_ci} 14868c2ecf20Sopenharmony_ci 14878c2ecf20Sopenharmony_cistatic void adaptive_pebs_save_regs(struct pt_regs *regs, 14888c2ecf20Sopenharmony_ci struct pebs_gprs *gprs) 14898c2ecf20Sopenharmony_ci{ 14908c2ecf20Sopenharmony_ci regs->ax = gprs->ax; 14918c2ecf20Sopenharmony_ci regs->bx = gprs->bx; 14928c2ecf20Sopenharmony_ci regs->cx = gprs->cx; 14938c2ecf20Sopenharmony_ci regs->dx = gprs->dx; 14948c2ecf20Sopenharmony_ci regs->si = gprs->si; 14958c2ecf20Sopenharmony_ci regs->di = gprs->di; 14968c2ecf20Sopenharmony_ci regs->bp = gprs->bp; 14978c2ecf20Sopenharmony_ci regs->sp = gprs->sp; 14988c2ecf20Sopenharmony_ci#ifndef CONFIG_X86_32 14998c2ecf20Sopenharmony_ci regs->r8 = gprs->r8; 15008c2ecf20Sopenharmony_ci regs->r9 = gprs->r9; 15018c2ecf20Sopenharmony_ci regs->r10 = gprs->r10; 15028c2ecf20Sopenharmony_ci regs->r11 = gprs->r11; 15038c2ecf20Sopenharmony_ci regs->r12 = gprs->r12; 15048c2ecf20Sopenharmony_ci regs->r13 = gprs->r13; 15058c2ecf20Sopenharmony_ci regs->r14 = gprs->r14; 15068c2ecf20Sopenharmony_ci regs->r15 = gprs->r15; 15078c2ecf20Sopenharmony_ci#endif 15088c2ecf20Sopenharmony_ci} 15098c2ecf20Sopenharmony_ci 15108c2ecf20Sopenharmony_ci/* 15118c2ecf20Sopenharmony_ci * With adaptive PEBS the layout depends on what fields are configured. 15128c2ecf20Sopenharmony_ci */ 15138c2ecf20Sopenharmony_ci 15148c2ecf20Sopenharmony_cistatic void setup_pebs_adaptive_sample_data(struct perf_event *event, 15158c2ecf20Sopenharmony_ci struct pt_regs *iregs, void *__pebs, 15168c2ecf20Sopenharmony_ci struct perf_sample_data *data, 15178c2ecf20Sopenharmony_ci struct pt_regs *regs) 15188c2ecf20Sopenharmony_ci{ 15198c2ecf20Sopenharmony_ci struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 15208c2ecf20Sopenharmony_ci struct pebs_basic *basic = __pebs; 15218c2ecf20Sopenharmony_ci void *next_record = basic + 1; 15228c2ecf20Sopenharmony_ci u64 sample_type; 15238c2ecf20Sopenharmony_ci u64 format_size; 15248c2ecf20Sopenharmony_ci struct pebs_meminfo *meminfo = NULL; 15258c2ecf20Sopenharmony_ci struct pebs_gprs *gprs = NULL; 15268c2ecf20Sopenharmony_ci struct x86_perf_regs *perf_regs; 15278c2ecf20Sopenharmony_ci 15288c2ecf20Sopenharmony_ci if (basic == NULL) 15298c2ecf20Sopenharmony_ci return; 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_ci perf_regs = container_of(regs, struct x86_perf_regs, regs); 15328c2ecf20Sopenharmony_ci perf_regs->xmm_regs = NULL; 15338c2ecf20Sopenharmony_ci 15348c2ecf20Sopenharmony_ci sample_type = event->attr.sample_type; 15358c2ecf20Sopenharmony_ci format_size = basic->format_size; 15368c2ecf20Sopenharmony_ci perf_sample_data_init(data, 0, event->hw.last_period); 15378c2ecf20Sopenharmony_ci data->period = event->hw.last_period; 15388c2ecf20Sopenharmony_ci 15398c2ecf20Sopenharmony_ci if (event->attr.use_clockid == 0) 15408c2ecf20Sopenharmony_ci data->time = native_sched_clock_from_tsc(basic->tsc); 15418c2ecf20Sopenharmony_ci 15428c2ecf20Sopenharmony_ci /* 15438c2ecf20Sopenharmony_ci * We must however always use iregs for the unwinder to stay sane; the 15448c2ecf20Sopenharmony_ci * record BP,SP,IP can point into thin air when the record is from a 15458c2ecf20Sopenharmony_ci * previous PMI context or an (I)RET happened between the record and 15468c2ecf20Sopenharmony_ci * PMI. 15478c2ecf20Sopenharmony_ci */ 15488c2ecf20Sopenharmony_ci if (sample_type & PERF_SAMPLE_CALLCHAIN) 15498c2ecf20Sopenharmony_ci data->callchain = perf_callchain(event, iregs); 15508c2ecf20Sopenharmony_ci 15518c2ecf20Sopenharmony_ci *regs = *iregs; 15528c2ecf20Sopenharmony_ci /* The ip in basic is EventingIP */ 15538c2ecf20Sopenharmony_ci set_linear_ip(regs, basic->ip); 15548c2ecf20Sopenharmony_ci regs->flags = PERF_EFLAGS_EXACT; 15558c2ecf20Sopenharmony_ci 15568c2ecf20Sopenharmony_ci /* 15578c2ecf20Sopenharmony_ci * The record for MEMINFO is in front of GP 15588c2ecf20Sopenharmony_ci * But PERF_SAMPLE_TRANSACTION needs gprs->ax. 15598c2ecf20Sopenharmony_ci * Save the pointer here but process later. 15608c2ecf20Sopenharmony_ci */ 15618c2ecf20Sopenharmony_ci if (format_size & PEBS_DATACFG_MEMINFO) { 15628c2ecf20Sopenharmony_ci meminfo = next_record; 15638c2ecf20Sopenharmony_ci next_record = meminfo + 1; 15648c2ecf20Sopenharmony_ci } 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_ci if (format_size & PEBS_DATACFG_GP) { 15678c2ecf20Sopenharmony_ci gprs = next_record; 15688c2ecf20Sopenharmony_ci next_record = gprs + 1; 15698c2ecf20Sopenharmony_ci 15708c2ecf20Sopenharmony_ci if (event->attr.precise_ip < 2) { 15718c2ecf20Sopenharmony_ci set_linear_ip(regs, gprs->ip); 15728c2ecf20Sopenharmony_ci regs->flags &= ~PERF_EFLAGS_EXACT; 15738c2ecf20Sopenharmony_ci } 15748c2ecf20Sopenharmony_ci 15758c2ecf20Sopenharmony_ci if (sample_type & PERF_SAMPLE_REGS_INTR) 15768c2ecf20Sopenharmony_ci adaptive_pebs_save_regs(regs, gprs); 15778c2ecf20Sopenharmony_ci } 15788c2ecf20Sopenharmony_ci 15798c2ecf20Sopenharmony_ci if (format_size & PEBS_DATACFG_MEMINFO) { 15808c2ecf20Sopenharmony_ci if (sample_type & PERF_SAMPLE_WEIGHT) 15818c2ecf20Sopenharmony_ci data->weight = meminfo->latency ?: 15828c2ecf20Sopenharmony_ci intel_get_tsx_weight(meminfo->tsx_tuning); 15838c2ecf20Sopenharmony_ci 15848c2ecf20Sopenharmony_ci if (sample_type & PERF_SAMPLE_DATA_SRC) 15858c2ecf20Sopenharmony_ci data->data_src.val = get_data_src(event, meminfo->aux); 15868c2ecf20Sopenharmony_ci 15878c2ecf20Sopenharmony_ci if (sample_type & (PERF_SAMPLE_ADDR | PERF_SAMPLE_PHYS_ADDR)) 15888c2ecf20Sopenharmony_ci data->addr = meminfo->address; 15898c2ecf20Sopenharmony_ci 15908c2ecf20Sopenharmony_ci if (sample_type & PERF_SAMPLE_TRANSACTION) 15918c2ecf20Sopenharmony_ci data->txn = intel_get_tsx_transaction(meminfo->tsx_tuning, 15928c2ecf20Sopenharmony_ci gprs ? gprs->ax : 0); 15938c2ecf20Sopenharmony_ci } 15948c2ecf20Sopenharmony_ci 15958c2ecf20Sopenharmony_ci if (format_size & PEBS_DATACFG_XMMS) { 15968c2ecf20Sopenharmony_ci struct pebs_xmm *xmm = next_record; 15978c2ecf20Sopenharmony_ci 15988c2ecf20Sopenharmony_ci next_record = xmm + 1; 15998c2ecf20Sopenharmony_ci perf_regs->xmm_regs = xmm->xmm; 16008c2ecf20Sopenharmony_ci } 16018c2ecf20Sopenharmony_ci 16028c2ecf20Sopenharmony_ci if (format_size & PEBS_DATACFG_LBRS) { 16038c2ecf20Sopenharmony_ci struct lbr_entry *lbr = next_record; 16048c2ecf20Sopenharmony_ci int num_lbr = ((format_size >> PEBS_DATACFG_LBR_SHIFT) 16058c2ecf20Sopenharmony_ci & 0xff) + 1; 16068c2ecf20Sopenharmony_ci next_record = next_record + num_lbr * sizeof(struct lbr_entry); 16078c2ecf20Sopenharmony_ci 16088c2ecf20Sopenharmony_ci if (has_branch_stack(event)) { 16098c2ecf20Sopenharmony_ci intel_pmu_store_pebs_lbrs(lbr); 16108c2ecf20Sopenharmony_ci data->br_stack = &cpuc->lbr_stack; 16118c2ecf20Sopenharmony_ci } 16128c2ecf20Sopenharmony_ci } 16138c2ecf20Sopenharmony_ci 16148c2ecf20Sopenharmony_ci WARN_ONCE(next_record != __pebs + (format_size >> 48), 16158c2ecf20Sopenharmony_ci "PEBS record size %llu, expected %llu, config %llx\n", 16168c2ecf20Sopenharmony_ci format_size >> 48, 16178c2ecf20Sopenharmony_ci (u64)(next_record - __pebs), 16188c2ecf20Sopenharmony_ci basic->format_size); 16198c2ecf20Sopenharmony_ci} 16208c2ecf20Sopenharmony_ci 16218c2ecf20Sopenharmony_cistatic inline void * 16228c2ecf20Sopenharmony_ciget_next_pebs_record_by_bit(void *base, void *top, int bit) 16238c2ecf20Sopenharmony_ci{ 16248c2ecf20Sopenharmony_ci struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 16258c2ecf20Sopenharmony_ci void *at; 16268c2ecf20Sopenharmony_ci u64 pebs_status; 16278c2ecf20Sopenharmony_ci 16288c2ecf20Sopenharmony_ci /* 16298c2ecf20Sopenharmony_ci * fmt0 does not have a status bitfield (does not use 16308c2ecf20Sopenharmony_ci * perf_record_nhm format) 16318c2ecf20Sopenharmony_ci */ 16328c2ecf20Sopenharmony_ci if (x86_pmu.intel_cap.pebs_format < 1) 16338c2ecf20Sopenharmony_ci return base; 16348c2ecf20Sopenharmony_ci 16358c2ecf20Sopenharmony_ci if (base == NULL) 16368c2ecf20Sopenharmony_ci return NULL; 16378c2ecf20Sopenharmony_ci 16388c2ecf20Sopenharmony_ci for (at = base; at < top; at += cpuc->pebs_record_size) { 16398c2ecf20Sopenharmony_ci unsigned long status = get_pebs_status(at); 16408c2ecf20Sopenharmony_ci 16418c2ecf20Sopenharmony_ci if (test_bit(bit, (unsigned long *)&status)) { 16428c2ecf20Sopenharmony_ci /* PEBS v3 has accurate status bits */ 16438c2ecf20Sopenharmony_ci if (x86_pmu.intel_cap.pebs_format >= 3) 16448c2ecf20Sopenharmony_ci return at; 16458c2ecf20Sopenharmony_ci 16468c2ecf20Sopenharmony_ci if (status == (1 << bit)) 16478c2ecf20Sopenharmony_ci return at; 16488c2ecf20Sopenharmony_ci 16498c2ecf20Sopenharmony_ci /* clear non-PEBS bit and re-check */ 16508c2ecf20Sopenharmony_ci pebs_status = status & cpuc->pebs_enabled; 16518c2ecf20Sopenharmony_ci pebs_status &= PEBS_COUNTER_MASK; 16528c2ecf20Sopenharmony_ci if (pebs_status == (1 << bit)) 16538c2ecf20Sopenharmony_ci return at; 16548c2ecf20Sopenharmony_ci } 16558c2ecf20Sopenharmony_ci } 16568c2ecf20Sopenharmony_ci return NULL; 16578c2ecf20Sopenharmony_ci} 16588c2ecf20Sopenharmony_ci 16598c2ecf20Sopenharmony_civoid intel_pmu_auto_reload_read(struct perf_event *event) 16608c2ecf20Sopenharmony_ci{ 16618c2ecf20Sopenharmony_ci WARN_ON(!(event->hw.flags & PERF_X86_EVENT_AUTO_RELOAD)); 16628c2ecf20Sopenharmony_ci 16638c2ecf20Sopenharmony_ci perf_pmu_disable(event->pmu); 16648c2ecf20Sopenharmony_ci intel_pmu_drain_pebs_buffer(); 16658c2ecf20Sopenharmony_ci perf_pmu_enable(event->pmu); 16668c2ecf20Sopenharmony_ci} 16678c2ecf20Sopenharmony_ci 16688c2ecf20Sopenharmony_ci/* 16698c2ecf20Sopenharmony_ci * Special variant of intel_pmu_save_and_restart() for auto-reload. 16708c2ecf20Sopenharmony_ci */ 16718c2ecf20Sopenharmony_cistatic int 16728c2ecf20Sopenharmony_ciintel_pmu_save_and_restart_reload(struct perf_event *event, int count) 16738c2ecf20Sopenharmony_ci{ 16748c2ecf20Sopenharmony_ci struct hw_perf_event *hwc = &event->hw; 16758c2ecf20Sopenharmony_ci int shift = 64 - x86_pmu.cntval_bits; 16768c2ecf20Sopenharmony_ci u64 period = hwc->sample_period; 16778c2ecf20Sopenharmony_ci u64 prev_raw_count, new_raw_count; 16788c2ecf20Sopenharmony_ci s64 new, old; 16798c2ecf20Sopenharmony_ci 16808c2ecf20Sopenharmony_ci WARN_ON(!period); 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_ci /* 16838c2ecf20Sopenharmony_ci * drain_pebs() only happens when the PMU is disabled. 16848c2ecf20Sopenharmony_ci */ 16858c2ecf20Sopenharmony_ci WARN_ON(this_cpu_read(cpu_hw_events.enabled)); 16868c2ecf20Sopenharmony_ci 16878c2ecf20Sopenharmony_ci prev_raw_count = local64_read(&hwc->prev_count); 16888c2ecf20Sopenharmony_ci rdpmcl(hwc->event_base_rdpmc, new_raw_count); 16898c2ecf20Sopenharmony_ci local64_set(&hwc->prev_count, new_raw_count); 16908c2ecf20Sopenharmony_ci 16918c2ecf20Sopenharmony_ci /* 16928c2ecf20Sopenharmony_ci * Since the counter increments a negative counter value and 16938c2ecf20Sopenharmony_ci * overflows on the sign switch, giving the interval: 16948c2ecf20Sopenharmony_ci * 16958c2ecf20Sopenharmony_ci * [-period, 0] 16968c2ecf20Sopenharmony_ci * 16978c2ecf20Sopenharmony_ci * the difference between two consequtive reads is: 16988c2ecf20Sopenharmony_ci * 16998c2ecf20Sopenharmony_ci * A) value2 - value1; 17008c2ecf20Sopenharmony_ci * when no overflows have happened in between, 17018c2ecf20Sopenharmony_ci * 17028c2ecf20Sopenharmony_ci * B) (0 - value1) + (value2 - (-period)); 17038c2ecf20Sopenharmony_ci * when one overflow happened in between, 17048c2ecf20Sopenharmony_ci * 17058c2ecf20Sopenharmony_ci * C) (0 - value1) + (n - 1) * (period) + (value2 - (-period)); 17068c2ecf20Sopenharmony_ci * when @n overflows happened in between. 17078c2ecf20Sopenharmony_ci * 17088c2ecf20Sopenharmony_ci * Here A) is the obvious difference, B) is the extension to the 17098c2ecf20Sopenharmony_ci * discrete interval, where the first term is to the top of the 17108c2ecf20Sopenharmony_ci * interval and the second term is from the bottom of the next 17118c2ecf20Sopenharmony_ci * interval and C) the extension to multiple intervals, where the 17128c2ecf20Sopenharmony_ci * middle term is the whole intervals covered. 17138c2ecf20Sopenharmony_ci * 17148c2ecf20Sopenharmony_ci * An equivalent of C, by reduction, is: 17158c2ecf20Sopenharmony_ci * 17168c2ecf20Sopenharmony_ci * value2 - value1 + n * period 17178c2ecf20Sopenharmony_ci */ 17188c2ecf20Sopenharmony_ci new = ((s64)(new_raw_count << shift) >> shift); 17198c2ecf20Sopenharmony_ci old = ((s64)(prev_raw_count << shift) >> shift); 17208c2ecf20Sopenharmony_ci local64_add(new - old + count * period, &event->count); 17218c2ecf20Sopenharmony_ci 17228c2ecf20Sopenharmony_ci local64_set(&hwc->period_left, -new); 17238c2ecf20Sopenharmony_ci 17248c2ecf20Sopenharmony_ci perf_event_update_userpage(event); 17258c2ecf20Sopenharmony_ci 17268c2ecf20Sopenharmony_ci return 0; 17278c2ecf20Sopenharmony_ci} 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_cistatic __always_inline void 17308c2ecf20Sopenharmony_ci__intel_pmu_pebs_event(struct perf_event *event, 17318c2ecf20Sopenharmony_ci struct pt_regs *iregs, 17328c2ecf20Sopenharmony_ci struct perf_sample_data *data, 17338c2ecf20Sopenharmony_ci void *base, void *top, 17348c2ecf20Sopenharmony_ci int bit, int count, 17358c2ecf20Sopenharmony_ci void (*setup_sample)(struct perf_event *, 17368c2ecf20Sopenharmony_ci struct pt_regs *, 17378c2ecf20Sopenharmony_ci void *, 17388c2ecf20Sopenharmony_ci struct perf_sample_data *, 17398c2ecf20Sopenharmony_ci struct pt_regs *)) 17408c2ecf20Sopenharmony_ci{ 17418c2ecf20Sopenharmony_ci struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 17428c2ecf20Sopenharmony_ci struct hw_perf_event *hwc = &event->hw; 17438c2ecf20Sopenharmony_ci struct x86_perf_regs perf_regs; 17448c2ecf20Sopenharmony_ci struct pt_regs *regs = &perf_regs.regs; 17458c2ecf20Sopenharmony_ci void *at = get_next_pebs_record_by_bit(base, top, bit); 17468c2ecf20Sopenharmony_ci static struct pt_regs dummy_iregs; 17478c2ecf20Sopenharmony_ci 17488c2ecf20Sopenharmony_ci if (hwc->flags & PERF_X86_EVENT_AUTO_RELOAD) { 17498c2ecf20Sopenharmony_ci /* 17508c2ecf20Sopenharmony_ci * Now, auto-reload is only enabled in fixed period mode. 17518c2ecf20Sopenharmony_ci * The reload value is always hwc->sample_period. 17528c2ecf20Sopenharmony_ci * May need to change it, if auto-reload is enabled in 17538c2ecf20Sopenharmony_ci * freq mode later. 17548c2ecf20Sopenharmony_ci */ 17558c2ecf20Sopenharmony_ci intel_pmu_save_and_restart_reload(event, count); 17568c2ecf20Sopenharmony_ci } else if (!intel_pmu_save_and_restart(event)) 17578c2ecf20Sopenharmony_ci return; 17588c2ecf20Sopenharmony_ci 17598c2ecf20Sopenharmony_ci if (!iregs) 17608c2ecf20Sopenharmony_ci iregs = &dummy_iregs; 17618c2ecf20Sopenharmony_ci 17628c2ecf20Sopenharmony_ci while (count > 1) { 17638c2ecf20Sopenharmony_ci setup_sample(event, iregs, at, data, regs); 17648c2ecf20Sopenharmony_ci perf_event_output(event, data, regs); 17658c2ecf20Sopenharmony_ci at += cpuc->pebs_record_size; 17668c2ecf20Sopenharmony_ci at = get_next_pebs_record_by_bit(at, top, bit); 17678c2ecf20Sopenharmony_ci count--; 17688c2ecf20Sopenharmony_ci } 17698c2ecf20Sopenharmony_ci 17708c2ecf20Sopenharmony_ci setup_sample(event, iregs, at, data, regs); 17718c2ecf20Sopenharmony_ci if (iregs == &dummy_iregs) { 17728c2ecf20Sopenharmony_ci /* 17738c2ecf20Sopenharmony_ci * The PEBS records may be drained in the non-overflow context, 17748c2ecf20Sopenharmony_ci * e.g., large PEBS + context switch. Perf should treat the 17758c2ecf20Sopenharmony_ci * last record the same as other PEBS records, and doesn't 17768c2ecf20Sopenharmony_ci * invoke the generic overflow handler. 17778c2ecf20Sopenharmony_ci */ 17788c2ecf20Sopenharmony_ci perf_event_output(event, data, regs); 17798c2ecf20Sopenharmony_ci } else { 17808c2ecf20Sopenharmony_ci /* 17818c2ecf20Sopenharmony_ci * All but the last records are processed. 17828c2ecf20Sopenharmony_ci * The last one is left to be able to call the overflow handler. 17838c2ecf20Sopenharmony_ci */ 17848c2ecf20Sopenharmony_ci if (perf_event_overflow(event, data, regs)) 17858c2ecf20Sopenharmony_ci x86_pmu_stop(event, 0); 17868c2ecf20Sopenharmony_ci } 17878c2ecf20Sopenharmony_ci} 17888c2ecf20Sopenharmony_ci 17898c2ecf20Sopenharmony_cistatic void intel_pmu_drain_pebs_core(struct pt_regs *iregs, struct perf_sample_data *data) 17908c2ecf20Sopenharmony_ci{ 17918c2ecf20Sopenharmony_ci struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 17928c2ecf20Sopenharmony_ci struct debug_store *ds = cpuc->ds; 17938c2ecf20Sopenharmony_ci struct perf_event *event = cpuc->events[0]; /* PMC0 only */ 17948c2ecf20Sopenharmony_ci struct pebs_record_core *at, *top; 17958c2ecf20Sopenharmony_ci int n; 17968c2ecf20Sopenharmony_ci 17978c2ecf20Sopenharmony_ci if (!x86_pmu.pebs_active) 17988c2ecf20Sopenharmony_ci return; 17998c2ecf20Sopenharmony_ci 18008c2ecf20Sopenharmony_ci at = (struct pebs_record_core *)(unsigned long)ds->pebs_buffer_base; 18018c2ecf20Sopenharmony_ci top = (struct pebs_record_core *)(unsigned long)ds->pebs_index; 18028c2ecf20Sopenharmony_ci 18038c2ecf20Sopenharmony_ci /* 18048c2ecf20Sopenharmony_ci * Whatever else happens, drain the thing 18058c2ecf20Sopenharmony_ci */ 18068c2ecf20Sopenharmony_ci ds->pebs_index = ds->pebs_buffer_base; 18078c2ecf20Sopenharmony_ci 18088c2ecf20Sopenharmony_ci if (!test_bit(0, cpuc->active_mask)) 18098c2ecf20Sopenharmony_ci return; 18108c2ecf20Sopenharmony_ci 18118c2ecf20Sopenharmony_ci WARN_ON_ONCE(!event); 18128c2ecf20Sopenharmony_ci 18138c2ecf20Sopenharmony_ci if (!event->attr.precise_ip) 18148c2ecf20Sopenharmony_ci return; 18158c2ecf20Sopenharmony_ci 18168c2ecf20Sopenharmony_ci n = top - at; 18178c2ecf20Sopenharmony_ci if (n <= 0) { 18188c2ecf20Sopenharmony_ci if (event->hw.flags & PERF_X86_EVENT_AUTO_RELOAD) 18198c2ecf20Sopenharmony_ci intel_pmu_save_and_restart_reload(event, 0); 18208c2ecf20Sopenharmony_ci return; 18218c2ecf20Sopenharmony_ci } 18228c2ecf20Sopenharmony_ci 18238c2ecf20Sopenharmony_ci __intel_pmu_pebs_event(event, iregs, data, at, top, 0, n, 18248c2ecf20Sopenharmony_ci setup_pebs_fixed_sample_data); 18258c2ecf20Sopenharmony_ci} 18268c2ecf20Sopenharmony_ci 18278c2ecf20Sopenharmony_cistatic void intel_pmu_pebs_event_update_no_drain(struct cpu_hw_events *cpuc, int size) 18288c2ecf20Sopenharmony_ci{ 18298c2ecf20Sopenharmony_ci struct perf_event *event; 18308c2ecf20Sopenharmony_ci int bit; 18318c2ecf20Sopenharmony_ci 18328c2ecf20Sopenharmony_ci /* 18338c2ecf20Sopenharmony_ci * The drain_pebs() could be called twice in a short period 18348c2ecf20Sopenharmony_ci * for auto-reload event in pmu::read(). There are no 18358c2ecf20Sopenharmony_ci * overflows have happened in between. 18368c2ecf20Sopenharmony_ci * It needs to call intel_pmu_save_and_restart_reload() to 18378c2ecf20Sopenharmony_ci * update the event->count for this case. 18388c2ecf20Sopenharmony_ci */ 18398c2ecf20Sopenharmony_ci for_each_set_bit(bit, (unsigned long *)&cpuc->pebs_enabled, size) { 18408c2ecf20Sopenharmony_ci event = cpuc->events[bit]; 18418c2ecf20Sopenharmony_ci if (event->hw.flags & PERF_X86_EVENT_AUTO_RELOAD) 18428c2ecf20Sopenharmony_ci intel_pmu_save_and_restart_reload(event, 0); 18438c2ecf20Sopenharmony_ci } 18448c2ecf20Sopenharmony_ci} 18458c2ecf20Sopenharmony_ci 18468c2ecf20Sopenharmony_cistatic void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, struct perf_sample_data *data) 18478c2ecf20Sopenharmony_ci{ 18488c2ecf20Sopenharmony_ci struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 18498c2ecf20Sopenharmony_ci struct debug_store *ds = cpuc->ds; 18508c2ecf20Sopenharmony_ci struct perf_event *event; 18518c2ecf20Sopenharmony_ci void *base, *at, *top; 18528c2ecf20Sopenharmony_ci short counts[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS] = {}; 18538c2ecf20Sopenharmony_ci short error[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS] = {}; 18548c2ecf20Sopenharmony_ci int bit, i, size; 18558c2ecf20Sopenharmony_ci u64 mask; 18568c2ecf20Sopenharmony_ci 18578c2ecf20Sopenharmony_ci if (!x86_pmu.pebs_active) 18588c2ecf20Sopenharmony_ci return; 18598c2ecf20Sopenharmony_ci 18608c2ecf20Sopenharmony_ci base = (struct pebs_record_nhm *)(unsigned long)ds->pebs_buffer_base; 18618c2ecf20Sopenharmony_ci top = (struct pebs_record_nhm *)(unsigned long)ds->pebs_index; 18628c2ecf20Sopenharmony_ci 18638c2ecf20Sopenharmony_ci ds->pebs_index = ds->pebs_buffer_base; 18648c2ecf20Sopenharmony_ci 18658c2ecf20Sopenharmony_ci mask = (1ULL << x86_pmu.max_pebs_events) - 1; 18668c2ecf20Sopenharmony_ci size = x86_pmu.max_pebs_events; 18678c2ecf20Sopenharmony_ci if (x86_pmu.flags & PMU_FL_PEBS_ALL) { 18688c2ecf20Sopenharmony_ci mask |= ((1ULL << x86_pmu.num_counters_fixed) - 1) << INTEL_PMC_IDX_FIXED; 18698c2ecf20Sopenharmony_ci size = INTEL_PMC_IDX_FIXED + x86_pmu.num_counters_fixed; 18708c2ecf20Sopenharmony_ci } 18718c2ecf20Sopenharmony_ci 18728c2ecf20Sopenharmony_ci if (unlikely(base >= top)) { 18738c2ecf20Sopenharmony_ci intel_pmu_pebs_event_update_no_drain(cpuc, size); 18748c2ecf20Sopenharmony_ci return; 18758c2ecf20Sopenharmony_ci } 18768c2ecf20Sopenharmony_ci 18778c2ecf20Sopenharmony_ci for (at = base; at < top; at += x86_pmu.pebs_record_size) { 18788c2ecf20Sopenharmony_ci struct pebs_record_nhm *p = at; 18798c2ecf20Sopenharmony_ci u64 pebs_status; 18808c2ecf20Sopenharmony_ci 18818c2ecf20Sopenharmony_ci pebs_status = p->status & cpuc->pebs_enabled; 18828c2ecf20Sopenharmony_ci pebs_status &= mask; 18838c2ecf20Sopenharmony_ci 18848c2ecf20Sopenharmony_ci /* PEBS v3 has more accurate status bits */ 18858c2ecf20Sopenharmony_ci if (x86_pmu.intel_cap.pebs_format >= 3) { 18868c2ecf20Sopenharmony_ci for_each_set_bit(bit, (unsigned long *)&pebs_status, size) 18878c2ecf20Sopenharmony_ci counts[bit]++; 18888c2ecf20Sopenharmony_ci 18898c2ecf20Sopenharmony_ci continue; 18908c2ecf20Sopenharmony_ci } 18918c2ecf20Sopenharmony_ci 18928c2ecf20Sopenharmony_ci /* 18938c2ecf20Sopenharmony_ci * On some CPUs the PEBS status can be zero when PEBS is 18948c2ecf20Sopenharmony_ci * racing with clearing of GLOBAL_STATUS. 18958c2ecf20Sopenharmony_ci * 18968c2ecf20Sopenharmony_ci * Normally we would drop that record, but in the 18978c2ecf20Sopenharmony_ci * case when there is only a single active PEBS event 18988c2ecf20Sopenharmony_ci * we can assume it's for that event. 18998c2ecf20Sopenharmony_ci */ 19008c2ecf20Sopenharmony_ci if (!pebs_status && cpuc->pebs_enabled && 19018c2ecf20Sopenharmony_ci !(cpuc->pebs_enabled & (cpuc->pebs_enabled-1))) 19028c2ecf20Sopenharmony_ci pebs_status = p->status = cpuc->pebs_enabled; 19038c2ecf20Sopenharmony_ci 19048c2ecf20Sopenharmony_ci bit = find_first_bit((unsigned long *)&pebs_status, 19058c2ecf20Sopenharmony_ci x86_pmu.max_pebs_events); 19068c2ecf20Sopenharmony_ci if (bit >= x86_pmu.max_pebs_events) 19078c2ecf20Sopenharmony_ci continue; 19088c2ecf20Sopenharmony_ci 19098c2ecf20Sopenharmony_ci /* 19108c2ecf20Sopenharmony_ci * The PEBS hardware does not deal well with the situation 19118c2ecf20Sopenharmony_ci * when events happen near to each other and multiple bits 19128c2ecf20Sopenharmony_ci * are set. But it should happen rarely. 19138c2ecf20Sopenharmony_ci * 19148c2ecf20Sopenharmony_ci * If these events include one PEBS and multiple non-PEBS 19158c2ecf20Sopenharmony_ci * events, it doesn't impact PEBS record. The record will 19168c2ecf20Sopenharmony_ci * be handled normally. (slow path) 19178c2ecf20Sopenharmony_ci * 19188c2ecf20Sopenharmony_ci * If these events include two or more PEBS events, the 19198c2ecf20Sopenharmony_ci * records for the events can be collapsed into a single 19208c2ecf20Sopenharmony_ci * one, and it's not possible to reconstruct all events 19218c2ecf20Sopenharmony_ci * that caused the PEBS record. It's called collision. 19228c2ecf20Sopenharmony_ci * If collision happened, the record will be dropped. 19238c2ecf20Sopenharmony_ci */ 19248c2ecf20Sopenharmony_ci if (pebs_status != (1ULL << bit)) { 19258c2ecf20Sopenharmony_ci for_each_set_bit(i, (unsigned long *)&pebs_status, size) 19268c2ecf20Sopenharmony_ci error[i]++; 19278c2ecf20Sopenharmony_ci continue; 19288c2ecf20Sopenharmony_ci } 19298c2ecf20Sopenharmony_ci 19308c2ecf20Sopenharmony_ci counts[bit]++; 19318c2ecf20Sopenharmony_ci } 19328c2ecf20Sopenharmony_ci 19338c2ecf20Sopenharmony_ci for_each_set_bit(bit, (unsigned long *)&mask, size) { 19348c2ecf20Sopenharmony_ci if ((counts[bit] == 0) && (error[bit] == 0)) 19358c2ecf20Sopenharmony_ci continue; 19368c2ecf20Sopenharmony_ci 19378c2ecf20Sopenharmony_ci event = cpuc->events[bit]; 19388c2ecf20Sopenharmony_ci if (WARN_ON_ONCE(!event)) 19398c2ecf20Sopenharmony_ci continue; 19408c2ecf20Sopenharmony_ci 19418c2ecf20Sopenharmony_ci if (WARN_ON_ONCE(!event->attr.precise_ip)) 19428c2ecf20Sopenharmony_ci continue; 19438c2ecf20Sopenharmony_ci 19448c2ecf20Sopenharmony_ci /* log dropped samples number */ 19458c2ecf20Sopenharmony_ci if (error[bit]) { 19468c2ecf20Sopenharmony_ci perf_log_lost_samples(event, error[bit]); 19478c2ecf20Sopenharmony_ci 19488c2ecf20Sopenharmony_ci if (iregs && perf_event_account_interrupt(event)) 19498c2ecf20Sopenharmony_ci x86_pmu_stop(event, 0); 19508c2ecf20Sopenharmony_ci } 19518c2ecf20Sopenharmony_ci 19528c2ecf20Sopenharmony_ci if (counts[bit]) { 19538c2ecf20Sopenharmony_ci __intel_pmu_pebs_event(event, iregs, data, base, 19548c2ecf20Sopenharmony_ci top, bit, counts[bit], 19558c2ecf20Sopenharmony_ci setup_pebs_fixed_sample_data); 19568c2ecf20Sopenharmony_ci } 19578c2ecf20Sopenharmony_ci } 19588c2ecf20Sopenharmony_ci} 19598c2ecf20Sopenharmony_ci 19608c2ecf20Sopenharmony_cistatic void intel_pmu_drain_pebs_icl(struct pt_regs *iregs, struct perf_sample_data *data) 19618c2ecf20Sopenharmony_ci{ 19628c2ecf20Sopenharmony_ci short counts[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS] = {}; 19638c2ecf20Sopenharmony_ci struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 19648c2ecf20Sopenharmony_ci struct debug_store *ds = cpuc->ds; 19658c2ecf20Sopenharmony_ci struct perf_event *event; 19668c2ecf20Sopenharmony_ci void *base, *at, *top; 19678c2ecf20Sopenharmony_ci int bit, size; 19688c2ecf20Sopenharmony_ci u64 mask; 19698c2ecf20Sopenharmony_ci 19708c2ecf20Sopenharmony_ci if (!x86_pmu.pebs_active) 19718c2ecf20Sopenharmony_ci return; 19728c2ecf20Sopenharmony_ci 19738c2ecf20Sopenharmony_ci base = (struct pebs_basic *)(unsigned long)ds->pebs_buffer_base; 19748c2ecf20Sopenharmony_ci top = (struct pebs_basic *)(unsigned long)ds->pebs_index; 19758c2ecf20Sopenharmony_ci 19768c2ecf20Sopenharmony_ci ds->pebs_index = ds->pebs_buffer_base; 19778c2ecf20Sopenharmony_ci 19788c2ecf20Sopenharmony_ci mask = ((1ULL << x86_pmu.max_pebs_events) - 1) | 19798c2ecf20Sopenharmony_ci (((1ULL << x86_pmu.num_counters_fixed) - 1) << INTEL_PMC_IDX_FIXED); 19808c2ecf20Sopenharmony_ci size = INTEL_PMC_IDX_FIXED + x86_pmu.num_counters_fixed; 19818c2ecf20Sopenharmony_ci 19828c2ecf20Sopenharmony_ci if (unlikely(base >= top)) { 19838c2ecf20Sopenharmony_ci intel_pmu_pebs_event_update_no_drain(cpuc, size); 19848c2ecf20Sopenharmony_ci return; 19858c2ecf20Sopenharmony_ci } 19868c2ecf20Sopenharmony_ci 19878c2ecf20Sopenharmony_ci for (at = base; at < top; at += cpuc->pebs_record_size) { 19888c2ecf20Sopenharmony_ci u64 pebs_status; 19898c2ecf20Sopenharmony_ci 19908c2ecf20Sopenharmony_ci pebs_status = get_pebs_status(at) & cpuc->pebs_enabled; 19918c2ecf20Sopenharmony_ci pebs_status &= mask; 19928c2ecf20Sopenharmony_ci 19938c2ecf20Sopenharmony_ci for_each_set_bit(bit, (unsigned long *)&pebs_status, size) 19948c2ecf20Sopenharmony_ci counts[bit]++; 19958c2ecf20Sopenharmony_ci } 19968c2ecf20Sopenharmony_ci 19978c2ecf20Sopenharmony_ci for_each_set_bit(bit, (unsigned long *)&mask, size) { 19988c2ecf20Sopenharmony_ci if (counts[bit] == 0) 19998c2ecf20Sopenharmony_ci continue; 20008c2ecf20Sopenharmony_ci 20018c2ecf20Sopenharmony_ci event = cpuc->events[bit]; 20028c2ecf20Sopenharmony_ci if (WARN_ON_ONCE(!event)) 20038c2ecf20Sopenharmony_ci continue; 20048c2ecf20Sopenharmony_ci 20058c2ecf20Sopenharmony_ci if (WARN_ON_ONCE(!event->attr.precise_ip)) 20068c2ecf20Sopenharmony_ci continue; 20078c2ecf20Sopenharmony_ci 20088c2ecf20Sopenharmony_ci __intel_pmu_pebs_event(event, iregs, data, base, 20098c2ecf20Sopenharmony_ci top, bit, counts[bit], 20108c2ecf20Sopenharmony_ci setup_pebs_adaptive_sample_data); 20118c2ecf20Sopenharmony_ci } 20128c2ecf20Sopenharmony_ci} 20138c2ecf20Sopenharmony_ci 20148c2ecf20Sopenharmony_ci/* 20158c2ecf20Sopenharmony_ci * BTS, PEBS probe and setup 20168c2ecf20Sopenharmony_ci */ 20178c2ecf20Sopenharmony_ci 20188c2ecf20Sopenharmony_civoid __init intel_ds_init(void) 20198c2ecf20Sopenharmony_ci{ 20208c2ecf20Sopenharmony_ci /* 20218c2ecf20Sopenharmony_ci * No support for 32bit formats 20228c2ecf20Sopenharmony_ci */ 20238c2ecf20Sopenharmony_ci if (!boot_cpu_has(X86_FEATURE_DTES64)) 20248c2ecf20Sopenharmony_ci return; 20258c2ecf20Sopenharmony_ci 20268c2ecf20Sopenharmony_ci x86_pmu.bts = boot_cpu_has(X86_FEATURE_BTS); 20278c2ecf20Sopenharmony_ci x86_pmu.pebs = boot_cpu_has(X86_FEATURE_PEBS); 20288c2ecf20Sopenharmony_ci x86_pmu.pebs_buffer_size = PEBS_BUFFER_SIZE; 20298c2ecf20Sopenharmony_ci if (x86_pmu.version <= 4) 20308c2ecf20Sopenharmony_ci x86_pmu.pebs_no_isolation = 1; 20318c2ecf20Sopenharmony_ci 20328c2ecf20Sopenharmony_ci if (x86_pmu.pebs) { 20338c2ecf20Sopenharmony_ci char pebs_type = x86_pmu.intel_cap.pebs_trap ? '+' : '-'; 20348c2ecf20Sopenharmony_ci char *pebs_qual = ""; 20358c2ecf20Sopenharmony_ci int format = x86_pmu.intel_cap.pebs_format; 20368c2ecf20Sopenharmony_ci 20378c2ecf20Sopenharmony_ci if (format < 4) 20388c2ecf20Sopenharmony_ci x86_pmu.intel_cap.pebs_baseline = 0; 20398c2ecf20Sopenharmony_ci 20408c2ecf20Sopenharmony_ci switch (format) { 20418c2ecf20Sopenharmony_ci case 0: 20428c2ecf20Sopenharmony_ci pr_cont("PEBS fmt0%c, ", pebs_type); 20438c2ecf20Sopenharmony_ci x86_pmu.pebs_record_size = sizeof(struct pebs_record_core); 20448c2ecf20Sopenharmony_ci /* 20458c2ecf20Sopenharmony_ci * Using >PAGE_SIZE buffers makes the WRMSR to 20468c2ecf20Sopenharmony_ci * PERF_GLOBAL_CTRL in intel_pmu_enable_all() 20478c2ecf20Sopenharmony_ci * mysteriously hang on Core2. 20488c2ecf20Sopenharmony_ci * 20498c2ecf20Sopenharmony_ci * As a workaround, we don't do this. 20508c2ecf20Sopenharmony_ci */ 20518c2ecf20Sopenharmony_ci x86_pmu.pebs_buffer_size = PAGE_SIZE; 20528c2ecf20Sopenharmony_ci x86_pmu.drain_pebs = intel_pmu_drain_pebs_core; 20538c2ecf20Sopenharmony_ci break; 20548c2ecf20Sopenharmony_ci 20558c2ecf20Sopenharmony_ci case 1: 20568c2ecf20Sopenharmony_ci pr_cont("PEBS fmt1%c, ", pebs_type); 20578c2ecf20Sopenharmony_ci x86_pmu.pebs_record_size = sizeof(struct pebs_record_nhm); 20588c2ecf20Sopenharmony_ci x86_pmu.drain_pebs = intel_pmu_drain_pebs_nhm; 20598c2ecf20Sopenharmony_ci break; 20608c2ecf20Sopenharmony_ci 20618c2ecf20Sopenharmony_ci case 2: 20628c2ecf20Sopenharmony_ci pr_cont("PEBS fmt2%c, ", pebs_type); 20638c2ecf20Sopenharmony_ci x86_pmu.pebs_record_size = sizeof(struct pebs_record_hsw); 20648c2ecf20Sopenharmony_ci x86_pmu.drain_pebs = intel_pmu_drain_pebs_nhm; 20658c2ecf20Sopenharmony_ci break; 20668c2ecf20Sopenharmony_ci 20678c2ecf20Sopenharmony_ci case 3: 20688c2ecf20Sopenharmony_ci pr_cont("PEBS fmt3%c, ", pebs_type); 20698c2ecf20Sopenharmony_ci x86_pmu.pebs_record_size = 20708c2ecf20Sopenharmony_ci sizeof(struct pebs_record_skl); 20718c2ecf20Sopenharmony_ci x86_pmu.drain_pebs = intel_pmu_drain_pebs_nhm; 20728c2ecf20Sopenharmony_ci x86_pmu.large_pebs_flags |= PERF_SAMPLE_TIME; 20738c2ecf20Sopenharmony_ci break; 20748c2ecf20Sopenharmony_ci 20758c2ecf20Sopenharmony_ci case 4: 20768c2ecf20Sopenharmony_ci x86_pmu.drain_pebs = intel_pmu_drain_pebs_icl; 20778c2ecf20Sopenharmony_ci x86_pmu.pebs_record_size = sizeof(struct pebs_basic); 20788c2ecf20Sopenharmony_ci if (x86_pmu.intel_cap.pebs_baseline) { 20798c2ecf20Sopenharmony_ci x86_pmu.large_pebs_flags |= 20808c2ecf20Sopenharmony_ci PERF_SAMPLE_BRANCH_STACK | 20818c2ecf20Sopenharmony_ci PERF_SAMPLE_TIME; 20828c2ecf20Sopenharmony_ci x86_pmu.flags |= PMU_FL_PEBS_ALL; 20838c2ecf20Sopenharmony_ci pebs_qual = "-baseline"; 20848c2ecf20Sopenharmony_ci x86_get_pmu(smp_processor_id())->capabilities |= PERF_PMU_CAP_EXTENDED_REGS; 20858c2ecf20Sopenharmony_ci } else { 20868c2ecf20Sopenharmony_ci /* Only basic record supported */ 20878c2ecf20Sopenharmony_ci x86_pmu.large_pebs_flags &= 20888c2ecf20Sopenharmony_ci ~(PERF_SAMPLE_ADDR | 20898c2ecf20Sopenharmony_ci PERF_SAMPLE_TIME | 20908c2ecf20Sopenharmony_ci PERF_SAMPLE_DATA_SRC | 20918c2ecf20Sopenharmony_ci PERF_SAMPLE_TRANSACTION | 20928c2ecf20Sopenharmony_ci PERF_SAMPLE_REGS_USER | 20938c2ecf20Sopenharmony_ci PERF_SAMPLE_REGS_INTR); 20948c2ecf20Sopenharmony_ci } 20958c2ecf20Sopenharmony_ci pr_cont("PEBS fmt4%c%s, ", pebs_type, pebs_qual); 20968c2ecf20Sopenharmony_ci 20978c2ecf20Sopenharmony_ci if (x86_pmu.intel_cap.pebs_output_pt_available) { 20988c2ecf20Sopenharmony_ci pr_cont("PEBS-via-PT, "); 20998c2ecf20Sopenharmony_ci x86_get_pmu(smp_processor_id())->capabilities |= PERF_PMU_CAP_AUX_OUTPUT; 21008c2ecf20Sopenharmony_ci } 21018c2ecf20Sopenharmony_ci 21028c2ecf20Sopenharmony_ci break; 21038c2ecf20Sopenharmony_ci 21048c2ecf20Sopenharmony_ci default: 21058c2ecf20Sopenharmony_ci pr_cont("no PEBS fmt%d%c, ", format, pebs_type); 21068c2ecf20Sopenharmony_ci x86_pmu.pebs = 0; 21078c2ecf20Sopenharmony_ci } 21088c2ecf20Sopenharmony_ci } 21098c2ecf20Sopenharmony_ci} 21108c2ecf20Sopenharmony_ci 21118c2ecf20Sopenharmony_civoid perf_restore_debug_store(void) 21128c2ecf20Sopenharmony_ci{ 21138c2ecf20Sopenharmony_ci struct debug_store *ds = __this_cpu_read(cpu_hw_events.ds); 21148c2ecf20Sopenharmony_ci 21158c2ecf20Sopenharmony_ci if (!x86_pmu.bts && !x86_pmu.pebs) 21168c2ecf20Sopenharmony_ci return; 21178c2ecf20Sopenharmony_ci 21188c2ecf20Sopenharmony_ci wrmsrl(MSR_IA32_DS_AREA, (unsigned long)ds); 21198c2ecf20Sopenharmony_ci} 2120