@@ -2270,6 +2270,117 @@ static void setup_pebs_adaptive_sample_data(struct perf_event *event,
22702270 format_group );
22712271}
22722272
2273+ static inline bool arch_pebs_record_continued (struct arch_pebs_header * header )
2274+ {
2275+ /* Continue bit or null PEBS record indicates fragment follows. */
2276+ return header -> cont || !(header -> format & GENMASK_ULL (63 , 16 ));
2277+ }
2278+
2279+ static void setup_arch_pebs_sample_data (struct perf_event * event ,
2280+ struct pt_regs * iregs ,
2281+ void * __pebs ,
2282+ struct perf_sample_data * data ,
2283+ struct pt_regs * regs )
2284+ {
2285+ struct cpu_hw_events * cpuc = this_cpu_ptr (& cpu_hw_events );
2286+ u64 sample_type = event -> attr .sample_type ;
2287+ struct arch_pebs_header * header = NULL ;
2288+ struct arch_pebs_aux * meminfo = NULL ;
2289+ struct arch_pebs_gprs * gprs = NULL ;
2290+ struct x86_perf_regs * perf_regs ;
2291+ void * next_record ;
2292+ void * at = __pebs ;
2293+
2294+ if (at == NULL )
2295+ return ;
2296+
2297+ perf_regs = container_of (regs , struct x86_perf_regs , regs );
2298+ perf_regs -> xmm_regs = NULL ;
2299+
2300+ __setup_perf_sample_data (event , iregs , data );
2301+
2302+ * regs = * iregs ;
2303+
2304+ again :
2305+ header = at ;
2306+ next_record = at + sizeof (struct arch_pebs_header );
2307+ if (header -> basic ) {
2308+ struct arch_pebs_basic * basic = next_record ;
2309+ u16 retire = 0 ;
2310+
2311+ next_record = basic + 1 ;
2312+
2313+ if (sample_type & PERF_SAMPLE_WEIGHT_STRUCT )
2314+ retire = basic -> valid ? basic -> retire : 0 ;
2315+ __setup_pebs_basic_group (event , regs , data , sample_type ,
2316+ basic -> ip , basic -> tsc , retire );
2317+ }
2318+
2319+ /*
2320+ * The record for MEMINFO is in front of GP
2321+ * But PERF_SAMPLE_TRANSACTION needs gprs->ax.
2322+ * Save the pointer here but process later.
2323+ */
2324+ if (header -> aux ) {
2325+ meminfo = next_record ;
2326+ next_record = meminfo + 1 ;
2327+ }
2328+
2329+ if (header -> gpr ) {
2330+ gprs = next_record ;
2331+ next_record = gprs + 1 ;
2332+
2333+ __setup_pebs_gpr_group (event , regs ,
2334+ (struct pebs_gprs * )gprs ,
2335+ sample_type );
2336+ }
2337+
2338+ if (header -> aux ) {
2339+ u64 ax = gprs ? gprs -> ax : 0 ;
2340+
2341+ __setup_pebs_meminfo_group (event , data , sample_type ,
2342+ meminfo -> cache_latency ,
2343+ meminfo -> instr_latency ,
2344+ meminfo -> address , meminfo -> aux ,
2345+ meminfo -> tsx_tuning , ax );
2346+ }
2347+
2348+ if (header -> xmm ) {
2349+ struct pebs_xmm * xmm ;
2350+
2351+ next_record += sizeof (struct arch_pebs_xer_header );
2352+
2353+ xmm = next_record ;
2354+ perf_regs -> xmm_regs = xmm -> xmm ;
2355+ next_record = xmm + 1 ;
2356+ }
2357+
2358+ if (header -> lbr ) {
2359+ struct arch_pebs_lbr_header * lbr_header = next_record ;
2360+ struct lbr_entry * lbr ;
2361+ int num_lbr ;
2362+
2363+ next_record = lbr_header + 1 ;
2364+ lbr = next_record ;
2365+
2366+ num_lbr = header -> lbr == ARCH_PEBS_LBR_NUM_VAR ?
2367+ lbr_header -> depth :
2368+ header -> lbr * ARCH_PEBS_BASE_LBR_ENTRIES ;
2369+ next_record += num_lbr * sizeof (struct lbr_entry );
2370+
2371+ if (has_branch_stack (event )) {
2372+ intel_pmu_store_pebs_lbrs (lbr );
2373+ intel_pmu_lbr_save_brstack (data , cpuc , event );
2374+ }
2375+ }
2376+
2377+ /* Parse followed fragments if there are. */
2378+ if (arch_pebs_record_continued (header )) {
2379+ at = at + header -> size ;
2380+ goto again ;
2381+ }
2382+ }
2383+
22732384static inline void *
22742385get_next_pebs_record_by_bit (void * base , void * top , int bit )
22752386{
@@ -2753,6 +2864,78 @@ static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs, struct perf_sample_d
27532864 setup_pebs_adaptive_sample_data );
27542865}
27552866
2867+ static void intel_pmu_drain_arch_pebs (struct pt_regs * iregs ,
2868+ struct perf_sample_data * data )
2869+ {
2870+ short counts [INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS ] = {};
2871+ void * last [INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS ];
2872+ struct cpu_hw_events * cpuc = this_cpu_ptr (& cpu_hw_events );
2873+ union arch_pebs_index index ;
2874+ struct x86_perf_regs perf_regs ;
2875+ struct pt_regs * regs = & perf_regs .regs ;
2876+ void * base , * at , * top ;
2877+ u64 mask ;
2878+
2879+ rdmsrq (MSR_IA32_PEBS_INDEX , index .whole );
2880+
2881+ if (unlikely (!index .wr )) {
2882+ intel_pmu_pebs_event_update_no_drain (cpuc , X86_PMC_IDX_MAX );
2883+ return ;
2884+ }
2885+
2886+ base = cpuc -> ds_pebs_vaddr ;
2887+ top = (void * )((u64 )cpuc -> ds_pebs_vaddr +
2888+ (index .wr << ARCH_PEBS_INDEX_WR_SHIFT ));
2889+
2890+ index .wr = 0 ;
2891+ index .full = 0 ;
2892+ wrmsrq (MSR_IA32_PEBS_INDEX , index .whole );
2893+
2894+ mask = hybrid (cpuc -> pmu , arch_pebs_cap ).counters & cpuc -> pebs_enabled ;
2895+
2896+ if (!iregs )
2897+ iregs = & dummy_iregs ;
2898+
2899+ /* Process all but the last event for each counter. */
2900+ for (at = base ; at < top ;) {
2901+ struct arch_pebs_header * header ;
2902+ struct arch_pebs_basic * basic ;
2903+ u64 pebs_status ;
2904+
2905+ header = at ;
2906+
2907+ if (WARN_ON_ONCE (!header -> size ))
2908+ break ;
2909+
2910+ /* 1st fragment or single record must have basic group */
2911+ if (!header -> basic ) {
2912+ at += header -> size ;
2913+ continue ;
2914+ }
2915+
2916+ basic = at + sizeof (struct arch_pebs_header );
2917+ pebs_status = mask & basic -> applicable_counters ;
2918+ __intel_pmu_handle_pebs_record (iregs , regs , data , at ,
2919+ pebs_status , counts , last ,
2920+ setup_arch_pebs_sample_data );
2921+
2922+ /* Skip non-last fragments */
2923+ while (arch_pebs_record_continued (header )) {
2924+ if (!header -> size )
2925+ break ;
2926+ at += header -> size ;
2927+ header = at ;
2928+ }
2929+
2930+ /* Skip last fragment or the single record */
2931+ at += header -> size ;
2932+ }
2933+
2934+ __intel_pmu_handle_last_pebs_record (iregs , regs , data , mask ,
2935+ counts , last ,
2936+ setup_arch_pebs_sample_data );
2937+ }
2938+
27562939static void __init intel_arch_pebs_init (void )
27572940{
27582941 /*
@@ -2762,6 +2945,7 @@ static void __init intel_arch_pebs_init(void)
27622945 */
27632946 x86_pmu .arch_pebs = 1 ;
27642947 x86_pmu .pebs_buffer_size = PEBS_BUFFER_SIZE ;
2948+ x86_pmu .drain_pebs = intel_pmu_drain_arch_pebs ;
27652949 x86_pmu .pebs_capable = ~0ULL ;
27662950
27672951 x86_pmu .pebs_enable = __intel_pmu_pebs_enable ;
0 commit comments