GNU Linux-libre 5.13.14-gnu1
[releases.git] / tools / perf / arch / arm64 / util / header.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <perf/cpumap.h>
4 #include <util/cpumap.h>
5 #include <internal/cpumap.h>
6 #include <api/fs/fs.h>
7 #include <errno.h>
8 #include "debug.h"
9 #include "header.h"
10
11 #define MIDR "/regs/identification/midr_el1"
12 #define MIDR_SIZE 19
13 #define MIDR_REVISION_MASK      0xf
14 #define MIDR_VARIANT_SHIFT      20
15 #define MIDR_VARIANT_MASK       (0xf << MIDR_VARIANT_SHIFT)
16
17 static int _get_cpuid(char *buf, size_t sz, struct perf_cpu_map *cpus)
18 {
19         const char *sysfs = sysfs__mountpoint();
20         u64 midr = 0;
21         int cpu;
22
23         if (!sysfs || sz < MIDR_SIZE)
24                 return EINVAL;
25
26         cpus = perf_cpu_map__get(cpus);
27
28         for (cpu = 0; cpu < perf_cpu_map__nr(cpus); cpu++) {
29                 char path[PATH_MAX];
30                 FILE *file;
31
32                 scnprintf(path, PATH_MAX, "%s/devices/system/cpu/cpu%d"MIDR,
33                                 sysfs, cpus->map[cpu]);
34
35                 file = fopen(path, "r");
36                 if (!file) {
37                         pr_debug("fopen failed for file %s\n", path);
38                         continue;
39                 }
40
41                 if (!fgets(buf, MIDR_SIZE, file)) {
42                         fclose(file);
43                         continue;
44                 }
45                 fclose(file);
46
47                 /* Ignore/clear Variant[23:20] and
48                  * Revision[3:0] of MIDR
49                  */
50                 midr = strtoul(buf, NULL, 16);
51                 midr &= (~(MIDR_VARIANT_MASK | MIDR_REVISION_MASK));
52                 scnprintf(buf, MIDR_SIZE, "0x%016lx", midr);
53                 /* got midr break loop */
54                 break;
55         }
56
57         perf_cpu_map__put(cpus);
58
59         if (!midr)
60                 return EINVAL;
61
62         return 0;
63 }
64
65 int get_cpuid(char *buf, size_t sz)
66 {
67         struct perf_cpu_map *cpus = perf_cpu_map__new(NULL);
68         int ret;
69
70         if (!cpus)
71                 return EINVAL;
72
73         ret = _get_cpuid(buf, sz, cpus);
74
75         perf_cpu_map__put(cpus);
76
77         return ret;
78 }
79
80 char *get_cpuid_str(struct perf_pmu *pmu)
81 {
82         char *buf = NULL;
83         int res;
84
85         if (!pmu || !pmu->cpus)
86                 return NULL;
87
88         buf = malloc(MIDR_SIZE);
89         if (!buf)
90                 return NULL;
91
92         /* read midr from list of cpus mapped to this pmu */
93         res = _get_cpuid(buf, MIDR_SIZE, pmu->cpus);
94         if (res) {
95                 pr_err("failed to get cpuid string for PMU %s\n", pmu->name);
96                 free(buf);
97                 buf = NULL;
98         }
99
100         return buf;
101 }