mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00

On ARM the cpuid is dependent on the core type of the CPU in question. The PMU was passed for the sake of the CPU map but this means in places a temporary PMU is created just to pass a CPU value. Just pass the CPU and fix up the callers. As there are no longer PMU users in header.h, shuffle forward declarations earlier to work around build failures. Reviewed-by: James Clark <james.clark@linaro.org> Signed-off-by: Ian Rogers <irogers@google.com> Tested-by: Xu Yang <xu.yang_2@nxp.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Albert Ou <aou@eecs.berkeley.edu> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Alexandre Ghiti <alexghiti@rivosinc.com> Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com> Cc: Ben Zong-You Xie <ben717@andestech.com> Cc: Benjamin Gray <bgray@linux.ibm.com> Cc: Bibo Mao <maobibo@loongson.cn> Cc: Clément Le Goffic <clement.legoffic@foss.st.com> Cc: Dima Kogan <dima@secretsauce.net> Cc: Dr. David Alan Gilbert <linux@treblig.org> Cc: Huacai Chen <chenhuacai@kernel.org> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: John Garry <john.g.garry@oracle.com> Cc: Kan Liang <kan.liang@linux.intel.com> Cc: Leo Yan <leo.yan@linux.dev> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Mike Leach <mike.leach@linaro.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Palmer Dabbelt <palmer@dabbelt.com> Cc: Paul Walmsley <paul.walmsley@sifive.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ravi Bangoria <ravi.bangoria@amd.com> Cc: Sandipan Das <sandipan.das@amd.com> Cc: Will Deacon <will@kernel.org> Cc: Yicong Yang <yangyicong@hisilicon.com> Cc: linux-arm-kernel@lists.infradead.org Cc: linux-riscv@lists.infradead.org Link: https://lore.kernel.org/r/20241107162035.52206-7-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
126 lines
2.9 KiB
C
126 lines
2.9 KiB
C
#include <linux/kernel.h>
|
|
#include <linux/bits.h>
|
|
#include <linux/bitfield.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <perf/cpumap.h>
|
|
#include <api/fs/fs.h>
|
|
#include <errno.h>
|
|
#include "debug.h"
|
|
#include "header.h"
|
|
|
|
#define MIDR "/regs/identification/midr_el1"
|
|
#define MIDR_SIZE 19
|
|
#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 cpu)
|
|
{
|
|
char path[PATH_MAX];
|
|
FILE *file;
|
|
const char *sysfs = sysfs__mountpoint();
|
|
|
|
assert(cpu.cpu != -1);
|
|
if (!sysfs || sz < MIDR_SIZE)
|
|
return EINVAL;
|
|
|
|
scnprintf(path, PATH_MAX, "%s/devices/system/cpu/cpu%d" MIDR, sysfs, cpu.cpu);
|
|
|
|
file = fopen(path, "r");
|
|
if (!file) {
|
|
pr_debug("fopen failed for file %s\n", path);
|
|
return EINVAL;
|
|
}
|
|
|
|
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, struct perf_cpu cpu)
|
|
{
|
|
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;
|
|
|
|
perf_cpu_map__for_each_cpu(cpu, idx, cpus) {
|
|
int ret = _get_cpuid(buf, sz, cpu);
|
|
|
|
if (ret == 0)
|
|
return 0;
|
|
}
|
|
return EINVAL;
|
|
}
|
|
|
|
char *get_cpuid_str(struct perf_cpu cpu)
|
|
{
|
|
char *buf = malloc(MIDR_SIZE);
|
|
int res;
|
|
|
|
if (!buf)
|
|
return NULL;
|
|
|
|
/* read midr from list of cpus mapped to this pmu */
|
|
res = get_cpuid(buf, MIDR_SIZE, cpu);
|
|
if (res) {
|
|
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;
|
|
}
|