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 
_get_cpuid(char * buf,size_t sz,struct perf_cpu_map * cpus)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 
get_cpuid(char * buf,size_t sz)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 
get_cpuid_str(struct perf_pmu * pmu)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 }
102