Commit 11fa7cb8 authored by Adrian Hunter's avatar Adrian Hunter Committed by Arnaldo Carvalho de Melo

perf tools: Pass Intel PT information for decoding MTC and CYC

Record additional information in the AUXTRACE_INFO event in preparation
for decoding MTC and CYC packets.  Pass the information to the decoder.

The AUXTRACE_INFO record can be extended by using the size to indicate
the presence of new members.

The additional information includes PMU config bit positions and the TSC
to CTC (hardware crystal clock) ratio needed to decode MTC packets.
Signed-off-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/1437150840-31811-20-git-send-email-adrian.hunter@intel.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 3d498078
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/log2.h> #include <linux/log2.h>
#include <cpuid.h>
#include "../../perf.h" #include "../../perf.h"
#include "../../util/session.h" #include "../../util/session.h"
...@@ -261,6 +262,15 @@ static size_t intel_pt_info_priv_size(struct auxtrace_record *itr __maybe_unused ...@@ -261,6 +262,15 @@ static size_t intel_pt_info_priv_size(struct auxtrace_record *itr __maybe_unused
return INTEL_PT_AUXTRACE_PRIV_SIZE; return INTEL_PT_AUXTRACE_PRIV_SIZE;
} }
static void intel_pt_tsc_ctc_ratio(u32 *n, u32 *d)
{
unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0;
__get_cpuid(0x15, &eax, &ebx, &ecx, &edx);
*n = ebx;
*d = eax;
}
static int intel_pt_info_fill(struct auxtrace_record *itr, static int intel_pt_info_fill(struct auxtrace_record *itr,
struct perf_session *session, struct perf_session *session,
struct auxtrace_info_event *auxtrace_info, struct auxtrace_info_event *auxtrace_info,
...@@ -272,7 +282,8 @@ static int intel_pt_info_fill(struct auxtrace_record *itr, ...@@ -272,7 +282,8 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
struct perf_event_mmap_page *pc; struct perf_event_mmap_page *pc;
struct perf_tsc_conversion tc = { .time_mult = 0, }; struct perf_tsc_conversion tc = { .time_mult = 0, };
bool cap_user_time_zero = false, per_cpu_mmaps; bool cap_user_time_zero = false, per_cpu_mmaps;
u64 tsc_bit, noretcomp_bit; u64 tsc_bit, mtc_bit, mtc_freq_bits, cyc_bit, noretcomp_bit;
u32 tsc_ctc_ratio_n, tsc_ctc_ratio_d;
int err; int err;
if (priv_size != INTEL_PT_AUXTRACE_PRIV_SIZE) if (priv_size != INTEL_PT_AUXTRACE_PRIV_SIZE)
...@@ -281,6 +292,12 @@ static int intel_pt_info_fill(struct auxtrace_record *itr, ...@@ -281,6 +292,12 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
intel_pt_parse_terms(&intel_pt_pmu->format, "tsc", &tsc_bit); intel_pt_parse_terms(&intel_pt_pmu->format, "tsc", &tsc_bit);
intel_pt_parse_terms(&intel_pt_pmu->format, "noretcomp", intel_pt_parse_terms(&intel_pt_pmu->format, "noretcomp",
&noretcomp_bit); &noretcomp_bit);
intel_pt_parse_terms(&intel_pt_pmu->format, "mtc", &mtc_bit);
mtc_freq_bits = perf_pmu__format_bits(&intel_pt_pmu->format,
"mtc_period");
intel_pt_parse_terms(&intel_pt_pmu->format, "cyc", &cyc_bit);
intel_pt_tsc_ctc_ratio(&tsc_ctc_ratio_n, &tsc_ctc_ratio_d);
if (!session->evlist->nr_mmaps) if (!session->evlist->nr_mmaps)
return -EINVAL; return -EINVAL;
...@@ -311,6 +328,11 @@ static int intel_pt_info_fill(struct auxtrace_record *itr, ...@@ -311,6 +328,11 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
auxtrace_info->priv[INTEL_PT_HAVE_SCHED_SWITCH] = ptr->have_sched_switch; auxtrace_info->priv[INTEL_PT_HAVE_SCHED_SWITCH] = ptr->have_sched_switch;
auxtrace_info->priv[INTEL_PT_SNAPSHOT_MODE] = ptr->snapshot_mode; auxtrace_info->priv[INTEL_PT_SNAPSHOT_MODE] = ptr->snapshot_mode;
auxtrace_info->priv[INTEL_PT_PER_CPU_MMAPS] = per_cpu_mmaps; auxtrace_info->priv[INTEL_PT_PER_CPU_MMAPS] = per_cpu_mmaps;
auxtrace_info->priv[INTEL_PT_MTC_BIT] = mtc_bit;
auxtrace_info->priv[INTEL_PT_MTC_FREQ_BITS] = mtc_freq_bits;
auxtrace_info->priv[INTEL_PT_TSC_CTC_N] = tsc_ctc_ratio_n;
auxtrace_info->priv[INTEL_PT_TSC_CTC_D] = tsc_ctc_ratio_d;
auxtrace_info->priv[INTEL_PT_CYC_BIT] = cyc_bit;
return 0; return 0;
} }
......
...@@ -87,6 +87,9 @@ struct intel_pt_params { ...@@ -87,6 +87,9 @@ struct intel_pt_params {
uint64_t period; uint64_t period;
enum intel_pt_period_type period_type; enum intel_pt_period_type period_type;
unsigned max_non_turbo_ratio; unsigned max_non_turbo_ratio;
unsigned int mtc_period;
uint32_t tsc_ctc_ratio_n;
uint32_t tsc_ctc_ratio_d;
}; };
struct intel_pt_decoder; struct intel_pt_decoder;
......
...@@ -91,6 +91,11 @@ struct intel_pt { ...@@ -91,6 +91,11 @@ struct intel_pt {
bool synth_needs_swap; bool synth_needs_swap;
u64 tsc_bit; u64 tsc_bit;
u64 mtc_bit;
u64 mtc_freq_bits;
u32 tsc_ctc_ratio_n;
u32 tsc_ctc_ratio_d;
u64 cyc_bit;
u64 noretcomp_bit; u64 noretcomp_bit;
unsigned max_non_turbo_ratio; unsigned max_non_turbo_ratio;
}; };
...@@ -568,6 +573,25 @@ static bool intel_pt_return_compression(struct intel_pt *pt) ...@@ -568,6 +573,25 @@ static bool intel_pt_return_compression(struct intel_pt *pt)
return true; return true;
} }
static unsigned int intel_pt_mtc_period(struct intel_pt *pt)
{
struct perf_evsel *evsel;
unsigned int shift;
u64 config;
if (!pt->mtc_freq_bits)
return 0;
for (shift = 0, config = pt->mtc_freq_bits; !(config & 1); shift++)
config >>= 1;
evlist__for_each(pt->session->evlist, evsel) {
if (intel_pt_get_config(pt, &evsel->attr, &config))
return (config & pt->mtc_freq_bits) >> shift;
}
return 0;
}
static bool intel_pt_timeless_decoding(struct intel_pt *pt) static bool intel_pt_timeless_decoding(struct intel_pt *pt)
{ {
struct perf_evsel *evsel; struct perf_evsel *evsel;
...@@ -668,6 +692,9 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt, ...@@ -668,6 +692,9 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
params.data = ptq; params.data = ptq;
params.return_compression = intel_pt_return_compression(pt); params.return_compression = intel_pt_return_compression(pt);
params.max_non_turbo_ratio = pt->max_non_turbo_ratio; params.max_non_turbo_ratio = pt->max_non_turbo_ratio;
params.mtc_period = intel_pt_mtc_period(pt);
params.tsc_ctc_ratio_n = pt->tsc_ctc_ratio_n;
params.tsc_ctc_ratio_d = pt->tsc_ctc_ratio_d;
if (pt->synth_opts.instructions) { if (pt->synth_opts.instructions) {
if (pt->synth_opts.period) { if (pt->synth_opts.period) {
...@@ -1751,16 +1778,20 @@ static struct perf_evsel *intel_pt_find_sched_switch(struct perf_evlist *evlist) ...@@ -1751,16 +1778,20 @@ static struct perf_evsel *intel_pt_find_sched_switch(struct perf_evlist *evlist)
} }
static const char * const intel_pt_info_fmts[] = { static const char * const intel_pt_info_fmts[] = {
[INTEL_PT_PMU_TYPE] = " PMU Type %"PRId64"\n", [INTEL_PT_PMU_TYPE] = " PMU Type %"PRId64"\n",
[INTEL_PT_TIME_SHIFT] = " Time Shift %"PRIu64"\n", [INTEL_PT_TIME_SHIFT] = " Time Shift %"PRIu64"\n",
[INTEL_PT_TIME_MULT] = " Time Muliplier %"PRIu64"\n", [INTEL_PT_TIME_MULT] = " Time Muliplier %"PRIu64"\n",
[INTEL_PT_TIME_ZERO] = " Time Zero %"PRIu64"\n", [INTEL_PT_TIME_ZERO] = " Time Zero %"PRIu64"\n",
[INTEL_PT_CAP_USER_TIME_ZERO] = " Cap Time Zero %"PRId64"\n", [INTEL_PT_CAP_USER_TIME_ZERO] = " Cap Time Zero %"PRId64"\n",
[INTEL_PT_TSC_BIT] = " TSC bit %#"PRIx64"\n", [INTEL_PT_TSC_BIT] = " TSC bit %#"PRIx64"\n",
[INTEL_PT_NORETCOMP_BIT] = " NoRETComp bit %#"PRIx64"\n", [INTEL_PT_NORETCOMP_BIT] = " NoRETComp bit %#"PRIx64"\n",
[INTEL_PT_HAVE_SCHED_SWITCH] = " Have sched_switch %"PRId64"\n", [INTEL_PT_HAVE_SCHED_SWITCH] = " Have sched_switch %"PRId64"\n",
[INTEL_PT_SNAPSHOT_MODE] = " Snapshot mode %"PRId64"\n", [INTEL_PT_SNAPSHOT_MODE] = " Snapshot mode %"PRId64"\n",
[INTEL_PT_PER_CPU_MMAPS] = " Per-cpu maps %"PRId64"\n", [INTEL_PT_PER_CPU_MMAPS] = " Per-cpu maps %"PRId64"\n",
[INTEL_PT_MTC_BIT] = " MTC bit %#"PRIx64"\n",
[INTEL_PT_TSC_CTC_N] = " TSC:CTC numerator %"PRIu64"\n",
[INTEL_PT_TSC_CTC_D] = " TSC:CTC denominator %"PRIu64"\n",
[INTEL_PT_CYC_BIT] = " CYC bit %#"PRIx64"\n",
}; };
static void intel_pt_print_info(u64 *arr, int start, int finish) static void intel_pt_print_info(u64 *arr, int start, int finish)
...@@ -1812,6 +1843,17 @@ int intel_pt_process_auxtrace_info(union perf_event *event, ...@@ -1812,6 +1843,17 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
intel_pt_print_info(&auxtrace_info->priv[0], INTEL_PT_PMU_TYPE, intel_pt_print_info(&auxtrace_info->priv[0], INTEL_PT_PMU_TYPE,
INTEL_PT_PER_CPU_MMAPS); INTEL_PT_PER_CPU_MMAPS);
if (auxtrace_info->header.size >= sizeof(struct auxtrace_info_event) +
(sizeof(u64) * INTEL_PT_CYC_BIT)) {
pt->mtc_bit = auxtrace_info->priv[INTEL_PT_MTC_BIT];
pt->mtc_freq_bits = auxtrace_info->priv[INTEL_PT_MTC_FREQ_BITS];
pt->tsc_ctc_ratio_n = auxtrace_info->priv[INTEL_PT_TSC_CTC_N];
pt->tsc_ctc_ratio_d = auxtrace_info->priv[INTEL_PT_TSC_CTC_D];
pt->cyc_bit = auxtrace_info->priv[INTEL_PT_CYC_BIT];
intel_pt_print_info(&auxtrace_info->priv[0], INTEL_PT_MTC_BIT,
INTEL_PT_CYC_BIT);
}
pt->timeless_decoding = intel_pt_timeless_decoding(pt); pt->timeless_decoding = intel_pt_timeless_decoding(pt);
pt->have_tsc = intel_pt_have_tsc(pt); pt->have_tsc = intel_pt_have_tsc(pt);
pt->sampling_mode = false; pt->sampling_mode = false;
......
...@@ -29,6 +29,11 @@ enum { ...@@ -29,6 +29,11 @@ enum {
INTEL_PT_HAVE_SCHED_SWITCH, INTEL_PT_HAVE_SCHED_SWITCH,
INTEL_PT_SNAPSHOT_MODE, INTEL_PT_SNAPSHOT_MODE,
INTEL_PT_PER_CPU_MMAPS, INTEL_PT_PER_CPU_MMAPS,
INTEL_PT_MTC_BIT,
INTEL_PT_MTC_FREQ_BITS,
INTEL_PT_TSC_CTC_N,
INTEL_PT_TSC_CTC_D,
INTEL_PT_CYC_BIT,
INTEL_PT_AUXTRACE_PRIV_MAX, INTEL_PT_AUXTRACE_PRIV_MAX,
}; };
......
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