Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/perf/arch/x86/util/topdown.c
26288 views
1
// SPDX-License-Identifier: GPL-2.0
2
#include "util/evlist.h"
3
#include "util/pmu.h"
4
#include "util/pmus.h"
5
#include "util/topdown.h"
6
#include "topdown.h"
7
#include "evsel.h"
8
9
// cmask=0, inv=0, pc=0, edge=0, umask=4, event=0
10
#define TOPDOWN_SLOTS 0x0400
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_pmus__find_by_type(PERF_TYPE_RAW);
29
if (pmu && perf_pmu__have_event(pmu, "slots"))
30
has_perf_metrics = true;
31
32
cached = true;
33
return has_perf_metrics;
34
}
35
36
bool arch_is_topdown_slots(const struct evsel *evsel)
37
{
38
return evsel->core.attr.type == PERF_TYPE_RAW &&
39
evsel->core.attr.config == TOPDOWN_SLOTS &&
40
evsel->core.attr.config1 == 0;
41
}
42
43
bool arch_is_topdown_metrics(const struct evsel *evsel)
44
{
45
// cmask=0, inv=0, pc=0, edge=0, umask=0x80-0x87, event=0
46
return evsel->core.attr.type == PERF_TYPE_RAW &&
47
(evsel->core.attr.config & 0xFFFFF8FF) == 0x8000 &&
48
evsel->core.attr.config1 == 0;
49
}
50
51
/*
52
* Check whether a topdown group supports sample-read.
53
*
54
* Only Topdown metric supports sample-read. The slots
55
* event must be the leader of the topdown group.
56
*/
57
bool arch_topdown_sample_read(struct evsel *leader)
58
{
59
struct evsel *evsel;
60
61
if (!evsel__sys_has_perf_metrics(leader))
62
return false;
63
64
if (!arch_is_topdown_slots(leader))
65
return false;
66
67
/*
68
* If slots event as leader event but no topdown metric events
69
* in group, slots event should still sample as leader.
70
*/
71
evlist__for_each_entry(leader->evlist, evsel) {
72
if (evsel->core.leader != leader->core.leader)
73
continue;
74
if (evsel != leader && arch_is_topdown_metrics(evsel))
75
return true;
76
}
77
78
return false;
79
}
80
81
/*
82
* Make a copy of the topdown metric event metric_event with the given index but
83
* change its configuration to be a topdown slots event. Copying from
84
* metric_event ensures modifiers are the same.
85
*/
86
int topdown_insert_slots_event(struct list_head *list, int idx, struct evsel *metric_event)
87
{
88
struct evsel *evsel = evsel__new_idx(&metric_event->core.attr, idx);
89
90
if (!evsel)
91
return -ENOMEM;
92
93
evsel->core.attr.config = TOPDOWN_SLOTS;
94
evsel->core.cpus = perf_cpu_map__get(metric_event->core.cpus);
95
evsel->core.pmu_cpus = perf_cpu_map__get(metric_event->core.pmu_cpus);
96
evsel->core.is_pmu_core = true;
97
evsel->pmu = metric_event->pmu;
98
evsel->name = strdup("slots");
99
evsel->precise_max = metric_event->precise_max;
100
evsel->sample_read = metric_event->sample_read;
101
evsel->weak_group = metric_event->weak_group;
102
evsel->bpf_counter = metric_event->bpf_counter;
103
evsel->retire_lat = metric_event->retire_lat;
104
evsel__set_leader(evsel, evsel__leader(metric_event));
105
list_add_tail(&evsel->core.node, list);
106
return 0;
107
}
108
109