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