Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf parse-events: Remove non-json software events

Remove the hard coded encodings from parse-events. This has the
consequence that software events are matched using the sysfs/json
priority, will be case insensitive and will be wildcarded across PMUs.
As there were software and hardware types in the parsing code, the
removal means software vs hardware logic can be removed and hardware
assumed.

Now the perf json provides detailed descriptions of software events,
remove the previous listing support that didn't contain event
descriptions. When globbing is required for the "sw" option in perf
list, use string PMU globbing as was done previously for the tool PMU.

The output of `perf list sw` command changed like this.

Before:
List of pre-defined events (to be used in -e or -M):

alignment-faults [Software event]
bpf-output [Software event]
cgroup-switches [Software event]
context-switches OR cs [Software event]
cpu-clock [Software event]
cpu-migrations OR migrations [Software event]
dummy [Software event]
emulation-faults [Software event]
major-faults [Software event]
minor-faults [Software event]
page-faults OR faults [Software event]
task-clock [Software event]

After:
List of pre-defined events (to be used in -e or -M):

software:
alignment-faults
[Number of kernel handled memory alignment faults. Unit: software]
bpf-output
[An event used by BPF programs to write to the perf ring buffer. Unit: software]
cgroup-switches
[Number of context switches to a task in a different cgroup. Unit: software]
context-switches
[Number of context switches [This event is an alias of cs]. Unit: software]
cpu-clock
[Per-CPU high-resolution timer based event. Unit: software]
cpu-migrations
[Number of times a process has migrated to a new CPU [This event is an alias of migrations]. Unit: software]
cs
[Number of context switches [This event is an alias of context-switches]. Unit: software]
dummy
[A placeholder event that doesn't count anything. Unit: software]
...

Signed-off-by: Ian Rogers <irogers@google.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Link: https://lore.kernel.org/r/20250725185202.68671-4-irogers@google.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>

authored by

Ian Rogers and committed by
Namhyung Kim
6e9fa413 9957d8c8

+33 -107
+9 -10
tools/perf/builtin-list.c
··· 623 623 else if (strcmp(argv[i], "sw") == 0 || 624 624 strcmp(argv[i], "software") == 0) { 625 625 char *old_pmu_glob = default_ps.pmu_glob; 626 + static const char * const sw_globs[] = { "software", "tool" }; 626 627 627 - print_symbol_events(&print_cb, ps, PERF_TYPE_SOFTWARE, 628 - event_symbols_sw, PERF_COUNT_SW_MAX); 629 - default_ps.pmu_glob = strdup("tool"); 630 - if (!default_ps.pmu_glob) { 631 - ret = -1; 632 - goto out; 628 + for (size_t j = 0; j < ARRAY_SIZE(sw_globs); j++) { 629 + default_ps.pmu_glob = strdup(sw_globs[j]); 630 + if (!default_ps.pmu_glob) { 631 + ret = -1; 632 + goto out; 633 + } 634 + perf_pmus__print_pmu_events(&print_cb, ps); 635 + zfree(&default_ps.pmu_glob); 633 636 } 634 - perf_pmus__print_pmu_events(&print_cb, ps); 635 - zfree(&default_ps.pmu_glob); 636 637 default_ps.pmu_glob = old_pmu_glob; 637 638 } else if (strcmp(argv[i], "cache") == 0 || 638 639 strcmp(argv[i], "hwcache") == 0) ··· 680 679 default_ps.event_glob = s; 681 680 print_symbol_events(&print_cb, ps, PERF_TYPE_HARDWARE, 682 681 event_symbols_hw, PERF_COUNT_HW_MAX); 683 - print_symbol_events(&print_cb, ps, PERF_TYPE_SOFTWARE, 684 - event_symbols_sw, PERF_COUNT_SW_MAX); 685 682 print_hwcache_events(&print_cb, ps); 686 683 perf_pmus__print_pmu_events(&print_cb, ps); 687 684 print_tracepoint_events(&print_cb, ps);
-51
tools/perf/util/parse-events.c
··· 84 84 }, 85 85 }; 86 86 87 - const struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = { 88 - [PERF_COUNT_SW_CPU_CLOCK] = { 89 - .symbol = "cpu-clock", 90 - .alias = "", 91 - }, 92 - [PERF_COUNT_SW_TASK_CLOCK] = { 93 - .symbol = "task-clock", 94 - .alias = "", 95 - }, 96 - [PERF_COUNT_SW_PAGE_FAULTS] = { 97 - .symbol = "page-faults", 98 - .alias = "faults", 99 - }, 100 - [PERF_COUNT_SW_CONTEXT_SWITCHES] = { 101 - .symbol = "context-switches", 102 - .alias = "cs", 103 - }, 104 - [PERF_COUNT_SW_CPU_MIGRATIONS] = { 105 - .symbol = "cpu-migrations", 106 - .alias = "migrations", 107 - }, 108 - [PERF_COUNT_SW_PAGE_FAULTS_MIN] = { 109 - .symbol = "minor-faults", 110 - .alias = "", 111 - }, 112 - [PERF_COUNT_SW_PAGE_FAULTS_MAJ] = { 113 - .symbol = "major-faults", 114 - .alias = "", 115 - }, 116 - [PERF_COUNT_SW_ALIGNMENT_FAULTS] = { 117 - .symbol = "alignment-faults", 118 - .alias = "", 119 - }, 120 - [PERF_COUNT_SW_EMULATION_FAULTS] = { 121 - .symbol = "emulation-faults", 122 - .alias = "", 123 - }, 124 - [PERF_COUNT_SW_DUMMY] = { 125 - .symbol = "dummy", 126 - .alias = "", 127 - }, 128 - [PERF_COUNT_SW_BPF_OUTPUT] = { 129 - .symbol = "bpf-output", 130 - .alias = "", 131 - }, 132 - [PERF_COUNT_SW_CGROUP_SWITCHES] = { 133 - .symbol = "cgroup-switches", 134 - .alias = "", 135 - }, 136 - }; 137 - 138 87 static const char *const event_types[] = { 139 88 [PERF_TYPE_HARDWARE] = "hardware", 140 89 [PERF_TYPE_SOFTWARE] = "software",
-1
tools/perf/util/parse-events.h
··· 264 264 const char *alias; 265 265 }; 266 266 extern const struct event_symbol event_symbols_hw[]; 267 - extern const struct event_symbol event_symbols_sw[]; 268 267 269 268 char *parse_events_formats_error_string(char *additional_terms); 270 269
+13 -25
tools/perf/util/parse-events.l
··· 117 117 yyless(0); \ 118 118 } while (0) 119 119 120 - static int sym(yyscan_t scanner, int type, int config) 120 + static int sym(yyscan_t scanner, int config) 121 121 { 122 122 YYSTYPE *yylval = parse_events_get_lval(scanner); 123 123 124 - yylval->num = (type << 16) + config; 125 - return type == PERF_TYPE_HARDWARE ? PE_VALUE_SYM_HW : PE_VALUE_SYM_SW; 124 + yylval->num = config; 125 + return PE_VALUE_SYM_HW; 126 126 } 127 127 128 128 static int term(yyscan_t scanner, enum parse_events__term_type type) ··· 391 391 <<EOF>> { BEGIN(INITIAL); } 392 392 } 393 393 394 - cpu-cycles|cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); } 395 - stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); } 396 - stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); } 397 - instructions { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); } 398 - cache-references { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); } 399 - cache-misses { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); } 400 - branch-instructions|branches { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); } 401 - branch-misses { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES); } 402 - bus-cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES); } 403 - ref-cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES); } 404 - cpu-clock { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); } 405 - task-clock { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK); } 406 - page-faults|faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS); } 407 - minor-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN); } 408 - major-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ); } 409 - context-switches|cs { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES); } 410 - cpu-migrations|migrations { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS); } 411 - alignment-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); } 412 - emulation-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); } 413 - dummy { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); } 414 - bpf-output { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_BPF_OUTPUT); } 415 - cgroup-switches { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CGROUP_SWITCHES); } 394 + cpu-cycles|cycles { return sym(yyscanner, PERF_COUNT_HW_CPU_CYCLES); } 395 + stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); } 396 + stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); } 397 + instructions { return sym(yyscanner, PERF_COUNT_HW_INSTRUCTIONS); } 398 + cache-references { return sym(yyscanner, PERF_COUNT_HW_CACHE_REFERENCES); } 399 + cache-misses { return sym(yyscanner, PERF_COUNT_HW_CACHE_MISSES); } 400 + branch-instructions|branches { return sym(yyscanner, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); } 401 + branch-misses { return sym(yyscanner, PERF_COUNT_HW_BRANCH_MISSES); } 402 + bus-cycles { return sym(yyscanner, PERF_COUNT_HW_BUS_CYCLES); } 403 + ref-cycles { return sym(yyscanner, PERF_COUNT_HW_REF_CPU_CYCLES); } 416 404 417 405 {lc_type} { return str(yyscanner, PE_LEGACY_CACHE); } 418 406 {lc_type}-{lc_op_result} { return str(yyscanner, PE_LEGACY_CACHE); }
+11 -18
tools/perf/util/parse-events.y
··· 55 55 %} 56 56 57 57 %token PE_START_EVENTS PE_START_TERMS 58 - %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_TERM 58 + %token PE_VALUE PE_VALUE_SYM_HW PE_TERM 59 59 %token PE_EVENT_NAME 60 60 %token PE_RAW PE_NAME 61 61 %token PE_MODIFIER_EVENT PE_MODIFIER_BP PE_BP_COLON PE_BP_SLASH ··· 66 66 %token PE_TERM_HW 67 67 %type <num> PE_VALUE 68 68 %type <num> PE_VALUE_SYM_HW 69 - %type <num> PE_VALUE_SYM_SW 70 69 %type <mod> PE_MODIFIER_EVENT 71 70 %type <term_type> PE_TERM 72 - %type <num> value_sym 73 71 %type <str> PE_RAW 74 72 %type <str> PE_NAME 75 73 %type <str> PE_LEGACY_CACHE ··· 304 306 $$ = list; 305 307 } 306 308 307 - value_sym: 308 - PE_VALUE_SYM_HW 309 - | 310 - PE_VALUE_SYM_SW 311 - 312 309 event_legacy_symbol: 313 - value_sym '/' event_config '/' 310 + PE_VALUE_SYM_HW '/' event_config '/' 314 311 { 315 312 struct list_head *list; 316 - int type = $1 >> 16; 317 - int config = $1 & 255; 318 313 int err; 319 - bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE); 320 314 321 315 list = alloc_list(); 322 316 if (!list) 323 317 YYNOMEM; 324 - err = parse_events_add_numeric(_parse_state, list, type, config, $3, wildcard); 318 + err = parse_events_add_numeric(_parse_state, list, 319 + PERF_TYPE_HARDWARE, $1, 320 + $3, 321 + /*wildcard=*/true); 325 322 parse_events_terms__delete($3); 326 323 if (err) { 327 324 free_list_evsel(list); ··· 325 332 $$ = list; 326 333 } 327 334 | 328 - value_sym sep_slash_slash_dc 335 + PE_VALUE_SYM_HW sep_slash_slash_dc 329 336 { 330 337 struct list_head *list; 331 - int type = $1 >> 16; 332 - int config = $1 & 255; 333 - bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE); 334 338 int err; 335 339 336 340 list = alloc_list(); 337 341 if (!list) 338 342 YYNOMEM; 339 - err = parse_events_add_numeric(_parse_state, list, type, config, /*head_config=*/NULL, wildcard); 343 + err = parse_events_add_numeric(_parse_state, list, 344 + PERF_TYPE_HARDWARE, $1, 345 + /*head_config=*/NULL, 346 + /*wildcard=*/true); 340 347 if (err) 341 348 PE_ABORT(err); 342 349 $$ = list;
-2
tools/perf/util/print-events.c
··· 521 521 { 522 522 print_symbol_events(print_cb, print_state, PERF_TYPE_HARDWARE, 523 523 event_symbols_hw, PERF_COUNT_HW_MAX); 524 - print_symbol_events(print_cb, print_state, PERF_TYPE_SOFTWARE, 525 - event_symbols_sw, PERF_COUNT_SW_MAX); 526 524 527 525 print_hwcache_events(print_cb, print_state); 528 526