0001 #include <stdio.h>
0002 #include <stdlib.h>
0003 #include <perf/cpumap.h>
0004 #include <util/cpumap.h>
0005 #include <internal/cpumap.h>
0006 #include <api/fs/fs.h>
0007 #include <errno.h>
0008 #include "debug.h"
0009 #include "header.h"
0010
0011 #define MIDR "/regs/identification/midr_el1"
0012 #define MIDR_SIZE 19
0013 #define MIDR_REVISION_MASK 0xf
0014 #define MIDR_VARIANT_SHIFT 20
0015 #define MIDR_VARIANT_MASK (0xf << MIDR_VARIANT_SHIFT)
0016
0017 static int _get_cpuid(char *buf, size_t sz, struct perf_cpu_map *cpus)
0018 {
0019 const char *sysfs = sysfs__mountpoint();
0020 u64 midr = 0;
0021 int cpu;
0022
0023 if (!sysfs || sz < MIDR_SIZE)
0024 return EINVAL;
0025
0026 cpus = perf_cpu_map__get(cpus);
0027
0028 for (cpu = 0; cpu < perf_cpu_map__nr(cpus); cpu++) {
0029 char path[PATH_MAX];
0030 FILE *file;
0031
0032 scnprintf(path, PATH_MAX, "%s/devices/system/cpu/cpu%d"MIDR,
0033 sysfs, cpus->map[cpu]);
0034
0035 file = fopen(path, "r");
0036 if (!file) {
0037 pr_debug("fopen failed for file %s\n", path);
0038 continue;
0039 }
0040
0041 if (!fgets(buf, MIDR_SIZE, file)) {
0042 fclose(file);
0043 continue;
0044 }
0045 fclose(file);
0046
0047
0048
0049
0050 midr = strtoul(buf, NULL, 16);
0051 midr &= (~(MIDR_VARIANT_MASK | MIDR_REVISION_MASK));
0052 scnprintf(buf, MIDR_SIZE, "0x%016lx", midr);
0053
0054 break;
0055 }
0056
0057 perf_cpu_map__put(cpus);
0058
0059 if (!midr)
0060 return EINVAL;
0061
0062 return 0;
0063 }
0064
0065 int get_cpuid(char *buf, size_t sz)
0066 {
0067 struct perf_cpu_map *cpus = perf_cpu_map__new(NULL);
0068 int ret;
0069
0070 if (!cpus)
0071 return EINVAL;
0072
0073 ret = _get_cpuid(buf, sz, cpus);
0074
0075 perf_cpu_map__put(cpus);
0076
0077 return ret;
0078 }
0079
0080 char *get_cpuid_str(struct perf_pmu *pmu)
0081 {
0082 char *buf = NULL;
0083 int res;
0084
0085 if (!pmu || !pmu->cpus)
0086 return NULL;
0087
0088 buf = malloc(MIDR_SIZE);
0089 if (!buf)
0090 return NULL;
0091
0092
0093 res = _get_cpuid(buf, MIDR_SIZE, pmu->cpus);
0094 if (res) {
0095 pr_err("failed to get cpuid string for PMU %s\n", pmu->name);
0096 free(buf);
0097 buf = NULL;
0098 }
0099
0100 return buf;
0101 }