mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
perf list: Give more details about raw event encodings
List all the PMUs, not just the first core one, and list real format specifiers with value ranges. Before: $ perf list ... rNNN [Raw hardware event descriptor] cpu/t1=v1[,t2=v2,t3 ...]/modifier [Raw hardware event descriptor] [(see 'man perf-list' on how to encode it)] mem:<addr>[/len][:access] [Hardware breakpoint] ... After: $ perf list ... rNNN [Raw event descriptor] cpu/event=0..255,pc,edge,.../modifier [Raw event descriptor] [(see 'man perf-list' or 'man perf-record' on how to encode it)] breakpoint//modifier [Raw event descriptor] cstate_core/event=0..0xffffffffffffffff/modifier [Raw event descriptor] cstate_pkg/event=0..0xffffffffffffffff/modifier [Raw event descriptor] i915/i915_eventid=0..0x1fffff/modifier [Raw event descriptor] intel_bts//modifier [Raw event descriptor] intel_pt/ptw,event,cyc_thresh=0..15,.../modifier [Raw event descriptor] kprobe/retprobe/modifier [Raw event descriptor] msr/event=0..0xffffffffffffffff/modifier [Raw event descriptor] power/event=0..255/modifier [Raw event descriptor] software//modifier [Raw event descriptor] tracepoint//modifier [Raw event descriptor] uncore_arb/event=0..255,edge,inv,.../modifier [Raw event descriptor] uncore_cbox/event=0..255,edge,inv,.../modifier [Raw event descriptor] uncore_clock/event=0..255/modifier [Raw event descriptor] uncore_imc_free_running/event=0..255,umask=0..255/modifier[Raw event descriptor] uprobe/ref_ctr_offset=0..0xffffffff,retprobe/modifier[Raw event descriptor] mem:<addr>[/len][:access] [Hardware breakpoint] ... With '--details' provide more details on the formats encoding: cpu/event=0..255,pc,edge,.../modifier [Raw event descriptor] [(see 'man perf-list' or 'man perf-record' on how to encode it)] cpu/event=0..255,pc,edge,offcore_rsp=0..0xffffffffffffffff,ldlat=0..0xffff,inv, umask=0..255,frontend=0..0xffffff,cmask=0..255,config=0..0xffffffffffffffff, config1=0..0xffffffffffffffff,config2=0..0xffffffffffffffff,config3=0..0xffffffffffffffff, name=string,period=number,freq=number,branch_type=(u|k|hv|any|...),time, call-graph=(fp|dwarf|lbr),stack-size=number,max-stack=number,nr=number,inherit,no-inherit, overwrite,no-overwrite,percore,aux-output,aux-sample-size=number/modifier breakpoint//modifier [Raw event descriptor] breakpoint//modifier cstate_core/event=0..0xffffffffffffffff/modifier [Raw event descriptor] cstate_core/event=0..0xffffffffffffffff/modifier cstate_pkg/event=0..0xffffffffffffffff/modifier [Raw event descriptor] cstate_pkg/event=0..0xffffffffffffffff/modifier i915/i915_eventid=0..0x1fffff/modifier [Raw event descriptor] i915/i915_eventid=0..0x1fffff/modifier intel_bts//modifier [Raw event descriptor] intel_bts//modifier intel_pt/ptw,event,cyc_thresh=0..15,.../modifier [Raw event descriptor] intel_pt/ptw,event,cyc_thresh=0..15,pt,notnt,branch,tsc,pwr_evt,fup_on_ptw,cyc,noretcomp, mtc,psb_period=0..15,mtc_period=0..15/modifier kprobe/retprobe/modifier [Raw event descriptor] kprobe/retprobe/modifier msr/event=0..0xffffffffffffffff/modifier [Raw event descriptor] msr/event=0..0xffffffffffffffff/modifier power/event=0..255/modifier [Raw event descriptor] power/event=0..255/modifier software//modifier [Raw event descriptor] software//modifier tracepoint//modifier [Raw event descriptor] tracepoint//modifier uncore_arb/event=0..255,edge,inv,.../modifier [Raw event descriptor] uncore_arb/event=0..255,edge,inv,umask=0..255,cmask=0..31/modifier uncore_cbox/event=0..255,edge,inv,.../modifier [Raw event descriptor] uncore_cbox/event=0..255,edge,inv,umask=0..255,cmask=0..31/modifier uncore_clock/event=0..255/modifier [Raw event descriptor] uncore_clock/event=0..255/modifier uncore_imc_free_running/event=0..255,umask=0..255/modifier[Raw event descriptor] uncore_imc_free_running/event=0..255,umask=0..255/modifier uprobe/ref_ctr_offset=0..0xffffffff,retprobe/modifier[Raw event descriptor] uprobe/ref_ctr_offset=0..0xffffffff,retprobe/modifier Committer notes: Address this build error in various distros: 55 58.44 ubuntu:24.04 : FAIL gcc version 13.2.0 (Ubuntu 13.2.0-17ubuntu2) util/pmu.c:1638:70: error: '_Static_assert' with no message is a C2x extension [-Werror,-Wc2x-extensions] 1638 | _Static_assert(ARRAY_SIZE(terms) == __PARSE_EVENTS__TERM_TYPE_NR - 6); | ^ | , "" 1 error generated. Signed-off-by: Ian Rogers <irogers@google.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Tested-by: Kan Liang <kan.liang@linux.intel.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: James Clark <james.clark@arm.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ravi Bangoria <ravi.bangoria@amd.com> Cc: Yang Jihong <yangjihong1@huawei.com> Link: https://lore.kernel.org/r/20240308001915.4060155-5-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
aa1f4ad287
commit
4ccf3bb703
5 changed files with 161 additions and 19 deletions
|
@ -1603,6 +1603,62 @@ bool perf_pmu__has_format(const struct perf_pmu *pmu, const char *name)
|
|||
return false;
|
||||
}
|
||||
|
||||
int perf_pmu__for_each_format(struct perf_pmu *pmu, void *state, pmu_format_callback cb)
|
||||
{
|
||||
static const char *const terms[] = {
|
||||
"config=0..0xffffffffffffffff",
|
||||
"config1=0..0xffffffffffffffff",
|
||||
"config2=0..0xffffffffffffffff",
|
||||
"config3=0..0xffffffffffffffff",
|
||||
"name=string",
|
||||
"period=number",
|
||||
"freq=number",
|
||||
"branch_type=(u|k|hv|any|...)",
|
||||
"time",
|
||||
"call-graph=(fp|dwarf|lbr)",
|
||||
"stack-size=number",
|
||||
"max-stack=number",
|
||||
"nr=number",
|
||||
"inherit",
|
||||
"no-inherit",
|
||||
"overwrite",
|
||||
"no-overwrite",
|
||||
"percore",
|
||||
"aux-output",
|
||||
"aux-sample-size=number",
|
||||
};
|
||||
struct perf_pmu_format *format;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* max-events and driver-config are missing above as are the internal
|
||||
* types user, metric-id, raw, legacy cache and hardware. Assert against
|
||||
* the enum parse_events__term_type so they are kept in sync.
|
||||
*/
|
||||
_Static_assert(ARRAY_SIZE(terms) == __PARSE_EVENTS__TERM_TYPE_NR - 6,
|
||||
"perf_pmu__for_each_format()'s terms must be kept in sync with enum parse_events__term_type");
|
||||
list_for_each_entry(format, &pmu->format, list) {
|
||||
perf_pmu_format__load(pmu, format);
|
||||
ret = cb(state, format->name, (int)format->value, format->bits);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (!pmu->is_core)
|
||||
return 0;
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(terms); i++) {
|
||||
int config = PERF_PMU_FORMAT_VALUE_CONFIG;
|
||||
|
||||
if (i < PERF_PMU_FORMAT_VALUE_CONFIG_END)
|
||||
config = i;
|
||||
|
||||
ret = cb(state, terms[i], config, /*bits=*/NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool is_pmu_core(const char *name)
|
||||
{
|
||||
return !strcmp(name, "cpu") || !strcmp(name, "cpum_cf") || is_sysfs_pmu_core(name);
|
||||
|
@ -1697,8 +1753,12 @@ int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus,
|
|||
pmu_add_cpu_aliases(pmu);
|
||||
list_for_each_entry(event, &pmu->aliases, list) {
|
||||
size_t buf_used;
|
||||
int pmu_name_len;
|
||||
|
||||
info.pmu_name = event->pmu_name ?: pmu->name;
|
||||
pmu_name_len = skip_duplicate_pmus
|
||||
? pmu_name_len_no_suffix(info.pmu_name, /*num=*/NULL)
|
||||
: (int)strlen(info.pmu_name);
|
||||
info.alias = NULL;
|
||||
if (event->desc) {
|
||||
info.name = event->name;
|
||||
|
@ -1723,7 +1783,7 @@ int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus,
|
|||
info.encoding_desc = buf + buf_used;
|
||||
parse_events_terms__to_strbuf(&event->terms, &sb);
|
||||
buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used,
|
||||
"%s/%s/", info.pmu_name, sb.buf) + 1;
|
||||
"%.*s/%s/", pmu_name_len, info.pmu_name, sb.buf) + 1;
|
||||
info.topic = event->topic;
|
||||
info.str = sb.buf;
|
||||
info.deprecated = event->deprecated;
|
||||
|
|
|
@ -196,6 +196,8 @@ struct pmu_event_info {
|
|||
};
|
||||
|
||||
typedef int (*pmu_event_callback)(void *state, struct pmu_event_info *info);
|
||||
typedef int (*pmu_format_callback)(void *state, const char *name, int config,
|
||||
const unsigned long *bits);
|
||||
|
||||
void pmu_add_sys_aliases(struct perf_pmu *pmu);
|
||||
int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
|
||||
|
@ -215,6 +217,7 @@ int perf_pmu__find_event(struct perf_pmu *pmu, const char *event, void *state, p
|
|||
int perf_pmu__format_parse(struct perf_pmu *pmu, int dirfd, bool eager_load);
|
||||
void perf_pmu_format__set_value(void *format, int config, unsigned long *bits);
|
||||
bool perf_pmu__has_format(const struct perf_pmu *pmu, const char *name);
|
||||
int perf_pmu__for_each_format(struct perf_pmu *pmu, void *state, pmu_format_callback cb);
|
||||
|
||||
bool is_pmu_core(const char *name);
|
||||
bool perf_pmu__supports_legacy_cache(const struct perf_pmu *pmu);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "pmus.h"
|
||||
#include "pmu.h"
|
||||
#include "print-events.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
/*
|
||||
* core_pmus: A PMU belongs to core_pmus if it's name is "cpu" or it's sysfs
|
||||
|
@ -503,6 +504,99 @@ void perf_pmus__print_pmu_events(const struct print_callbacks *print_cb, void *p
|
|||
zfree(&aliases);
|
||||
}
|
||||
|
||||
struct build_format_string_args {
|
||||
struct strbuf short_string;
|
||||
struct strbuf long_string;
|
||||
int num_formats;
|
||||
};
|
||||
|
||||
static int build_format_string(void *state, const char *name, int config,
|
||||
const unsigned long *bits)
|
||||
{
|
||||
struct build_format_string_args *args = state;
|
||||
unsigned int num_bits;
|
||||
int ret1, ret2 = 0;
|
||||
|
||||
(void)config;
|
||||
args->num_formats++;
|
||||
if (args->num_formats > 1) {
|
||||
strbuf_addch(&args->long_string, ',');
|
||||
if (args->num_formats < 4)
|
||||
strbuf_addch(&args->short_string, ',');
|
||||
}
|
||||
num_bits = bits ? bitmap_weight(bits, PERF_PMU_FORMAT_BITS) : 0;
|
||||
if (num_bits <= 1) {
|
||||
ret1 = strbuf_addf(&args->long_string, "%s", name);
|
||||
if (args->num_formats < 4)
|
||||
ret2 = strbuf_addf(&args->short_string, "%s", name);
|
||||
} else if (num_bits > 8) {
|
||||
ret1 = strbuf_addf(&args->long_string, "%s=0..0x%llx", name,
|
||||
ULLONG_MAX >> (64 - num_bits));
|
||||
if (args->num_formats < 4) {
|
||||
ret2 = strbuf_addf(&args->short_string, "%s=0..0x%llx", name,
|
||||
ULLONG_MAX >> (64 - num_bits));
|
||||
}
|
||||
} else {
|
||||
ret1 = strbuf_addf(&args->long_string, "%s=0..%llu", name,
|
||||
ULLONG_MAX >> (64 - num_bits));
|
||||
if (args->num_formats < 4) {
|
||||
ret2 = strbuf_addf(&args->short_string, "%s=0..%llu", name,
|
||||
ULLONG_MAX >> (64 - num_bits));
|
||||
}
|
||||
}
|
||||
return ret1 < 0 ? ret1 : (ret2 < 0 ? ret2 : 0);
|
||||
}
|
||||
|
||||
void perf_pmus__print_raw_pmu_events(const struct print_callbacks *print_cb, void *print_state)
|
||||
{
|
||||
bool skip_duplicate_pmus = print_cb->skip_duplicate_pmus(print_state);
|
||||
struct perf_pmu *(*scan_fn)(struct perf_pmu *);
|
||||
struct perf_pmu *pmu = NULL;
|
||||
|
||||
if (skip_duplicate_pmus)
|
||||
scan_fn = perf_pmus__scan_skip_duplicates;
|
||||
else
|
||||
scan_fn = perf_pmus__scan;
|
||||
|
||||
while ((pmu = scan_fn(pmu)) != NULL) {
|
||||
struct build_format_string_args format_args = {
|
||||
.short_string = STRBUF_INIT,
|
||||
.long_string = STRBUF_INIT,
|
||||
.num_formats = 0,
|
||||
};
|
||||
int len = pmu_name_len_no_suffix(pmu->name, /*num=*/NULL);
|
||||
const char *desc = "(see 'man perf-list' or 'man perf-record' on how to encode it)";
|
||||
|
||||
if (!pmu->is_core)
|
||||
desc = NULL;
|
||||
|
||||
strbuf_addf(&format_args.short_string, "%.*s/", len, pmu->name);
|
||||
strbuf_addf(&format_args.long_string, "%.*s/", len, pmu->name);
|
||||
perf_pmu__for_each_format(pmu, &format_args, build_format_string);
|
||||
|
||||
if (format_args.num_formats > 3)
|
||||
strbuf_addf(&format_args.short_string, ",.../modifier");
|
||||
else
|
||||
strbuf_addf(&format_args.short_string, "/modifier");
|
||||
|
||||
strbuf_addf(&format_args.long_string, "/modifier");
|
||||
print_cb->print_event(print_state,
|
||||
/*topic=*/NULL,
|
||||
/*pmu_name=*/NULL,
|
||||
format_args.short_string.buf,
|
||||
/*event_alias=*/NULL,
|
||||
/*scale_unit=*/NULL,
|
||||
/*deprecated=*/false,
|
||||
"Raw event descriptor",
|
||||
desc,
|
||||
/*long_desc=*/NULL,
|
||||
format_args.long_string.buf);
|
||||
|
||||
strbuf_release(&format_args.short_string);
|
||||
strbuf_release(&format_args.long_string);
|
||||
}
|
||||
}
|
||||
|
||||
bool perf_pmus__have_event(const char *pname, const char *name)
|
||||
{
|
||||
struct perf_pmu *pmu = perf_pmus__find(pname);
|
||||
|
|
|
@ -18,6 +18,7 @@ struct perf_pmu *perf_pmus__scan_core(struct perf_pmu *pmu);
|
|||
const struct perf_pmu *perf_pmus__pmu_for_pmu_filter(const char *str);
|
||||
|
||||
void perf_pmus__print_pmu_events(const struct print_callbacks *print_cb, void *print_state);
|
||||
void perf_pmus__print_raw_pmu_events(const struct print_callbacks *print_cb, void *print_state);
|
||||
bool perf_pmus__have_event(const char *pname, const char *name);
|
||||
int perf_pmus__num_core_pmus(void);
|
||||
bool perf_pmus__supports_extended_type(void);
|
||||
|
|
|
@ -39,7 +39,7 @@ static const char * const event_type_descriptors[] = {
|
|||
"Software event",
|
||||
"Tracepoint event",
|
||||
"Hardware cache event",
|
||||
"Raw hardware event descriptor",
|
||||
"Raw event descriptor",
|
||||
"Hardware breakpoint",
|
||||
};
|
||||
|
||||
|
@ -416,8 +416,6 @@ void print_symbol_events(const struct print_callbacks *print_cb, void *print_sta
|
|||
*/
|
||||
void print_events(const struct print_callbacks *print_cb, void *print_state)
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
print_symbol_events(print_cb, print_state, PERF_TYPE_HARDWARE,
|
||||
event_symbols_hw, PERF_COUNT_HW_MAX);
|
||||
print_symbol_events(print_cb, print_state, PERF_TYPE_SOFTWARE,
|
||||
|
@ -441,21 +439,7 @@ void print_events(const struct print_callbacks *print_cb, void *print_state)
|
|||
/*long_desc=*/NULL,
|
||||
/*encoding_desc=*/NULL);
|
||||
|
||||
if (asprintf(&tmp, "%s/t1=v1[,t2=v2,t3 ...]/modifier",
|
||||
perf_pmus__scan_core(/*pmu=*/NULL)->name) > 0) {
|
||||
print_cb->print_event(print_state,
|
||||
/*topic=*/NULL,
|
||||
/*pmu_name=*/NULL,
|
||||
tmp,
|
||||
/*event_alias=*/NULL,
|
||||
/*scale_unit=*/NULL,
|
||||
/*deprecated=*/false,
|
||||
event_type_descriptors[PERF_TYPE_RAW],
|
||||
"(see 'man perf-list' on how to encode it)",
|
||||
/*long_desc=*/NULL,
|
||||
/*encoding_desc=*/NULL);
|
||||
free(tmp);
|
||||
}
|
||||
perf_pmus__print_raw_pmu_events(print_cb, print_state);
|
||||
|
||||
print_cb->print_event(print_state,
|
||||
/*topic=*/NULL,
|
||||
|
|
Loading…
Reference in a new issue