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