perf tool_pmu: Switch to standard pmu functions and json descriptions
authorIan Rogers <irogers@google.com>
Wed, 2 Oct 2024 03:20:12 +0000 (20:20 -0700)
committerNamhyung Kim <namhyung@kernel.org>
Fri, 11 Oct 2024 06:40:33 +0000 (23:40 -0700)
Use the regular PMU approaches with tool json events to reduce the
amount of special tool_pmu code - tool_pmu__config_terms and
tool_pmu__for_each_event_cb are removed. Some functions remain, like
tool_pmu__str_to_event, as conveniences to metricgroups. Add
tool_pmu__skip_event/tool_pmu__num_skip_events to handle the case that
tool json events shouldn't appear on certain architectures. This isn't
done in jevents.py due to complexity in the empty-pmu-events.c and
when all vendor json is built into the tool.

Signed-off-by: Ian Rogers <irogers@google.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Link: https://lore.kernel.org/r/20241002032016.333748-10-irogers@google.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
tools/perf/util/pmu.c
tools/perf/util/pmus.c
tools/perf/util/tool_pmu.c
tools/perf/util/tool_pmu.h

index 9228650a62d26e00f08ecd8d60c243a9a458b1d7..0789758598c0768b487685091a323fe17bec4b1d 100644 (file)
@@ -1549,9 +1549,6 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
 {
        bool zero = !!pmu->perf_event_attr_init_default;
 
-       if (perf_pmu__is_tool(pmu))
-               return tool_pmu__config_terms(attr, head_terms, err);
-
        /* Fake PMU doesn't have proper terms so nothing to configure in attr. */
        if (perf_pmu__is_fake(pmu))
                return 0;
@@ -1664,8 +1661,8 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct parse_events_terms *head_
        info->scale    = 0.0;
        info->snapshot = false;
 
-       /* Tool/fake PMU doesn't rewrite terms. */
-       if (perf_pmu__is_tool(pmu) || perf_pmu__is_fake(pmu))
+       /* Fake PMU doesn't rewrite terms. */
+       if (perf_pmu__is_fake(pmu))
                goto out;
 
        list_for_each_entry_safe(term, h, &head_terms->terms, list) {
@@ -1835,8 +1832,8 @@ bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name)
 {
        if (!name)
                return false;
-       if (perf_pmu__is_tool(pmu))
-               return tool_pmu__str_to_event(name) != TOOL_PMU__EVENT_NONE;
+       if (perf_pmu__is_tool(pmu) && tool_pmu__skip_event(name))
+               return false;
        if (perf_pmu__find_alias(pmu, name, /*load=*/ true) != NULL)
                return true;
        if (pmu->cpu_aliases_added || !pmu->events_table)
@@ -1848,9 +1845,6 @@ size_t perf_pmu__num_events(struct perf_pmu *pmu)
 {
        size_t nr;
 
-       if (perf_pmu__is_tool(pmu))
-               return tool_pmu__num_events();
-
        pmu_aliases_parse(pmu);
        nr = pmu->sysfs_aliases + pmu->sys_json_aliases;
 
@@ -1861,6 +1855,9 @@ size_t perf_pmu__num_events(struct perf_pmu *pmu)
        else
                assert(pmu->cpu_json_aliases == 0);
 
+       if (perf_pmu__is_tool(pmu))
+               nr -= tool_pmu__num_skip_events();
+
        return pmu->selectable ? nr + 1 : nr;
 }
 
@@ -1911,15 +1908,15 @@ int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus,
        int ret = 0;
        struct strbuf sb;
 
-       if (perf_pmu__is_tool(pmu))
-               return tool_pmu__for_each_event_cb(pmu, state, cb);
-
        strbuf_init(&sb, /*hint=*/ 0);
        pmu_aliases_parse(pmu);
        pmu_add_cpu_aliases(pmu);
        list_for_each_entry(event, &pmu->aliases, list) {
                size_t buf_used, pmu_name_len;
 
+               if (perf_pmu__is_tool(pmu) && tool_pmu__skip_event(event->name))
+                       continue;
+
                info.pmu_name = event->pmu_name ?: pmu->name;
                pmu_name_len = pmu_deduped_name_len(pmu, info.pmu_name,
                                                    skip_duplicate_pmus);
@@ -2325,9 +2322,6 @@ const char *perf_pmu__name_from_config(struct perf_pmu *pmu, u64 config)
        if (!pmu)
                return NULL;
 
-       if (perf_pmu__is_tool(pmu))
-               return tool_pmu__event_to_str(config);
-
        pmu_aliases_parse(pmu);
        pmu_add_cpu_aliases(pmu);
        list_for_each_entry(event, &pmu->aliases, list) {
index 6e657c44de58eef5e732684e8baecb42484e93c2..107de86c26373a2baffe4488978d73a6fa7fd801 100644 (file)
@@ -440,6 +440,7 @@ static int perf_pmus__print_pmu_events__callback(void *vstate,
                pr_err("Unexpected event %s/%s/\n", info->pmu->name, info->name);
                return 1;
        }
+       assert(info->pmu != NULL || info->name != NULL);
        s = &state->aliases[state->index];
        s->pmu = info->pmu;
 #define COPY_STR(str) s->str = info->str ? strdup(info->str) : NULL
@@ -590,9 +591,6 @@ void perf_pmus__print_raw_pmu_events(const struct print_callbacks *print_cb, voi
                int len = pmu_name_len_no_suffix(pmu->name);
                const char *desc = "(see 'man perf-list' or 'man perf-record' on how to encode it)";
 
-               if (perf_pmu__is_tool(pmu))
-                       continue;
-
                if (!pmu->is_core)
                        desc = NULL;
 
index cfdc09dece1e536abf0861246bb6c7d9d83f106d..ea9d50f0252023dc7acdb4fb3cf8a4ee50759ed9 100644 (file)
@@ -33,101 +33,54 @@ static const char *const tool_pmu__event_names[TOOL_PMU__EVENT_MAX] = {
        "system_tsc_freq",
 };
 
-
-const char *tool_pmu__event_to_str(enum tool_pmu_event ev)
-{
-       if (ev > TOOL_PMU__EVENT_NONE && ev < TOOL_PMU__EVENT_MAX)
-               return tool_pmu__event_names[ev];
-
-       return NULL;
-}
-
-enum tool_pmu_event tool_pmu__str_to_event(const char *str)
+bool tool_pmu__skip_event(const char *name __maybe_unused)
 {
-       int i;
-
-       tool_pmu__for_each_event(i) {
-               if (!strcasecmp(str, tool_pmu__event_names[i])) {
 #if !defined(__aarch64__)
-                       /* The slots event should only appear on arm64. */
-                       if (i == TOOL_PMU__EVENT_SLOTS)
-                               return TOOL_PMU__EVENT_NONE;
+       /* The slots event should only appear on arm64. */
+       if (strcasecmp(name, "slots") == 0)
+               return true;
 #endif
-                       return i;
-               }
-       }
-       return TOOL_PMU__EVENT_NONE;
+#if !defined(__i386__) && !defined(__x86_64__)
+       /* The system_tsc_freq event should only appear on x86. */
+       if (strcasecmp(name, "system_tsc_freq") == 0)
+               return true;
+#endif
+       return false;
 }
 
-static int tool_pmu__config_term(struct perf_event_attr *attr,
-                                struct parse_events_term *term,
-                                struct parse_events_error *err)
+int tool_pmu__num_skip_events(void)
 {
-       if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER) {
-               enum tool_pmu_event ev = tool_pmu__str_to_event(term->config);
+       int num = 0;
 
-               if (ev == TOOL_PMU__EVENT_NONE)
-                       goto err_out;
-
-               attr->config = ev;
-               return 0;
-       }
-err_out:
-       if (err) {
-               char *err_str;
-
-               parse_events_error__handle(err, term->err_val,
-                                       asprintf(&err_str,
-                                               "unexpected tool event term (%s) %s",
-                                               parse_events__term_type_str(term->type_term),
-                                               term->config) < 0
-                                       ? strdup("unexpected tool event term")
-                                       : err_str,
-                                       NULL);
-       }
-       return -EINVAL;
+#if !defined(__aarch64__)
+       num++;
+#endif
+#if !defined(__i386__) && !defined(__x86_64__)
+       num++;
+#endif
+       return num;
 }
 
-int tool_pmu__config_terms(struct perf_event_attr *attr,
-                          struct parse_events_terms *terms,
-                          struct parse_events_error *err)
+const char *tool_pmu__event_to_str(enum tool_pmu_event ev)
 {
-       struct parse_events_term *term;
-
-       list_for_each_entry(term, &terms->terms, list) {
-               if (tool_pmu__config_term(attr, term, err))
-                       return -EINVAL;
-       }
-
-       return 0;
+       if (ev > TOOL_PMU__EVENT_NONE && ev < TOOL_PMU__EVENT_MAX)
+               return tool_pmu__event_names[ev];
 
+       return NULL;
 }
 
-int tool_pmu__for_each_event_cb(struct perf_pmu *pmu, void *state, pmu_event_callback cb)
+enum tool_pmu_event tool_pmu__str_to_event(const char *str)
 {
-       struct pmu_event_info info = {
-               .pmu = pmu,
-               .event_type_desc = "Tool event",
-       };
        int i;
 
+       if (tool_pmu__skip_event(str))
+               return TOOL_PMU__EVENT_NONE;
+
        tool_pmu__for_each_event(i) {
-               int ret;
-
-               info.name = tool_pmu__event_to_str(i);
-               info.alias = NULL;
-               info.scale_unit = NULL;
-               info.desc = NULL;
-               info.long_desc = NULL;
-               info.encoding_desc = NULL;
-               info.topic = NULL;
-               info.pmu_name = pmu->name;
-               info.deprecated = false;
-               ret = cb(state, &info);
-               if (ret)
-                       return ret;
+               if (!strcasecmp(str, tool_pmu__event_names[i]))
+                       return i;
        }
-       return 0;
+       return TOOL_PMU__EVENT_NONE;
 }
 
 bool perf_pmu__is_tool(const struct perf_pmu *pmu)
@@ -546,6 +499,8 @@ struct perf_pmu *perf_pmus__tool_pmu(void)
                .caps = LIST_HEAD_INIT(tool.caps),
                .format = LIST_HEAD_INIT(tool.format),
        };
+       if (!tool.events_table)
+               tool.events_table = find_core_events_table("common", "common");
 
        return &tool;
 }
index ecdf316525bbb571d67d26ce3f45962b146b00c2..a60184859080f1d930250147c920a01b5cd6664c 100644 (file)
@@ -29,17 +29,11 @@ enum tool_pmu_event {
 #define tool_pmu__for_each_event(ev)                                   \
        for ((ev) = TOOL_PMU__EVENT_DURATION_TIME; (ev) < TOOL_PMU__EVENT_MAX; ev++)
 
-static inline size_t tool_pmu__num_events(void)
-{
-       return TOOL_PMU__EVENT_MAX - 1;
-}
-
 const char *tool_pmu__event_to_str(enum tool_pmu_event ev);
 enum tool_pmu_event tool_pmu__str_to_event(const char *str);
-int tool_pmu__config_terms(struct perf_event_attr *attr,
-                          struct parse_events_terms *terms,
-                          struct parse_events_error *err);
-int tool_pmu__for_each_event_cb(struct perf_pmu *pmu, void *state, pmu_event_callback cb);
+bool tool_pmu__skip_event(const char *name);
+int tool_pmu__num_skip_events(void);
+
 bool tool_pmu__read_event(enum tool_pmu_event ev, u64 *result);
 
 u64 tool_pmu__cpu_slots_per_cycle(void);