1 // SPDX-License-Identifier: GPL-2.0 2 #include <stdio.h> 3 #include "api/fs/fs.h" 4 #include "util/pmu.h" 5 #include "util/topdown.h" 6 #include "util/evlist.h" 7 #include "util/debug.h" 8 #include "util/pmu-hybrid.h" 9 #include "topdown.h" 10 #include "evsel.h" 11 12 /* Check whether there is a PMU which supports the perf metrics. */ 13 bool topdown_sys_has_perf_metrics(void) 14 { 15 static bool has_perf_metrics; 16 static bool cached; 17 struct perf_pmu *pmu; 18 19 if (cached) 20 return has_perf_metrics; 21 22 /* 23 * The perf metrics feature is a core PMU feature. 24 * The PERF_TYPE_RAW type is the type of a core PMU. 25 * The slots event is only available when the core PMU 26 * supports the perf metrics feature. 27 */ 28 pmu = perf_pmu__find_by_type(PERF_TYPE_RAW); 29 if (pmu && pmu_have_event(pmu->name, "slots")) 30 has_perf_metrics = true; 31 32 cached = true; 33 return has_perf_metrics; 34 } 35 36 /* 37 * Check whether we can use a group for top down. 38 * Without a group may get bad results due to multiplexing. 39 */ 40 bool arch_topdown_check_group(bool *warn) 41 { 42 int n; 43 44 if (sysctl__read_int("kernel/nmi_watchdog", &n) < 0) 45 return false; 46 if (n > 0) { 47 *warn = true; 48 return false; 49 } 50 return true; 51 } 52 53 void arch_topdown_group_warn(void) 54 { 55 fprintf(stderr, 56 "nmi_watchdog enabled with topdown. May give wrong results.\n" 57 "Disable with echo 0 > /proc/sys/kernel/nmi_watchdog\n"); 58 } 59 60 #define TOPDOWN_SLOTS 0x0400 61 62 /* 63 * Check whether a topdown group supports sample-read. 64 * 65 * Only Topdown metric supports sample-read. The slots 66 * event must be the leader of the topdown group. 67 */ 68 69 bool arch_topdown_sample_read(struct evsel *leader) 70 { 71 if (!evsel__sys_has_perf_metrics(leader)) 72 return false; 73 74 if (leader->core.attr.config == TOPDOWN_SLOTS) 75 return true; 76 77 return false; 78 } 79 80 const char *arch_get_topdown_pmu_name(struct evlist *evlist, bool warn) 81 { 82 const char *pmu_name; 83 84 if (!perf_pmu__has_hybrid()) 85 return "cpu"; 86 87 if (!evlist->hybrid_pmu_name) { 88 if (warn) 89 pr_warning("WARNING: default to use cpu_core topdown events\n"); 90 evlist->hybrid_pmu_name = perf_pmu__hybrid_type_to_pmu("core"); 91 } 92 93 pmu_name = evlist->hybrid_pmu_name; 94 95 return pmu_name; 96 } 97