aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/tools/perf/arch/arm64/util/header.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/arch/arm64/util/header.c')
-rw-r--r--tools/perf/arch/arm64/util/header.c135
1 files changed, 80 insertions, 55 deletions
diff --git a/tools/perf/arch/arm64/util/header.c b/tools/perf/arch/arm64/util/header.c
index d730666ab95d..f445a2dd6293 100644
--- a/tools/perf/arch/arm64/util/header.c
+++ b/tools/perf/arch/arm64/util/header.c
@@ -1,8 +1,9 @@
+#include <linux/kernel.h>
+#include <linux/bits.h>
+#include <linux/bitfield.h>
#include <stdio.h>
#include <stdlib.h>
#include <perf/cpumap.h>
-#include <util/cpumap.h>
-#include <internal/cpumap.h>
#include <api/fs/fs.h>
#include <errno.h>
#include "debug.h"
@@ -10,92 +11,116 @@
#define MIDR "/regs/identification/midr_el1"
#define MIDR_SIZE 19
-#define MIDR_REVISION_MASK 0xf
-#define MIDR_VARIANT_SHIFT 20
-#define MIDR_VARIANT_MASK (0xf << MIDR_VARIANT_SHIFT)
+#define MIDR_REVISION_MASK GENMASK(3, 0)
+#define MIDR_VARIANT_MASK GENMASK(23, 20)
-static int _get_cpuid(char *buf, size_t sz, struct perf_cpu_map *cpus)
+static int _get_cpuid(char *buf, size_t sz, struct perf_cpu cpu)
{
+ char path[PATH_MAX];
+ FILE *file;
const char *sysfs = sysfs__mountpoint();
- u64 midr = 0;
- int cpu;
+ assert(cpu.cpu != -1);
if (!sysfs || sz < MIDR_SIZE)
return EINVAL;
- cpus = perf_cpu_map__get(cpus);
+ scnprintf(path, PATH_MAX, "%s/devices/system/cpu/cpu%d" MIDR, sysfs, cpu.cpu);
- for (cpu = 0; cpu < perf_cpu_map__nr(cpus); cpu++) {
- char path[PATH_MAX];
- FILE *file;
-
- scnprintf(path, PATH_MAX, "%s/devices/system/cpu/cpu%d"MIDR,
- sysfs, cpus->map[cpu]);
-
- file = fopen(path, "r");
- if (!file) {
- pr_debug("fopen failed for file %s\n", path);
- continue;
- }
-
- if (!fgets(buf, MIDR_SIZE, file)) {
- fclose(file);
- continue;
- }
- fclose(file);
-
- /* Ignore/clear Variant[23:20] and
- * Revision[3:0] of MIDR
- */
- midr = strtoul(buf, NULL, 16);
- midr &= (~(MIDR_VARIANT_MASK | MIDR_REVISION_MASK));
- scnprintf(buf, MIDR_SIZE, "0x%016lx", midr);
- /* got midr break loop */
- break;
+ file = fopen(path, "r");
+ if (!file) {
+ pr_debug("fopen failed for file %s\n", path);
+ return EINVAL;
}
- perf_cpu_map__put(cpus);
-
- if (!midr)
+ if (!fgets(buf, MIDR_SIZE, file)) {
+ pr_debug("Failed to read file %s\n", path);
+ fclose(file);
return EINVAL;
-
+ }
+ fclose(file);
return 0;
}
-int get_cpuid(char *buf, size_t sz)
+int get_cpuid(char *buf, size_t sz, struct perf_cpu cpu)
{
- struct perf_cpu_map *cpus = perf_cpu_map__new(NULL);
- int ret;
+ struct perf_cpu_map *cpus;
+ int idx;
+
+ if (cpu.cpu != -1)
+ return _get_cpuid(buf, sz, cpu);
+ cpus = perf_cpu_map__new_online_cpus();
if (!cpus)
return EINVAL;
- ret = _get_cpuid(buf, sz, cpus);
-
- perf_cpu_map__put(cpus);
+ perf_cpu_map__for_each_cpu(cpu, idx, cpus) {
+ int ret = _get_cpuid(buf, sz, cpu);
- return ret;
+ if (ret == 0)
+ return 0;
+ }
+ return EINVAL;
}
-char *get_cpuid_str(struct perf_pmu *pmu)
+char *get_cpuid_str(struct perf_cpu cpu)
{
- char *buf = NULL;
+ char *buf = malloc(MIDR_SIZE);
int res;
- if (!pmu || !pmu->cpus)
- return NULL;
-
- buf = malloc(MIDR_SIZE);
if (!buf)
return NULL;
/* read midr from list of cpus mapped to this pmu */
- res = _get_cpuid(buf, MIDR_SIZE, pmu->cpus);
+ res = get_cpuid(buf, MIDR_SIZE, cpu);
if (res) {
- pr_err("failed to get cpuid string for PMU %s\n", pmu->name);
+ pr_err("failed to get cpuid string for CPU %d\n", cpu.cpu);
free(buf);
buf = NULL;
}
return buf;
}
+
+/*
+ * Return 0 if idstr is a higher or equal to version of the same part as
+ * mapcpuid. Therefore, if mapcpuid has 0 for revision and variant then any
+ * version of idstr will match as long as it's the same CPU type.
+ *
+ * Return 1 if the CPU type is different or the version of idstr is lower.
+ */
+int strcmp_cpuid_str(const char *mapcpuid, const char *idstr)
+{
+ u64 map_id = strtoull(mapcpuid, NULL, 16);
+ char map_id_variant = FIELD_GET(MIDR_VARIANT_MASK, map_id);
+ char map_id_revision = FIELD_GET(MIDR_REVISION_MASK, map_id);
+ u64 id = strtoull(idstr, NULL, 16);
+ char id_variant = FIELD_GET(MIDR_VARIANT_MASK, id);
+ char id_revision = FIELD_GET(MIDR_REVISION_MASK, id);
+ u64 id_fields = ~(MIDR_VARIANT_MASK | MIDR_REVISION_MASK);
+
+ /* Compare without version first */
+ if ((map_id & id_fields) != (id & id_fields))
+ return 1;
+
+ /*
+ * ID matches, now compare version.
+ *
+ * Arm revisions (like r0p0) are compared here like two digit semver
+ * values eg. 1.3 < 2.0 < 2.1 < 2.2.
+ *
+ * r = high value = 'Variant' field in MIDR
+ * p = low value = 'Revision' field in MIDR
+ *
+ */
+ if (id_variant > map_id_variant)
+ return 0;
+
+ if (id_variant == map_id_variant && id_revision >= map_id_revision)
+ return 0;
+
+ /*
+ * variant is less than mapfile variant or variants are the same but
+ * the revision doesn't match. Return no match.
+ */
+ return 1;
+}