mirror of
https://github.com/torvalds/linux.git
synced 2025-04-12 16:47:42 +00:00

Passing NULL to perf_cpu_map__new() performs perf_cpu_map__new_online_cpus(), just directly call perf_cpu_map__new_online_cpus() to be more intention revealing. Reviewed-by: James Clark <james.clark@arm.com> Signed-off-by: Ian Rogers <irogers@google.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Alexandre Ghiti <alexghiti@rivosinc.com> Cc: Andrew Jones <ajones@ventanamicro.com> Cc: André Almeida <andrealmeid@igalia.com> Cc: Athira Jajeev <atrajeev@linux.vnet.ibm.com> Cc: Atish Patra <atishp@rivosinc.com> Cc: Changbin Du <changbin.du@huawei.com> Cc: Darren Hart <dvhart@infradead.org> Cc: Davidlohr Bueso <dave@stgolabs.net> 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: K Prateek Nayak <kprateek.nayak@amd.com> Cc: Kajol Jain <kjain@linux.ibm.com> Cc: Kan Liang <kan.liang@linux.intel.com> Cc: Leo Yan <leo.yan@linaro.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Mike Leach <mike.leach@linaro.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Nick Desaulniers <ndesaulniers@google.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Paran Lee <p4ranlee@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ravi Bangoria <ravi.bangoria@amd.com> Cc: Sandipan Das <sandipan.das@amd.com> Cc: Sean Christopherson <seanjc@google.com> Cc: Steinar H. Gunderson <sesse@google.com> Cc: Suzuki Poulouse <suzuki.poulose@arm.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Will Deacon <will@kernel.org> Cc: Yang Jihong <yangjihong1@huawei.com> Cc: Yang Li <yang.lee@linux.alibaba.com> Cc: Yanteng Si <siyanteng@loongson.cn> Cc: bpf@vger.kernel.org Cc: coresight@lists.linaro.org Cc: linux-arm-kernel@lists.infradead.org Link: https://lore.kernel.org/r/20231129060211.1890454-5-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
139 lines
3.1 KiB
C
139 lines
3.1 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 <util/cpumap.h>
|
|
#include <internal/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_map *cpus)
|
|
{
|
|
const char *sysfs = sysfs__mountpoint();
|
|
int cpu;
|
|
int ret = EINVAL;
|
|
|
|
if (!sysfs || sz < MIDR_SIZE)
|
|
return EINVAL;
|
|
|
|
cpus = perf_cpu_map__get(cpus);
|
|
|
|
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, RC_CHK_ACCESS(cpus)->map[cpu].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);
|
|
|
|
/* got midr break loop */
|
|
ret = 0;
|
|
break;
|
|
}
|
|
|
|
perf_cpu_map__put(cpus);
|
|
return ret;
|
|
}
|
|
|
|
int get_cpuid(char *buf, size_t sz)
|
|
{
|
|
struct perf_cpu_map *cpus = perf_cpu_map__new_online_cpus();
|
|
int ret;
|
|
|
|
if (!cpus)
|
|
return EINVAL;
|
|
|
|
ret = _get_cpuid(buf, sz, cpus);
|
|
|
|
perf_cpu_map__put(cpus);
|
|
|
|
return ret;
|
|
}
|
|
|
|
char *get_cpuid_str(struct perf_pmu *pmu)
|
|
{
|
|
char *buf = NULL;
|
|
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);
|
|
if (res) {
|
|
pr_err("failed to get cpuid string for PMU %s\n", pmu->name);
|
|
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;
|
|
}
|