Commit 5fe2cf7d authored by Adrian Hunter's avatar Adrian Hunter Committed by Arnaldo Carvalho de Melo

perf intel-pt: Synthesize CBR events when last seen value changes

The first core-to-bus ratio (CBR) event will not be shown if --itrace
's' option (skip initial number of events) is used, nor if time
intervals are specified that do not include the start of tracing. Change
the logic to record the last CBR value seen by the user, and synthesize
CBR events whenever that changes.
Signed-off-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/20190622093248.581-5-adrian.hunter@intel.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 51b09186
...@@ -171,6 +171,7 @@ struct intel_pt_queue { ...@@ -171,6 +171,7 @@ struct intel_pt_queue {
u64 last_in_cyc_cnt; u64 last_in_cyc_cnt;
u64 last_br_insn_cnt; u64 last_br_insn_cnt;
u64 last_br_cyc_cnt; u64 last_br_cyc_cnt;
unsigned int cbr_seen;
char insn[INTEL_PT_INSN_BUF_SZ]; char insn[INTEL_PT_INSN_BUF_SZ];
}; };
...@@ -1052,6 +1053,8 @@ static int intel_pt_setup_queue(struct intel_pt *pt, ...@@ -1052,6 +1053,8 @@ static int intel_pt_setup_queue(struct intel_pt *pt,
ptq->cpu = queue->cpu; ptq->cpu = queue->cpu;
ptq->tid = queue->tid; ptq->tid = queue->tid;
ptq->cbr_seen = UINT_MAX;
if (pt->sampling_mode && !pt->snapshot_mode && if (pt->sampling_mode && !pt->snapshot_mode &&
pt->timeless_decoding) pt->timeless_decoding)
ptq->step_through_buffers = true; ptq->step_through_buffers = true;
...@@ -1184,6 +1187,17 @@ static inline bool intel_pt_skip_event(struct intel_pt *pt) ...@@ -1184,6 +1187,17 @@ static inline bool intel_pt_skip_event(struct intel_pt *pt)
pt->num_events++ < pt->synth_opts.initial_skip; pt->num_events++ < pt->synth_opts.initial_skip;
} }
/*
* Cannot count CBR as skipped because it won't go away until cbr == cbr_seen.
* Also ensure CBR is first non-skipped event by allowing for 4 more samples
* from this decoder state.
*/
static inline bool intel_pt_skip_cbr_event(struct intel_pt *pt)
{
return pt->synth_opts.initial_skip &&
pt->num_events + 4 < pt->synth_opts.initial_skip;
}
static void intel_pt_prep_a_sample(struct intel_pt_queue *ptq, static void intel_pt_prep_a_sample(struct intel_pt_queue *ptq,
union perf_event *event, union perf_event *event,
struct perf_sample *sample) struct perf_sample *sample)
...@@ -1429,9 +1443,11 @@ static int intel_pt_synth_cbr_sample(struct intel_pt_queue *ptq) ...@@ -1429,9 +1443,11 @@ static int intel_pt_synth_cbr_sample(struct intel_pt_queue *ptq)
struct perf_synth_intel_cbr raw; struct perf_synth_intel_cbr raw;
u32 flags; u32 flags;
if (intel_pt_skip_event(pt)) if (intel_pt_skip_cbr_event(pt))
return 0; return 0;
ptq->cbr_seen = ptq->state->cbr;
intel_pt_prep_p_sample(pt, ptq, event, &sample); intel_pt_prep_p_sample(pt, ptq, event, &sample);
sample.id = ptq->pt->cbr_id; sample.id = ptq->pt->cbr_id;
...@@ -1868,8 +1884,7 @@ static inline bool intel_pt_is_switch_ip(struct intel_pt_queue *ptq, u64 ip) ...@@ -1868,8 +1884,7 @@ static inline bool intel_pt_is_switch_ip(struct intel_pt_queue *ptq, u64 ip)
} }
#define INTEL_PT_PWR_EVT (INTEL_PT_MWAIT_OP | INTEL_PT_PWR_ENTRY | \ #define INTEL_PT_PWR_EVT (INTEL_PT_MWAIT_OP | INTEL_PT_PWR_ENTRY | \
INTEL_PT_EX_STOP | INTEL_PT_PWR_EXIT | \ INTEL_PT_EX_STOP | INTEL_PT_PWR_EXIT)
INTEL_PT_CBR_CHG)
static int intel_pt_sample(struct intel_pt_queue *ptq) static int intel_pt_sample(struct intel_pt_queue *ptq)
{ {
...@@ -1901,31 +1916,33 @@ static int intel_pt_sample(struct intel_pt_queue *ptq) ...@@ -1901,31 +1916,33 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
return err; return err;
} }
if (pt->sample_pwr_events && (state->type & INTEL_PT_PWR_EVT)) { if (pt->sample_pwr_events) {
if (state->type & INTEL_PT_CBR_CHG) { if (ptq->state->cbr != ptq->cbr_seen) {
err = intel_pt_synth_cbr_sample(ptq); err = intel_pt_synth_cbr_sample(ptq);
if (err) if (err)
return err; return err;
} }
if (state->type & INTEL_PT_MWAIT_OP) { if (state->type & INTEL_PT_PWR_EVT) {
err = intel_pt_synth_mwait_sample(ptq); if (state->type & INTEL_PT_MWAIT_OP) {
if (err) err = intel_pt_synth_mwait_sample(ptq);
return err; if (err)
} return err;
if (state->type & INTEL_PT_PWR_ENTRY) { }
err = intel_pt_synth_pwre_sample(ptq); if (state->type & INTEL_PT_PWR_ENTRY) {
if (err) err = intel_pt_synth_pwre_sample(ptq);
return err; if (err)
} return err;
if (state->type & INTEL_PT_EX_STOP) { }
err = intel_pt_synth_exstop_sample(ptq); if (state->type & INTEL_PT_EX_STOP) {
if (err) err = intel_pt_synth_exstop_sample(ptq);
return err; if (err)
} return err;
if (state->type & INTEL_PT_PWR_EXIT) { }
err = intel_pt_synth_pwrx_sample(ptq); if (state->type & INTEL_PT_PWR_EXIT) {
if (err) err = intel_pt_synth_pwrx_sample(ptq);
return err; if (err)
return err;
}
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment