xref: /openbmc/linux/tools/perf/arch/arm64/util/pmu.c (revision 1eaf496e)
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(pmu))) {
15 		if (!is_pmu_core(pmu->name))
16 			continue;
17 
18 		/*
19 		 * The cpumap should cover all CPUs. Otherwise, some CPUs may
20 		 * not support some events or have different event IDs.
21 		 */
22 		if (RC_CHK_ACCESS(pmu->cpus)->nr != cpu__max_cpu().cpu)
23 			return NULL;
24 
25 		return pmu;
26 	}
27 	return NULL;
28 }
29 
30 const struct pmu_metrics_table *pmu_metrics_table__find(void)
31 {
32 	struct perf_pmu *pmu = pmu__find_core_pmu();
33 
34 	if (pmu)
35 		return perf_pmu__find_metrics_table(pmu);
36 
37 	return NULL;
38 }
39 
40 const struct pmu_events_table *pmu_events_table__find(void)
41 {
42 	struct perf_pmu *pmu = pmu__find_core_pmu();
43 
44 	if (pmu)
45 		return perf_pmu__find_events_table(pmu);
46 
47 	return NULL;
48 }
49 
50 double perf_pmu__cpu_slots_per_cycle(void)
51 {
52 	char path[PATH_MAX];
53 	unsigned long long slots = 0;
54 	struct perf_pmu *pmu = pmu__find_core_pmu();
55 
56 	if (pmu) {
57 		perf_pmu__pathname_scnprintf(path, sizeof(path),
58 					     pmu->name, "caps/slots");
59 		/*
60 		 * The value of slots is not greater than 32 bits, but sysfs__read_int
61 		 * can't read value with 0x prefix, so use sysfs__read_ull instead.
62 		 */
63 		sysfs__read_ull(path, &slots);
64 	}
65 
66 	return slots ? (double)slots : NAN;
67 }
68