xref: /openbmc/linux/tools/perf/arch/arm64/util/header.c (revision 09b35b41)
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <api/fs/fs.h>
4 #include "debug.h"
5 #include "header.h"
6 
7 #define MIDR "/regs/identification/midr_el1"
8 #define MIDR_SIZE 19
9 #define MIDR_REVISION_MASK      0xf
10 #define MIDR_VARIANT_SHIFT      20
11 #define MIDR_VARIANT_MASK       (0xf << MIDR_VARIANT_SHIFT)
12 
13 char *get_cpuid_str(struct perf_pmu *pmu)
14 {
15 	char *buf = NULL;
16 	char path[PATH_MAX];
17 	const char *sysfs = sysfs__mountpoint();
18 	int cpu;
19 	u64 midr = 0;
20 	struct perf_cpu_map *cpus;
21 	FILE *file;
22 
23 	if (!sysfs || !pmu || !pmu->cpus)
24 		return NULL;
25 
26 	buf = malloc(MIDR_SIZE);
27 	if (!buf)
28 		return NULL;
29 
30 	/* read midr from list of cpus mapped to this pmu */
31 	cpus = perf_cpu_map__get(pmu->cpus);
32 	for (cpu = 0; cpu < cpus->nr; cpu++) {
33 		scnprintf(path, PATH_MAX, "%s/devices/system/cpu/cpu%d"MIDR,
34 				sysfs, cpus->map[cpu]);
35 
36 		file = fopen(path, "r");
37 		if (!file) {
38 			pr_debug("fopen failed for file %s\n", path);
39 			continue;
40 		}
41 
42 		if (!fgets(buf, MIDR_SIZE, file)) {
43 			fclose(file);
44 			continue;
45 		}
46 		fclose(file);
47 
48 		/* Ignore/clear Variant[23:20] and
49 		 * Revision[3:0] of MIDR
50 		 */
51 		midr = strtoul(buf, NULL, 16);
52 		midr &= (~(MIDR_VARIANT_MASK | MIDR_REVISION_MASK));
53 		scnprintf(buf, MIDR_SIZE, "0x%016lx", midr);
54 		/* got midr break loop */
55 		break;
56 	}
57 
58 	if (!midr) {
59 		pr_err("failed to get cpuid string for PMU %s\n", pmu->name);
60 		free(buf);
61 		buf = NULL;
62 	}
63 
64 	perf_cpu_map__put(cpus);
65 	return buf;
66 }
67