perf pmu: Count sys and cpuid JSON events separately

Sys events are eagerly loaded as each event has a compat option that may
mean the event is or isn't associated with the PMU.

These shouldn't be counted as loaded_json_events as that is used for
JSON events matching the CPUID that may or may not have been loaded. The
mismatch causes issues on ARM64 that uses sys events.

Fixes: e6ff1eed3584362d ("perf pmu: Lazily add JSON events")
Closes: https://lore.kernel.org/lkml/20240510024729.1075732-1-justin.he@arm.com/
Reported-by: Jia He <justin.he@arm.com>
Signed-off-by: Ian Rogers <irogers@google.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: John Garry <john.g.garry@oracle.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20240511003601.2666907-1-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by Ian Rogers and committed by Arnaldo Carvalho de Melo d9c5f5f9 193a9e30

+53 -23
+49 -21
tools/perf/util/pmu.c
··· 36 36 37 37 #define UNIT_MAX_LEN 31 /* max length for event unit name */ 38 38 39 + enum event_source { 40 + /* An event loaded from /sys/devices/<pmu>/events. */ 41 + EVENT_SRC_SYSFS, 42 + /* An event loaded from a CPUID matched json file. */ 43 + EVENT_SRC_CPU_JSON, 44 + /* 45 + * An event loaded from a /sys/devices/<pmu>/identifier matched json 46 + * file. 47 + */ 48 + EVENT_SRC_SYS_JSON, 49 + }; 50 + 39 51 /** 40 52 * struct perf_pmu_alias - An event either read from sysfs or builtin in 41 53 * pmu-events.c, created by parsing the pmu-events json files. ··· 533 521 534 522 static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name, 535 523 const char *desc, const char *val, FILE *val_fd, 536 - const struct pmu_event *pe) 524 + const struct pmu_event *pe, enum event_source src) 537 525 { 538 526 struct perf_pmu_alias *alias; 539 527 int ret; ··· 586 574 } 587 575 snprintf(alias->unit, sizeof(alias->unit), "%s", unit); 588 576 } 589 - if (!pe) { 590 - /* Update an event from sysfs with json data. */ 591 - struct update_alias_data data = { 592 - .pmu = pmu, 593 - .alias = alias, 594 - }; 595 - 577 + switch (src) { 578 + default: 579 + case EVENT_SRC_SYSFS: 596 580 alias->from_sysfs = true; 597 581 if (pmu->events_table) { 582 + /* Update an event from sysfs with json data. */ 583 + struct update_alias_data data = { 584 + .pmu = pmu, 585 + .alias = alias, 586 + }; 598 587 if (pmu_events_table__find_event(pmu->events_table, pmu, name, 599 588 update_alias, &data) == 0) 600 - pmu->loaded_json_aliases++; 589 + pmu->cpu_json_aliases++; 601 590 } 602 - } 603 - 604 - if (!pe) 605 591 pmu->sysfs_aliases++; 606 - else 607 - pmu->loaded_json_aliases++; 592 + break; 593 + case EVENT_SRC_CPU_JSON: 594 + pmu->cpu_json_aliases++; 595 + break; 596 + case EVENT_SRC_SYS_JSON: 597 + pmu->sys_json_aliases++; 598 + break; 599 + 600 + } 608 601 list_add_tail(&alias->list, &pmu->aliases); 609 602 return 0; 610 603 } ··· 670 653 } 671 654 672 655 if (perf_pmu__new_alias(pmu, name, /*desc=*/ NULL, 673 - /*val=*/ NULL, file, /*pe=*/ NULL) < 0) 656 + /*val=*/ NULL, file, /*pe=*/ NULL, 657 + EVENT_SRC_SYSFS) < 0) 674 658 pr_debug("Cannot set up %s\n", name); 675 659 fclose(file); 676 660 } ··· 964 946 { 965 947 struct perf_pmu *pmu = vdata; 966 948 967 - perf_pmu__new_alias(pmu, pe->name, pe->desc, pe->event, /*val_fd=*/ NULL, pe); 949 + perf_pmu__new_alias(pmu, pe->name, pe->desc, pe->event, /*val_fd=*/ NULL, 950 + pe, EVENT_SRC_CPU_JSON); 968 951 return 0; 969 952 } 970 953 ··· 1000 981 return 0; 1001 982 1002 983 if (pmu_uncore_alias_match(pe->pmu, pmu->name) && 1003 - pmu_uncore_identifier_match(pe->compat, pmu->id)) { 984 + pmu_uncore_identifier_match(pe->compat, pmu->id)) { 1004 985 perf_pmu__new_alias(pmu, 1005 986 pe->name, 1006 987 pe->desc, 1007 988 pe->event, 1008 989 /*val_fd=*/ NULL, 1009 - pe); 990 + pe, 991 + EVENT_SRC_SYS_JSON); 1010 992 } 1011 993 1012 994 return 0; ··· 1102 1082 pmu->max_precise = pmu_max_precise(dirfd, pmu); 1103 1083 pmu->alias_name = pmu_find_alias_name(pmu, dirfd); 1104 1084 pmu->events_table = perf_pmu__find_events_table(pmu); 1085 + /* 1086 + * Load the sys json events/aliases when loading the PMU as each event 1087 + * may have a different compat regular expression. We therefore can't 1088 + * know the number of sys json events/aliases without computing the 1089 + * regular expressions for them all. 1090 + */ 1105 1091 pmu_add_sys_aliases(pmu); 1106 1092 list_add_tail(&pmu->list, pmus); 1107 1093 ··· 1765 1739 size_t nr; 1766 1740 1767 1741 pmu_aliases_parse(pmu); 1768 - nr = pmu->sysfs_aliases; 1742 + nr = pmu->sysfs_aliases + pmu->sys_json_aliases;; 1769 1743 1770 1744 if (pmu->cpu_aliases_added) 1771 - nr += pmu->loaded_json_aliases; 1745 + nr += pmu->cpu_json_aliases; 1772 1746 else if (pmu->events_table) 1773 - nr += pmu_events_table__num_events(pmu->events_table, pmu) - pmu->loaded_json_aliases; 1747 + nr += pmu_events_table__num_events(pmu->events_table, pmu) - pmu->cpu_json_aliases; 1748 + else 1749 + assert(pmu->cpu_json_aliases == 0); 1774 1750 1775 1751 return pmu->selectable ? nr + 1 : nr; 1776 1752 }
+4 -2
tools/perf/util/pmu.h
··· 123 123 const struct pmu_events_table *events_table; 124 124 /** @sysfs_aliases: Number of sysfs aliases loaded. */ 125 125 uint32_t sysfs_aliases; 126 - /** @sysfs_aliases: Number of json event aliases loaded. */ 127 - uint32_t loaded_json_aliases; 126 + /** @cpu_json_aliases: Number of json event aliases loaded specific to the CPUID. */ 127 + uint32_t cpu_json_aliases; 128 + /** @sys_json_aliases: Number of json event aliases loaded matching the PMU's identifier. */ 129 + uint32_t sys_json_aliases; 128 130 /** @sysfs_aliases_loaded: Are sysfs aliases loaded from disk? */ 129 131 bool sysfs_aliases_loaded; 130 132 /**