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