2023-06-12 15:16 UTC+0000 ~ Yafang Shao <laoar.shao@xxxxxxxxx> > Add new functions and macros to get perf event names. These names are > copied from tool/perf/util/{parse-events,evsel}.c, so that in the future we > will have a good chance to use the same code. > > Suggested-by: Jiri Olsa <olsajiri@xxxxxxxxx> > Signed-off-by: Yafang Shao <laoar.shao@xxxxxxxxx> > --- > tools/bpf/bpftool/perf.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++ > tools/bpf/bpftool/perf.h | 11 +++++ Although the names are deceiving, I think these should all be moved to link.c and link.h, where we'll actually use them, or to some other file with a new name. File perf.c is for implementing "bpftool perf ...". > 2 files changed, 118 insertions(+) > create mode 100644 tools/bpf/bpftool/perf.h > > diff --git a/tools/bpf/bpftool/perf.c b/tools/bpf/bpftool/perf.c > index 9174344..fbdf88c 100644 > --- a/tools/bpf/bpftool/perf.c > +++ b/tools/bpf/bpftool/perf.c > @@ -18,6 +18,113 @@ > #include <bpf/bpf.h> > > #include "main.h" > +#include "perf.h" > + > +static const char *perf_type_name[PERF_TYPE_MAX] = { > + [PERF_TYPE_HARDWARE] = "hardware", > + [PERF_TYPE_SOFTWARE] = "software", > + [PERF_TYPE_TRACEPOINT] = "tracepoint", > + [PERF_TYPE_HW_CACHE] = "hw-cache", > + [PERF_TYPE_RAW] = "raw", > + [PERF_TYPE_BREAKPOINT] = "breakpoint", > +}; > + > +const char *event_symbols_hw[PERF_COUNT_HW_MAX] = { > + [PERF_COUNT_HW_CPU_CYCLES] = "cpu-cycles", > + [PERF_COUNT_HW_INSTRUCTIONS] = "instructions", > + [PERF_COUNT_HW_CACHE_REFERENCES] = "cache-references", > + [PERF_COUNT_HW_CACHE_MISSES] = "cache-misses", > + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = "branch-instructions", > + [PERF_COUNT_HW_BRANCH_MISSES] = "branch-misses", > + [PERF_COUNT_HW_BUS_CYCLES] = "bus-cycles", > + [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = "stalled-cycles-frontend", > + [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = "stalled-cycles-backend", > + [PERF_COUNT_HW_REF_CPU_CYCLES] = "ref-cycles", > +}; > + > +const char *event_symbols_sw[PERF_COUNT_SW_MAX] = { > + [PERF_COUNT_SW_CPU_CLOCK] = "cpu-clock", > + [PERF_COUNT_SW_TASK_CLOCK] = "task-clock", > + [PERF_COUNT_SW_PAGE_FAULTS] = "page-faults", > + [PERF_COUNT_SW_CONTEXT_SWITCHES] = "context-switches", > + [PERF_COUNT_SW_CPU_MIGRATIONS] = "cpu-migrations", > + [PERF_COUNT_SW_PAGE_FAULTS_MIN] = "minor-faults", > + [PERF_COUNT_SW_PAGE_FAULTS_MAJ] = "major-faults", > + [PERF_COUNT_SW_ALIGNMENT_FAULTS] = "alignment-faults", > + [PERF_COUNT_SW_EMULATION_FAULTS] = "emulation-faults", > + [PERF_COUNT_SW_DUMMY] = "dummy", > + [PERF_COUNT_SW_BPF_OUTPUT] = "bpf-output", > + [PERF_COUNT_SW_CGROUP_SWITCHES] = "cgroup-switches", > +}; > + > +const char *evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX] = { > + [PERF_COUNT_HW_CACHE_L1D] = "L1-dcache", > + [PERF_COUNT_HW_CACHE_L1I] = "L1-icache", > + [PERF_COUNT_HW_CACHE_LL] = "LLC", > + [PERF_COUNT_HW_CACHE_DTLB] = "dTLB", > + [PERF_COUNT_HW_CACHE_ITLB] = "iTLB", > + [PERF_COUNT_HW_CACHE_BPU] = "branch", > + [PERF_COUNT_HW_CACHE_NODE] = "node", > +}; > + > +const char *evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX] = { > + [PERF_COUNT_HW_CACHE_OP_READ] = "load", > + [PERF_COUNT_HW_CACHE_OP_WRITE] = "store", > + [PERF_COUNT_HW_CACHE_OP_PREFETCH] = "prefetch", > +}; > + > +const char *evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX] = { > + [PERF_COUNT_HW_CACHE_RESULT_ACCESS] = "refs", > + [PERF_COUNT_HW_CACHE_RESULT_MISS] = "misses", > +}; > + > +const char *perf_type_str(enum perf_type_id t) > +{ > + if (t < 0 || t >= ARRAY_SIZE(perf_type_name)) > + return NULL; > + > + return perf_type_name[t]; > +} > + > +const char *perf_hw_str(enum perf_hw_id t) > +{ > + if (t < 0 || t >= ARRAY_SIZE(event_symbols_hw)) > + return NULL; > + > + return event_symbols_hw[t]; > +} > + > +const char *perf_hw_cache_str(enum perf_hw_cache_id t) > +{ > + if (t < 0 || t >= ARRAY_SIZE(evsel__hw_cache)) > + return NULL; > + > + return evsel__hw_cache[t]; > +} > + > +const char *perf_hw_cache_op_str(enum perf_hw_cache_op_id t) > +{ > + if (t < 0 || t >= ARRAY_SIZE(evsel__hw_cache_op)) > + return NULL; > + > + return evsel__hw_cache_op[t]; > +} > + > +const char *perf_hw_cache_op_result_str(enum perf_hw_cache_op_result_id t) > +{ > + if (t < 0 || t >= ARRAY_SIZE(evsel__hw_cache_result)) > + return NULL; > + > + return evsel__hw_cache_result[t]; > +} > + > +const char *perf_sw_str(enum perf_sw_ids t) > +{ > + if (t < 0 || t >= ARRAY_SIZE(event_symbols_sw)) > + return NULL; > + > + return event_symbols_sw[t]; > +} > > /* 0: undecided, 1: supported, 2: not supported */ > static int perf_query_supported; > diff --git a/tools/bpf/bpftool/perf.h b/tools/bpf/bpftool/perf.h > new file mode 100644 > index 0000000..3fd7e42 > --- /dev/null > +++ b/tools/bpf/bpftool/perf.h > @@ -0,0 +1,11 @@ > +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ > +/* Copyright (C) 2023 Yafang Shao <laoar.shao@xxxxxxxxx> */ > + > +#include <linux/perf_event.h> > + > +const char *perf_type_str(enum perf_type_id t); > +const char *perf_hw_str(enum perf_hw_id t); > +const char *perf_hw_cache_str(enum perf_hw_cache_id t); > +const char *perf_hw_cache_op_str(enum perf_hw_cache_op_id t); > +const char *perf_hw_cache_op_result_str(enum perf_hw_cache_op_result_id t); > +const char *perf_sw_str(enum perf_sw_ids t); I'm not sure we need all these API functions if we keep the arrays in bpftool. I'd probably have just a generic one and pass it the name of the relevant array in argument. Although I've got no objection with the current form if it helps unifying the code with perf in the future.