Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf intel-pt: Synthesize CFE (Control Flow Event) / EVD (Event Data) event

Synthesize an attribute event and sample events for Intel PT Event Trace
events represented by CFE and EVD packets.

Committer notes:

Make 'struct perf_synth_intel_evd evd[]' evd[0] at the end of 'struct
perf_synth_intel_evt' as it is breaking the build with in many compilers
with (e.g. clang version 13.0.0 (Fedora 13.0.0-3.fc35)):

util/intel-pt.c:2213:31: error: field 'cfe' with variable sized type 'struct perf_synth_intel_evt' not at the end of a struct or class is a GNU extension [-Werror,-Wgnu-variable-sized-type-not-at-end]
struct perf_synth_intel_evt cfe;
^

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: https://lore.kernel.org/r/20220124084201.2699795-15-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Adrian Hunter and committed by
Arnaldo Carvalho de Melo
ef3b2ba9 f2be829e

+63 -1
+1 -1
tools/perf/util/event.h
··· 308 308 }; 309 309 u32 cfe; 310 310 }; 311 - struct perf_synth_intel_evd evd[]; 311 + struct perf_synth_intel_evd evd[0]; 312 312 }; 313 313 314 314 struct perf_synth_intel_iflag_chg {
+62
tools/perf/util/intel-pt.c
··· 49 49 #define INTEL_PT_CFG_PASS_THRU BIT_ULL(0) 50 50 #define INTEL_PT_CFG_PWR_EVT_EN BIT_ULL(4) 51 51 #define INTEL_PT_CFG_BRANCH_EN BIT_ULL(13) 52 + #define INTEL_PT_CFG_EVT_EN BIT_ULL(31) 52 53 53 54 struct range { 54 55 u64 start; ··· 120 119 bool single_pebs; 121 120 bool sample_pebs; 122 121 struct evsel *pebs_evsel; 122 + 123 + u64 evt_sample_type; 124 + u64 evt_id; 123 125 124 126 u64 tsc_bit; 125 127 u64 mtc_bit; ··· 2170 2166 return err; 2171 2167 } 2172 2168 2169 + static int intel_pt_synth_events_sample(struct intel_pt_queue *ptq) 2170 + { 2171 + struct intel_pt *pt = ptq->pt; 2172 + union perf_event *event = ptq->event_buf; 2173 + struct perf_sample sample = { .ip = 0, }; 2174 + struct { 2175 + struct perf_synth_intel_evt cfe; 2176 + struct perf_synth_intel_evd evd[INTEL_PT_MAX_EVDS]; 2177 + } raw; 2178 + int i; 2179 + 2180 + if (intel_pt_skip_event(pt)) 2181 + return 0; 2182 + 2183 + intel_pt_prep_p_sample(pt, ptq, event, &sample); 2184 + 2185 + sample.id = ptq->pt->evt_id; 2186 + sample.stream_id = ptq->pt->evt_id; 2187 + 2188 + raw.cfe.type = ptq->state->cfe_type; 2189 + raw.cfe.reserved = 0; 2190 + raw.cfe.ip = !!(ptq->state->flags & INTEL_PT_FUP_IP); 2191 + raw.cfe.vector = ptq->state->cfe_vector; 2192 + raw.cfe.evd_cnt = ptq->state->evd_cnt; 2193 + 2194 + for (i = 0; i < ptq->state->evd_cnt; i++) { 2195 + raw.evd[i].et = 0; 2196 + raw.evd[i].evd_type = ptq->state->evd[i].type; 2197 + raw.evd[i].payload = ptq->state->evd[i].payload; 2198 + } 2199 + 2200 + sample.raw_size = perf_synth__raw_size(raw) + 2201 + ptq->state->evd_cnt * sizeof(struct perf_synth_intel_evd); 2202 + sample.raw_data = perf_synth__raw_data(&raw); 2203 + 2204 + return intel_pt_deliver_synth_event(pt, event, &sample, 2205 + pt->evt_sample_type); 2206 + } 2207 + 2173 2208 static int intel_pt_synth_error(struct intel_pt *pt, int code, int cpu, 2174 2209 pid_t pid, pid_t tid, u64 ip, u64 timestamp) 2175 2210 { ··· 2313 2270 err = intel_pt_synth_pebs_sample(ptq); 2314 2271 if (err) 2315 2272 return err; 2273 + } 2274 + 2275 + if (pt->synth_opts.intr_events) { 2276 + if (state->type & INTEL_PT_EVT) { 2277 + err = intel_pt_synth_events_sample(ptq); 2278 + if (err) 2279 + return err; 2280 + } 2316 2281 } 2317 2282 2318 2283 if (pt->sample_pwr_events) { ··· 3517 3466 return err; 3518 3467 pt->pwrx_id = id; 3519 3468 intel_pt_set_event_name(evlist, id, "pwrx"); 3469 + id += 1; 3470 + } 3471 + 3472 + if (pt->synth_opts.intr_events && (evsel->core.attr.config & INTEL_PT_CFG_EVT_EN)) { 3473 + attr.config = PERF_SYNTH_INTEL_EVT; 3474 + err = intel_pt_synth_event(session, "evt", &attr, id); 3475 + if (err) 3476 + return err; 3477 + pt->evt_sample_type = attr.sample_type; 3478 + pt->evt_id = id; 3479 + intel_pt_set_event_name(evlist, id, "evt"); 3520 3480 id += 1; 3521 3481 } 3522 3482