if (topdown_sys_has_perf_metrics() &&
(arch_evsel__must_be_in_group(lhs) || arch_evsel__must_be_in_group(rhs))) {
/* Ensure the topdown slots comes first. */
- if (strcasestr(lhs->name, "slots") && !strcasestr(lhs->name, "uops_retired.slots"))
+ if (arch_is_topdown_slots(lhs))
return -1;
- if (strcasestr(rhs->name, "slots") && !strcasestr(rhs->name, "uops_retired.slots"))
+ if (arch_is_topdown_slots(rhs))
return 1;
/* Followed by topdown events. */
- if (strcasestr(lhs->name, "topdown") && !strcasestr(rhs->name, "topdown"))
+ if (arch_is_topdown_metrics(lhs) && !arch_is_topdown_metrics(rhs))
return -1;
- if (!strcasestr(lhs->name, "topdown") && strcasestr(rhs->name, "topdown"))
+ if (!arch_is_topdown_metrics(lhs) && arch_is_topdown_metrics(rhs))
return 1;
}
#include "util/pmu.h"
#include "util/pmus.h"
#include "linux/string.h"
+#include "topdown.h"
#include "evsel.h"
#include "util/debug.h"
#include "env.h"
strcasestr(evsel->name, "uops_retired.slots"))
return false;
- return strcasestr(evsel->name, "topdown") || strcasestr(evsel->name, "slots");
+ return arch_is_topdown_metrics(evsel) || arch_is_topdown_slots(evsel);
}
int arch_evsel__hw_name(struct evsel *evsel, char *bf, size_t size)
}
#define TOPDOWN_SLOTS 0x0400
+bool arch_is_topdown_slots(const struct evsel *evsel)
+{
+ if (evsel->core.attr.config == TOPDOWN_SLOTS)
+ return true;
+
+ return false;
+}
+
+static int compare_topdown_event(void *vstate, struct pmu_event_info *info)
+{
+ int *config = vstate;
+ int event = 0;
+ int umask = 0;
+ char *str;
+
+ if (!strcasestr(info->name, "topdown"))
+ return 0;
+
+ str = strcasestr(info->str, "event=");
+ if (str)
+ sscanf(str, "event=%x", &event);
+
+ str = strcasestr(info->str, "umask=");
+ if (str)
+ sscanf(str, "umask=%x", &umask);
+
+ if (event == 0 && *config == (event | umask << 8))
+ return 1;
+
+ return 0;
+}
+
+bool arch_is_topdown_metrics(const struct evsel *evsel)
+{
+ struct perf_pmu *pmu = evsel__find_pmu(evsel);
+ int config = evsel->core.attr.config;
+
+ if (!pmu || !pmu->is_core)
+ return false;
+
+ if (perf_pmu__for_each_event(pmu, false, &config,
+ compare_topdown_event))
+ return true;
+
+ return false;
+}
/*
* Check whether a topdown group supports sample-read.
if (!evsel__sys_has_perf_metrics(leader))
return false;
- if (leader->core.attr.config == TOPDOWN_SLOTS)
+ if (arch_is_topdown_slots(leader))
return true;
return false;