xref: /openbmc/linux/tools/perf/arch/arm64/util/header.c (revision 151f4e2b)
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <api/fs/fs.h>
4 #include "header.h"
5 
6 #define MIDR "/regs/identification/midr_el1"
7 #define MIDR_SIZE 19
8 #define MIDR_REVISION_MASK      0xf
9 #define MIDR_VARIANT_SHIFT      20
10 #define MIDR_VARIANT_MASK       (0xf << MIDR_VARIANT_SHIFT)
11 
12 char *get_cpuid_str(struct perf_pmu *pmu)
13 {
14 	char *buf = NULL;
15 	char path[PATH_MAX];
16 	const char *sysfs = sysfs__mountpoint();
17 	int cpu;
18 	u64 midr = 0;
19 	struct cpu_map *cpus;
20 	FILE *file;
21 
22 	if (!sysfs || !pmu || !pmu->cpus)
23 		return NULL;
24 
25 	buf = malloc(MIDR_SIZE);
26 	if (!buf)
27 		return NULL;
28 
29 	/* read midr from list of cpus mapped to this pmu */
30 	cpus = cpu_map__get(pmu->cpus);
31 	for (cpu = 0; cpu < cpus->nr; cpu++) {
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 	if (!midr) {
58 		pr_err("failed to get cpuid string for PMU %s\n", pmu->name);
59 		free(buf);
60 		buf = NULL;
61 	}
62 
63 	cpu_map__put(cpus);
64 	return buf;
65 }
66