* [PATCH v2 1/3] perf list: Print matching PMU events for --unit
@ 2025-11-20 0:47 Namhyung Kim
2025-11-20 0:47 ` [PATCH v2 2/3] perf list: Share print state with JSON output Namhyung Kim
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Namhyung Kim @ 2025-11-20 0:47 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo, Ian Rogers, James Clark
Cc: Jiri Olsa, Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
linux-perf-users
When --unit option is used, pmu_glob is set to the argument. It should
match with event PMU and display the matching ones only. But it also
shows raw events and metrics after that.
$ perf list --unit tool
List of pre-defined events (to be used in -e or -M):
tool:
core_wide
[1 if not SMT,if SMT are events being gathered on all SMT threads 1 otherwise 0. Unit: tool]
duration_time
[Wall clock interval time in nanoseconds. Unit: tool]
has_pmem
[1 if persistent memory installed otherwise 0. Unit: tool]
num_cores
[Number of cores. A core consists of 1 or more thread,with each thread being associated with a logical Linux CPU. Unit: tool]
num_cpus
[Number of logical Linux CPUs. There may be multiple such CPUs on a core. Unit: tool]
...
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]
drm_i915//modifier [Raw event descriptor]
hwmon_acpitz//modifier [Raw event descriptor]
hwmon_ac//modifier [Raw event descriptor]
hwmon_bat0//modifier [Raw event descriptor]
hwmon_coretemp//modifier [Raw event descriptor]
...
Metric Groups:
Backend: [Grouping from Top-down Microarchitecture Analysis Metrics spreadsheet]
tma_core_bound
[This metric represents fraction of slots where Core non-memory issues were of a bottleneck]
tma_info_core_ilp
[Instruction-Level-Parallelism (average number of uops executed when there is execution) per thread (logical-processor)]
tma_info_memory_l2mpki
[L2 cache true misses per kilo instruction for retired demand loads]
...
This change makes it print the tool PMU events only.
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/builtin-list.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index 16400366f8276a7a..28bf1fc7f5eeff8f 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -130,7 +130,7 @@ static void default_print_event(void *ps, const char *topic,
if (deprecated && !print_state->deprecated)
return;
- if (print_state->pmu_glob && pmu_name && !strglobmatch(pmu_name, print_state->pmu_glob))
+ if (print_state->pmu_glob && (!pmu_name || !strglobmatch(pmu_name, print_state->pmu_glob)))
return;
if (print_state->exclude_abi && pmu_type < PERF_TYPE_MAX && pmu_type != PERF_TYPE_RAW)
@@ -612,8 +612,10 @@ int cmd_list(int argc, const char **argv)
print_cb.print_start(ps);
if (argc == 0) {
- default_ps.metrics = true;
- default_ps.metricgroups = true;
+ if (!unit_name) {
+ default_ps.metrics = true;
+ default_ps.metricgroups = true;
+ }
print_events(&print_cb, ps);
goto out;
}
--
2.52.0.rc1.455.g30608eb744-goog
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 2/3] perf list: Share print state with JSON output
2025-11-20 0:47 [PATCH v2 1/3] perf list: Print matching PMU events for --unit Namhyung Kim
@ 2025-11-20 0:47 ` Namhyung Kim
2025-11-20 5:30 ` Ian Rogers
2025-11-20 0:47 ` [PATCH v2 3/3] perf list: Support filtering in " Namhyung Kim
2025-11-21 20:02 ` [PATCH v2 1/3] perf list: Print matching PMU events for --unit Namhyung Kim
2 siblings, 1 reply; 7+ messages in thread
From: Namhyung Kim @ 2025-11-20 0:47 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo, Ian Rogers, James Clark
Cc: Jiri Olsa, Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
linux-perf-users
The JSON print state has only one different field (need_sep). Let's
add the default print state to the json state and use it. Then we can
use the 'ps' variable to update the state properly.
This is a preparation for the next commit.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/builtin-list.c | 127 +++++++++++++++++++-------------------
1 file changed, 65 insertions(+), 62 deletions(-)
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index 28bf1fc7f5eeff8f..6c5913f129f39c94 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -283,8 +283,8 @@ static void default_print_metric(void *ps,
}
struct json_print_state {
- /** @fp: File to write output to. */
- FILE *fp;
+ /** The shared print_state */
+ struct print_state common;
/** Should a separator be printed prior to the next item? */
bool need_sep;
};
@@ -292,7 +292,7 @@ struct json_print_state {
static void json_print_start(void *ps)
{
struct json_print_state *print_state = ps;
- FILE *fp = print_state->fp;
+ FILE *fp = print_state->common.fp;
fprintf(fp, "[\n");
}
@@ -300,7 +300,7 @@ static void json_print_start(void *ps)
static void json_print_end(void *ps)
{
struct json_print_state *print_state = ps;
- FILE *fp = print_state->fp;
+ FILE *fp = print_state->common.fp;
fprintf(fp, "%s]\n", print_state->need_sep ? "\n" : "");
}
@@ -370,7 +370,7 @@ static void json_print_event(void *ps, const char *topic,
{
struct json_print_state *print_state = ps;
bool need_sep = false;
- FILE *fp = print_state->fp;
+ FILE *fp = print_state->common.fp;
struct strbuf buf;
strbuf_init(&buf, 0);
@@ -446,7 +446,7 @@ static void json_print_metric(void *ps __maybe_unused, const char *group,
{
struct json_print_state *print_state = ps;
bool need_sep = false;
- FILE *fp = print_state->fp;
+ FILE *fp = print_state->common.fp;
struct strbuf buf;
strbuf_init(&buf, 0);
@@ -521,10 +521,12 @@ int cmd_list(int argc, const char **argv)
.fp = stdout,
.desc = true,
};
- struct print_state json_ps = {
- .fp = stdout,
+ struct json_print_state json_ps = {
+ .common = {
+ .fp = stdout,
+ },
};
- void *ps = &default_ps;
+ struct print_state *ps = &default_ps;
struct print_callbacks print_cb = {
.print_start = default_print_start,
.print_end = default_print_end,
@@ -572,9 +574,11 @@ int cmd_list(int argc, const char **argv)
argc = parse_options(argc, argv, list_options, list_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
+ if (json)
+ ps = &json_ps.common;
+
if (output_path) {
- default_ps.fp = fopen(output_path, "w");
- json_ps.fp = default_ps.fp;
+ ps->fp = fopen(output_path, "w");
}
setup_pager();
@@ -590,14 +594,13 @@ int cmd_list(int argc, const char **argv)
.print_metric = json_print_metric,
.skip_duplicate_pmus = json_skip_duplicate_pmus,
};
- ps = &json_ps;
} else {
- default_ps.last_topic = strdup("");
- assert(default_ps.last_topic);
- default_ps.visited_metrics = strlist__new(NULL, NULL);
- assert(default_ps.visited_metrics);
+ ps->last_topic = strdup("");
+ assert(ps->last_topic);
+ ps->visited_metrics = strlist__new(NULL, NULL);
+ assert(ps->visited_metrics);
if (unit_name)
- default_ps.pmu_glob = strdup(unit_name);
+ ps->pmu_glob = strdup(unit_name);
else if (cputype) {
const struct perf_pmu *pmu = perf_pmus__pmu_for_pmu_filter(cputype);
@@ -606,15 +609,15 @@ int cmd_list(int argc, const char **argv)
ret = -1;
goto out;
}
- default_ps.pmu_glob = strdup(pmu->name);
+ ps->pmu_glob = strdup(pmu->name);
}
}
print_cb.print_start(ps);
if (argc == 0) {
if (!unit_name) {
- default_ps.metrics = true;
- default_ps.metricgroups = true;
+ ps->metrics = true;
+ ps->metricgroups = true;
}
print_events(&print_cb, ps);
goto out;
@@ -636,57 +639,57 @@ int cmd_list(int argc, const char **argv)
default_ps.pmu_glob = old_pmu_glob;
} else if (strcmp(argv[i], "hw") == 0 ||
strcmp(argv[i], "hardware") == 0) {
- char *old_event_glob = default_ps.event_glob;
+ char *old_event_glob = ps->event_glob;
- default_ps.event_glob = strdup("legacy hardware");
- if (!default_ps.event_glob) {
+ ps->event_glob = strdup("legacy hardware");
+ if (!ps->event_glob) {
ret = -1;
goto out;
}
perf_pmus__print_pmu_events(&print_cb, ps);
- zfree(&default_ps.event_glob);
- default_ps.event_glob = old_event_glob;
+ zfree(&ps->event_glob);
+ ps->event_glob = old_event_glob;
} else if (strcmp(argv[i], "sw") == 0 ||
strcmp(argv[i], "software") == 0) {
- char *old_pmu_glob = default_ps.pmu_glob;
+ char *old_pmu_glob = ps->pmu_glob;
static const char * const sw_globs[] = { "software", "tool" };
for (size_t j = 0; j < ARRAY_SIZE(sw_globs); j++) {
- default_ps.pmu_glob = strdup(sw_globs[j]);
- if (!default_ps.pmu_glob) {
+ ps->pmu_glob = strdup(sw_globs[j]);
+ if (!ps->pmu_glob) {
ret = -1;
goto out;
}
perf_pmus__print_pmu_events(&print_cb, ps);
- zfree(&default_ps.pmu_glob);
+ zfree(&ps->pmu_glob);
}
- default_ps.pmu_glob = old_pmu_glob;
+ ps->pmu_glob = old_pmu_glob;
} else if (strcmp(argv[i], "cache") == 0 ||
strcmp(argv[i], "hwcache") == 0) {
- char *old_event_glob = default_ps.event_glob;
+ char *old_event_glob = ps->event_glob;
- default_ps.event_glob = strdup("legacy cache");
- if (!default_ps.event_glob) {
+ ps->event_glob = strdup("legacy cache");
+ if (!ps->event_glob) {
ret = -1;
goto out;
}
perf_pmus__print_pmu_events(&print_cb, ps);
- zfree(&default_ps.event_glob);
- default_ps.event_glob = old_event_glob;
+ zfree(&ps->event_glob);
+ ps->event_glob = old_event_glob;
} else if (strcmp(argv[i], "pmu") == 0) {
- default_ps.exclude_abi = true;
+ ps->exclude_abi = true;
perf_pmus__print_pmu_events(&print_cb, ps);
- default_ps.exclude_abi = false;
+ ps->exclude_abi = false;
} else if (strcmp(argv[i], "sdt") == 0)
print_sdt_events(&print_cb, ps);
else if (strcmp(argv[i], "metric") == 0 || strcmp(argv[i], "metrics") == 0) {
- default_ps.metricgroups = false;
- default_ps.metrics = true;
+ ps->metricgroups = false;
+ ps->metrics = true;
metricgroup__print(&print_cb, ps);
} else if (strcmp(argv[i], "metricgroup") == 0 ||
strcmp(argv[i], "metricgroups") == 0) {
- default_ps.metricgroups = true;
- default_ps.metrics = false;
+ ps->metricgroups = true;
+ ps->metrics = false;
metricgroup__print(&print_cb, ps);
}
#ifdef HAVE_LIBPFM
@@ -694,40 +697,40 @@ int cmd_list(int argc, const char **argv)
print_libpfm_events(&print_cb, ps);
#endif
else if ((sep = strchr(argv[i], ':')) != NULL) {
- char *old_pmu_glob = default_ps.pmu_glob;
- char *old_event_glob = default_ps.event_glob;
+ char *old_pmu_glob = ps->pmu_glob;
+ char *old_event_glob = ps->event_glob;
- default_ps.event_glob = strdup(argv[i]);
- if (!default_ps.event_glob) {
+ ps->event_glob = strdup(argv[i]);
+ if (!ps->event_glob) {
ret = -1;
goto out;
}
- default_ps.pmu_glob = strdup("tracepoint");
- if (!default_ps.pmu_glob) {
- zfree(&default_ps.event_glob);
+ ps->pmu_glob = strdup("tracepoint");
+ if (!ps->pmu_glob) {
+ zfree(&ps->event_glob);
ret = -1;
goto out;
}
perf_pmus__print_pmu_events(&print_cb, ps);
- zfree(&default_ps.pmu_glob);
- default_ps.pmu_glob = old_pmu_glob;
+ zfree(&ps->pmu_glob);
+ ps->pmu_glob = old_pmu_glob;
print_sdt_events(&print_cb, ps);
- default_ps.metrics = true;
- default_ps.metricgroups = true;
+ ps->metrics = true;
+ ps->metricgroups = true;
metricgroup__print(&print_cb, ps);
- zfree(&default_ps.event_glob);
- default_ps.event_glob = old_event_glob;
+ zfree(&ps->event_glob);
+ ps->event_glob = old_event_glob;
} else {
if (asprintf(&s, "*%s*", argv[i]) < 0) {
printf("Critical: Not enough memory! Trying to continue...\n");
continue;
}
- default_ps.event_glob = s;
+ ps->event_glob = s;
perf_pmus__print_pmu_events(&print_cb, ps);
print_sdt_events(&print_cb, ps);
- default_ps.metrics = true;
- default_ps.metricgroups = true;
+ ps->metrics = true;
+ ps->metricgroups = true;
metricgroup__print(&print_cb, ps);
free(s);
}
@@ -735,12 +738,12 @@ int cmd_list(int argc, const char **argv)
out:
print_cb.print_end(ps);
- free(default_ps.pmu_glob);
- free(default_ps.last_topic);
- free(default_ps.last_metricgroups);
- strlist__delete(default_ps.visited_metrics);
+ free(ps->pmu_glob);
+ free(ps->last_topic);
+ free(ps->last_metricgroups);
+ strlist__delete(ps->visited_metrics);
if (output_path)
- fclose(default_ps.fp);
+ fclose(ps->fp);
return ret;
}
--
2.52.0.rc1.455.g30608eb744-goog
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 3/3] perf list: Support filtering in JSON output
2025-11-20 0:47 [PATCH v2 1/3] perf list: Print matching PMU events for --unit Namhyung Kim
2025-11-20 0:47 ` [PATCH v2 2/3] perf list: Share print state with JSON output Namhyung Kim
@ 2025-11-20 0:47 ` Namhyung Kim
2025-11-20 5:42 ` Ian Rogers
2025-11-21 20:02 ` [PATCH v2 1/3] perf list: Print matching PMU events for --unit Namhyung Kim
2 siblings, 1 reply; 7+ messages in thread
From: Namhyung Kim @ 2025-11-20 0:47 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo, Ian Rogers, James Clark
Cc: Jiri Olsa, Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
linux-perf-users
Like regular output mode, it should honor command line arguments to
limit to a certain type of PMUs or events.
$ perf list -j hw
[
{
"Unit": "cpu",
"Topic": "legacy hardware",
"EventName": "branch-instructions",
"EventType": "Kernel PMU event",
"BriefDescription": "Retired branch instructions [This event is an alias of branches]",
"Encoding": "cpu/event=0xc4\n/"
},
{
"Unit": "cpu",
"Topic": "legacy hardware",
"EventName": "branch-misses",
"EventType": "Kernel PMU event",
"BriefDescription": "Mispredicted branch instructions",
"Encoding": "cpu/event=0xc5\n/"
},
...
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/builtin-list.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index 6c5913f129f39c94..5cbca0bacd35237e 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -373,6 +373,23 @@ static void json_print_event(void *ps, const char *topic,
FILE *fp = print_state->common.fp;
struct strbuf buf;
+ if (deprecated && !print_state->common.deprecated)
+ return;
+
+ if (print_state->common.pmu_glob &&
+ (!pmu_name || !strglobmatch(pmu_name, print_state->common.pmu_glob)))
+ return;
+
+ if (print_state->common.exclude_abi && pmu_type < PERF_TYPE_MAX &&
+ pmu_type != PERF_TYPE_RAW)
+ return;
+
+ if (print_state->common.event_glob &&
+ (!event_name || !strglobmatch(event_name, print_state->common.event_glob)) &&
+ (!event_alias || !strglobmatch(event_alias, print_state->common.event_glob)) &&
+ (!topic || !strglobmatch_nocase(topic, print_state->common.event_glob)))
+ return;
+
strbuf_init(&buf, 0);
fprintf(fp, "%s{\n", print_state->need_sep ? ",\n" : "");
print_state->need_sep = true;
@@ -449,6 +466,13 @@ static void json_print_metric(void *ps __maybe_unused, const char *group,
FILE *fp = print_state->common.fp;
struct strbuf buf;
+ if (print_state->common.event_glob &&
+ (!print_state->common.metrics || !name ||
+ !strglobmatch(name, print_state->common.event_glob)) &&
+ (!print_state->common.metricgroups || !group ||
+ !strglobmatch(group, print_state->common.event_glob)))
+ return;
+
strbuf_init(&buf, 0);
fprintf(fp, "%s{\n", print_state->need_sep ? ",\n" : "");
print_state->need_sep = true;
--
2.52.0.rc1.455.g30608eb744-goog
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2 2/3] perf list: Share print state with JSON output
2025-11-20 0:47 ` [PATCH v2 2/3] perf list: Share print state with JSON output Namhyung Kim
@ 2025-11-20 5:30 ` Ian Rogers
0 siblings, 0 replies; 7+ messages in thread
From: Ian Rogers @ 2025-11-20 5:30 UTC (permalink / raw)
To: Namhyung Kim
Cc: Arnaldo Carvalho de Melo, James Clark, Jiri Olsa, Adrian Hunter,
Peter Zijlstra, Ingo Molnar, LKML, linux-perf-users
On Wed, Nov 19, 2025 at 4:47 PM Namhyung Kim <namhyung@kernel.org> wrote:
>
> The JSON print state has only one different field (need_sep). Let's
> add the default print state to the json state and use it. Then we can
> use the 'ps' variable to update the state properly.
>
> This is a preparation for the next commit.
>
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Reviewed-by: Ian Rogers <irogers@google.com>
Thanks,
Ian
> ---
> tools/perf/builtin-list.c | 127 +++++++++++++++++++-------------------
> 1 file changed, 65 insertions(+), 62 deletions(-)
>
> diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
> index 28bf1fc7f5eeff8f..6c5913f129f39c94 100644
> --- a/tools/perf/builtin-list.c
> +++ b/tools/perf/builtin-list.c
> @@ -283,8 +283,8 @@ static void default_print_metric(void *ps,
> }
>
> struct json_print_state {
> - /** @fp: File to write output to. */
> - FILE *fp;
> + /** The shared print_state */
> + struct print_state common;
> /** Should a separator be printed prior to the next item? */
> bool need_sep;
> };
> @@ -292,7 +292,7 @@ struct json_print_state {
> static void json_print_start(void *ps)
> {
> struct json_print_state *print_state = ps;
> - FILE *fp = print_state->fp;
> + FILE *fp = print_state->common.fp;
>
> fprintf(fp, "[\n");
> }
> @@ -300,7 +300,7 @@ static void json_print_start(void *ps)
> static void json_print_end(void *ps)
> {
> struct json_print_state *print_state = ps;
> - FILE *fp = print_state->fp;
> + FILE *fp = print_state->common.fp;
>
> fprintf(fp, "%s]\n", print_state->need_sep ? "\n" : "");
> }
> @@ -370,7 +370,7 @@ static void json_print_event(void *ps, const char *topic,
> {
> struct json_print_state *print_state = ps;
> bool need_sep = false;
> - FILE *fp = print_state->fp;
> + FILE *fp = print_state->common.fp;
> struct strbuf buf;
>
> strbuf_init(&buf, 0);
> @@ -446,7 +446,7 @@ static void json_print_metric(void *ps __maybe_unused, const char *group,
> {
> struct json_print_state *print_state = ps;
> bool need_sep = false;
> - FILE *fp = print_state->fp;
> + FILE *fp = print_state->common.fp;
> struct strbuf buf;
>
> strbuf_init(&buf, 0);
> @@ -521,10 +521,12 @@ int cmd_list(int argc, const char **argv)
> .fp = stdout,
> .desc = true,
> };
> - struct print_state json_ps = {
> - .fp = stdout,
> + struct json_print_state json_ps = {
> + .common = {
> + .fp = stdout,
> + },
> };
> - void *ps = &default_ps;
> + struct print_state *ps = &default_ps;
> struct print_callbacks print_cb = {
> .print_start = default_print_start,
> .print_end = default_print_end,
> @@ -572,9 +574,11 @@ int cmd_list(int argc, const char **argv)
> argc = parse_options(argc, argv, list_options, list_usage,
> PARSE_OPT_STOP_AT_NON_OPTION);
>
> + if (json)
> + ps = &json_ps.common;
> +
> if (output_path) {
> - default_ps.fp = fopen(output_path, "w");
> - json_ps.fp = default_ps.fp;
> + ps->fp = fopen(output_path, "w");
> }
>
> setup_pager();
> @@ -590,14 +594,13 @@ int cmd_list(int argc, const char **argv)
> .print_metric = json_print_metric,
> .skip_duplicate_pmus = json_skip_duplicate_pmus,
> };
> - ps = &json_ps;
> } else {
> - default_ps.last_topic = strdup("");
> - assert(default_ps.last_topic);
> - default_ps.visited_metrics = strlist__new(NULL, NULL);
> - assert(default_ps.visited_metrics);
> + ps->last_topic = strdup("");
> + assert(ps->last_topic);
> + ps->visited_metrics = strlist__new(NULL, NULL);
> + assert(ps->visited_metrics);
> if (unit_name)
> - default_ps.pmu_glob = strdup(unit_name);
> + ps->pmu_glob = strdup(unit_name);
> else if (cputype) {
> const struct perf_pmu *pmu = perf_pmus__pmu_for_pmu_filter(cputype);
>
> @@ -606,15 +609,15 @@ int cmd_list(int argc, const char **argv)
> ret = -1;
> goto out;
> }
> - default_ps.pmu_glob = strdup(pmu->name);
> + ps->pmu_glob = strdup(pmu->name);
> }
> }
> print_cb.print_start(ps);
>
> if (argc == 0) {
> if (!unit_name) {
> - default_ps.metrics = true;
> - default_ps.metricgroups = true;
> + ps->metrics = true;
> + ps->metricgroups = true;
> }
> print_events(&print_cb, ps);
> goto out;
> @@ -636,57 +639,57 @@ int cmd_list(int argc, const char **argv)
> default_ps.pmu_glob = old_pmu_glob;
> } else if (strcmp(argv[i], "hw") == 0 ||
> strcmp(argv[i], "hardware") == 0) {
> - char *old_event_glob = default_ps.event_glob;
> + char *old_event_glob = ps->event_glob;
>
> - default_ps.event_glob = strdup("legacy hardware");
> - if (!default_ps.event_glob) {
> + ps->event_glob = strdup("legacy hardware");
> + if (!ps->event_glob) {
> ret = -1;
> goto out;
> }
> perf_pmus__print_pmu_events(&print_cb, ps);
> - zfree(&default_ps.event_glob);
> - default_ps.event_glob = old_event_glob;
> + zfree(&ps->event_glob);
> + ps->event_glob = old_event_glob;
> } else if (strcmp(argv[i], "sw") == 0 ||
> strcmp(argv[i], "software") == 0) {
> - char *old_pmu_glob = default_ps.pmu_glob;
> + char *old_pmu_glob = ps->pmu_glob;
> static const char * const sw_globs[] = { "software", "tool" };
>
> for (size_t j = 0; j < ARRAY_SIZE(sw_globs); j++) {
> - default_ps.pmu_glob = strdup(sw_globs[j]);
> - if (!default_ps.pmu_glob) {
> + ps->pmu_glob = strdup(sw_globs[j]);
> + if (!ps->pmu_glob) {
> ret = -1;
> goto out;
> }
> perf_pmus__print_pmu_events(&print_cb, ps);
> - zfree(&default_ps.pmu_glob);
> + zfree(&ps->pmu_glob);
> }
> - default_ps.pmu_glob = old_pmu_glob;
> + ps->pmu_glob = old_pmu_glob;
> } else if (strcmp(argv[i], "cache") == 0 ||
> strcmp(argv[i], "hwcache") == 0) {
> - char *old_event_glob = default_ps.event_glob;
> + char *old_event_glob = ps->event_glob;
>
> - default_ps.event_glob = strdup("legacy cache");
> - if (!default_ps.event_glob) {
> + ps->event_glob = strdup("legacy cache");
> + if (!ps->event_glob) {
> ret = -1;
> goto out;
> }
> perf_pmus__print_pmu_events(&print_cb, ps);
> - zfree(&default_ps.event_glob);
> - default_ps.event_glob = old_event_glob;
> + zfree(&ps->event_glob);
> + ps->event_glob = old_event_glob;
> } else if (strcmp(argv[i], "pmu") == 0) {
> - default_ps.exclude_abi = true;
> + ps->exclude_abi = true;
> perf_pmus__print_pmu_events(&print_cb, ps);
> - default_ps.exclude_abi = false;
> + ps->exclude_abi = false;
> } else if (strcmp(argv[i], "sdt") == 0)
> print_sdt_events(&print_cb, ps);
> else if (strcmp(argv[i], "metric") == 0 || strcmp(argv[i], "metrics") == 0) {
> - default_ps.metricgroups = false;
> - default_ps.metrics = true;
> + ps->metricgroups = false;
> + ps->metrics = true;
> metricgroup__print(&print_cb, ps);
> } else if (strcmp(argv[i], "metricgroup") == 0 ||
> strcmp(argv[i], "metricgroups") == 0) {
> - default_ps.metricgroups = true;
> - default_ps.metrics = false;
> + ps->metricgroups = true;
> + ps->metrics = false;
> metricgroup__print(&print_cb, ps);
> }
> #ifdef HAVE_LIBPFM
> @@ -694,40 +697,40 @@ int cmd_list(int argc, const char **argv)
> print_libpfm_events(&print_cb, ps);
> #endif
> else if ((sep = strchr(argv[i], ':')) != NULL) {
> - char *old_pmu_glob = default_ps.pmu_glob;
> - char *old_event_glob = default_ps.event_glob;
> + char *old_pmu_glob = ps->pmu_glob;
> + char *old_event_glob = ps->event_glob;
>
> - default_ps.event_glob = strdup(argv[i]);
> - if (!default_ps.event_glob) {
> + ps->event_glob = strdup(argv[i]);
> + if (!ps->event_glob) {
> ret = -1;
> goto out;
> }
>
> - default_ps.pmu_glob = strdup("tracepoint");
> - if (!default_ps.pmu_glob) {
> - zfree(&default_ps.event_glob);
> + ps->pmu_glob = strdup("tracepoint");
> + if (!ps->pmu_glob) {
> + zfree(&ps->event_glob);
> ret = -1;
> goto out;
> }
> perf_pmus__print_pmu_events(&print_cb, ps);
> - zfree(&default_ps.pmu_glob);
> - default_ps.pmu_glob = old_pmu_glob;
> + zfree(&ps->pmu_glob);
> + ps->pmu_glob = old_pmu_glob;
> print_sdt_events(&print_cb, ps);
> - default_ps.metrics = true;
> - default_ps.metricgroups = true;
> + ps->metrics = true;
> + ps->metricgroups = true;
> metricgroup__print(&print_cb, ps);
> - zfree(&default_ps.event_glob);
> - default_ps.event_glob = old_event_glob;
> + zfree(&ps->event_glob);
> + ps->event_glob = old_event_glob;
> } else {
> if (asprintf(&s, "*%s*", argv[i]) < 0) {
> printf("Critical: Not enough memory! Trying to continue...\n");
> continue;
> }
> - default_ps.event_glob = s;
> + ps->event_glob = s;
> perf_pmus__print_pmu_events(&print_cb, ps);
> print_sdt_events(&print_cb, ps);
> - default_ps.metrics = true;
> - default_ps.metricgroups = true;
> + ps->metrics = true;
> + ps->metricgroups = true;
> metricgroup__print(&print_cb, ps);
> free(s);
> }
> @@ -735,12 +738,12 @@ int cmd_list(int argc, const char **argv)
>
> out:
> print_cb.print_end(ps);
> - free(default_ps.pmu_glob);
> - free(default_ps.last_topic);
> - free(default_ps.last_metricgroups);
> - strlist__delete(default_ps.visited_metrics);
> + free(ps->pmu_glob);
> + free(ps->last_topic);
> + free(ps->last_metricgroups);
> + strlist__delete(ps->visited_metrics);
> if (output_path)
> - fclose(default_ps.fp);
> + fclose(ps->fp);
>
> return ret;
> }
> --
> 2.52.0.rc1.455.g30608eb744-goog
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 3/3] perf list: Support filtering in JSON output
2025-11-20 0:47 ` [PATCH v2 3/3] perf list: Support filtering in " Namhyung Kim
@ 2025-11-20 5:42 ` Ian Rogers
2025-11-20 19:11 ` Namhyung Kim
0 siblings, 1 reply; 7+ messages in thread
From: Ian Rogers @ 2025-11-20 5:42 UTC (permalink / raw)
To: Namhyung Kim
Cc: Arnaldo Carvalho de Melo, James Clark, Jiri Olsa, Adrian Hunter,
Peter Zijlstra, Ingo Molnar, LKML, linux-perf-users
On Wed, Nov 19, 2025 at 4:47 PM Namhyung Kim <namhyung@kernel.org> wrote:
>
> Like regular output mode, it should honor command line arguments to
> limit to a certain type of PMUs or events.
>
> $ perf list -j hw
> [
> {
> "Unit": "cpu",
> "Topic": "legacy hardware",
> "EventName": "branch-instructions",
> "EventType": "Kernel PMU event",
> "BriefDescription": "Retired branch instructions [This event is an alias of branches]",
> "Encoding": "cpu/event=0xc4\n/"
> },
> {
> "Unit": "cpu",
> "Topic": "legacy hardware",
> "EventName": "branch-misses",
> "EventType": "Kernel PMU event",
> "BriefDescription": "Mispredicted branch instructions",
> "Encoding": "cpu/event=0xc5\n/"
I think these newlines can be fixed by changing:
https://web.git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/tree/tools/perf/util/pmu.c?h=perf-tools-next#n643
```
ret = io__getline(&io, &alias->terms, &line_len) < 0 ? -errno : 0;
if (ret) {
...
}
```
to something like:
```
ret = io__getline(&io, &alias->terms, &line_len) < 0 ? -errno : 0;
if (ret) {
...
}
if (alias->terms[line_len - 1] == '\n')
alias->terms[line_len - 1] = '\0';
```
> },
> ...
>
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Reviewed-by: Ian Rogers <irogers@google.com>
Thanks,
Ian
> ---
> tools/perf/builtin-list.c | 24 ++++++++++++++++++++++++
> 1 file changed, 24 insertions(+)
>
> diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
> index 6c5913f129f39c94..5cbca0bacd35237e 100644
> --- a/tools/perf/builtin-list.c
> +++ b/tools/perf/builtin-list.c
> @@ -373,6 +373,23 @@ static void json_print_event(void *ps, const char *topic,
> FILE *fp = print_state->common.fp;
> struct strbuf buf;
>
> + if (deprecated && !print_state->common.deprecated)
> + return;
> +
> + if (print_state->common.pmu_glob &&
> + (!pmu_name || !strglobmatch(pmu_name, print_state->common.pmu_glob)))
> + return;
> +
> + if (print_state->common.exclude_abi && pmu_type < PERF_TYPE_MAX &&
> + pmu_type != PERF_TYPE_RAW)
> + return;
> +
> + if (print_state->common.event_glob &&
> + (!event_name || !strglobmatch(event_name, print_state->common.event_glob)) &&
> + (!event_alias || !strglobmatch(event_alias, print_state->common.event_glob)) &&
> + (!topic || !strglobmatch_nocase(topic, print_state->common.event_glob)))
> + return;
> +
> strbuf_init(&buf, 0);
> fprintf(fp, "%s{\n", print_state->need_sep ? ",\n" : "");
> print_state->need_sep = true;
> @@ -449,6 +466,13 @@ static void json_print_metric(void *ps __maybe_unused, const char *group,
> FILE *fp = print_state->common.fp;
> struct strbuf buf;
>
> + if (print_state->common.event_glob &&
> + (!print_state->common.metrics || !name ||
> + !strglobmatch(name, print_state->common.event_glob)) &&
> + (!print_state->common.metricgroups || !group ||
> + !strglobmatch(group, print_state->common.event_glob)))
> + return;
> +
> strbuf_init(&buf, 0);
> fprintf(fp, "%s{\n", print_state->need_sep ? ",\n" : "");
> print_state->need_sep = true;
> --
> 2.52.0.rc1.455.g30608eb744-goog
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 3/3] perf list: Support filtering in JSON output
2025-11-20 5:42 ` Ian Rogers
@ 2025-11-20 19:11 ` Namhyung Kim
0 siblings, 0 replies; 7+ messages in thread
From: Namhyung Kim @ 2025-11-20 19:11 UTC (permalink / raw)
To: Ian Rogers
Cc: Arnaldo Carvalho de Melo, James Clark, Jiri Olsa, Adrian Hunter,
Peter Zijlstra, Ingo Molnar, LKML, linux-perf-users
On Wed, Nov 19, 2025 at 09:42:51PM -0800, Ian Rogers wrote:
> On Wed, Nov 19, 2025 at 4:47 PM Namhyung Kim <namhyung@kernel.org> wrote:
> >
> > Like regular output mode, it should honor command line arguments to
> > limit to a certain type of PMUs or events.
> >
> > $ perf list -j hw
> > [
> > {
> > "Unit": "cpu",
> > "Topic": "legacy hardware",
> > "EventName": "branch-instructions",
> > "EventType": "Kernel PMU event",
> > "BriefDescription": "Retired branch instructions [This event is an alias of branches]",
> > "Encoding": "cpu/event=0xc4\n/"
> > },
> > {
> > "Unit": "cpu",
> > "Topic": "legacy hardware",
> > "EventName": "branch-misses",
> > "EventType": "Kernel PMU event",
> > "BriefDescription": "Mispredicted branch instructions",
> > "Encoding": "cpu/event=0xc5\n/"
>
> I think these newlines can be fixed by changing:
> https://web.git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/tree/tools/perf/util/pmu.c?h=perf-tools-next#n643
> ```
> ret = io__getline(&io, &alias->terms, &line_len) < 0 ? -errno : 0;
> if (ret) {
> ...
> }
> ```
> to something like:
> ```
> ret = io__getline(&io, &alias->terms, &line_len) < 0 ? -errno : 0;
> if (ret) {
> ...
> }
> if (alias->terms[line_len - 1] == '\n')
> alias->terms[line_len - 1] = '\0';
> ```
Yep, will do in a separate patch.
>
> > },
> > ...
> >
> > Signed-off-by: Namhyung Kim <namhyung@kernel.org>
>
> Reviewed-by: Ian Rogers <irogers@google.com>
Thanks for your review!
Namhyung
> > ---
> > tools/perf/builtin-list.c | 24 ++++++++++++++++++++++++
> > 1 file changed, 24 insertions(+)
> >
> > diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
> > index 6c5913f129f39c94..5cbca0bacd35237e 100644
> > --- a/tools/perf/builtin-list.c
> > +++ b/tools/perf/builtin-list.c
> > @@ -373,6 +373,23 @@ static void json_print_event(void *ps, const char *topic,
> > FILE *fp = print_state->common.fp;
> > struct strbuf buf;
> >
> > + if (deprecated && !print_state->common.deprecated)
> > + return;
> > +
> > + if (print_state->common.pmu_glob &&
> > + (!pmu_name || !strglobmatch(pmu_name, print_state->common.pmu_glob)))
> > + return;
> > +
> > + if (print_state->common.exclude_abi && pmu_type < PERF_TYPE_MAX &&
> > + pmu_type != PERF_TYPE_RAW)
> > + return;
> > +
> > + if (print_state->common.event_glob &&
> > + (!event_name || !strglobmatch(event_name, print_state->common.event_glob)) &&
> > + (!event_alias || !strglobmatch(event_alias, print_state->common.event_glob)) &&
> > + (!topic || !strglobmatch_nocase(topic, print_state->common.event_glob)))
> > + return;
> > +
> > strbuf_init(&buf, 0);
> > fprintf(fp, "%s{\n", print_state->need_sep ? ",\n" : "");
> > print_state->need_sep = true;
> > @@ -449,6 +466,13 @@ static void json_print_metric(void *ps __maybe_unused, const char *group,
> > FILE *fp = print_state->common.fp;
> > struct strbuf buf;
> >
> > + if (print_state->common.event_glob &&
> > + (!print_state->common.metrics || !name ||
> > + !strglobmatch(name, print_state->common.event_glob)) &&
> > + (!print_state->common.metricgroups || !group ||
> > + !strglobmatch(group, print_state->common.event_glob)))
> > + return;
> > +
> > strbuf_init(&buf, 0);
> > fprintf(fp, "%s{\n", print_state->need_sep ? ",\n" : "");
> > print_state->need_sep = true;
> > --
> > 2.52.0.rc1.455.g30608eb744-goog
> >
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 1/3] perf list: Print matching PMU events for --unit
2025-11-20 0:47 [PATCH v2 1/3] perf list: Print matching PMU events for --unit Namhyung Kim
2025-11-20 0:47 ` [PATCH v2 2/3] perf list: Share print state with JSON output Namhyung Kim
2025-11-20 0:47 ` [PATCH v2 3/3] perf list: Support filtering in " Namhyung Kim
@ 2025-11-21 20:02 ` Namhyung Kim
2 siblings, 0 replies; 7+ messages in thread
From: Namhyung Kim @ 2025-11-21 20:02 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo, Ian Rogers, James Clark, Namhyung Kim
Cc: Jiri Olsa, Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
linux-perf-users
On Wed, 19 Nov 2025 16:47:24 -0800, Namhyung Kim wrote:
> When --unit option is used, pmu_glob is set to the argument. It should
> match with event PMU and display the matching ones only. But it also
> shows raw events and metrics after that.
>
> $ perf list --unit tool
> List of pre-defined events (to be used in -e or -M):
>
> [...]
Applied to perf-tools-next, thanks!
Best regards,
Namhyung
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-11-21 20:02 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-20 0:47 [PATCH v2 1/3] perf list: Print matching PMU events for --unit Namhyung Kim
2025-11-20 0:47 ` [PATCH v2 2/3] perf list: Share print state with JSON output Namhyung Kim
2025-11-20 5:30 ` Ian Rogers
2025-11-20 0:47 ` [PATCH v2 3/3] perf list: Support filtering in " Namhyung Kim
2025-11-20 5:42 ` Ian Rogers
2025-11-20 19:11 ` Namhyung Kim
2025-11-21 20:02 ` [PATCH v2 1/3] perf list: Print matching PMU events for --unit Namhyung Kim
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).