| #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 0xf | |
| #define MIDR_VARIANT_SHIFT 20 | |
| #define MIDR_VARIANT_MASK (0xf << MIDR_VARIANT_SHIFT) | |
| static int _get_cpuid(char *buf, size_t sz, struct perf_cpu_map *cpus) | |
| { | |
| const char *sysfs = sysfs__mountpoint(); | |
| u64 midr = 0; | |
| int cpu; | |
| 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, 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; | |
| } | |
| perf_cpu_map__put(cpus); | |
| if (!midr) | |
| return EINVAL; | |
| return 0; | |
| } | |
| int get_cpuid(char *buf, size_t sz) | |
| { | |
| struct perf_cpu_map *cpus = perf_cpu_map__new(NULL); | |
| 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; | |
| } |