xref: /openbmc/linux/tools/perf/arch/arm64/util/pmu.c (revision 9d6a1df9)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 #include <internal/cpumap.h>
4 #include "../../../util/cpumap.h"
5 #include "../../../util/pmu.h"
6 #include "../../../util/pmus.h"
7 #include <api/fs/fs.h>
8 #include <math.h>
9 
10 static struct perf_pmu *pmu__find_core_pmu(void)
11 {
12 	struct perf_pmu *pmu = NULL;
13 
14 	while ((pmu = perf_pmus__scan_core(pmu))) {
15 		/*
16 		 * The cpumap should cover all CPUs. Otherwise, some CPUs may
17 		 * not support some events or have different event IDs.
18 		 */
19 		if (RC_CHK_ACCESS(pmu->cpus)->nr != cpu__max_cpu().cpu)
20 			return NULL;
21 
22 		return pmu;
23 	}
24 	return NULL;
25 }
26 
27 const struct pmu_metrics_table *pmu_metrics_table__find(void)
28 {
29 	struct perf_pmu *pmu = pmu__find_core_pmu();
30 
31 	if (pmu)
32 		return perf_pmu__find_metrics_table(pmu);
33 
34 	return NULL;
35 }
36 
37 const struct pmu_events_table *pmu_events_table__find(void)
38 {
39 	struct perf_pmu *pmu = pmu__find_core_pmu();
40 
41 	if (pmu)
42 		return perf_pmu__find_events_table(pmu);
43 
44 	return NULL;
45 }
46 
47 double perf_pmu__cpu_slots_per_cycle(void)
48 {
49 	char path[PATH_MAX];
50 	unsigned long long slots = 0;
51 	struct perf_pmu *pmu = pmu__find_core_pmu();
52 
53 	if (pmu) {
54 		perf_pmu__pathname_scnprintf(path, sizeof(path),
55 					     pmu->name, "caps/slots");
56 		/*
57 		 * The value of slots is not greater than 32 bits, but sysfs__read_int
58 		 * can't read value with 0x prefix, so use sysfs__read_ull instead.
59 		 */
60 		sysfs__read_ull(path, &slots);
61 	}
62 
63 	return slots ? (double)slots : NAN;
64 }
65