1 #include <linux/kernel.h>
2 #include <linux/bits.h>
3 #include <linux/bitfield.h>
6 #include <perf/cpumap.h>
12 #define MIDR "/regs/identification/midr_el1"
14 #define MIDR_REVISION_MASK GENMASK(3, 0)
15 #define MIDR_VARIANT_MASK GENMASK(23, 20)
17 static int _get_cpuid(char *buf
, size_t sz
, struct perf_cpu cpu
)
21 const char *sysfs
= sysfs__mountpoint();
23 assert(cpu
.cpu
!= -1);
24 if (!sysfs
|| sz
< MIDR_SIZE
)
27 scnprintf(path
, PATH_MAX
, "%s/devices/system/cpu/cpu%d" MIDR
, sysfs
, cpu
.cpu
);
29 file
= fopen(path
, "r");
31 pr_debug("fopen failed for file %s\n", path
);
35 if (!fgets(buf
, MIDR_SIZE
, file
)) {
36 pr_debug("Failed to read file %s\n", path
);
44 int get_cpuid(char *buf
, size_t sz
, struct perf_cpu cpu
)
46 struct perf_cpu_map
*cpus
;
50 return _get_cpuid(buf
, sz
, cpu
);
52 cpus
= perf_cpu_map__new_online_cpus();
56 perf_cpu_map__for_each_cpu(cpu
, idx
, cpus
) {
57 int ret
= _get_cpuid(buf
, sz
, cpu
);
65 char *get_cpuid_str(struct perf_cpu cpu
)
67 char *buf
= malloc(MIDR_SIZE
);
73 /* read midr from list of cpus mapped to this pmu */
74 res
= get_cpuid(buf
, MIDR_SIZE
, cpu
);
76 pr_err("failed to get cpuid string for CPU %d\n", cpu
.cpu
);
85 * Return 0 if idstr is a higher or equal to version of the same part as
86 * mapcpuid. Therefore, if mapcpuid has 0 for revision and variant then any
87 * version of idstr will match as long as it's the same CPU type.
89 * Return 1 if the CPU type is different or the version of idstr is lower.
91 int strcmp_cpuid_str(const char *mapcpuid
, const char *idstr
)
93 u64 map_id
= strtoull(mapcpuid
, NULL
, 16);
94 char map_id_variant
= FIELD_GET(MIDR_VARIANT_MASK
, map_id
);
95 char map_id_revision
= FIELD_GET(MIDR_REVISION_MASK
, map_id
);
96 u64 id
= strtoull(idstr
, NULL
, 16);
97 char id_variant
= FIELD_GET(MIDR_VARIANT_MASK
, id
);
98 char id_revision
= FIELD_GET(MIDR_REVISION_MASK
, id
);
99 u64 id_fields
= ~(MIDR_VARIANT_MASK
| MIDR_REVISION_MASK
);
101 /* Compare without version first */
102 if ((map_id
& id_fields
) != (id
& id_fields
))
106 * ID matches, now compare version.
108 * Arm revisions (like r0p0) are compared here like two digit semver
109 * values eg. 1.3 < 2.0 < 2.1 < 2.2.
111 * r = high value = 'Variant' field in MIDR
112 * p = low value = 'Revision' field in MIDR
115 if (id_variant
> map_id_variant
)
118 if (id_variant
== map_id_variant
&& id_revision
>= map_id_revision
)
122 * variant is less than mapfile variant or variants are the same but
123 * the revision doesn't match. Return no match.